From 9988fb744c80b7c5beb65a59717764eb4978f795 Mon Sep 17 00:00:00 2001 From: DavHau Date: Thu, 11 Jul 2024 18:39:00 +0700 Subject: [PATCH] vars: implement sops.defaultGroups --- nixosModules/clanCore/default.nix | 10 +-- nixosModules/clanCore/facts/secret/sops.nix | 9 --- nixosModules/clanCore/outputs.nix | 1 + nixosModules/clanCore/sops.nix | 11 +++ pkgs/clan-cli/clan_cli/vars/generate.py | 2 +- pkgs/clan-cli/tests/test_vars.py | 74 +++++++++------------ 6 files changed, 50 insertions(+), 57 deletions(-) create mode 100644 nixosModules/clanCore/sops.nix diff --git a/nixosModules/clanCore/default.nix b/nixosModules/clanCore/default.nix index d367afa4..cb469bee 100644 --- a/nixosModules/clanCore/default.nix +++ b/nixosModules/clanCore/default.nix @@ -2,8 +2,10 @@ imports = [ ./backups.nix ./facts - ./manual.nix ./imports.nix + ./inventory/interface.nix + ./manual.nix + ./meta/interface.nix ./metadata.nix ./networking.nix ./nix-settings.nix @@ -11,12 +13,10 @@ ./outputs.nix ./packages.nix ./schema.nix + ./sops.nix + ./vars ./vm.nix ./wayland-proxy-virtwl.nix ./zerotier - # Inventory - ./inventory/interface.nix - ./meta/interface.nix - ./vars ]; } diff --git a/nixosModules/clanCore/facts/secret/sops.nix b/nixosModules/clanCore/facts/secret/sops.nix index 0ab30d86..eb9caa30 100644 --- a/nixosModules/clanCore/facts/secret/sops.nix +++ b/nixosModules/clanCore/facts/secret/sops.nix @@ -33,15 +33,6 @@ let secrets = filterDir containsMachineOrGroups secretsDir; in { - options = { - clan.core.sops.defaultGroups = lib.mkOption { - type = lib.types.listOf lib.types.str; - default = [ ]; - example = [ "admins" ]; - description = "The default groups to for encryption use when no groups are specified."; - }; - }; - config = lib.mkIf (config.clan.core.facts.secretStore == "sops") { # Before we generate a secret we cannot know the path yet, so we need to set it to an empty string clan.core.facts.secretPathFunction = diff --git a/nixosModules/clanCore/outputs.nix b/nixosModules/clanCore/outputs.nix index aa71b41b..4369d4bf 100644 --- a/nixosModules/clanCore/outputs.nix +++ b/nixosModules/clanCore/outputs.nix @@ -73,6 +73,7 @@ services ; }; + sops.defaultGroups = config.clan.core.sops.defaultGroups; inherit (config.clan.core.networking) targetHost buildHost; inherit (config.clan.deployment) requireExplicitUpdate; }; diff --git a/nixosModules/clanCore/sops.nix b/nixosModules/clanCore/sops.nix new file mode 100644 index 00000000..80e62bf5 --- /dev/null +++ b/nixosModules/clanCore/sops.nix @@ -0,0 +1,11 @@ +{ lib, ... }: +{ + options = { + clan.core.sops.defaultGroups = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + example = [ "admins" ]; + description = "The default groups to for encryption use when no groups are specified."; + }; + }; +} diff --git a/pkgs/clan-cli/clan_cli/vars/generate.py b/pkgs/clan-cli/clan_cli/vars/generate.py index 9a54abb6..52320a77 100644 --- a/pkgs/clan-cli/clan_cli/vars/generate.py +++ b/pkgs/clan-cli/clan_cli/vars/generate.py @@ -99,7 +99,7 @@ def execute_generator( # store secrets files = machine.vars_generators[generator_name]["files"] for file_name, file in files.items(): - groups = file.get("groups", []) + groups = machine.deployment["sops"]["defaultGroups"] secret_file = generator_dir / file_name if not secret_file.is_file(): diff --git a/pkgs/clan-cli/tests/test_vars.py b/pkgs/clan-cli/tests/test_vars.py index 73670ca0..bf41ee27 100644 --- a/pkgs/clan-cli/tests/test_vars.py +++ b/pkgs/clan-cli/tests/test_vars.py @@ -1,4 +1,5 @@ import os +from collections import defaultdict from pathlib import Path import pytest @@ -8,35 +9,28 @@ from helpers import cli from root import CLAN_CORE +def def_value() -> defaultdict: + return defaultdict(def_value) + + +# allows defining nested dictionary in a single line +nested_dict = lambda: defaultdict(def_value) + + @pytest.mark.impure def test_generate_public_var( monkeypatch: pytest.MonkeyPatch, temporary_home: Path, # age_keys: list["KeyPair"], ) -> None: + config = nested_dict() + my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"] + my_generator["files"]["my_secret"]["secret"] = False + my_generator["script"] = "echo hello > $out/my_secret" flake = generate_flake( temporary_home, flake_template=CLAN_CORE / "templates" / "minimal", - machine_configs=dict( - my_machine=dict( - clan=dict( - core=dict( - vars=dict( - generators=dict( - my_generator=dict( - files=dict( - my_secret=dict( - secret=False, - ) - ), - script="echo hello > $out/my_secret", - ) - ) - ) - ) - ) - ) - ), + machine_configs=dict(my_machine=config), ) monkeypatch.chdir(flake.path) cli.run(["vars", "generate", "--flake", str(flake.path), "my_machine"]) @@ -48,34 +42,21 @@ def test_generate_public_var( @pytest.mark.impure -def test_generate_secret_var( +def test_generate_secret_var_with_default_group( monkeypatch: pytest.MonkeyPatch, temporary_home: Path, sops_setup: SopsSetup, ) -> None: + user = os.environ.get("USER", "user") + config = nested_dict() + config["clan"]["core"]["sops"]["defaultGroups"] = ["my_group"] + my_generator = config["clan"]["core"]["vars"]["generators"]["my_generator"] + my_generator["files"]["my_secret"]["secret"] = True + my_generator["script"] = "echo hello > $out/my_secret" flake = generate_flake( temporary_home, flake_template=CLAN_CORE / "templates" / "minimal", - machine_configs=dict( - my_machine=dict( - clan=dict( - core=dict( - vars=dict( - generators=dict( - my_generator=dict( - files=dict( - my_secret=dict( - secret=True, - ) - ), - script="echo hello > $out/my_secret", - ) - ) - ) - ) - ) - ) - ), + machine_configs=dict(my_machine=config), ) monkeypatch.chdir(flake.path) cli.run( @@ -85,10 +66,11 @@ def test_generate_secret_var( "add", "--flake", str(flake.path), - os.environ.get("USER", "user"), + user, sops_setup.keys[0].pubkey, ] ) + cli.run(["secrets", "groups", "add-user", "my_group", user]) cli.run(["vars", "generate", "--flake", str(flake.path), "my_machine"]) assert not ( flake.path / "machines" / "my_machine" / "vars" / "my_generator" / "my_secret" @@ -96,3 +78,11 @@ def test_generate_secret_var( assert ( flake.path / "sops" / "secrets" / "vars-my_machine-my_generator-my_secret" ).is_dir() + assert ( + flake.path + / "sops" + / "secrets" + / "vars-my_machine-my_generator-my_secret" + / "groups" + / "my_group" + ).exists()