From 6fafafa064becae826d78abe697077647dbb7534 Mon Sep 17 00:00:00 2001 From: DavHau Date: Mon, 9 Sep 2024 21:16:29 +0200 Subject: [PATCH] vars/password-store: use standard paths; fix share flag --- pkgs/clan-cli/clan_cli/vars/_types.py | 17 ++++++++++------- pkgs/clan-cli/clan_cli/vars/check.py | 7 +++++-- .../vars/secret_modules/password_store.py | 11 +++-------- pkgs/clan-cli/tests/test_vars.py | 16 ++++++++++++++-- 4 files changed, 32 insertions(+), 19 deletions(-) diff --git a/pkgs/clan-cli/clan_cli/vars/_types.py b/pkgs/clan-cli/clan_cli/vars/_types.py index b09286945..a9765d613 100644 --- a/pkgs/clan-cli/clan_cli/vars/_types.py +++ b/pkgs/clan-cli/clan_cli/vars/_types.py @@ -103,16 +103,19 @@ class StoreBase(ABC): def is_secret_store(self) -> bool: pass + def rel_dir(self, generator_name: str, var_name: str, shared: bool = False) -> Path: + if shared: + return Path(f"shared/{generator_name}/{var_name}") + return Path(f"per-machine/{self.machine.name}/{generator_name}/{var_name}") + def directory( self, generator_name: str, var_name: str, shared: bool = False ) -> Path: - if shared: - base_path = self.machine.flake_dir / "vars" / "shared" - else: - base_path = ( - self.machine.flake_dir / "vars" / "per-machine" / self.machine.name - ) - return base_path / generator_name / var_name + return ( + Path(self.machine.flake_dir) + / "vars" + / self.rel_dir(generator_name, var_name, shared) + ) def exists(self, generator_name: str, name: str, shared: bool = False) -> bool: directory = self.directory(generator_name, name, shared) diff --git a/pkgs/clan-cli/clan_cli/vars/check.py b/pkgs/clan-cli/clan_cli/vars/check.py index 0032c08c2..bf0e8feee 100644 --- a/pkgs/clan-cli/clan_cli/vars/check.py +++ b/pkgs/clan-cli/clan_cli/vars/check.py @@ -21,14 +21,17 @@ def check_vars(machine: Machine, generator_name: None | str = None) -> bool: else: generators = list(machine.vars_generators.keys()) for generator_name in generators: + shared = machine.vars_generators[generator_name]["share"] for name, file in machine.vars_generators[generator_name]["files"].items(): - if file["secret"] and not secret_vars_store.exists(generator_name, name): + if file["secret"] and not secret_vars_store.exists( + generator_name, name, shared=shared + ): log.info( f"Secret fact '{name}' for service '{generator_name}' in machine {machine.name} is missing." ) missing_secret_vars.append((generator_name, name)) if not file["secret"] and not public_vars_store.exists( - generator_name, name + generator_name, name, shared=shared ): log.info( f"Public fact '{name}' for service '{generator_name}' in machine {machine.name} is missing." diff --git a/pkgs/clan-cli/clan_cli/vars/secret_modules/password_store.py b/pkgs/clan-cli/clan_cli/vars/secret_modules/password_store.py index 986410d2f..7c7a1f44a 100644 --- a/pkgs/clan-cli/clan_cli/vars/secret_modules/password_store.py +++ b/pkgs/clan-cli/clan_cli/vars/secret_modules/password_store.py @@ -23,11 +23,6 @@ class SecretStore(SecretStoreBase): "PASSWORD_STORE_DIR", f"{os.environ['HOME']}/.password-store" ) - def _var_path(self, generator_name: str, name: str, shared: bool) -> Path: - if shared: - return Path(f"shared/{generator_name}/{name}") - return Path(f"machines/{self.machine.name}/{generator_name}/{name}") - def _set( self, generator_name: str, @@ -43,7 +38,7 @@ class SecretStore(SecretStoreBase): "pass", "insert", "-m", - str(self._var_path(generator_name, name, shared)), + str(self.rel_dir(generator_name, name, shared)), ], ), input=value, @@ -58,7 +53,7 @@ class SecretStore(SecretStoreBase): [ "pass", "show", - str(self._var_path(generator_name, name, shared)), + str(self.rel_dir(generator_name, name, shared)), ], ), check=True, @@ -70,7 +65,7 @@ class SecretStore(SecretStoreBase): return False return ( Path(self._password_store_dir) - / f"{self._var_path(generator_name, name, shared)}.gpg" + / f"{self.rel_dir(generator_name, name, shared)}.gpg" ).exists() def generate_hash(self) -> bytes: diff --git a/pkgs/clan-cli/tests/test_vars.py b/pkgs/clan-cli/tests/test_vars.py index a666d4e1c..24fdf0915 100644 --- a/pkgs/clan-cli/tests/test_vars.py +++ b/pkgs/clan-cli/tests/test_vars.py @@ -181,6 +181,12 @@ def test_generate_secret_var_password_store( my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"] my_generator["files"]["my_secret"]["secret"] = True my_generator["script"] = "echo hello > $out/my_secret" + my_shared_generator = config["clan"]["core"]["vars"]["generators"][ + "my_shared_generator" + ] + my_shared_generator["share"] = True + my_shared_generator["files"]["my_shared_secret"]["secret"] = True + my_shared_generator["script"] = "echo hello > $out/my_shared_secret" flake = generate_flake( temporary_home, flake_template=CLAN_CORE / "templates" / "minimal", @@ -219,8 +225,11 @@ def test_generate_secret_var_password_store( store = password_store.SecretStore( Machine(name="my_machine", flake=FlakeId(str(flake.path))) ) - assert store.exists("my_generator", "my_secret") - assert store.get("my_generator", "my_secret").decode() == "hello\n" + assert store.exists("my_generator", "my_secret", shared=False) + assert not store.exists("my_generator", "my_secret", shared=True) + assert store.exists("my_shared_generator", "my_shared_secret", shared=True) + assert not store.exists("my_shared_generator", "my_shared_secret", shared=False) + assert store.get("my_generator", "my_secret", shared=False).decode() == "hello\n" vars_text = stringify_all_vars(machine) assert "my_generator/my_secret" in vars_text @@ -382,7 +391,10 @@ def test_share_flag( ) monkeypatch.chdir(flake.path) sops_setup.init() + machine = Machine(name="my_machine", flake=FlakeId(str(flake.path))) + assert not check_vars(machine) cli.run(["vars", "generate", "--flake", str(flake.path), "my_machine"]) + assert check_vars(machine) sops_store = sops.SecretStore( Machine(name="my_machine", flake=FlakeId(str(flake.path))) )