This commit is contained in:
musjj 2025-12-21 15:02:26 -05:00 committed by GitHub
commit 51be135cf0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 57 additions and 1 deletions

View file

@ -98,6 +98,7 @@ let
gnupgHome = cfg.gnupg.home; gnupgHome = cfg.gnupg.home;
sshKeyPaths = cfg.gnupg.sshKeyPaths; sshKeyPaths = cfg.gnupg.sshKeyPaths;
ageKeyFile = cfg.age.keyFile; ageKeyFile = cfg.age.keyFile;
ageSshKeyFile = cfg.age.sshKeyFile;
ageSshKeyPaths = cfg.age.sshKeyPaths; ageSshKeyPaths = cfg.age.sshKeyPaths;
placeholderBySecretName = cfg.placeholder; placeholderBySecretName = cfg.placeholder;
userMode = true; 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 { sshKeyPaths = lib.mkOption {
type = lib.types.listOf lib.types.path; type = lib.types.listOf lib.types.path;
default = [ ]; default = [ ];
description = '' description = ''
Paths to ssh keys added as age keys during sops 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.sshKeyPaths != [ ]
|| cfg.gnupg.qubes-split-gpg.enable == true || cfg.gnupg.qubes-split-gpg.enable == true
|| cfg.age.keyFile != null || cfg.age.keyFile != null
|| cfg.age.sshKeyFile != null
|| cfg.age.sshKeyPaths != [ ]; || 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"; 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";
} }

View file

@ -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 { sshKeyPaths = lib.mkOption {
type = lib.types.listOf lib.types.path; type = lib.types.listOf lib.types.path;
default = defaultImportKeys "ed25519"; default = defaultImportKeys "ed25519";
defaultText = lib.literalMD "The ed25519 keys from {option}`config.services.openssh.hostKeys`"; defaultText = lib.literalMD "The ed25519 keys from {option}`config.services.openssh.hostKeys`";
description = '' description = ''
Paths to ssh keys added as age keys during sops 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.home != null
|| cfg.gnupg.sshKeyPaths != [ ] || cfg.gnupg.sshKeyPaths != [ ]
|| cfg.age.keyFile != null || cfg.age.keyFile != null
|| cfg.age.sshKeyFile != null
|| cfg.age.sshKeyPaths != [ ]; || cfg.age.sshKeyPaths != [ ];
message = "No key source configured for sops. Either set services.openssh.enable or set sops.age.keyFile or sops.gnupg.home"; message = "No key source configured for sops. Either set services.openssh.enable or set sops.age.keyFile or sops.gnupg.home";
} }

View file

@ -15,6 +15,7 @@ writeTextFile {
gnupgHome = cfg.gnupg.home; gnupgHome = cfg.gnupg.home;
sshKeyPaths = cfg.gnupg.sshKeyPaths; sshKeyPaths = cfg.gnupg.sshKeyPaths;
ageKeyFile = cfg.age.keyFile; ageKeyFile = cfg.age.keyFile;
ageSshKeyFile = cfg.age.sshKeyFile;
ageSshKeyPaths = cfg.age.sshKeyPaths; ageSshKeyPaths = cfg.age.sshKeyPaths;
useTmpfs = false; useTmpfs = false;
placeholderBySecretName = cfg.placeholder; placeholderBySecretName = cfg.placeholder;

View file

@ -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 { sshKeyPaths = lib.mkOption {
type = lib.types.listOf lib.types.path; type = lib.types.listOf lib.types.path;
default = defaultImportKeys "ed25519"; default = defaultImportKeys "ed25519";
defaultText = lib.literalMD "The ed25519 keys from {option}`config.services.openssh.hostKeys`"; defaultText = lib.literalMD "The ed25519 keys from {option}`config.services.openssh.hostKeys`";
description = '' description = ''
Paths to ssh keys added as age keys during sops 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.home != null
|| cfg.gnupg.sshKeyPaths != [ ] || cfg.gnupg.sshKeyPaths != [ ]
|| cfg.age.keyFile != null || cfg.age.keyFile != null
|| cfg.age.sshKeyFile != null
|| cfg.age.sshKeyPaths != [ ]; || cfg.age.sshKeyPaths != [ ];
message = "No key source configured for sops. Either set services.openssh.enable or set sops.age.keyFile or sops.gnupg.home"; message = "No key source configured for sops. Either set services.openssh.enable or set sops.age.keyFile or sops.gnupg.home";
} }

View file

@ -40,6 +40,7 @@ else
gnupgHome = cfg.gnupg.home; gnupgHome = cfg.gnupg.home;
sshKeyPaths = cfg.gnupg.sshKeyPaths; sshKeyPaths = cfg.gnupg.sshKeyPaths;
ageKeyFile = cfg.age.keyFile; ageKeyFile = cfg.age.keyFile;
ageSshKeyFile = cfg.age.sshKeyFile;
ageSshKeyPaths = cfg.age.sshKeyPaths; ageSshKeyPaths = cfg.age.sshKeyPaths;
useTmpfs = cfg.useTmpfs; useTmpfs = cfg.useTmpfs;
placeholderBySecretName = cfg.placeholder; placeholderBySecretName = cfg.placeholder;

View file

@ -79,6 +79,7 @@ type manifest struct {
SSHKeyPaths []string `json:"sshKeyPaths"` SSHKeyPaths []string `json:"sshKeyPaths"`
GnupgHome string `json:"gnupgHome"` GnupgHome string `json:"gnupgHome"`
AgeKeyFile string `json:"ageKeyFile"` AgeKeyFile string `json:"ageKeyFile"`
AgeSSHKeyFile string `json:"ageSshKeyFile"`
AgeSSHKeyPaths []string `json:"ageSshKeyPaths"` AgeSSHKeyPaths []string `json:"ageSshKeyPaths"`
UseTmpfs bool `json:"useTmpfs"` UseTmpfs bool `json:"useTmpfs"`
UserMode bool `json:"userMode"` UserMode bool `json:"userMode"`
@ -1341,7 +1342,7 @@ func installSecrets(args []string) error {
} }
// Import age keys // 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") keyfile := filepath.Join(manifest.SecretsMountPoint, "age-keys.txt")
err = os.Setenv("SOPS_AGE_KEY_FILE", keyfile) err = os.Setenv("SOPS_AGE_KEY_FILE", keyfile)
if err != nil { 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 { if err := decryptSecrets(manifest.Secrets); err != nil {
return err return err
} }