add authorizedKeys option to ssh service

this has no apparent use as it stands, but opens the door to
having the keys managed by an external secrets service
This commit is contained in:
Daniel Barlow 2024-08-23 20:35:07 +01:00
parent e835473945
commit 869a508c0a
3 changed files with 35 additions and 4 deletions

View File

@ -184,7 +184,11 @@ in rec {
dependencies = [ config.services.hostname ];
};
services.sshd = svc.ssh.build { };
services.sshd = svc.ssh.build {
authorizedKeys = {
root = rsecrets.root.openssh.authorizedKeys.keys;
};
};
services.lns-address = let
ns = "$(output_word ${services.bootstrap-dhcpc} dns 1)";

View File

@ -19,6 +19,7 @@ in {
type = liminix.lib.types.serviceDefn;
};
};
config.programs.busybox.options.FEATURE_FANCY_ECHO = "y";
config.system.service = {
ssh = config.system.callService ./ssh.nix {
address = mkOption {
@ -41,6 +42,16 @@ in {
type = types.bool; default = false;
description = "Allow remote hosts to connect to local forwarded ports (by default they are bound to loopback)";
};
authorizedKeys = mkOption {
type = types.nullOr (types.attrsOf (types.listOf types.nonEmptyStr));
example = {
root = ["ssh-rsa AAAAB3N...aZaZ"];
alice = ["ssh-rsa AAAAB3N...qS4r"];
bob = [];
};
default = null;
description = "Authorized SSH public keys for each username. If this optin is provided it overrides any keys found in /home/{username}/.ssh";
};
extraConfig = mkOption {
type = types.separatedString " ";
default = "";

View File

@ -3,10 +3,11 @@
, dropbear
, lib
}:
p :
{authorizedKeys, ...} @ p :
let
name = "sshd";
inherit (liminix.services) longrun;
inherit (lib) concatStringsSep;
inherit (lib) concatStringsSep mapAttrs mapAttrsToList;
options =
[
"-e" # pass environment to child
@ -21,19 +22,34 @@ let
(lib.optional (! p.allowLocalPortForward) "-j") ++
(lib.optional (! p.allowRemotePortForward) "-k") ++
(lib.optional (! p.allowRemoteConnectionToForwardedPorts) "-a") ++
(lib.optionals (authorizedKeys != null)
["-U" "/run/${name}/authorized_keys/%n"]) ++
[(if p.address != null
then "-p ${p.address}:${p.port}"
else "-p ${builtins.toString p.port}")] ++
[p.extraConfig];
authKeysConcat =
if authorizedKeys != null
then mapAttrs
(n : v : concatStringsSep "\\n" v)
authorizedKeys
else {};
in
longrun {
name = "sshd";
inherit name;
# we need /run/dropbear to point to hostkey storage, as that
# pathname is hardcoded into the binary.
# env -i clears the environment so we don't pass anything weird to
# ssh sessions
run = ''
ln -s $(mkstate dropbear) /run
mkdir -p /run/${name}/authorized_keys
${concatStringsSep "\n"
(mapAttrsToList
(n : v : "echo -e '${v}' > /run/${name}/authorized_keys/${n} ")
authKeysConcat
)
}
. /etc/profile # sets PATH but do we need this? it's the same file as ashrc
exec env -i ENV=/etc/ashrc PATH=$PATH ${dropbear}/bin/dropbear ${concatStringsSep " " options}
'';