diff --git a/modules/home-manager/sops.nix b/modules/home-manager/sops.nix index 4906b4c..d3c1ab0 100644 --- a/modules/home-manager/sops.nix +++ b/modules/home-manager/sops.nix @@ -98,6 +98,7 @@ let gnupgHome = cfg.gnupg.home; sshKeyPaths = cfg.gnupg.sshKeyPaths; ageKeyFile = cfg.age.keyFile; + ageSshKeyFile = cfg.age.sshKeyFile; ageSshKeyPaths = cfg.age.sshKeyPaths; placeholderBySecretName = cfg.placeholder; userMode = true; @@ -259,11 +260,26 @@ in ''; }; + sshKeyFile = lib.mkOption { + type = lib.types.nullOr pathNotInStore; + default = null; + example = "/home/someuser/.ssh/id_ed25519"; + description = '' + Path to ssh key file that will be used by age for sops decryption. + + Unlike {option}`config.sops.age.sshKeyPaths`, this option makes use of + the native ssh key support in age and requires no conversion. + ''; + }; + sshKeyPaths = lib.mkOption { type = lib.types.listOf lib.types.path; default = [ ]; description = '' Paths to ssh keys added as age keys during sops description. + + These ssh keys will be converted into age keys automatically using + ssh-to-age before they are fed to age. ''; }; }; @@ -310,6 +326,7 @@ in || cfg.gnupg.sshKeyPaths != [ ] || cfg.gnupg.qubes-split-gpg.enable == true || cfg.age.keyFile != null + || cfg.age.sshKeyFile != null || cfg.age.sshKeyPaths != [ ]; message = "No key source configured for sops. Either set services.openssh.enable or set sops.age.keyFile or sops.gnupg.home or sops.gnupg.qubes-split-gpg.enable"; } diff --git a/modules/nix-darwin/default.nix b/modules/nix-darwin/default.nix index f169a30..88e1ffe 100644 --- a/modules/nix-darwin/default.nix +++ b/modules/nix-darwin/default.nix @@ -300,12 +300,27 @@ in ''; }; + sshKeyFile = lib.mkOption { + type = lib.types.nullOr pathNotInStore; + default = null; + example = "/etc/ssh/ssh_host_ed25519_key"; + description = '' + Path to ssh key file that will be used by age for sops decryption. + + Unlike {option}`config.sops.age.sshKeyPaths`, this option makes use of + the native ssh key support in age and requires no conversion. + ''; + }; + sshKeyPaths = lib.mkOption { type = lib.types.listOf lib.types.path; default = defaultImportKeys "ed25519"; defaultText = lib.literalMD "The ed25519 keys from {option}`config.services.openssh.hostKeys`"; description = '' Paths to ssh keys added as age keys during sops description. + + These ssh keys will be converted into age keys automatically using + ssh-to-age before they are fed to age. ''; }; }; @@ -345,6 +360,7 @@ in cfg.gnupg.home != null || cfg.gnupg.sshKeyPaths != [ ] || cfg.age.keyFile != null + || cfg.age.sshKeyFile != null || cfg.age.sshKeyPaths != [ ]; message = "No key source configured for sops. Either set services.openssh.enable or set sops.age.keyFile or sops.gnupg.home"; } diff --git a/modules/nix-darwin/manifest-for.nix b/modules/nix-darwin/manifest-for.nix index 5015659..edc6b3e 100644 --- a/modules/nix-darwin/manifest-for.nix +++ b/modules/nix-darwin/manifest-for.nix @@ -15,6 +15,7 @@ writeTextFile { gnupgHome = cfg.gnupg.home; sshKeyPaths = cfg.gnupg.sshKeyPaths; ageKeyFile = cfg.age.keyFile; + ageSshKeyFile = cfg.age.sshKeyFile; ageSshKeyPaths = cfg.age.sshKeyPaths; useTmpfs = false; placeholderBySecretName = cfg.placeholder; diff --git a/modules/sops/default.nix b/modules/sops/default.nix index 0c236d5..2125184 100644 --- a/modules/sops/default.nix +++ b/modules/sops/default.nix @@ -352,12 +352,27 @@ in ''; }; + sshKeyFile = lib.mkOption { + type = lib.types.nullOr pathNotInStore; + default = null; + example = "/etc/ssh/ssh_host_ed25519_key"; + description = '' + Path to ssh key file that will be used by age for sops decryption. + + Unlike {option}`config.sops.age.sshKeyPaths`, this option makes use of + the native ssh key support in age and requires no conversion. + ''; + }; + sshKeyPaths = lib.mkOption { type = lib.types.listOf lib.types.path; default = defaultImportKeys "ed25519"; defaultText = lib.literalMD "The ed25519 keys from {option}`config.services.openssh.hostKeys`"; description = '' Paths to ssh keys added as age keys during sops description. + + These ssh keys will be converted into age keys automatically using + ssh-to-age before they are fed to age. ''; }; }; @@ -418,6 +433,7 @@ in cfg.gnupg.home != null || cfg.gnupg.sshKeyPaths != [ ] || cfg.age.keyFile != null + || cfg.age.sshKeyFile != null || cfg.age.sshKeyPaths != [ ]; message = "No key source configured for sops. Either set services.openssh.enable or set sops.age.keyFile or sops.gnupg.home"; } diff --git a/modules/sops/manifest-for.nix b/modules/sops/manifest-for.nix index 1824668..dc40065 100644 --- a/modules/sops/manifest-for.nix +++ b/modules/sops/manifest-for.nix @@ -40,6 +40,7 @@ else gnupgHome = cfg.gnupg.home; sshKeyPaths = cfg.gnupg.sshKeyPaths; ageKeyFile = cfg.age.keyFile; + ageSshKeyFile = cfg.age.sshKeyFile; ageSshKeyPaths = cfg.age.sshKeyPaths; useTmpfs = cfg.useTmpfs; placeholderBySecretName = cfg.placeholder; diff --git a/pkgs/sops-install-secrets/main.go b/pkgs/sops-install-secrets/main.go index cd2757e..bfcc506 100644 --- a/pkgs/sops-install-secrets/main.go +++ b/pkgs/sops-install-secrets/main.go @@ -79,6 +79,7 @@ type manifest struct { SSHKeyPaths []string `json:"sshKeyPaths"` GnupgHome string `json:"gnupgHome"` AgeKeyFile string `json:"ageKeyFile"` + AgeSSHKeyFile string `json:"ageSshKeyFile"` AgeSSHKeyPaths []string `json:"ageSshKeyPaths"` UseTmpfs bool `json:"useTmpfs"` UserMode bool `json:"userMode"` @@ -1341,7 +1342,7 @@ func installSecrets(args []string) error { } // Import age keys - if len(manifest.AgeSSHKeyPaths) != 0 || manifest.AgeKeyFile != "" { + if (len(manifest.AgeSSHKeyPaths) != 0 || manifest.AgeKeyFile != "") && manifest.AgeSSHKeyFile == "" { keyfile := filepath.Join(manifest.SecretsMountPoint, "age-keys.txt") err = os.Setenv("SOPS_AGE_KEY_FILE", keyfile) if err != nil { @@ -1382,6 +1383,10 @@ func installSecrets(args []string) error { } } + if manifest.AgeSSHKeyFile != "" { + os.Setenv("SOPS_AGE_SSH_PRIVATE_KEY_FILE", manifest.AgeSSHKeyFile) + } + if err := decryptSecrets(manifest.Secrets); err != nil { return err }