step-ssh-user

This commit is contained in:
John Lancaster
2026-03-15 16:15:27 -05:00
parent 2ace9cd2dd
commit b3bcfdcfcb
2 changed files with 27 additions and 28 deletions

View File

@@ -71,15 +71,15 @@ in
# #
# Home Manager Module # Home Manager Module
# #
flake.modules.homeManager.step-client = { config, pkgs, lib, ... }: flake.modules.homeManager.step-ssh-user = { config, pkgs, lib, ... }:
let let
cfg = config.step-client; cfg = config.step-ssh-user;
firstPrincipal = lib.head cfg.principals; firstPrincipal = lib.head cfg.principals;
principalArgs = lib.concatMapStrings principalArgs = lib.concatMapStringsSep " "
(principal: "--principal ${principal}") cfg.principals; (principal: "--principal \"${principal}\"") cfg.principals;
in in
{ {
options.step-client = { options.step-ssh-user = {
enable = lib.mkEnableOption "opionated step client config for SSH certs"; enable = lib.mkEnableOption "opionated step client config for SSH certs";
caURL = lib.mkOption { caURL = lib.mkOption {
type = lib.types.str; type = lib.types.str;
@@ -92,7 +92,7 @@ in
rootCertFile = { rootCertFile = {
path = lib.mkOption { path = lib.mkOption {
type = lib.types.str; type = lib.types.str;
description = "Path to where the root_ca.crt file will be stored for the user"; description = "String path to where the root_ca.crt file will be stored for the user";
default = "${config.home.homeDirectory}/.step/certs/root_ca.crt"; default = "${config.home.homeDirectory}/.step/certs/root_ca.crt";
}; };
source = lib.mkOption { source = lib.mkOption {
@@ -101,7 +101,7 @@ in
default = ../../keys/root_ca.crt; default = ../../keys/root_ca.crt;
}; };
}; };
sshHostProvisioner = lib.mkOption { provisioner = lib.mkOption {
type = lib.types.str; type = lib.types.str;
default = "admin"; default = "admin";
}; };
@@ -109,27 +109,23 @@ in
type = lib.types.listOf lib.types.str; type = lib.types.listOf lib.types.str;
default = [ ]; default = [ ];
}; };
publicKeyFile = lib.mkOption {
type = lib.types.str;
default = "${config.home.homeDirectory}/.ssh/id_ed25519.pub";
};
}; };
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
home.file.".step/certs/root_ca.crt".source = cfg.rootCertFile; home.file.".step/certs/root_ca.crt".source = cfg.rootCertFile.source;
home.file.".step/config/defaults.json".text = builtins.toJSON { home.file.".step/config/defaults.json".text = builtins.toJSON {
"ca-url" = cfg.caURL; "ca-url" = cfg.caURL;
fingerprint = cfg.fingerprint; fingerprint = cfg.fingerprint;
root = "${cfg.rootCertFile.path}"; root = "${cfg.rootCertFile.path}";
}; };
sops.secrets."janus/admin_jwk".mode = "0400"; sops.secrets."janus/admin_jwk".mode = "0400";
home.packages = lib.optionals cfg.certificates.enable [ home.packages = with pkgs; [
(pkgs.writeShellScriptBin "sign-ssh-cert" '' (writeShellScriptBin "sign-ssh-cert" ''
${lib.getExe pkgs.step-cli} ssh certificate \ ${lib.getExe pkgs.step-cli} ssh certificate \
--sign \ --sign \
${principalArgs} \ ${principalArgs} \
--provisioner "${cfg.sshHostProvisioner}" \ --provisioner "${cfg.provisioner}" \
--provisioner-password-file "${config.sops.secrets."janus/admin_jwk".path}" \ --provisioner-password-file "${config.sops.secrets."janus/admin_jwk".path}" \
"${firstPrincipal}" "${cfg.publicKeyFile}" "${firstPrincipal}" "${config.ssh.IdentityFile}.pub"
'') '')
]; ];
}; };

View File

@@ -57,10 +57,6 @@ in
flake.modules.homeManager.ssh = { pkgs, config, lib, ... }: flake.modules.homeManager.ssh = { pkgs, config, lib, ... }:
{ {
imports = with inputs.self.modules.homeManager; [
step-client
];
options.ssh = { options.ssh = {
IdentityFile = lib.mkOption { IdentityFile = lib.mkOption {
# Intentionally not using a path type here because that will end up with the private key getting copied into the store # Intentionally not using a path type here because that will end up with the private key getting copied into the store
@@ -69,16 +65,25 @@ in
description = "Path to the SSH identity file."; description = "Path to the SSH identity file.";
}; };
certificates = {
enable = lib.mkEnableOption "Enable SSH user certificates";
# sshCertProvisioner = lib.mkOption {
# type = lib.types.str;
# default = "admin";
# };
};
knownHostsFile = lib.mkOption {
type = lib.types.str;
default = "${config.home.homeDirectory}/.ssh/known_hosts";
};
matchSets = { matchSets = {
appdaemon = lib.mkEnableOption "Enable AppDaemon SSH targets"; appdaemon = lib.mkEnableOption "Enable AppDaemon SSH targets";
certs = lib.mkEnableOption "Enable Janus and Soteria SSH targets"; certs = lib.mkEnableOption "Enable Janus and Soteria SSH targets";
homelab = lib.mkEnableOption "Enable various Homelab targets"; homelab = lib.mkEnableOption "Enable various Homelab targets";
dev = lib.mkEnableOption "Enable development targets"; dev = lib.mkEnableOption "Enable development targets";
}; };
certificates = {
enable = lib.mkEnableOption "Enable SSH user certificates";
};
}; };
# All this stuff has to be wrapped in a config attribute because of the presence of the options here? # All this stuff has to be wrapped in a config attribute because of the presence of the options here?
@@ -87,9 +92,7 @@ in
identityFile = cfg.IdentityFile; identityFile = cfg.IdentityFile;
publicKeyFile = "${identityFile}.pub"; publicKeyFile = "${identityFile}.pub";
certificateFile = "${identityFile}-cert.pub"; certificateFile = "${identityFile}-cert.pub";
userKnownHostsFile = "${config.home.homeDirectory}/.ssh/known_hosts";
provisionerPasswordPath = config.sops.secrets."janus/admin_jwk".path; provisionerPasswordPath = config.sops.secrets."janus/admin_jwk".path;
sshHostProvisioner = config.step-client.sshHostProvisioner;
in { in {
home.file.".ssh/known_hosts" = { home.file.".ssh/known_hosts" = {
text = lib.concatStringsSep "\n" ( text = lib.concatStringsSep "\n" (
@@ -122,7 +125,7 @@ in
inherit identityFile certificateFile; inherit identityFile certificateFile;
hashKnownHosts = false; hashKnownHosts = false;
userKnownHostsFile = userKnownHostsFile; userKnownHostsFile = cfg.knownHostsFile;
addKeysToAgent = "yes"; addKeysToAgent = "yes";
forwardAgent = false; forwardAgent = false;