openssh: Change the way authorized keys are added to the system.
Instead of the somewhat hacky script that inserted public keys into the users' .ssh/authorized_keys files, use the AuthorizedKeysFile configuration directive in sshd_config and generate extra key files for each user (placed in /etc/authorized_keys.d/).
This commit is contained in:
parent
13617b803b
commit
68872f81cf
@ -40,102 +40,44 @@ let
|
|||||||
|
|
||||||
userOptions = {
|
userOptions = {
|
||||||
openssh.authorizedKeys = {
|
openssh.authorizedKeys = {
|
||||||
|
|
||||||
preserveExistingKeys = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = true;
|
|
||||||
description = ''
|
|
||||||
If this option is enabled, the keys specified in
|
|
||||||
<literal>keys</literal> and/or <literal>keyFiles</literal> will be
|
|
||||||
placed in a special section of the user's authorized_keys file
|
|
||||||
and any existing keys will be preserved. That section will be
|
|
||||||
regenerated each time NixOS is activated. However, if
|
|
||||||
<literal>preserveExisting</literal> isn't enabled, the complete file
|
|
||||||
will be generated, and any user modifications will be wiped out.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
keys = mkOption {
|
keys = mkOption {
|
||||||
type = types.listOf types.string;
|
type = types.listOf types.string;
|
||||||
default = [];
|
default = [];
|
||||||
description = ''
|
description = ''
|
||||||
A list of verbatim OpenSSH public keys that should be inserted into the
|
A list of verbatim OpenSSH public keys that should be added to the
|
||||||
user's authorized_keys file. You can combine the <literal>keys</literal> and
|
user's authorized keys. The keys are added to a file that the SSH
|
||||||
|
daemon reads in addition to the the user's authorized_keys file.
|
||||||
|
You can combine the <literal>keys</literal> and
|
||||||
<literal>keyFiles</literal> options.
|
<literal>keyFiles</literal> options.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
keyFiles = mkOption {
|
keyFiles = mkOption {
|
||||||
#type = types.listOf types.string;
|
|
||||||
default = [];
|
default = [];
|
||||||
description = ''
|
description = ''
|
||||||
A list of files each containing one OpenSSH public keys that should be
|
A list of files each containing one OpenSSH public key that should be
|
||||||
inserted into the user's authorized_keys file. You can combine
|
added to the user's authorized keys. The contents of the files are
|
||||||
the <literal>keyFiles</literal> and
|
read at build time and added to a file that the SSH daemon reads in
|
||||||
<literal>keys</literal> options.
|
addition to the the user's authorized_keys file. You can combine the
|
||||||
|
<literal>keyFiles</literal> and <literal>keys</literal> options.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
mkAuthkeyScript =
|
authKeysFiles = with {
|
||||||
let
|
mkAuthKeyFile = u: {
|
||||||
marker1 = "### NixOS auto-added key. Do not edit!";
|
target = "ssh/authorized_keys.d/${u.name}";
|
||||||
marker2 = "### NixOS will regenerate this file. Do not edit!";
|
mode = "0444";
|
||||||
users = map (userName: getAttr userName config.users.extraUsers) (attrNames config.users.extraUsers);
|
source = pkgs.writeText "${u.name}-authorized_keys" ''
|
||||||
usersWithKeys = flip filter users (u:
|
${concatStringsSep "\n" u.openssh.authorizedKeys.keys}
|
||||||
length u.openssh.authorizedKeys.keys != 0 || length u.openssh.authorizedKeys.keyFiles != 0
|
${concatMapStrings (f: builtins.readFile f + "\n") u.openssh.authorizedKeys.keyFiles}
|
||||||
);
|
'';
|
||||||
userLoop = flip concatMapStrings usersWithKeys (u:
|
};
|
||||||
let
|
usersWithKeys = attrValues (flip filterAttrs config.users.extraUsers (n: u:
|
||||||
authKeys = concatStringsSep "," u.openssh.authorizedKeys.keys;
|
length u.openssh.authorizedKeys.keys != 0 || length u.openssh.authorizedKeys.keyFiles != 0
|
||||||
authKeyFiles = concatStrings (map (x: " ${x}") u.openssh.authorizedKeys.keyFiles);
|
));
|
||||||
preserveExisting = if u.openssh.authorizedKeys.preserveExistingKeys then "true" else "false";
|
}; map mkAuthKeyFile usersWithKeys;
|
||||||
in ''
|
|
||||||
mkAuthKeysFile "${u.name}" "${authKeys}" "${authKeyFiles}" "${preserveExisting}"
|
|
||||||
''
|
|
||||||
);
|
|
||||||
in ''
|
|
||||||
mkAuthKeysFile() {
|
|
||||||
local userName="$1"
|
|
||||||
local authKeys="$2"
|
|
||||||
local authKeyFiles="$3"
|
|
||||||
local preserveExisting="$4"
|
|
||||||
|
|
||||||
eval homeDir=~$userName
|
|
||||||
if ! [ -d "$homeDir" ]; then
|
|
||||||
echo "User $userName does not exist"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
if ! [ -d "$homeDir/.ssh" ]; then
|
|
||||||
mkdir -v -m 700 "$homeDir/.ssh"
|
|
||||||
chown "$userName":users "$homeDir/.ssh"
|
|
||||||
fi
|
|
||||||
local authKeysFile="$homeDir/.ssh/authorized_keys"
|
|
||||||
touch "$authKeysFile"
|
|
||||||
if [ "$preserveExisting" == false ]; then
|
|
||||||
rm -f "$authKeysFile"
|
|
||||||
echo "${marker2}" > "$authKeysFile"
|
|
||||||
else
|
|
||||||
sed -i '/${marker1}/ d' "$authKeysFile"
|
|
||||||
fi
|
|
||||||
IFS=,
|
|
||||||
for f in $authKeys; do
|
|
||||||
echo "$f ${marker1}" >> "$authKeysFile"
|
|
||||||
done
|
|
||||||
unset IFS
|
|
||||||
for f in $authKeyFiles; do
|
|
||||||
if [ -f "$f" ]; then
|
|
||||||
echo "$(cat "$f") ${marker1}" >> "$authKeysFile"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
chown "$userName" "$authKeysFile"
|
|
||||||
}
|
|
||||||
|
|
||||||
${userLoop}
|
|
||||||
'';
|
|
||||||
|
|
||||||
|
|
||||||
in
|
in
|
||||||
|
|
||||||
@ -305,7 +247,7 @@ in
|
|||||||
home = "/var/empty";
|
home = "/var/empty";
|
||||||
};
|
};
|
||||||
|
|
||||||
environment.etc = [
|
environment.etc = authKeysFiles ++ [
|
||||||
{ source = "${pkgs.openssh}/etc/ssh/moduli";
|
{ source = "${pkgs.openssh}/etc/ssh/moduli";
|
||||||
target = "ssh/moduli";
|
target = "ssh/moduli";
|
||||||
}
|
}
|
||||||
@ -326,12 +268,10 @@ in
|
|||||||
LOCALE_ARCHIVE = "/run/current-system/sw/lib/locale/locale-archive";
|
LOCALE_ARCHIVE = "/run/current-system/sw/lib/locale/locale-archive";
|
||||||
};
|
};
|
||||||
|
|
||||||
path = [ pkgs.openssh pkgs.gnused ];
|
path = [ pkgs.openssh ];
|
||||||
|
|
||||||
preStart =
|
preStart =
|
||||||
''
|
''
|
||||||
${mkAuthkeyScript}
|
|
||||||
|
|
||||||
mkdir -m 0755 -p /etc/ssh
|
mkdir -m 0755 -p /etc/ssh
|
||||||
|
|
||||||
if ! test -f ${cfg.hostKeyPath}; then
|
if ! test -f ${cfg.hostKeyPath}; then
|
||||||
@ -379,6 +319,8 @@ in
|
|||||||
GatewayPorts ${cfg.gatewayPorts}
|
GatewayPorts ${cfg.gatewayPorts}
|
||||||
PasswordAuthentication ${if cfg.passwordAuthentication then "yes" else "no"}
|
PasswordAuthentication ${if cfg.passwordAuthentication then "yes" else "no"}
|
||||||
ChallengeResponseAuthentication ${if cfg.challengeResponseAuthentication then "yes" else "no"}
|
ChallengeResponseAuthentication ${if cfg.challengeResponseAuthentication then "yes" else "no"}
|
||||||
|
|
||||||
|
AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2 /etc/ssh/authorized_keys.d/%u
|
||||||
'';
|
'';
|
||||||
|
|
||||||
assertions = [{ assertion = if cfg.forwardX11 then cfgc.setXAuthLocation else true;
|
assertions = [{ assertion = if cfg.forwardX11 then cfgc.setXAuthLocation else true;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user