diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix index 6e8be412de83..d379265960bb 100644 --- a/nixos/modules/security/pam.nix +++ b/nixos/modules/security/pam.nix @@ -638,7 +638,7 @@ let password sufficient ${pkgs.pam_mysql}/lib/security/pam_mysql.so config_file=/etc/security/pam_mysql.conf '' + optionalString config.services.sssd.enable '' - password sufficient ${pkgs.sssd}/lib/security/pam_sss.so use_authtok + password sufficient ${pkgs.sssd}/lib/security/pam_sss.so '' + optionalString config.security.pam.krb5.enable '' password sufficient ${pam_krb5}/lib/security/pam_krb5.so use_first_pass diff --git a/nixos/tests/sssd-ldap.nix b/nixos/tests/sssd-ldap.nix index ff83e96068a9..60f3b1a415da 100644 --- a/nixos/tests/sssd-ldap.nix +++ b/nixos/tests/sssd-ldap.nix @@ -6,17 +6,33 @@ let ldapRootPassword = "foobar"; testUser = "alice"; -in import ./make-test-python.nix ({pkgs, ...}: { + testPassword = "foobar"; + testNewPassword = "barfoo"; +in +import ./make-test-python.nix ({ pkgs, ... }: { name = "sssd-ldap"; meta = with pkgs.lib.maintainers; { - maintainers = [ bbigras ]; + maintainers = [ bbigras s1341 ]; }; nodes.machine = { pkgs, ... }: { + security.pam.services.systemd-user.makeHomeDir = true; + environment.etc."cert.pem".text = builtins.readFile ./common/acme/server/acme.test.cert.pem; + environment.etc."key.pem".text = builtins.readFile ./common/acme/server/acme.test.key.pem; services.openldap = { enable = true; + urlList = [ "ldap:///" "ldaps:///" ]; settings = { + attrs = { + olcTLSCACertificateFile = "/etc/cert.pem"; + olcTLSCertificateFile = "/etc/cert.pem"; + olcTLSCertificateKeyFile = "/etc/key.pem"; + olcTLSCipherSuite = "HIGH:MEDIUM:+3DES:+RC4:+aNULL"; + olcTLSCRLCheck = "none"; + olcTLSVerifyClient = "never"; + olcTLSProtocolMin = "3.1"; + }; children = { "cn=schema".includes = [ "${pkgs.openldap}/etc/schema/core.ldif" @@ -32,6 +48,23 @@ in import ./make-test-python.nix ({pkgs, ...}: { olcSuffix = dbSuffix; olcRootDN = "cn=${ldapRootUser},${dbSuffix}"; olcRootPW = ldapRootPassword; + olcAccess = [ + /* + custom access rules for userPassword attributes + */ + '' + {0}to attrs=userPassword + by self write + by anonymous auth + by * none'' + + /* + allow read on anything else + */ + '' + {1}to * + by * read'' + ]; }; }; }; @@ -55,7 +88,7 @@ in import ./make-test-python.nix ({pkgs, ...}: { dn: uid=${testUser},ou=accounts,ou=posix,${dbSuffix} objectClass: person objectClass: posixAccount - # userPassword: somePasswordHash + userPassword: ${testPassword} homeDirectory: /home/${testUser} uidNumber: 1234 gidNumber: 1234 @@ -78,7 +111,9 @@ in import ./make-test-python.nix ({pkgs, ...}: { [domain/${dbDomain}] auth_provider = ldap id_provider = ldap - ldap_uri = ldap://127.0.0.1:389 + ldap_uri = ldaps://127.0.0.1:636 + ldap_tls_reqcert = allow + ldap_tls_cacert = /etc/cert.pem ldap_search_base = ${dbSuffix} ldap_default_bind_dn = cn=${ldapRootUser},${dbSuffix} ldap_default_authtok_type = password @@ -97,5 +132,42 @@ in import ./make-test-python.nix ({pkgs, ...}: { else: machine.wait_for_console_text("Backend is online") machine.succeed("getent passwd ${testUser}") + + with subtest("Log in as ${testUser}"): + machine.wait_until_tty_matches("1", "login: ") + machine.send_chars("${testUser}\n") + machine.wait_until_tty_matches("1", "login: ${testUser}") + machine.wait_until_succeeds("pgrep login") + machine.wait_until_tty_matches("1", "Password: ") + machine.send_chars("${testPassword}\n") + machine.wait_until_succeeds("pgrep -u ${testUser} bash") + machine.send_chars("touch done\n") + machine.wait_for_file("/home/${testUser}/done") + + with subtest("Change ${testUser}'s password"): + machine.send_chars("passwd\n") + machine.wait_until_tty_matches("1", "Current Password: ") + machine.send_chars("${testPassword}\n") + machine.wait_until_tty_matches("1", "New Password: ") + machine.send_chars("${testNewPassword}\n") + machine.wait_until_tty_matches("1", "Reenter new Password: ") + machine.send_chars("${testNewPassword}\n") + machine.wait_until_tty_matches("1", "passwd: password updated successfully") + + with subtest("Log in as ${testUser} with new password in virtual console 2"): + machine.send_key("alt-f2") + machine.wait_until_succeeds("[ $(fgconsole) = 2 ]") + machine.wait_for_unit("getty@tty2.service") + machine.wait_until_succeeds("pgrep -f 'agetty.*tty2'") + + machine.wait_until_tty_matches("2", "login: ") + machine.send_chars("${testUser}\n") + machine.wait_until_tty_matches("2", "login: ${testUser}") + machine.wait_until_succeeds("pgrep login") + machine.wait_until_tty_matches("2", "Password: ") + machine.send_chars("${testNewPassword}\n") + machine.wait_until_succeeds("pgrep -u ${testUser} bash") + machine.send_chars("touch done2\n") + machine.wait_for_file("/home/${testUser}/done2") ''; }) diff --git a/pkgs/os-specific/linux/pam/default.nix b/pkgs/os-specific/linux/pam/default.nix index 8b068100f32a..b16bebbe3d60 100644 --- a/pkgs/os-specific/linux/pam/default.nix +++ b/pkgs/os-specific/linux/pam/default.nix @@ -44,7 +44,7 @@ stdenv.mkDerivation rec { doCheck = false; # fails passthru.tests = { - inherit (nixosTests) pam-oath-login pam-u2f shadow; + inherit (nixosTests) pam-oath-login pam-u2f shadow sssd-ldap; }; meta = with lib; {