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

nixos/duosec: replace insecure skey option with secure secretKeyFile option

authored by Aaron Andersen and committed by GitHub b69b7a12 72dca363

+68 -36
+12
nixos/doc/manual/release-notes/rl-2009.xml
··· 96 <option>systemd.services.supybot.serviceConfig</option>. 97 </para> 98 </listitem> 99 </itemizedlist> 100 </section> 101
··· 96 <option>systemd.services.supybot.serviceConfig</option>. 97 </para> 98 </listitem> 99 + <listitem> 100 + <para> 101 + The <literal>security.duosec.skey</literal> option, which stored a secret in the 102 + nix store, has been replaced by a new 103 + <link linkend="opt-security.duosec.secretKeyFile">security.duosec.secretKeyFile</link> 104 + option for better security. 105 + </para> 106 + <para> 107 + <literal>security.duosec.ikey</literal> has been renamed to 108 + <link linkend="opt-security.duosec.integrationKey">security.duosec.integrationKey</link>. 109 + </para> 110 + </listitem> 111 </itemizedlist> 112 </section> 113
+56 -36
nixos/modules/security/duosec.nix
··· 9 10 configFilePam = '' 11 [duo] 12 - ikey=${cfg.ikey} 13 - skey=${cfg.skey} 14 host=${cfg.host} 15 ${optionalString (cfg.groups != "") ("groups="+cfg.groups)} 16 failmode=${cfg.failmode} ··· 24 motd=${boolToStr cfg.motd} 25 accept_env_factor=${boolToStr cfg.acceptEnvFactor} 26 ''; 27 - 28 - loginCfgFile = optionalAttrs cfg.ssh.enable { 29 - "duo/login_duo.conf" = 30 - { source = pkgs.writeText "login_duo.conf" configFileLogin; 31 - mode = "0600"; 32 - user = "sshd"; 33 - }; 34 - }; 35 - 36 - pamCfgFile = optional cfg.pam.enable { 37 - "duo/pam_duo.conf" = 38 - { source = pkgs.writeText "pam_duo.conf" configFilePam; 39 - mode = "0600"; 40 - user = "sshd"; 41 - }; 42 - }; 43 in 44 { 45 imports = [ 46 (mkRenamedOptionModule [ "security" "duosec" "group" ] [ "security" "duosec" "groups" ]) 47 ]; 48 49 options = { ··· 60 description = "If enabled, protect logins with Duo Security using PAM support."; 61 }; 62 63 - ikey = mkOption { 64 type = types.str; 65 description = "Integration key."; 66 }; 67 68 - skey = mkOption { 69 - type = types.str; 70 - description = "Secret key."; 71 }; 72 73 host = mkOption { ··· 195 }; 196 197 config = mkIf (cfg.ssh.enable || cfg.pam.enable) { 198 - environment.systemPackages = [ pkgs.duo-unix ]; 199 200 - security.wrappers.login_duo.source = "${pkgs.duo-unix.out}/bin/login_duo"; 201 - environment.etc = loginCfgFile // pamCfgFile; 202 203 - /* If PAM *and* SSH are enabled, then don't do anything special. 204 - If PAM isn't used, set the default SSH-only options. */ 205 - services.openssh.extraConfig = mkIf (cfg.ssh.enable || cfg.pam.enable) ( 206 - if cfg.pam.enable then "UseDNS no" else '' 207 - # Duo Security configuration 208 - ForceCommand ${config.security.wrapperDir}/login_duo 209 - PermitTunnel no 210 - ${optionalString (!cfg.allowTcpForwarding) '' 211 - AllowTcpForwarding no 212 - ''} 213 - ''); 214 }; 215 }
··· 9 10 configFilePam = '' 11 [duo] 12 + ikey=${cfg.integrationKey} 13 host=${cfg.host} 14 ${optionalString (cfg.groups != "") ("groups="+cfg.groups)} 15 failmode=${cfg.failmode} ··· 23 motd=${boolToStr cfg.motd} 24 accept_env_factor=${boolToStr cfg.acceptEnvFactor} 25 ''; 26 in 27 { 28 imports = [ 29 (mkRenamedOptionModule [ "security" "duosec" "group" ] [ "security" "duosec" "groups" ]) 30 + (mkRenamedOptionModule [ "security" "duosec" "ikey" ] [ "security" "duosec" "integrationKey" ]) 31 + (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.") 32 ]; 33 34 options = { ··· 45 description = "If enabled, protect logins with Duo Security using PAM support."; 46 }; 47 48 + integrationKey = mkOption { 49 type = types.str; 50 description = "Integration key."; 51 }; 52 53 + secretKeyFile = mkOption { 54 + type = types.path; 55 + default = null; 56 + description = '' 57 + A file containing your secret key. The security of your Duo application is tied to the security of your secret key. 58 + ''; 59 + example = "/run/keys/duo-skey"; 60 }; 61 62 host = mkOption { ··· 184 }; 185 186 config = mkIf (cfg.ssh.enable || cfg.pam.enable) { 187 + environment.systemPackages = [ pkgs.duo-unix ]; 188 + 189 + security.wrappers.login_duo.source = "${pkgs.duo-unix.out}/bin/login_duo"; 190 + 191 + system.activationScripts = { 192 + login_duo = mkIf cfg.ssh.enable '' 193 + if test -f "${cfg.secretKeyFile}"; then 194 + mkdir -m 0755 -p /etc/duo 195 + 196 + umask 0077 197 + conf="$(mktemp)" 198 + { 199 + cat ${pkgs.writeText "login_duo.conf" configFileLogin} 200 + printf 'skey = %s\n' "$(cat ${cfg.secretKeyFile})" 201 + } >"$conf" 202 + 203 + chown sshd "$conf" 204 + mv -fT "$conf" /etc/duo/login_duo.conf 205 + fi 206 + ''; 207 + pam_duo = mkIf cfg.pam.enable '' 208 + if test -f "${cfg.secretKeyFile}"; then 209 + mkdir -m 0755 -p /etc/duo 210 + 211 + umask 0077 212 + conf="$(mktemp)" 213 + { 214 + cat ${pkgs.writeText "login_duo.conf" configFilePam} 215 + printf 'skey = %s\n' "$(cat ${cfg.secretKeyFile})" 216 + } >"$conf" 217 218 + mv -fT "$conf" /etc/duo/pam_duo.conf 219 + fi 220 + ''; 221 + }; 222 223 + /* If PAM *and* SSH are enabled, then don't do anything special. 224 + If PAM isn't used, set the default SSH-only options. */ 225 + services.openssh.extraConfig = mkIf (cfg.ssh.enable || cfg.pam.enable) ( 226 + if cfg.pam.enable then "UseDNS no" else '' 227 + # Duo Security configuration 228 + ForceCommand ${config.security.wrapperDir}/login_duo 229 + PermitTunnel no 230 + ${optionalString (!cfg.allowTcpForwarding) '' 231 + AllowTcpForwarding no 232 + ''} 233 + ''); 234 }; 235 }