diff --git a/modules/security/pam.nix b/modules/security/pam.nix index f5cb453ef08..963aef55999 100644 --- a/modules/security/pam.nix +++ b/modules/security/pam.nix @@ -7,7 +7,7 @@ with pkgs.lib; let - inherit (pkgs) pam_usb pam_ldap pam_krb5 pam_ccreds; + inherit (pkgs) pam_ldap pam_krb5 pam_ccreds; otherService = pkgs.writeText "other.pam" '' @@ -37,6 +37,10 @@ let , # If set, user listed in /etc/pamusb.conf are able to log in with # the associated usb key. usbAuth ? config.security.pam.usb.enable + , # If set, the calling user's SSH agent is used to authenticate + # against the keys in the calling user's ~/.ssh/authorized_keys. + # This is useful for "sudo" on password-less remote systems. + sshAgentAuth ? false , # If set, use ConsoleKit's PAM connector module to claim # ownership of audio devices etc. ownDevices ? false @@ -70,16 +74,17 @@ let # Authentication management. ${optionalString rootOK "auth sufficient pam_rootok.so"} + ${optionalString sshAgentAuth + "auth sufficient ${pkgs.pam_ssh_agent_auth}/libexec/pam_ssh_agent_auth.so file=~/.ssh/authorized_keys"} ${optionalString usbAuth - "auth sufficient ${pam_usb}/lib/security/pam_usb.so"} - auth sufficient pam_unix.so ${ - optionalString allowNullPassword "nullok"} likeauth + "auth sufficient ${pkgs.pam_usb}/lib/security/pam_usb.so"} + auth sufficient pam_unix.so ${optionalString allowNullPassword "nullok"} likeauth ${optionalString config.users.ldap.enable "auth sufficient ${pam_ldap}/lib/security/pam_ldap.so use_first_pass"} - ${optionalString config.krb5.enable -''auth [default=ignore success=1 service_err=reset] ${pam_krb5}/lib/security/pam_krb5.so use_first_pass -auth [default=die success=done] ${pam_ccreds}/lib/security/pam_ccreds.so action=validate use_first_pass -auth sufficient ${pam_ccreds}/lib/security/pam_ccreds.so action=store use_first_pass + ${optionalString config.krb5.enable '' + auth [default=ignore success=1 service_err=reset] ${pam_krb5}/lib/security/pam_krb5.so use_first_pass + auth [default=die success=done] ${pam_ccreds}/lib/security/pam_ccreds.so action=validate use_first_pass + auth sufficient ${pam_ccreds}/lib/security/pam_ccreds.so action=store use_first_pass ''} auth required pam_deny.so @@ -184,6 +189,17 @@ in ''; }; + security.pam.enableSSHAgentAuth = mkOption { + default = false; + description = + '' + Enable sudo logins if the user's SSH agent provides a key + present in ~/.ssh/authorized_keys. + This allows machines to exclusively use SSH keys instead of + passwords. + ''; + }; + }; diff --git a/modules/security/sudo.nix b/modules/security/sudo.nix index 3f01633d67a..76c325d8d8f 100644 --- a/modules/security/sudo.nix +++ b/modules/security/sudo.nix @@ -30,13 +30,16 @@ in # configuration will fail to build. default = '' - # Don't edit this file. Set nixos option security.sudo.configFile instead + # Don't edit this file. Set the NixOS option ‘security.sudo.configFile’ instead. - # env vars to keep for root and %wheel also if not explicitly set + # Environment variables to keep for root and %wheel. Defaults:root,%wheel env_keep+=LOCALE_ARCHIVE Defaults:root,%wheel env_keep+=NIX_PATH Defaults:root,%wheel env_keep+=TERMINFO_DIRS + # Keep SSH_AUTH_SOCK so that pam_ssh_agent_auth.so can do its magic. + Defaults env_keep+=SSH_AUTH_SOCK + # "root" is allowed to do anything. root ALL=(ALL) SETENV: ALL @@ -60,15 +63,13 @@ in environment.systemPackages = [ sudo ]; - security.pam.services = [ { name = "sudo"; } ]; + security.pam.services = [ { name = "sudo"; sshAgentAuth = true; } ]; environment.etc = singleton - { source = pkgs.runCommand "sudoers" - { src = pkgs.writeText "sudoers-in" cfg.configFile; } + { source = pkgs.writeText "sudoers-in" cfg.configFile; # Make sure that the sudoers file is syntactically valid. # (currently disabled - NIXOS-66) #"${pkgs.sudo}/sbin/visudo -f $src -c && cp $src $out"; - "cp $src $out"; target = "sudoers"; mode = "0440"; };