From b21bfd6bb497083af67b6176412d0d56fd3f5de8 Mon Sep 17 00:00:00 2001 From: John Lancaster <32917998+jsl12@users.noreply.github.com> Date: Thu, 9 Jul 2026 09:01:34 -0500 Subject: [PATCH] ssh user certs in home-manager --- modules/features/ssh/default.nix | 25 ++++--------- modules/features/ssh/ssh-wrappers.nix | 12 ++++-- modules/hosts/john-pc/default.nix | 10 +++-- modules/users/john.nix | 54 ++++++++++++++------------- 4 files changed, 51 insertions(+), 50 deletions(-) diff --git a/modules/features/ssh/default.nix b/modules/features/ssh/default.nix index 957237b..b173846 100644 --- a/modules/features/ssh/default.nix +++ b/modules/features/ssh/default.nix @@ -65,10 +65,6 @@ in then adminJwkPath else null; }; - userScripts = mkUserScripts { - inherit cfg pkgs; - provisionerPasswordFile = adminJwkPath; - }; CAknownHosts = (lib.genAttrs caPatterns (_: { certAuthority = true; publicKey = lib.removeSuffix "\n" (builtins.readFile sshHostCAPath); @@ -157,10 +153,6 @@ in home-manager.users.root = lib.mkIf cfg.certificates.user.enable { home.stateVersion = lib.mkDefault config.system.stateVersion; imports = [ inputs.self.modules.homeManager.ssh-new ]; - home.packages = [ - userScripts.sign - userScripts.check - ]; ssh-new.certificates.user.enable = true; }; }; @@ -169,6 +161,10 @@ in flake.modules.homeManager.ssh-new = { config, pkgs, lib, ... }: let cfg = config.ssh-new; + userKeyPath = + if lib.hasPrefix "/" cfg.user.keyFile || lib.hasPrefix "~/" cfg.user.keyFile + then cfg.user.keyFile + else "${config.home.homeDirectory}/.ssh/${cfg.user.keyFile}"; hasAdminJwk = lib.hasAttrByPath [ "sops" "secrets" "janus/admin_jwk" ] config; adminJwkPath = if hasAdminJwk then config.sops.secrets."janus/admin_jwk".path else null; hostScripts = mkHostScripts { inherit cfg pkgs; }; @@ -186,16 +182,11 @@ in config = { home.file.".ssh/known_hosts" = lib.mkIf cfg.certificates.user.enable { text = knownHostsText; + force = true; }; - home.packages = [ + home.packages = lib.optionals cfg.certificates.user.enable [ userScripts.sign userScripts.check - ] - ++ lib.optionals cfg.host.enable-scripts [ - hostScripts.sign - hostScripts.renew - hostScripts.renewalCheck - hostScripts.check ]; programs.ssh = { enable = true; @@ -216,7 +207,7 @@ in PasswordAuthentication = "no"; PreferredAuthentications = "publickey"; IdentitiesOnly = true; - IdentityFile = cfg.user.keyFile; + IdentityFile = userKeyPath; StrictHostKeyChecking = "accept-new"; UserKnownHostsFile = "${config.home.homeDirectory}/.ssh/known_hosts"; @@ -232,7 +223,7 @@ in # SSH certificate settings ++ lib.optionals cfg.certificates.user.enable [ { - CertificateFile = "${cfg.user.keyFile}-cert.pub"; + CertificateFile = "${userKeyPath}-cert.pub"; } ] ); diff --git a/modules/features/ssh/ssh-wrappers.nix b/modules/features/ssh/ssh-wrappers.nix index a6ac784..c373914 100644 --- a/modules/features/ssh/ssh-wrappers.nix +++ b/modules/features/ssh/ssh-wrappers.nix @@ -67,7 +67,10 @@ in flake.wrappers.signUserWrapper = inputs.wrappers.lib.wrapModule ({config, lib, wlib, ... }: { imports = [ sshCertConfig ]; - config = let cfg = config.ssh-new; in { + config = + let + cfg = config.ssh-new; + in { binName = "ssh-user-cert-sign"; package = config.pkgs.step-cli; args = [ "ssh" "certificate" "--sign" ] @@ -84,11 +87,14 @@ in flake.wrappers.userCheckWrapper = inputs.wrappers.lib.wrapModule ({config, lib, wlib, ... }: { imports = [ sshCertConfig ]; - config = { + config = + let + cfg = config.ssh-new; + in { binName = "ssh-user-cert-check"; package = config.pkgs.openssh; exePath = lib.getExe' config.pkgs.openssh "ssh-keygen"; - args = [ "-Lf" "${config.ssh-new.user.keyFile}-cert.pub" ]; + args = [ "-Lf" "$HOME/.ssh/${config.ssh-new.user.keyFile}-cert.pub" ]; }; }); diff --git a/modules/hosts/john-pc/default.nix b/modules/hosts/john-pc/default.nix index 289c897..db0958f 100644 --- a/modules/hosts/john-pc/default.nix +++ b/modules/hosts/john-pc/default.nix @@ -47,10 +47,12 @@ in ]; docker.enable = true; - # ssh-new = { - # certificates.enable = true; - # host-scripts.enable = true; - # }; + ssh-new = { + certificates = { + provisioner = "admin"; + user.enable = true; + }; + }; # ssh = { # matchSets = { # certs = true; diff --git a/modules/users/john.nix b/modules/users/john.nix index 636ea6c..ac6a543 100644 --- a/modules/users/john.nix +++ b/modules/users/john.nix @@ -16,44 +16,46 @@ in authorizedKeys = [ # Shared keys for every host can go here. "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIAUa4dcg1TWc4pW++uodyhX4eOqrX/QYIxFWtEP7HFJ john@john-pc-ubuntu" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFn5ilhqaeDsOWSk7y29se2NvxGm8djlfL3RGLokj0q6 john@john-p14s" ]; }; flake.modules = { - nixos."${username}" = { config, pkgs, ... }: { + nixos."${username}" = { config, pkgs, ... }: let + selfMeta = inputs.self.meta.users."${username}"; + in { imports = [ baseUserModules.nixos."${username}" ]; users.users."${username}" = { - openssh.authorizedKeys.keys = inputs.self.meta.users."${username}".authorizedKeys; + openssh.authorizedKeys.keys = selfMeta.authorizedKeys; }; }; # This module will be imported by the user factory - homeManager."${username}" = { pkgs, ... }: - with inputs.self.meta.users."${username}"; - let - selfPkgs = inputs.self.packages.${pkgs.stdenv.hostPlatform.system}; - in { - home.stateVersion = "25.11"; - imports = with inputs.self.modules.homeManager; [ - ssh-new - shell-tools - git - ]; - xdg.enable = true; - home.packages = [ - selfPkgs.neovim-min - ]; - home.sessionVariables = { - EDITOR = "nvim"; - VISUAL = "nvim"; - GIT_EDITOR = "nvim"; - SOPS_EDITOR = "nvim"; - }; - programs.git.settings.user.name = name; - programs.git.settings.user.email = email; - programs.git.settings.core.editor = "nvim"; + homeManager."${username}" = { pkgs, ... }: let + selfMeta = inputs.self.meta.users."${username}"; + selfPkgs = inputs.self.packages.${pkgs.stdenv.hostPlatform.system}; + in { + home.stateVersion = "25.11"; + imports = with inputs.self.modules.homeManager; [ + ssh-new + shell-tools + git + ]; + xdg.enable = true; + home.packages = [ + selfPkgs.neovim-min + ]; + home.sessionVariables = { + EDITOR = "nvim"; + VISUAL = "nvim"; + GIT_EDITOR = "nvim"; + SOPS_EDITOR = "nvim"; }; + programs.git.settings.user.name = selfMeta.name; + programs.git.settings.user.email = selfMeta.email; + programs.git.settings.core.editor = "nvim"; + }; }; }