nixos/nixosTests.kerberos: add test suite for LDAP backend

Changed files
+201
nixos
tests
pkgs
by-name
op
openldap
+1
nixos/tests/kerberos/default.nix
···
{
mit = import ./mit.nix { inherit system pkgs; };
heimdal = import ./heimdal.nix { inherit system pkgs; };
+
ldap = import ./ldap { inherit system pkgs; };
}
+7
nixos/tests/kerberos/ldap/default.nix
···
+
{
+
system ? builtins.currentSystem,
+
pkgs ? import ../../../.. { inherit system; },
+
}:
+
{
+
mit = import ./mit.nix { inherit system pkgs; };
+
}
+192
nixos/tests/kerberos/ldap/mit.nix
···
+
import ../../make-test-python.nix (
+
{ pkgs, ... }:
+
let
+
DITRoot = "dc=example,dc=com";
+
realm = "EXAMPLE.COM";
+
+
krb5Package = pkgs.krb5.override { withLdap = true; };
+
+
# Password used by Kerberos services to bind to their identities
+
krbSrvPwd = "kerberos_service_password";
+
# Stash file read by Kerberos daemons containing the service password
+
# DO NOT DO THIS IN PRODUCTION! The stash file is a fundamental secret!
+
krbPwdStash = pkgs.runCommand "krb-pwd-stash" { } ''
+
for srv in cn=kadmin,${DITRoot} cn=kdc,${DITRoot}
+
do
+
echo -e "${krbSrvPwd}\n${krbSrvPwd}" | \
+
${krb5Package}/bin/kdb5_ldap_util -r ${realm} stashsrvpw -f $out $srv 2>&1 > /dev/null
+
done
+
'';
+
+
# The LDAP schema for Kerberos 5 objects is part of the source distribution of Kerberos 5
+
krbLdapSchema = pkgs.runCommand "krb-ldap-schema" { } ''
+
tar -Oxf ${krb5Package.src} \
+
${krb5Package.sourceRoot}/plugins/kdb/ldap/libkdb_ldap/kerberos.openldap.ldif > $out
+
'';
+
+
# Initial LDAP tree containing only the Kerberos services
+
ldapDIT = ''
+
dn: ${DITRoot}
+
objectClass: organization
+
objectClass: dcObject
+
dc: example
+
o: Example Company
+
+
dn: cn=kdc,${DITRoot}
+
objectClass: krbKdcService
+
objectClass: simpleSecurityObject
+
cn: kdc
+
userPassword: ${krbSrvPwd}
+
+
dn: cn=kadmin,${DITRoot}
+
objectClass: krbAdmService
+
objectClass: simpleSecurityObject
+
cn: kadmin
+
userPassword: ${krbSrvPwd}
+
'';
+
+
rootDnPwd = "ldap_root_password";
+
in
+
{
+
name = "kerberos_server-mit-ldap";
+
+
nodes.machine =
+
{ pkgs, ... }:
+
{
+
+
services.openldap = {
+
enable = true;
+
urlList = [
+
"ldapi:///"
+
"ldap://"
+
];
+
declarativeContents."${DITRoot}" = ldapDIT;
+
settings = {
+
children = {
+
"cn=schema".includes = [
+
"${pkgs.openldap}/etc/schema/core.ldif"
+
"${pkgs.openldap}/etc/schema/cosine.ldif"
+
"${pkgs.openldap}/etc/schema/inetorgperson.ldif"
+
"${pkgs.openldap}/etc/schema/nis.ldif"
+
"${krbLdapSchema}"
+
];
+
"olcDatabase={0}config" = {
+
attrs = {
+
objectClass = [ "olcDatabaseConfig" ];
+
olcDatabase = "{0}config";
+
};
+
};
+
"olcDatabase={1}mdb" = {
+
attrs = {
+
objectClass = [
+
"olcDatabaseConfig"
+
"olcMdbConfig"
+
];
+
olcDatabase = "{1}mdb";
+
olcDbDirectory = "/var/lib/openldap/db";
+
olcSuffix = DITRoot;
+
olcRootDN = "cn=root,${DITRoot}";
+
olcRootPW = rootDnPwd;
+
# A tiny but realistic ACL
+
olcAccess = [
+
''
+
to attrs=userPassword
+
by anonymous auth
+
by * none''
+
''
+
to dn.subtree="cn=${realm},cn=realms,${DITRoot}"
+
by dn.exact="cn=kdc,${DITRoot}" write
+
by dn.exact="cn=kadmin,${DITRoot}" write
+
by * none''
+
''
+
to *
+
by * read''
+
];
+
};
+
};
+
};
+
};
+
};
+
+
services.kerberos_server = {
+
enable = true;
+
settings = {
+
libdefaults.default_realm = realm;
+
realms = {
+
"${realm}" = {
+
acl = [
+
{
+
principal = "admin";
+
access = "all";
+
}
+
];
+
};
+
};
+
dbmodules = {
+
"${realm}" = {
+
db_library = "kldap";
+
ldap_kerberos_container_dn = "cn=realms,${DITRoot}";
+
ldap_kdc_dn = "cn=kdc,${DITRoot}";
+
ldap_kadmind_dn = "cn=kadmin,${DITRoot}";
+
ldap_service_password_file = toString krbPwdStash;
+
ldap_servers = "ldapi:///";
+
};
+
};
+
};
+
};
+
+
security.krb5 = {
+
enable = true;
+
package = krb5Package;
+
settings = {
+
libdefaults = {
+
default_realm = realm;
+
};
+
realms = {
+
"${realm}" = {
+
admin_server = "machine";
+
kdc = "machine";
+
};
+
};
+
};
+
};
+
+
users.extraUsers.alice = {
+
isNormalUser = true;
+
};
+
};
+
+
testScript = ''
+
machine.wait_for_unit("openldap.service")
+
+
with subtest("realm container initialization"):
+
machine.succeed(
+
# Passing a master key directly avoids the need for a separate master key stash file
+
"kdb5_ldap_util -D cn=root,${DITRoot} create -w ${rootDnPwd} -s -P master_key",
+
)
+
+
# These units are bound to fail, as they are started before the directory service is ready
+
machine.execute("systemctl restart kadmind.service kdc.service")
+
+
with subtest("service bind"):
+
for unit in ["kadmind", "kdc"]:
+
machine.wait_for_unit(f"{unit}.service")
+
+
with subtest("administration principal initialization"):
+
machine.succeed("kadmin.local add_principal -pw admin_pw admin")
+
+
with subtest("user principal creation and kinit"):
+
machine.succeed(
+
"kadmin -p admin -w admin_pw addprinc -pw alice_pw alice",
+
"echo alice_pw | sudo -u alice kinit",
+
)
+
# Make extra sure that the user principal actually exists in the directory
+
machine.succeed(
+
"ldapsearch -x -D cn=root,${DITRoot} -w ${rootDnPwd} \
+
-b ${DITRoot} 'krbPrincipalName=alice@${realm}' | grep 'numEntries: 1'"
+
)
+
'';
+
+
meta.maintainers = [ pkgs.lib.maintainers.nessdoor ];
+
}
+
)
+1
pkgs/by-name/op/openldap/package.nix
···
passthru.tests = {
inherit (nixosTests) openldap;
+
kerberosWithLdap = nixosTests.kerberos.ldap;
};
meta = with lib; {