Merge pull request 'clan-cli: secrets check command' (#800) from lassulus-check_secrets into main

This commit is contained in:
clan-bot
2024-02-02 16:43:25 +00:00
5 changed files with 48 additions and 10 deletions

View File

@@ -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)

View File

@@ -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"
)

View File

@@ -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)

View File

@@ -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")

View File

@@ -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: