1let
2 dbDomain = "example.org";
3 dbSuffix = "dc=example,dc=org";
4
5 ldapRootUser = "admin";
6 ldapRootPassword = "foobar";
7
8 testUser = "alice";
9 testPassword = "foobar";
10 testNewPassword = "barfoo";
11in
12import ./make-test-python.nix (
13 { pkgs, ... }:
14 {
15 name = "sssd-ldap";
16
17 meta = with pkgs.lib.maintainers; {
18 maintainers = [
19 bbigras
20 s1341
21 ];
22 };
23
24 nodes.machine =
25 { pkgs, ... }:
26 {
27 security.pam.services.systemd-user.makeHomeDir = true;
28 environment.etc."cert.pem".text = builtins.readFile ./common/acme/server/acme.test.cert.pem;
29 environment.etc."key.pem".text = builtins.readFile ./common/acme/server/acme.test.key.pem;
30 services.openldap = {
31 enable = true;
32 urlList = [
33 "ldap:///"
34 "ldaps:///"
35 ];
36 settings = {
37 attrs = {
38 olcTLSCACertificateFile = "/etc/cert.pem";
39 olcTLSCertificateFile = "/etc/cert.pem";
40 olcTLSCertificateKeyFile = "/etc/key.pem";
41 olcTLSCipherSuite = "HIGH:MEDIUM:+3DES:+RC4:+aNULL";
42 olcTLSCRLCheck = "none";
43 olcTLSVerifyClient = "never";
44 olcTLSProtocolMin = "3.1";
45 };
46 children = {
47 "cn=schema".includes = [
48 "${pkgs.openldap}/etc/schema/core.ldif"
49 "${pkgs.openldap}/etc/schema/cosine.ldif"
50 "${pkgs.openldap}/etc/schema/inetorgperson.ldif"
51 "${pkgs.openldap}/etc/schema/nis.ldif"
52 ];
53 "olcDatabase={1}mdb" = {
54 attrs = {
55 objectClass = [
56 "olcDatabaseConfig"
57 "olcMdbConfig"
58 ];
59 olcDatabase = "{1}mdb";
60 olcDbDirectory = "/var/lib/openldap/db";
61 olcSuffix = dbSuffix;
62 olcRootDN = "cn=${ldapRootUser},${dbSuffix}";
63 olcRootPW = ldapRootPassword;
64 olcAccess = [
65 # custom access rules for userPassword attributes
66 ''
67 {0}to attrs=userPassword
68 by self write
69 by anonymous auth
70 by * none''
71
72 # allow read on anything else
73 ''
74 {1}to *
75 by * read''
76 ];
77 };
78 };
79 };
80 };
81 declarativeContents = {
82 ${dbSuffix} = ''
83 dn: ${dbSuffix}
84 objectClass: top
85 objectClass: dcObject
86 objectClass: organization
87 o: ${dbDomain}
88
89 dn: ou=posix,${dbSuffix}
90 objectClass: top
91 objectClass: organizationalUnit
92
93 dn: ou=accounts,ou=posix,${dbSuffix}
94 objectClass: top
95 objectClass: organizationalUnit
96
97 dn: uid=${testUser},ou=accounts,ou=posix,${dbSuffix}
98 objectClass: person
99 objectClass: posixAccount
100 userPassword: ${testPassword}
101 homeDirectory: /home/${testUser}
102 loginShell: /run/current-system/sw/bin/bash
103 uidNumber: 1234
104 gidNumber: 1234
105 cn: ""
106 sn: ""
107 '';
108 };
109 };
110
111 services.sssd = {
112 enable = true;
113 # just for testing purposes, don't put this into the Nix store in production!
114 environmentFile = "${pkgs.writeText "ldap-root" "LDAP_BIND_PW=${ldapRootPassword}"}";
115 config = ''
116 [sssd]
117 config_file_version = 2
118 services = nss, pam, sudo
119 domains = ${dbDomain}
120
121 [domain/${dbDomain}]
122 auth_provider = ldap
123 id_provider = ldap
124 ldap_uri = ldaps://127.0.0.1:636
125 ldap_tls_reqcert = allow
126 ldap_tls_cacert = /etc/cert.pem
127 ldap_search_base = ${dbSuffix}
128 ldap_default_bind_dn = cn=${ldapRootUser},${dbSuffix}
129 ldap_default_authtok_type = password
130 ldap_default_authtok = $LDAP_BIND_PW
131 '';
132 };
133 };
134
135 testScript = ''
136 machine.start()
137 machine.wait_for_unit("openldap.service")
138 machine.wait_for_unit("sssd.service")
139 result = machine.execute("getent passwd ${testUser}")
140 if result[0] == 0:
141 assert "${testUser}" in result[1]
142 else:
143 machine.wait_for_console_text("Backend is online")
144 machine.succeed("getent passwd ${testUser}")
145
146 with subtest("Log in as ${testUser}"):
147 machine.wait_until_tty_matches("1", "login: ")
148 machine.send_chars("${testUser}\n")
149 machine.wait_until_tty_matches("1", "login: ${testUser}")
150 machine.wait_until_succeeds("pgrep login")
151 machine.wait_until_tty_matches("1", "Password: ")
152 machine.send_chars("${testPassword}\n")
153 machine.wait_until_succeeds("pgrep -u ${testUser} bash")
154 machine.send_chars("touch done\n")
155 machine.wait_for_file("/home/${testUser}/done")
156
157 with subtest("Change ${testUser}'s password"):
158 machine.send_chars("passwd\n")
159 machine.wait_until_tty_matches("1", "Current Password: ")
160 machine.send_chars("${testPassword}\n")
161 machine.wait_until_tty_matches("1", "New Password: ")
162 machine.send_chars("${testNewPassword}\n")
163 machine.wait_until_tty_matches("1", "Reenter new Password: ")
164 machine.send_chars("${testNewPassword}\n")
165 machine.wait_until_tty_matches("1", "passwd: password updated successfully")
166
167 with subtest("Log in as ${testUser} with new password in virtual console 2"):
168 machine.send_key("alt-f2")
169 machine.wait_until_succeeds("[ $(fgconsole) = 2 ]")
170 machine.wait_for_unit("getty@tty2.service")
171 machine.wait_until_succeeds("pgrep -f 'agetty.*tty2'")
172
173 machine.wait_until_tty_matches("2", "login: ")
174 machine.send_chars("${testUser}\n")
175 machine.wait_until_tty_matches("2", "login: ${testUser}")
176 machine.wait_until_succeeds("pgrep login")
177 machine.wait_until_tty_matches("2", "Password: ")
178 machine.send_chars("${testNewPassword}\n")
179 machine.wait_until_succeeds("pgrep -u ${testUser} bash")
180 machine.send_chars("touch done2\n")
181 machine.wait_for_file("/home/${testUser}/done2")
182 '';
183 }
184)