ssh: port to modules system

This commit is contained in:
2023-01-08 03:07:20 +00:00
parent ea5552daa7
commit 72d589cb2d
6 changed files with 92 additions and 40 deletions

View File

@@ -1,10 +1,22 @@
{ config, lib, ... }:
{
# persist the host key
environment.etc."ssh/host_keys".source = "/nix/persist/etc/ssh/host_keys";
# let openssh find our host keys
services.openssh.hostKeys = [
{ type = "rsa"; bits = 4096; path = "/etc/ssh/host_keys/ssh_host_rsa_key"; }
{ type = "ed25519"; path = "/etc/ssh/host_keys/ssh_host_ed25519_key"; }
];
sane.ssh.pubkeys = {
"colin@lappy" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDpmFdNSVPRol5hkbbCivRhyeENzb9HVyf9KutGLP2Zu";
"root@lappy" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILSJnqmVl9/SYQ0btvGb0REwwWY8wkdkGXQZfn/1geEc";
"root@desko" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFw9NoRaYrM6LbDd3aFBc4yyBlxGQn8HjeHd/dZ3CfHk";
"colin@desko" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPU5GlsSfbaarMvDA20bxpSZGWviEzXGD8gtrIowc1pX";
"root@servo" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOfdSmFkrVT6DhpgvFeQKm3Fh9VKZ9DbLYOPOJWYQ0E8";
"colin@servo" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPS1qFzKurAdB9blkWomq8gI1g0T3sTs9LsmFOj5VtqX";
"root@moby" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO1N/IT3nQYUD+dBlU1sTEEVMxfOyMkrrDeyHcYgnJvw";
"colin@moby" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICrR+gePnl0nV/vy7I5BzrGeyVL+9eOuXHU1yNE3uCwU";
};
}

View File

@@ -52,7 +52,11 @@ in
passwordFile = lib.mkIf (config.sops.secrets ? "colin-passwd") config.sops.secrets.colin-passwd.path;
shell = pkgs.zsh;
openssh.authorizedKeys.keys = builtins.attrValues (import ../../modules/pubkeys.nix).users;
openssh.authorizedKeys.keys =
let
user-keys = filter (k: k.user == "colin") (attrValues config.sane.ssh.pubkeys);
in
map (k: k.asUserKey) user-keys;
# mount encrypted stuff at login
# some other nix pam users:

View File

@@ -12,6 +12,7 @@
./persist
./services
./sops.nix
./ssh.nix
];
_module.args = {

View File

@@ -1,19 +1,22 @@
{ config, lib, pkgs, sane-lib, ... }:
with lib;
let
host = config.networking.hostName;
user_pubkey = (import ../pubkeys.nix).users."${host}";
known_hosts_text = builtins.concatStringsSep
user-pubkey = config.sane.ssh.pubkeys."colin@${host}".asUserKey;
host-keys = filter (k: k.user == "root") (attrValues config.sane.ssh.pubkeys);
known-hosts-text = concatStringsSep
"\n"
(builtins.attrValues (import ../pubkeys.nix).hosts);
(map (k: k.asHostKey) host-keys)
;
in lib.mkIf config.sane.home-manager.enable {
# ssh key is stored in private storage
sane.persist.home.private = [ ".ssh/id_ed25519" ];
sane.fs."/home/colin/.ssh/id_ed25519.pub" = sane-lib.fs.wantedText user_pubkey;
sane.fs."/home/colin/.ssh/id_ed25519.pub" = sane-lib.fs.wantedText user-pubkey;
home-manager.users.colin = {
programs.ssh.enable = true;
# this optionally accepts multiple known_hosts paths, separated by space.
programs.ssh.userKnownHostsFile = builtins.toString (pkgs.writeText "known_hosts" known_hosts_text);
programs.ssh.userKnownHostsFile = toString (pkgs.writeText "known_hosts" known-hosts-text);
};
}

View File

@@ -1,34 +0,0 @@
# create ssh key by running:
# - `ssh-keygen -t ed25519`
let
withHost = host: key: "${host} ${key}";
withUser = user: key: "${key} ${user}";
keys = rec {
lappy = {
host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILSJnqmVl9/SYQ0btvGb0REwwWY8wkdkGXQZfn/1geEc";
users.colin = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDpmFdNSVPRol5hkbbCivRhyeENzb9HVyf9KutGLP2Zu";
};
desko = {
host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFw9NoRaYrM6LbDd3aFBc4yyBlxGQn8HjeHd/dZ3CfHk";
users.colin = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPU5GlsSfbaarMvDA20bxpSZGWviEzXGD8gtrIowc1pX";
};
servo = {
host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOfdSmFkrVT6DhpgvFeQKm3Fh9VKZ9DbLYOPOJWYQ0E8";
users.colin = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPS1qFzKurAdB9blkWomq8gI1g0T3sTs9LsmFOj5VtqX";
};
moby = {
host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO1N/IT3nQYUD+dBlU1sTEEVMxfOyMkrrDeyHcYgnJvw";
users.colin = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICrR+gePnl0nV/vy7I5BzrGeyVL+9eOuXHU1yNE3uCwU";
};
"uninsane.org" = servo;
"git.uninsane.org" = servo;
};
in {
# map hostname -> something suitable for known_keys
hosts = builtins.mapAttrs (host: keys: withHost host keys.host) keys;
# map hostname -> something suitable for authorized_keys to allow access to colin@<hostname>
users = builtins.mapAttrs (host: keys: withUser "colin@${host}" keys.users.colin) keys;
}

66
modules/ssh.nix Normal file
View File

@@ -0,0 +1,66 @@
{ lib, ... }:
with lib;
let
key = types.submodule ({ name, config, ...}: {
options = {
typedPubkey = mkOption {
type = types.str;
description = ''
the pubkey with type attached.
e.g. "ssh-ed25519 <base64>"
'';
};
# type = mkOption {
# type = types.str;
# description = ''
# the type of the key, e.g. "id_ed25519"
# '';
# };
host = mkOption {
type = types.str;
description = ''
the hostname of a key
'';
};
user = mkOption {
type = types.str;
description = ''
the username of a key
'';
};
asUserKey = mkOption {
type = types.str;
description = ''
append the "user@host" value to the pubkey to make it usable for ~/.ssh/id_<x>.pub or authorized_keys
'';
};
asHostKey = mkOption {
type = types.str;
description = ''
prepend the "host" value to the pubkey to make it usable for ~/.ssh/known_hosts
'';
};
};
config = rec {
user = head (lib.splitString "@" name);
host = last (lib.splitString "@" name);
asUserKey = "${config.typedPubkey} ${name}";
asHostKey = "${host} ${config.typedPubkey}";
};
});
coercedToKey = types.coercedTo types.str (typedPubkey: {
inherit typedPubkey;
}) key;
in
{
options = {
sane.ssh.pubkeys = mkOption {
type = types.attrsOf coercedToKey;
default = [];
description = ''
mapping from "user@host" to pubkey.
'';
};
};
}