From 450f8a44f9bbfdea26fa4f4c26a62a5e7ac8fe4d Mon Sep 17 00:00:00 2001 From: Florian Klink Date: Tue, 5 May 2020 22:58:50 +0200 Subject: nixosTests.ldap: remove This seems to have worked in 15f105d41fb83bc93692702af96848e8887fc03c (5 months ago) but broke somewhere in the meantime. The current module doesn't seem to be underdocumented and might need a serious refactor. It requires quite some hacks to get it to work (see https://github.com/NixOS/nixpkgs/issues/86305#issuecomment-621129942), or how the ldap.nix test used systemd.services.openldap.preStart and made quite some assumptions on internals. Mic92 agreed on being added as a maintainer for the module, as he uses it a lot and can possibly fix eventual breakages. For the most basic startup breakages, the remaining openldap.nix test might suffice. --- nixos/modules/services/databases/openldap.nix | 4 + nixos/tests/all-tests.nix | 1 - nixos/tests/ldap.nix | 405 -------------------------- 3 files changed, 4 insertions(+), 406 deletions(-) delete mode 100644 nixos/tests/ldap.nix diff --git a/nixos/modules/services/databases/openldap.nix b/nixos/modules/services/databases/openldap.nix index 809f61cfa818..8c2851c37ac2 100644 --- a/nixos/modules/services/databases/openldap.nix +++ b/nixos/modules/services/databases/openldap.nix @@ -231,6 +231,10 @@ in }; + meta = { + maintainers = lib.maintainers.mic92; + }; + ###### implementation diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 46f552b26a46..06db744580fd 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -164,7 +164,6 @@ in kubernetes.rbac = handleTestOn ["x86_64-linux"] ./kubernetes/rbac.nix {}; latestKernel.hardened = handleTest ./hardened.nix { latestKernel = true; }; latestKernel.login = handleTest ./login.nix { latestKernel = true; }; - ldap = handleTest ./ldap.nix {}; leaps = handleTest ./leaps.nix {}; lidarr = handleTest ./lidarr.nix {}; lightdm = handleTest ./lightdm.nix {}; diff --git a/nixos/tests/ldap.nix b/nixos/tests/ldap.nix deleted file mode 100644 index 74b002fc00ee..000000000000 --- a/nixos/tests/ldap.nix +++ /dev/null @@ -1,405 +0,0 @@ -import ./make-test-python.nix ({ pkgs, lib, ...} : - -let - unlines = lib.concatStringsSep "\n"; - unlinesAttrs = f: as: unlines (lib.mapAttrsToList f as); - - dbDomain = "example.com"; - dbSuffix = "dc=example,dc=com"; - dbAdminDn = "cn=admin,${dbSuffix}"; - dbAdminPwd = "admin-password"; - # NOTE: slappasswd -h "{SSHA}" -s '${dbAdminPwd}' - dbAdminPwdHash = "{SSHA}i7FopSzkFQMrHzDMB1vrtkI0rBnwouP8"; - ldapUser = "test-ldap-user"; - ldapUserId = 10000; - ldapUserPwd = "user-password"; - # NOTE: slappasswd -h "{SSHA}" -s '${ldapUserPwd}' - ldapUserPwdHash = "{SSHA}v12XICMZNGT6r2KJ26rIkN8Vvvp4QX6i"; - ldapGroup = "test-ldap-group"; - ldapGroupId = 10000; - - mkClient = useDaemon: - { lib, ... }: - { - virtualisation.memorySize = 256; - virtualisation.vlans = [ 1 ]; - security.pam.services.su.rootOK = lib.mkForce false; - users.ldap.enable = true; - users.ldap.daemon = { - enable = useDaemon; - rootpwmoddn = "cn=admin,${dbSuffix}"; - rootpwmodpwFile = "/etc/nslcd.rootpwmodpw"; - }; - users.ldap.loginPam = true; - users.ldap.nsswitch = true; - users.ldap.server = "ldap://server"; - users.ldap.base = "ou=posix,${dbSuffix}"; - users.ldap.bind = { - distinguishedName = "cn=admin,${dbSuffix}"; - passwordFile = "/etc/ldap/bind.password"; - }; - # NOTE: passwords stored in clear in Nix's store, but this is a test. - environment.etc."ldap/bind.password".source = pkgs.writeText "password" dbAdminPwd; - environment.etc."nslcd.rootpwmodpw".source = pkgs.writeText "rootpwmodpw" dbAdminPwd; - }; -in - -{ - name = "ldap"; - meta = with pkgs.stdenv.lib.maintainers; { - maintainers = [ montag451 ]; - }; - - nodes = { - - server = - { pkgs, config, ... }: - let - inherit (config.services) openldap; - - slapdConfig = pkgs.writeText "cn=config.ldif" ('' - dn: cn=config - objectClass: olcGlobal - #olcPidFile: /run/slapd/slapd.pid - # List of arguments that were passed to the server - #olcArgsFile: /run/slapd/slapd.args - # Read slapd-config(5) for possible values - olcLogLevel: none - # The tool-threads parameter sets the actual amount of CPU's - # that is used for indexing. - olcToolThreads: 1 - - dn: olcDatabase={-1}frontend,cn=config - objectClass: olcDatabaseConfig - objectClass: olcFrontendConfig - # The maximum number of entries that is returned for a search operation - olcSizeLimit: 500 - # Allow unlimited access to local connection from the local root user - olcAccess: to * - by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage - by * break - # Allow unauthenticated read access for schema and base DN autodiscovery - olcAccess: to dn.exact="" - by * read - olcAccess: to dn.base="cn=Subschema" - by * read - - dn: olcDatabase=config,cn=config - objectClass: olcDatabaseConfig - olcRootDN: cn=admin,cn=config - #olcRootPW: - # NOTE: access to cn=config, system root can be manager - # with SASL mechanism (-Y EXTERNAL) over unix socket (-H ldapi://) - olcAccess: to * - by dn.exact="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" manage - by * break - - dn: cn=schema,cn=config - objectClass: olcSchemaConfig - - include: file://${pkgs.openldap}/etc/schema/core.ldif - include: file://${pkgs.openldap}/etc/schema/cosine.ldif - include: file://${pkgs.openldap}/etc/schema/nis.ldif - include: file://${pkgs.openldap}/etc/schema/inetorgperson.ldif - - dn: cn=module{0},cn=config - objectClass: olcModuleList - # Where the dynamically loaded modules are stored - #olcModulePath: /usr/lib/ldap - olcModuleLoad: back_mdb - - '' - + unlinesAttrs (olcSuffix: {conf, ...}: - "include: file://" + pkgs.writeText "config.ldif" conf - ) slapdDatabases - ); - - slapdDatabases = { - ${dbSuffix} = { - conf = '' - dn: olcBackend={1}mdb,cn=config - objectClass: olcBackendConfig - - dn: olcDatabase={1}mdb,cn=config - olcSuffix: ${dbSuffix} - olcDbDirectory: ${openldap.dataDir}/${dbSuffix} - objectClass: olcDatabaseConfig - objectClass: olcMdbConfig - # NOTE: checkpoint the database periodically in case of system failure - # and to speed up slapd shutdown. - olcDbCheckpoint: 512 30 - # Database max size is 1G - olcDbMaxSize: 1073741824 - olcLastMod: TRUE - # NOTE: database superuser. Needed for syncrepl, - # and used to auth as admin through a TCP connection. - olcRootDN: cn=admin,${dbSuffix} - olcRootPW: ${dbAdminPwdHash} - # - olcDbIndex: objectClass eq - olcDbIndex: cn,uid eq - olcDbIndex: uidNumber,gidNumber eq - olcDbIndex: member,memberUid eq - # - olcAccess: to attrs=userPassword - by self write - by anonymous auth - by dn="cn=admin,${dbSuffix}" write - by dn="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" write - by * none - olcAccess: to attrs=shadowLastChange - by self write - by dn="cn=admin,${dbSuffix}" write - by dn="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" write - by * none - olcAccess: to dn.sub="ou=posix,${dbSuffix}" - by self read - by dn="cn=admin,${dbSuffix}" read - by dn="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" read - olcAccess: to * - by self read - by * none - ''; - data = '' - dn: ${dbSuffix} - objectClass: top - objectClass: dcObject - objectClass: organization - o: ${dbDomain} - - dn: cn=admin,${dbSuffix} - objectClass: simpleSecurityObject - objectClass: organizationalRole - description: ${dbDomain} LDAP administrator - roleOccupant: ${dbSuffix} - userPassword: ${ldapUserPwdHash} - - dn: ou=posix,${dbSuffix} - objectClass: top - objectClass: organizationalUnit - - dn: ou=accounts,ou=posix,${dbSuffix} - objectClass: top - objectClass: organizationalUnit - - dn: ou=groups,ou=posix,${dbSuffix} - objectClass: top - objectClass: organizationalUnit - '' - + lib.concatMapStrings posixAccount [ - { uid=ldapUser; uidNumber=ldapUserId; gidNumber=ldapGroupId; userPassword=ldapUserPwdHash; } - ] - + lib.concatMapStrings posixGroup [ - { gid=ldapGroup; gidNumber=ldapGroupId; members=[]; } - ]; - }; - }; - - # NOTE: create a user account using the posixAccount objectClass. - posixAccount = - { uid - , uidNumber ? null - , gidNumber ? null - , cn ? "" - , sn ? "" - , userPassword ? "" - , loginShell ? "/bin/sh" - }: '' - - dn: uid=${uid},ou=accounts,ou=posix,${dbSuffix} - objectClass: person - objectClass: posixAccount - objectClass: shadowAccount - cn: ${cn} - gecos: - ${if gidNumber == null then "#" else "gidNumber: ${toString gidNumber}"} - homeDirectory: /home/${uid} - loginShell: ${loginShell} - sn: ${sn} - ${if uidNumber == null then "#" else "uidNumber: ${toString uidNumber}"} - ${if userPassword == "" then "#" else "userPassword: ${userPassword}"} - ''; - - # NOTE: create a group using the posixGroup objectClass. - posixGroup = - { gid - , gidNumber - , members - }: '' - - dn: cn=${gid},ou=groups,ou=posix,${dbSuffix} - objectClass: top - objectClass: posixGroup - gidNumber: ${toString gidNumber} - ${lib.concatMapStrings (member: "memberUid: ${member}\n") members} - ''; - in - { - virtualisation.memorySize = 256; - virtualisation.vlans = [ 1 ]; - networking.firewall.allowedTCPPorts = [ 389 ]; - services.openldap.enable = true; - services.openldap.dataDir = "/var/db/openldap"; - services.openldap.configDir = "/var/db/slapd"; - services.openldap.urlList = [ - "ldap:///" - "ldapi:///" - ]; - systemd.services.openldap = { - preStart = '' - set -e - # NOTE: slapd's config is always re-initialized. - rm -rf "${openldap.configDir}"/cn=config \ - "${openldap.configDir}"/cn=config.ldif - install -D -d -m 0700 -o "${openldap.user}" -g "${openldap.group}" "${openldap.configDir}" - # NOTE: olcDbDirectory must be created before adding the config. - '' + - unlinesAttrs (olcSuffix: {data, ...}: '' - # NOTE: database is always re-initialized. - rm -rf "${openldap.dataDir}/${olcSuffix}" - install -D -d -m 0700 -o "${openldap.user}" -g "${openldap.group}" \ - "${openldap.dataDir}/${olcSuffix}" - '') slapdDatabases - + '' - # NOTE: slapd is supposed to be stopped while in preStart, - # hence slap* commands can safely be used. - umask 0077 - ${pkgs.openldap}/bin/slapadd -n 0 \ - -F "${openldap.configDir}" \ - -l ${slapdConfig} - chown -R "${openldap.user}:${openldap.group}" "${openldap.configDir}" - # NOTE: slapadd(8): To populate the config database slapd-config(5), - # use -n 0 as it is always the first database. - # It must physically exist on the filesystem prior to this, however. - '' + - unlinesAttrs (olcSuffix: {data, ...}: '' - # NOTE: load database ${olcSuffix} - # (as root to avoid depending on sudo or chpst) - ${pkgs.openldap}/bin/slapadd \ - -F "${openldap.configDir}" \ - -l ${pkgs.writeText "data.ldif" data} - '' + '' - # NOTE: redundant with default openldap's preStart, but do not harm. - chown -R "${openldap.user}:${openldap.group}" \ - "${openldap.dataDir}/${olcSuffix}" - '') slapdDatabases; - }; - }; - - client1 = mkClient true; # use nss_pam_ldapd - client2 = mkClient false; # use nss_ldap and pam_ldap - }; - - testScript = '' - def expect_script(*commands): - script = ";".join(commands) - return f"${pkgs.expect}/bin/expect -c '{script}'" - - - server.start() - server.wait_for_unit("default.target") - - with subtest("slapd: auth as database admin with SASL and check a POSIX account"): - server.succeed( - 'test "$(ldapsearch -LLL -H ldapi:// -Y EXTERNAL ' - + "-b 'uid=${ldapUser},ou=accounts,ou=posix,${dbSuffix}' " - + "-s base uidNumber | " - + "sed -ne 's/^uidNumber: \\(.*\\)/\\1/p')\" -eq ${toString ldapUserId}" - ) - - with subtest("slapd: auth as database admin with password and check a POSIX account"): - server.succeed( - "test \"$(ldapsearch -LLL -H ldap://server -D 'cn=admin,${dbSuffix}' " - + "-w '${dbAdminPwd}' -b 'uid=${ldapUser},ou=accounts,ou=posix,${dbSuffix}' " - + "-s base uidNumber | " - + "sed -ne 's/^uidNumber: \\(.*\\)/\\1/p')\" -eq ${toString ldapUserId}" - ) - - client1.start() - client1.wait_for_unit("default.target") - - with subtest("password: su with password to a POSIX account"): - client1.succeed( - expect_script( - 'spawn su "${ldapUser}"', - 'expect "Password:"', - 'send "${ldapUserPwd}\n"', - 'expect "*"', - 'send "whoami\n"', - 'expect -ex "${ldapUser}" {exit}', - "exit 1", - ) - ) - - with subtest("password: change password of a POSIX account as root"): - client1.succeed( - "chpasswd <<<'${ldapUser}:new-password'", - expect_script( - 'spawn su "${ldapUser}"', - 'expect "Password:"', - 'send "new-password\n"', - 'expect "*"', - 'send "whoami\n"', - 'expect -ex "${ldapUser}" {exit}', - "exit 1", - ), - "chpasswd <<<'${ldapUser}:${ldapUserPwd}'", - ) - - with subtest("password: change password of a POSIX account from itself"): - client1.succeed( - "chpasswd <<<'${ldapUser}:${ldapUserPwd}' ", - expect_script( - "spawn su --login ${ldapUser} -c passwd", - 'expect "Password: "', - 'send "${ldapUserPwd}\n"', - 'expect "(current) UNIX password: "', - 'send "${ldapUserPwd}\n"', - 'expect "New password: "', - 'send "new-password\n"', - 'expect "Retype new password: "', - 'send "new-password\n"', - 'expect "passwd: password updated successfully" {exit}', - "exit 1", - ), - expect_script( - 'spawn su "${ldapUser}"', - 'expect "Password:"', - 'send "${ldapUserPwd}\n"', - 'expect "su: Authentication failure" {exit}', - "exit 1", - ), - expect_script( - 'spawn su "${ldapUser}"', - 'expect "Password:"', - 'send "new-password\n"', - 'expect "*"', - 'send "whoami\n"', - 'expect -ex "${ldapUser}" {exit}', - "exit 1", - ), - "chpasswd <<<'${ldapUser}:${ldapUserPwd}'", - ) - - client2.start() - client2.wait_for_unit("default.target") - - with subtest("NSS"): - client1.succeed( - "test \"$(id -u '${ldapUser}')\" -eq ${toString ldapUserId}", - "test \"$(id -u -n '${ldapUser}')\" = '${ldapUser}'", - "test \"$(id -g '${ldapUser}')\" -eq ${toString ldapGroupId}", - "test \"$(id -g -n '${ldapUser}')\" = '${ldapGroup}'", - "test \"$(id -u '${ldapUser}')\" -eq ${toString ldapUserId}", - "test \"$(id -u -n '${ldapUser}')\" = '${ldapUser}'", - "test \"$(id -g '${ldapUser}')\" -eq ${toString ldapGroupId}", - "test \"$(id -g -n '${ldapUser}')\" = '${ldapGroup}'", - ) - - with subtest("PAM"): - client1.succeed( - "echo ${ldapUserPwd} | su -l '${ldapUser}' -c true", - "echo ${ldapUserPwd} | su -l '${ldapUser}' -c true", - ) - ''; -}) -- cgit 1.4.1