Merge pull request #78938 from aanderse/duo-activation-scripts

nixos/duosec: replace insecure skey option with secure secretKeyFile option
This commit is contained in:
Aaron Andersen 2020-03-22 20:46:42 -04:00 committed by GitHub
commit b69b7a12af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 68 additions and 36 deletions

View File

@ -96,6 +96,18 @@
<option>systemd.services.supybot.serviceConfig</option>. <option>systemd.services.supybot.serviceConfig</option>.
</para> </para>
</listitem> </listitem>
<listitem>
<para>
The <literal>security.duosec.skey</literal> option, which stored a secret in the
nix store, has been replaced by a new
<link linkend="opt-security.duosec.secretKeyFile">security.duosec.secretKeyFile</link>
option for better security.
</para>
<para>
<literal>security.duosec.ikey</literal> has been renamed to
<link linkend="opt-security.duosec.integrationKey">security.duosec.integrationKey</link>.
</para>
</listitem>
</itemizedlist> </itemizedlist>
</section> </section>

View File

@ -9,8 +9,7 @@ let
configFilePam = '' configFilePam = ''
[duo] [duo]
ikey=${cfg.ikey} ikey=${cfg.integrationKey}
skey=${cfg.skey}
host=${cfg.host} host=${cfg.host}
${optionalString (cfg.groups != "") ("groups="+cfg.groups)} ${optionalString (cfg.groups != "") ("groups="+cfg.groups)}
failmode=${cfg.failmode} failmode=${cfg.failmode}
@ -24,26 +23,12 @@ let
motd=${boolToStr cfg.motd} motd=${boolToStr cfg.motd}
accept_env_factor=${boolToStr cfg.acceptEnvFactor} accept_env_factor=${boolToStr cfg.acceptEnvFactor}
''; '';
loginCfgFile = optionalAttrs cfg.ssh.enable {
"duo/login_duo.conf" =
{ source = pkgs.writeText "login_duo.conf" configFileLogin;
mode = "0600";
user = "sshd";
};
};
pamCfgFile = optional cfg.pam.enable {
"duo/pam_duo.conf" =
{ source = pkgs.writeText "pam_duo.conf" configFilePam;
mode = "0600";
user = "sshd";
};
};
in in
{ {
imports = [ imports = [
(mkRenamedOptionModule [ "security" "duosec" "group" ] [ "security" "duosec" "groups" ]) (mkRenamedOptionModule [ "security" "duosec" "group" ] [ "security" "duosec" "groups" ])
(mkRenamedOptionModule [ "security" "duosec" "ikey" ] [ "security" "duosec" "integrationKey" ])
(mkRemovedOptionModule [ "security" "duosec" "skey" ] "The insecure security.duosec.skey option has been replaced by a new security.duosec.secretKeyFile option. Use this new option to store a secure copy of your key instead.")
]; ];
options = { options = {
@ -60,14 +45,18 @@ in
description = "If enabled, protect logins with Duo Security using PAM support."; description = "If enabled, protect logins with Duo Security using PAM support.";
}; };
ikey = mkOption { integrationKey = mkOption {
type = types.str; type = types.str;
description = "Integration key."; description = "Integration key.";
}; };
skey = mkOption { secretKeyFile = mkOption {
type = types.str; type = types.path;
description = "Secret key."; default = null;
description = ''
A file containing your secret key. The security of your Duo application is tied to the security of your secret key.
'';
example = "/run/keys/duo-skey";
}; };
host = mkOption { host = mkOption {
@ -195,21 +184,52 @@ in
}; };
config = mkIf (cfg.ssh.enable || cfg.pam.enable) { config = mkIf (cfg.ssh.enable || cfg.pam.enable) {
environment.systemPackages = [ pkgs.duo-unix ]; environment.systemPackages = [ pkgs.duo-unix ];
security.wrappers.login_duo.source = "${pkgs.duo-unix.out}/bin/login_duo"; security.wrappers.login_duo.source = "${pkgs.duo-unix.out}/bin/login_duo";
environment.etc = loginCfgFile // pamCfgFile;
/* If PAM *and* SSH are enabled, then don't do anything special. system.activationScripts = {
If PAM isn't used, set the default SSH-only options. */ login_duo = mkIf cfg.ssh.enable ''
services.openssh.extraConfig = mkIf (cfg.ssh.enable || cfg.pam.enable) ( if test -f "${cfg.secretKeyFile}"; then
if cfg.pam.enable then "UseDNS no" else '' mkdir -m 0755 -p /etc/duo
# Duo Security configuration
ForceCommand ${config.security.wrapperDir}/login_duo umask 0077
PermitTunnel no conf="$(mktemp)"
${optionalString (!cfg.allowTcpForwarding) '' {
AllowTcpForwarding no cat ${pkgs.writeText "login_duo.conf" configFileLogin}
''} printf 'skey = %s\n' "$(cat ${cfg.secretKeyFile})"
''); } >"$conf"
chown sshd "$conf"
mv -fT "$conf" /etc/duo/login_duo.conf
fi
'';
pam_duo = mkIf cfg.pam.enable ''
if test -f "${cfg.secretKeyFile}"; then
mkdir -m 0755 -p /etc/duo
umask 0077
conf="$(mktemp)"
{
cat ${pkgs.writeText "login_duo.conf" configFilePam}
printf 'skey = %s\n' "$(cat ${cfg.secretKeyFile})"
} >"$conf"
mv -fT "$conf" /etc/duo/pam_duo.conf
fi
'';
};
/* If PAM *and* SSH are enabled, then don't do anything special.
If PAM isn't used, set the default SSH-only options. */
services.openssh.extraConfig = mkIf (cfg.ssh.enable || cfg.pam.enable) (
if cfg.pam.enable then "UseDNS no" else ''
# Duo Security configuration
ForceCommand ${config.security.wrapperDir}/login_duo
PermitTunnel no
${optionalString (!cfg.allowTcpForwarding) ''
AllowTcpForwarding no
''}
'');
}; };
} }