From ae3283a7625184348111d824d5527347d99f2588 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Thu, 7 Sep 2023 12:30:29 +0200 Subject: [PATCH 1/2] clan/secrets: fix if user/machine directory does not contain a key.json --- pkgs/clan-cli/clan_cli/secrets/sops.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/clan-cli/clan_cli/secrets/sops.py b/pkgs/clan-cli/clan_cli/secrets/sops.py index 67703d3..6a201e7 100644 --- a/pkgs/clan-cli/clan_cli/secrets/sops.py +++ b/pkgs/clan-cli/clan_cli/secrets/sops.py @@ -55,8 +55,9 @@ def ensure_user_or_machine(pub_key: str) -> SopsKey: for folder in folders: if folder.exists(): for user in folder.iterdir(): - if not user.is_dir(): + if not (user / "key.json").exists(): continue + if read_key(user) == pub_key: key.username = user.name return key From c3ccf68007cedf8254fd32ac70c42716c0702089 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Thu, 7 Sep 2023 12:48:34 +0200 Subject: [PATCH 2/2] only list valid secrets/users/machines Git often leaves empty directories behind --- pkgs/clan-cli/clan_cli/secrets/machines.py | 7 ++++++- pkgs/clan-cli/clan_cli/secrets/secrets.py | 12 +++++++++--- pkgs/clan-cli/clan_cli/secrets/users.py | 14 ++++++++++---- pkgs/clan-cli/tests/test_secrets_cli.py | 3 +++ 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/pkgs/clan-cli/clan_cli/secrets/machines.py b/pkgs/clan-cli/clan_cli/secrets/machines.py index 811e883..f96c88b 100644 --- a/pkgs/clan-cli/clan_cli/secrets/machines.py +++ b/pkgs/clan-cli/clan_cli/secrets/machines.py @@ -20,7 +20,12 @@ def get_machine(name: str) -> str: def list_machines() -> list[str]: - return list_objects(sops_machines_folder(), lambda x: validate_hostname(x)) + path = sops_machines_folder() + + def validate(name: str) -> bool: + return validate_hostname(name) and (path / name / "key.json").exists() + + return list_objects(path, validate) def add_secret(machine: str, secret: str) -> None: diff --git a/pkgs/clan-cli/clan_cli/secrets/secrets.py b/pkgs/clan-cli/clan_cli/secrets/secrets.py index 27378e9..ae1206e 100644 --- a/pkgs/clan-cli/clan_cli/secrets/secrets.py +++ b/pkgs/clan-cli/clan_cli/secrets/secrets.py @@ -172,9 +172,15 @@ def disallow_member(group_folder: Path, name: str) -> None: def list_secrets() -> list[str]: - return list_objects( - sops_secrets_folder(), lambda n: VALID_SECRET_NAME.match(n) is not None - ) + path = sops_secrets_folder() + + def validate(name: str) -> bool: + return ( + VALID_SECRET_NAME.match(name) is not None + and (path / name / "secret").exists() + ) + + return list_objects(path, validate) def list_command(args: argparse.Namespace) -> None: diff --git a/pkgs/clan-cli/clan_cli/secrets/users.py b/pkgs/clan-cli/clan_cli/secrets/users.py index 760218a..2faaf64 100644 --- a/pkgs/clan-cli/clan_cli/secrets/users.py +++ b/pkgs/clan-cli/clan_cli/secrets/users.py @@ -4,7 +4,7 @@ from . import secrets from .folders import list_objects, remove_object, sops_users_folder from .sops import read_key, write_key from .types import ( - VALID_SECRET_NAME, + VALID_USER_NAME, public_or_private_age_key_type, secret_name_type, user_name_type, @@ -24,9 +24,15 @@ def get_user(name: str) -> str: def list_users() -> list[str]: - return list_objects( - sops_users_folder(), lambda n: VALID_SECRET_NAME.match(n) is not None - ) + path = sops_users_folder() + + def validate(name: str) -> bool: + return ( + VALID_USER_NAME.match(name) is not None + and (path / name / "key.json").exists() + ) + + return list_objects(path, validate) def add_secret(user: str, secret: str) -> None: diff --git a/pkgs/clan-cli/tests/test_secrets_cli.py b/pkgs/clan-cli/tests/test_secrets_cli.py index 9daf81e..203def4 100644 --- a/pkgs/clan-cli/tests/test_secrets_cli.py +++ b/pkgs/clan-cli/tests/test_secrets_cli.py @@ -153,6 +153,9 @@ def test_secrets( cli.run(["secrets", "machines", "add", "machine1", age_keys[0].pubkey]) cli.run(["secrets", "machines", "add-secret", "machine1", "key"]) + capsys.readouterr() + cli.run(["secrets", "machines", "list"]) + assert capsys.readouterr().out == "machine1\n" with use_key(age_keys[0].privkey, monkeypatch): capsys.readouterr()