From 7aa275a5b4d2b49965b2baf2f6da469dc352ad8a Mon Sep 17 00:00:00 2001 From: Michael Hoang Date: Sat, 21 Dec 2024 12:41:19 +1100 Subject: [PATCH] install: upload `vars` needed for `activation` for installation --- nixosModules/clanCore/vars/interface.nix | 9 +++++---- pkgs/clan-cli/clan_cli/machines/install.py | 6 ++---- pkgs/clan-cli/clan_cli/vars/secret_modules/sops.py | 11 +++++++---- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/nixosModules/clanCore/vars/interface.nix b/nixosModules/clanCore/vars/interface.nix index 7204f9a67..77a60b2f0 100644 --- a/nixosModules/clanCore/vars/interface.nix +++ b/nixosModules/clanCore/vars/interface.nix @@ -5,7 +5,6 @@ ... }: let - inherit (lib) mkOption; inherit (builtins) hashString toJSON @@ -198,9 +197,11 @@ in }; neededFor = lib.mkOption { description = '' - Enabling this option causes the secret to be decrypted/installed before users and groups are created. - This can be used to retrieve user's passwords. - Setting this option moves the secret to /run/secrets-for-users and disallows setting owner and group to anything else than root. + This option determines when the secret will be decrypted and deployed to the target machine. + + By setting this to `activation`, the secret will be deployed prior to running `nixos-rebuild` or `nixos-install`. + By setting this to `user`, the secret will be deployed prior to users and groups are created, allowing + users' passwords to be managed by vars. The secret will be stored in `/run/secrets-for-users` and `owner` and `group` must be `root`. ''; type = lib.types.enum [ "activation" diff --git a/pkgs/clan-cli/clan_cli/machines/install.py b/pkgs/clan-cli/clan_cli/machines/install.py index 9a625f118..dc051de61 100644 --- a/pkgs/clan-cli/clan_cli/machines/install.py +++ b/pkgs/clan-cli/clan_cli/machines/install.py @@ -1,5 +1,4 @@ import argparse -import importlib import logging import os import sys @@ -44,9 +43,7 @@ def install_machine(opts: InstallOptions) -> None: machine = opts.machine machine.override_target_host = opts.target_host - secret_facts_module = importlib.import_module(machine.secret_facts_module) machine.info(f"installing {machine.name}") - secret_facts_store = secret_facts_module.SecretStore(machine=machine) h = machine.target_host target_host = f"{h.user or 'root'}@{h.host}" @@ -63,7 +60,8 @@ def install_machine(opts: InstallOptions) -> None: upload_dir_ = upload_dir_[1:] upload_dir = tmpdir / upload_dir_ upload_dir.mkdir(parents=True) - secret_facts_store.upload(upload_dir) + machine.secret_facts_store.upload(upload_dir) + machine.secret_vars_store.populate_dir(upload_dir) if opts.password: os.environ["SSHPASS"] = opts.password diff --git a/pkgs/clan-cli/clan_cli/vars/secret_modules/sops.py b/pkgs/clan-cli/clan_cli/vars/secret_modules/sops.py index ba43cbd31..a4f7c239e 100644 --- a/pkgs/clan-cli/clan_cli/vars/secret_modules/sops.py +++ b/pkgs/clan-cli/clan_cli/vars/secret_modules/sops.py @@ -172,17 +172,20 @@ class SecretStore(StoreBase): self.machine.flake_dir, sops_secrets_folder(self.machine.flake_dir) / key_name, ) + (output_dir / "key.txt").touch(mode=0o600) (output_dir / "key.txt").write_text(key) for generator in self.machine.vars_generators: for file in generator.files: if file.needed_for == "activation": - (output_dir / generator.name / file.name).parent.mkdir( + target_path = output_dir / generator.name / file.name + target_path.parent.mkdir( parents=True, exist_ok=True, ) - (output_dir / generator.name / file.name).write_bytes( - self.get(generator, file.name) - ) + # chmod after in case it doesn't have u+w + target_path.touch(mode=0o600) + target_path.write_bytes(self.get(generator, file.name)) + target_path.chmod(file.mode) def upload(self) -> None: with TemporaryDirectory(prefix="sops-upload-") as tempdir: