From c63a781dc62694e6d28e4c41ce960579831aa969 Mon Sep 17 00:00:00 2001 From: clerie Date: Thu, 21 Nov 2024 22:31:42 +0100 Subject: [PATCH] pkgs/clerie-sops: regenerate clerie-sops-config on every call to clerie-sops --- pkgs/clerie-sops/clerie-sops-config.nix | 44 ++++++-------------- pkgs/clerie-sops/clerie-sops-config.py | 55 +++++++++++++++++++++++++ pkgs/clerie-sops/clerie-sops.nix | 7 +++- 3 files changed, 74 insertions(+), 32 deletions(-) create mode 100755 pkgs/clerie-sops/clerie-sops-config.py diff --git a/pkgs/clerie-sops/clerie-sops-config.nix b/pkgs/clerie-sops/clerie-sops-config.nix index f7e13f7..60d9130 100644 --- a/pkgs/clerie-sops/clerie-sops-config.nix +++ b/pkgs/clerie-sops/clerie-sops-config.nix @@ -1,37 +1,19 @@ { pkgs, lib, ... }: -with lib; +pkgs.python313Packages.buildPythonPackage rec { + pname = "clerie-sops-config"; + version = "0.0.1"; -let - hosts = builtins.attrNames (builtins.readDir ../../hosts); + src = ./.; - mkAgeKey = hostname: ssh_pub_file: - pkgs.runCommand "${hostname}.age" { - buildInputs = [ pkgs.ssh-to-age ]; - } '' - ssh-to-age -i ${ssh_pub_file} -o $out - ''; + format = "other"; - ageKeysForHost = hostname: let - ssh_pub_file = ../../hosts + "/${hostname}/ssh.pub"; - in - if builtins.pathExists ssh_pub_file then [ - (fileContents (mkAgeKey hostname ssh_pub_file)) - ] else []; + propagatedBuildInputs = with pkgs; [ + ssh-to-age + ]; - mkCreationRules = hosts: - map (hostname: { - path_regex = escapeRegex "hosts/${hostname}/secrets.json"; - key_groups = [{ - pgp = [ - (fileContents (pkgs.clerie-keys + "/gpg/clerie@clerie.de.fingerprint.txt")) - ]; - age = ageKeysForHost hostname; - }]; - }) hosts; - - sops_config = { - creation_rules = mkCreationRules hosts; - }; -in - pkgs.writeText "sops.json" (builtins.toJSON sops_config) + installPhase = '' + mkdir -p $out/bin + cp clerie-sops-config.py $out/bin/clerie-sops-config + ''; +} diff --git a/pkgs/clerie-sops/clerie-sops-config.py b/pkgs/clerie-sops/clerie-sops-config.py new file mode 100755 index 0000000..254582b --- /dev/null +++ b/pkgs/clerie-sops/clerie-sops-config.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 + +import sys +import json +from pathlib import Path +import re +import subprocess + +def generate_sops_config(repo_root): + admin_keys = [] + + # hardcode fingerprints because we can't really generate them automatically currently + admin_keys.append("0C982F87B7AFBA0F504F90A2629E741947C87928") # clerie@clerie.de + + list_of_host_directories = sorted(list(filter(lambda path_object: path_object.is_dir(), (repo_root / "hosts").iterdir()))) + + creation_rules = [] + + for host_directory in list_of_host_directories: + host_secrets_file = host_directory / "secrets.json" + host_keys = [] + + ssh_host_key_file = host_directory / "ssh.pub" + + if ssh_host_key_file.is_file(): + + ssh_to_age_command = subprocess.run(["ssh-to-age", "-i", str(ssh_host_key_file)], capture_output=True, text=True) + if ssh_to_age_command.returncode == 0: + host_keys.append(ssh_to_age_command.stdout.strip()) + + creation_rules.append({ + "key_groups": [{ + "age": host_keys, + "pgp": admin_keys, + }], + "path_regex": re.escape(str(host_secrets_file)), + }) + + return { + "creation_rules": creation_rules, + } + + + + +if __name__ == "__main__": + if len(sys.argv) != 2: + print("No repo root specified") + exit(1) + + repo_root = Path(sys.argv[1]) + + sops_config = generate_sops_config(repo_root) + + print(json.dumps(sops_config)) diff --git a/pkgs/clerie-sops/clerie-sops.nix b/pkgs/clerie-sops/clerie-sops.nix index 1730e6b..13c5a08 100644 --- a/pkgs/clerie-sops/clerie-sops.nix +++ b/pkgs/clerie-sops/clerie-sops.nix @@ -4,8 +4,13 @@ pkgs.writeShellApplication { name = "clerie-sops"; runtimeInputs = with pkgs; [ sops + clerie-sops-config ]; text = '' - exec sops --config ${pkgs.clerie-sops-config} "$@" + REPO_ROOT="." + if GIT_ROOT=$(git rev-parse --show-toplevel); then + REPO_ROOT="$GIT_ROOT" + fi + exec sops --config <(clerie-sops-config "$REPO_ROOT") "$@" ''; }