Marco Ricci commited on 2024-08-18 09:41:16
Zeige 3 geänderte Dateien mit 75 Einfügungen und 31 Löschungen.
Instead of having both exporters reimplement the logic for determining the vault key and vault configuration path, implement this functionality in the `derivepassphrase.exporter` package, which is otherwise still empty.
... | ... |
@@ -0,0 +1,58 @@ |
1 |
+import os |
|
2 |
+ |
|
3 |
+ |
|
4 |
+def get_vault_key() -> bytes: |
|
5 |
+ """Automatically determine the vault master key/password. |
|
6 |
+ |
|
7 |
+ Query the `VAULT_KEY`, `LOGNAME`, `USER` and `USERNAME` environment |
|
8 |
+ variables, in that order. This is the same algorithm as vault uses. |
|
9 |
+ |
|
10 |
+ Returns: |
|
11 |
+ The master key/password. This is generally used as input to |
|
12 |
+ a key-derivation function to determine the *actual* encryption |
|
13 |
+ and signing keys for the vault configuration. |
|
14 |
+ |
|
15 |
+ Raises: |
|
16 |
+ KeyError: |
|
17 |
+ We cannot find any of the named environment variables. |
|
18 |
+ Please set `VAULT_KEY` manually to the desired value. |
|
19 |
+ |
|
20 |
+ """ |
|
21 |
+ |
|
22 |
+ username = ( |
|
23 |
+ os.environb.get(b'VAULT_KEY') |
|
24 |
+ or os.environb.get(b'LOGNAME') |
|
25 |
+ or os.environb.get(b'USER') |
|
26 |
+ or os.environb.get(b'USERNAME') |
|
27 |
+ ) |
|
28 |
+ if not username: |
|
29 |
+ env_var = 'VAULT_KEY' |
|
30 |
+ raise KeyError(env_var) |
|
31 |
+ return username |
|
32 |
+ |
|
33 |
+ |
|
34 |
+def get_vault_path() -> str | bytes | os.PathLike: |
|
35 |
+ """Automatically determine the vault configuration path. |
|
36 |
+ |
|
37 |
+ Query the `VAULT_PATH` environment variable, or default to |
|
38 |
+ `~/.vault`. This is the same algorithm as vault uses. If not |
|
39 |
+ absolute, then `VAULT_PATH` is relative to the home directory. |
|
40 |
+ |
|
41 |
+ Returns: |
|
42 |
+ The vault configuration path. Depending on the vault version, |
|
43 |
+ this may be a file or a directory. |
|
44 |
+ |
|
45 |
+ Raises: |
|
46 |
+ RuntimeError: |
|
47 |
+ We cannot determine the home directory. Please set `HOME` |
|
48 |
+ manually to the correct value. |
|
49 |
+ |
|
50 |
+ """ |
|
51 |
+ |
|
52 |
+ result = os.path.join( |
|
53 |
+ os.path.expanduser('~'), os.environ.get('VAULT_PATH', '.vault') |
|
54 |
+ ) |
|
55 |
+ if result.startswith('~'): |
|
56 |
+ msg = 'Cannot determine home directory' |
|
57 |
+ raise RuntimeError(msg) |
|
58 |
+ return result |
... | ... |
@@ -15,6 +15,8 @@ from cryptography.hazmat.primitives import ciphers, hashes, hmac, padding |
15 | 15 |
from cryptography.hazmat.primitives.ciphers import algorithms, modes |
16 | 16 |
from cryptography.hazmat.primitives.kdf import pbkdf2 |
17 | 17 |
|
18 |
+from derivepassphrase import exporter |
|
19 |
+ |
|
18 | 20 |
if TYPE_CHECKING: |
19 | 21 |
from collections.abc import Iterator |
20 | 22 |
|
... | ... |
@@ -24,15 +26,6 @@ IV_SIZE = 16 |
24 | 26 |
KEY_SIZE = MAC_SIZE = 32 |
25 | 27 |
ENCRYPTED_KEYPAIR_SIZE = 128 |
26 | 28 |
VERSION_SIZE = 1 |
27 |
-MASTER_KEYS_KEY = ( |
|
28 |
- os.getenv('VAULT_KEY') |
|
29 |
- or os.getenv('LOGNAME') |
|
30 |
- or os.getenv('USER') |
|
31 |
- or os.getenv('USERNAME') |
|
32 |
-) |
|
33 |
-VAULT_PATH = os.path.join( |
|
34 |
- os.path.expanduser('~'), os.getenv('VAULT_PATH', '.vault') |
|
35 |
-) |
|
36 | 29 |
|
37 | 30 |
logger = logging.getLogger(__name__) |
38 | 31 |
|
... | ... |
@@ -448,18 +441,21 @@ def store(config: dict[str, Any], path: str, json_contents: bytes) -> None: |
448 | 441 |
|
449 | 442 |
|
450 | 443 |
def export_storeroom_data( |
451 |
- storeroom_path: str | bytes | os.PathLike = VAULT_PATH, |
|
452 |
- master_keys_key: str | bytes | None = MASTER_KEYS_KEY, |
|
444 |
+ storeroom_path: str | bytes | os.PathLike | None = None, |
|
445 |
+ master_keys_key: str | bytes | None = None, |
|
453 | 446 |
) -> dict[str, Any]: |
454 | 447 |
"""Export the full configuration stored in the storeroom. |
455 | 448 |
|
456 | 449 |
Args: |
457 | 450 |
storeroom_path: |
458 |
- Path to the storeroom; usually `~/.vault`. |
|
451 |
+ Path to the storeroom; usually `~/.vault`. If not given, |
|
452 |
+ then query [`derivepassphrase.exporter.get_vault_path`][] |
|
453 |
+ for the value. |
|
459 | 454 |
master_keys_key: |
460 |
- Encryption key/password for the master keys. If not set via |
|
461 |
- the `VAULT_KEY` environment variable, this usually is the |
|
462 |
- user's username. |
|
455 |
+ Encryption key/password for the master keys, usually the |
|
456 |
+ username, or passed via the `VAULT_KEY` environment |
|
457 |
+ variable. If not given, then query |
|
458 |
+ [`derivepassphrase.exporter.get_vault_key`][] for the value. |
|
463 | 459 |
|
464 | 460 |
Returns: |
465 | 461 |
The full configuration, as stored in the storeroom. |
... | ... |
@@ -477,9 +473,10 @@ def export_storeroom_data( |
477 | 473 |
|
478 | 474 |
""" |
479 | 475 |
|
476 |
+ if storeroom_path is None: |
|
477 |
+ storeroom_path = exporter.get_vault_path() |
|
480 | 478 |
if master_keys_key is None: |
481 |
- msg = 'Cannot determine master key; please set VAULT_KEY' |
|
482 |
- raise RuntimeError(msg) |
|
479 |
+ master_keys_key = exporter.get_vault_key() |
|
483 | 480 |
with open( |
484 | 481 |
os.path.join(os.fsdecode(storeroom_path), '.keys'), encoding='utf-8' |
485 | 482 |
) as master_keys_file: |
... | ... |
@@ -15,7 +15,7 @@ from cryptography.hazmat.primitives import ciphers, hashes, hmac, padding |
15 | 15 |
from cryptography.hazmat.primitives.ciphers import algorithms, modes |
16 | 16 |
from cryptography.hazmat.primitives.kdf import pbkdf2 |
17 | 17 |
|
18 |
-from derivepassphrase import vault |
|
18 |
+from derivepassphrase import exporter, vault |
|
19 | 19 |
|
20 | 20 |
logger = logging.getLogger(__name__) |
21 | 21 |
|
... | ... |
@@ -252,20 +252,9 @@ if __name__ == '__main__': |
252 | 252 |
import os |
253 | 253 |
|
254 | 254 |
logging.basicConfig(level=('DEBUG' if os.getenv('DEBUG') else 'WARNING')) |
255 |
- with open( |
|
256 |
- os.path.join( |
|
257 |
- os.path.expanduser('~'), os.getenv('VAULT_PATH', '.vault') |
|
258 |
- ), |
|
259 |
- 'rb', |
|
260 |
- ) as infile: |
|
255 |
+ with open(exporter.get_vault_path(), 'rb') as infile: |
|
261 | 256 |
contents = base64.standard_b64decode(infile.read()) |
262 |
- password = ( |
|
263 |
- os.getenv('VAULT_KEY') |
|
264 |
- or os.getenv('LOGNAME') |
|
265 |
- or os.getenv('USER') |
|
266 |
- or os.getenv('USERNAME') |
|
267 |
- ) |
|
268 |
- assert password |
|
257 |
+ password = exporter.get_vault_key() |
|
269 | 258 |
try: |
270 | 259 |
config = V03Reader(contents, password).run() |
271 | 260 |
except ValueError: |
272 | 261 |