From ece289d0cc5925ceb2e02ab81e622d61004ccfae Mon Sep 17 00:00:00 2001 From: lassulus Date: Fri, 2 Feb 2024 17:28:33 +0100 Subject: [PATCH 1/3] clan-cli secrets: add check command --- pkgs/clan-cli/clan_cli/secrets/__init__.py | 4 +++ pkgs/clan-cli/clan_cli/secrets/check.py | 42 ++++++++++++++++++++++ pkgs/clan-cli/clan_cli/secrets/generate.py | 9 ++--- 3 files changed, 48 insertions(+), 7 deletions(-) create mode 100644 pkgs/clan-cli/clan_cli/secrets/check.py diff --git a/pkgs/clan-cli/clan_cli/secrets/__init__.py b/pkgs/clan-cli/clan_cli/secrets/__init__.py index 01ac958d2..54be7b9c3 100644 --- a/pkgs/clan-cli/clan_cli/secrets/__init__.py +++ b/pkgs/clan-cli/clan_cli/secrets/__init__.py @@ -1,6 +1,7 @@ # !/usr/bin/env python3 import argparse +from .check import register_check_parser from .generate import register_generate_parser from .groups import register_groups_parser from .import_sops import register_import_sops_parser @@ -32,6 +33,9 @@ def register_parser(parser: argparse.ArgumentParser) -> None: import_sops_parser = subparser.add_parser("import-sops", help="import a sops file") register_import_sops_parser(import_sops_parser) + check_parser = subparser.add_parser("check", help="check if secrets are up to date") + register_check_parser(check_parser) + parser_generate = subparser.add_parser( "generate", help="generate secrets for machines if they don't exist yet" ) diff --git a/pkgs/clan-cli/clan_cli/secrets/check.py b/pkgs/clan-cli/clan_cli/secrets/check.py new file mode 100644 index 000000000..facf13c6e --- /dev/null +++ b/pkgs/clan-cli/clan_cli/secrets/check.py @@ -0,0 +1,42 @@ +import argparse +import importlib +import logging + +from ..machines.machines import Machine + +log = logging.getLogger(__name__) + + +def check_secrets(machine: Machine) -> bool: + secrets_module = importlib.import_module(machine.secrets_module) + secret_store = secrets_module.SecretStore(machine=machine) + + missing_secrets = [] + missing_facts = [] + for service in machine.secrets_data: + for secret in machine.secrets_data[service]["secrets"]: + if not secret_store.exists(service, secret): + log.info(f"Secret {secret} for service {service} is missing") + missing_secrets.append((service, secret)) + + for fact in machine.secrets_data[service]["facts"].values(): + if not (machine.flake / fact).exists(): + log.info(f"Fact {fact} for service {service} is missing") + missing_facts.append((service, fact)) + + if missing_secrets or missing_facts: + return False + return True + + +def check_command(args: argparse.Namespace) -> None: + machine = Machine(name=args.machine, flake=args.flake) + check_secrets(machine) + + +def register_check_parser(parser: argparse.ArgumentParser) -> None: + parser.add_argument( + "machine", + help="The machine to check secrets for", + ) + parser.set_defaults(func=check_command) diff --git a/pkgs/clan-cli/clan_cli/secrets/generate.py b/pkgs/clan-cli/clan_cli/secrets/generate.py index f9e07dcbc..ead23e849 100644 --- a/pkgs/clan-cli/clan_cli/secrets/generate.py +++ b/pkgs/clan-cli/clan_cli/secrets/generate.py @@ -11,6 +11,7 @@ from clan_cli.cmd import run from ..errors import ClanError from ..machines.machines import Machine from ..nix import nix_shell +from .check import check_secrets log = logging.getLogger(__name__) @@ -24,13 +25,7 @@ def generate_secrets(machine: Machine) -> None: print(service) tmpdir = Path(d) / service # check if all secrets exist and generate them if at least one is missing - needs_regeneration = any( - not secret_store.exists(service, secret) - for secret in machine.secrets_data[service]["secrets"] - ) or any( - not (machine.flake / fact).exists() - for fact in machine.secrets_data[service]["facts"].values() - ) + needs_regeneration = not check_secrets(machine) for fact in machine.secrets_data[service]["facts"].values(): if not (machine.flake / fact).exists(): print(f"fact {fact} is missing") From 8cbedfd3b82c9e898d07e61a0bb28275e22f1109 Mon Sep 17 00:00:00 2001 From: lassulus Date: Fri, 2 Feb 2024 17:29:35 +0100 Subject: [PATCH 2/3] clan-cli password-store: remove debug print --- pkgs/clan-cli/clan_cli/secrets/modules/password_store.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/clan-cli/clan_cli/secrets/modules/password_store.py b/pkgs/clan-cli/clan_cli/secrets/modules/password_store.py index 8e1ffc27d..15592e89e 100644 --- a/pkgs/clan-cli/clan_cli/secrets/modules/password_store.py +++ b/pkgs/clan-cli/clan_cli/secrets/modules/password_store.py @@ -35,7 +35,6 @@ class SecretStore: "PASSWORD_STORE_DIR", f"{os.environ['HOME']}/.password-store" ) secret_path = Path(password_store) / f"machines/{self.machine.name}/{name}.gpg" - print(f"checking {secret_path}") return secret_path.exists() def generate_hash(self) -> bytes: From 62f46751c7d4ad13b6a5cb2261b11fc4522d2a18 Mon Sep 17 00:00:00 2001 From: lassulus Date: Fri, 2 Feb 2024 17:31:12 +0100 Subject: [PATCH 3/3] clan-cli machines: remove debug prints --- pkgs/clan-cli/clan_cli/machines/machines.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkgs/clan-cli/clan_cli/machines/machines.py b/pkgs/clan-cli/clan_cli/machines/machines.py index 6c85770bb..2ed457462 100644 --- a/pkgs/clan-cli/clan_cli/machines/machines.py +++ b/pkgs/clan-cli/clan_cli/machines/machines.py @@ -43,7 +43,6 @@ class Machine: self._deployment_info = json.loads( self.build_nix("config.system.clan.deployment.file").read_text() ) - print(f"self_deployment_info: {self.deployment_info}") return self._deployment_info @property @@ -141,7 +140,6 @@ class Machine: else: flake = self.flake - log.info(f"building {flake}#{attr}") outpath = run(nix_build([f"{flake}#{attr}"])).stdout.strip() self.build_cache[attr] = Path(outpath) return Path(outpath)