82 lines
2.4 KiB
Nix
82 lines
2.4 KiB
Nix
{ config, lib, pkgs, ... }:
|
|
|
|
with lib;
|
|
let
|
|
hostname = config.instance.hostname;
|
|
has-attrs = set: length (attrNames set) > 0;
|
|
host-keypairs =
|
|
if (hasAttr hostname config.fudo.secrets.files.host-ssh-keypairs) then
|
|
config.fudo.secrets.files.host-ssh-keypairs.${hostname}
|
|
else [];
|
|
|
|
|
|
sshfp-filename = host: keypair: "ssh-${host}-${keypair.key-type}.sshfp-record";
|
|
|
|
dns-sshfp-records = host: keypair: let
|
|
filename = sshfp-filename host keypair;
|
|
in pkgs.stdenv.mkDerivation {
|
|
name = "${host}-sshfp-record";
|
|
|
|
phases = [ "installPhase" ];
|
|
|
|
buildInputs = with pkgs; [ openssh ];
|
|
|
|
installPhase = ''
|
|
mkdir $out
|
|
ssh-keygen -r REMOVEME -f "${keypair.public-key}" | sed 's/^REMOVEME IN SSHFP //' > $out/${filename}
|
|
'';
|
|
};
|
|
|
|
host-cfg = config.fudo.hosts.${hostname};
|
|
|
|
in {
|
|
config = {
|
|
fudo = {
|
|
secrets.host-secrets.${hostname} = listToAttrs
|
|
(map
|
|
(keypair: nameValuePair "host-${keypair.key-type}-private-key" {
|
|
source-file = keypair.private-key;
|
|
target-file = "/var/run/ssh/private/host-${keypair.key-type}-private-key";
|
|
user = "root";
|
|
})
|
|
host-keypairs);
|
|
|
|
hosts = mapAttrs (hostname: keypairs: {
|
|
ssh-pubkeys = map (keypair: keypair.public-key) keypairs;
|
|
ssh-fingerprints = map (keypair:
|
|
let
|
|
fingerprint-derivation = dns-sshfp-records hostname keypair;
|
|
filename = sshfp-filename hostname keypair;
|
|
in builtins.readFile "${fingerprint-derivation}/${filename}") keypairs;
|
|
}) config.fudo.secrets.files.host-ssh-keypairs;
|
|
|
|
|
|
};
|
|
|
|
services.openssh.hostKeys = map (keypair: {
|
|
path = "/var/run/ssh/private/host-${keypair.key-type}-private-key";
|
|
type = keypair.key-type;
|
|
}) host-keypairs;
|
|
|
|
programs.ssh.knownHosts = let
|
|
|
|
keyed-hosts =
|
|
filterAttrs (h: o: o.ssh-pubkeys != [])
|
|
config.fudo.hosts;
|
|
|
|
crossProduct = f: list0: list1:
|
|
concatMap (el0: map (el1: f el0 el1) list1) list0;
|
|
|
|
all-hostnames = hostname: opts:
|
|
[ hostname ] ++
|
|
(crossProduct (host: domain: "${host}.${domain}")
|
|
([ hostname ] ++ opts.aliases)
|
|
([ opts.domain ] ++ opts.extra-domains));
|
|
|
|
in mapAttrs (hostname: hostOpts: {
|
|
publicKeyFile = builtins.head hostOpts.ssh-pubkeys;
|
|
hostNames = all-hostnames hostname host-cfg;
|
|
}) keyed-hosts;
|
|
};
|
|
}
|