sshd: add host ssh cert support

This commit is contained in:
Jörg Thalheim
2024-11-08 16:14:16 +01:00
committed by kenji
parent 902c6a12bb
commit 4f0c44f3dd
5 changed files with 137 additions and 24 deletions

View File

@@ -1,3 +1,13 @@
---
description = "Enables secure remote access to the machine over ssh"
description = "Enables secure remote access to the machine over ssh."
categories = ["System"]
features = [ "inventory" ]
---
This module will setup the opensshd service.
It will generate a host key for each machine
## Roles
###

View File

@@ -1,25 +1,6 @@
{ config, pkgs, ... }:
# Dont import this file
# It is only here for backwards compatibility.
# Dont author new modules with this file.
{
services.openssh.enable = true;
services.openssh.settings.PasswordAuthentication = false;
services.openssh.hostKeys = [
{
path = config.clan.core.facts.services.openssh.secret."ssh.id_ed25519".path;
type = "ed25519";
}
];
clan.core.facts.services.openssh = {
secret."ssh.id_ed25519" = { };
public."ssh.id_ed25519.pub" = { };
generator.path = [
pkgs.coreutils
pkgs.openssh
];
generator.script = ''
ssh-keygen -t ed25519 -N "" -f $secrets/ssh.id_ed25519
mv $secrets/ssh.id_ed25519.pub $facts/ssh.id_ed25519.pub
'';
};
imports = [ ./roles/server.nix ];
}

View File

@@ -0,0 +1,11 @@
{ ... }:
{
imports = [
../shared.nix
];
programs.ssh.knownHosts.ssh-ca = lib.mkIf (config.clan.sshd.certificate.searchDomains != [ ]) {
certAuthority = true;
extraHostNames = builtins.map (domain: "*.${domain}") config.clan.sshd.certificate.searchDomains;
publicKey = config.clan.core.vars.generators.openssh-ca.files."id_ed25519.pub".value;
};
}

View File

@@ -0,0 +1,68 @@
{
config,
pkgs,
lib,
...
}:
let
stringSet = list: builtins.attrNames (builtins.groupBy lib.id list);
signArgs = builtins.concatStringsSep " " (
builtins.map (domain: "-n ${lib.escapeShellArg "${config.clan.core.machineName}.${domain}"}") (
stringSet config.clan.sshd.certificate.searchDomains
)
);
cfg = config.clan.sshd;
in
{
imports = [ ../shared.nix ];
config = {
services.openssh = {
enable = true;
settings.PasswordAuthentication = false;
settings.HostCertificate = lib.mkIf (
cfg.certificate.searchDomains != [ ]
) config.clan.core.vars.generators.openssh-cert.files."ssh.id_ed25519-cert.pub".path;
hostKeys = [
{
path = config.clan.core.vars.generators.openssh.files."ssh.id_ed25519".path;
type = "ed25519";
}
];
};
clan.core.vars.generators.openssh = {
files."ssh.id_ed25519" = { };
files."ssh.id_ed25519.pub".secret = false;
migrateFact = "openssh";
runtimeInputs = [
pkgs.coreutils
pkgs.openssh
];
script = ''
ssh-keygen -t ed25519 -N "" -f $out/ssh.id_ed25519
'';
};
clan.core.vars.generators.openssh-cert = lib.mkIf (cfg.certificate.searchDomains != [ ]) {
files."ssh.id_ed25519-cert.pub".secret = false;
dependencies = [
"openssh"
"openssh-ca"
];
runtimeInputs = [
pkgs.openssh
pkgs.jq
];
script = ''
ssh-keygen \
-s $in/openssh-ca/id_ed25519 \
-I ${config.clan.core.machineName} \
${builtins.toString signArgs} \
$in/openssh/ssh.id_ed25519.pub
mv $in/openssh/ssh.id_ed25519-cert.pub $out/ssh.id_ed25519-cert.pub
'';
};
};
}

View File

@@ -0,0 +1,43 @@
{
config,
lib,
pkgs,
...
}:
{
options = {
clan.sshd.certificate = {
# TODO: allow per-server domains that we than collect in the inventory
#domains = lib.mkOption {
# type = lib.types.listOf lib.types.str;
# default = [ ];
# example = [ "git.mydomain.com" ];
# description = "List of domains to include in the certificate. This option will not prepend the machine name in front of each domain.";
#};
searchDomains = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = [ "mydomain.com" ];
description = "List of domains to include in the certificate. This option will prepend the machine name in front of each domain before adding it to the certificate.";
};
};
};
config = {
clan.core.vars.generators.openssh-ca =
lib.mkIf (config.clan.sshd.certificate.searchDomains != [ ])
{
share = true;
files.id_ed25519.deploy = false;
files."id_ed25519.pub" = {
deploy = false;
secret = false;
};
runtimeInputs = [
pkgs.openssh
];
script = ''
ssh-keygen -t ed25519 -N "" -f $out/id_ed25519
'';
};
};
}