{ pkgs, lib, config, inputs, ... }: with lib; let baseDN = concatMapStringsSep "," (part: "dc=${part}") (splitString "." "informatik.hs-fulda.de"); ldap-sync = let wrapped = pkgs.callPackage inputs.ldap-sync { }; env = pkgs.runCommand "ldap-sync-env" { } '' mkdir -p $out ln -s ${config.sops.secrets."ldap/sync/config".path} $out/ldap-sync.properties ''; in pkgs.runCommand "ldap-sync-wrapper" { nativeBuildInputs = [ pkgs.makeWrapper ]; } '' mkdir -p $out/bin makeWrapper "${wrapped}/bin/ldap-sync" $out/bin/ldap-sync \ --chdir "${env}" ''; in { services.openldap = { enable = true; package = (pkgs.openldap.overrideAttrs (final: prev: { configureFlags = prev.configureFlags ++ [ "--enable-overlays" "--enable-remoteauth" "--enable-spasswd" "--with-cyrus-sasl" ]; doCheck = false; })).override { cyrus_sasl = pkgs.cyrus_sasl.override { enableLdap = true; }; }; urlList = [ "ldap:///" "ldaps:///" ]; settings = { attrs = { olcLogLevel = "config ACL stats stats2 trace"; olcTLSCertificateFile = config.sops.secrets."ldap/tls/crt".path; olcTLSCertificateKeyFile = config.sops.secrets."ldap/tls/key".path; olcTLSCRLCheck = "none"; olcTLSVerifyClient = "never"; olcTLSProtocolMin = "3.1"; olcSaslHost = "localhost"; olcSaslSecProps = "none"; olcSizeLimit = "unlimited"; }; children = { "cn=schema".includes = [ "${config.services.openldap.package}/etc/schema/core.ldif" "${config.services.openldap.package}/etc/schema/cosine.ldif" "${config.services.openldap.package}/etc/schema/inetorgperson.ldif" "${config.services.openldap.package}/etc/schema/nis.ldif" ]; "olcDatabase={1}mdb" = { attrs = { objectClass = [ "olcDatabaseConfig" "olcMdbConfig" ]; olcDatabase = "{1}mdb"; olcDbDirectory = "/var/lib/openldap/db"; olcSuffix = baseDN; olcRootDN = "cn=root,${baseDN}"; olcRootPW.path = config.sops.secrets."ldap/root/password".path; # Increase max DB size to fit all the users olcDbMaxSize = "10737418240"; olcDbIndex = [ "uid,uidNumber pres,eq" "cn,sn pres,eq,sub" "objectClass eq" ]; olcAccess = [ # Custom access rules for userPassword attributes ''{0}to attrs=userPassword by self read by anonymous auth by * none '' # Synced is managed by sync ''{1}to dn.subtree="ou=synced,ou=users,dc=informatik,dc=hs-fulda,dc=de" by dn.base="cn=sync,dc=informatik,dc=hs-fulda,dc=de" manage by * break '' # Allow login to read users ''{2}to dn.subtree="ou=users,dc=informatik,dc=hs-fulda,dc=de" by dn.base="cn=login,dc=informatik,dc=hs-fulda,dc=de" read by self read by * break '' # Prevent access ''{3}to * by * none '' ]; }; children = { "olcOverlay={0}remoteauth" = { attrs = { objectClass = [ "olcOverlayConfig" "olcRemoteAuthCfg" ]; olcOverlay = "{0}remoteauth"; olcRemoteAuthTLS = "starttls=yes tls_cacert=\"/etc/ssl/certs/ca-certificates.crt\""; olcRemoteAuthDNAttribute = "seeAlso"; olcRemoteAuthDomainAttribute = "associatedDomain"; olcRemoteAuthDefaultDomain = "upstream"; olcRemoteAuthDefaultRealm = "file://${config.sops.secrets."ldap/upstream".path}"; olcRemoteAuthRetryCount = "3"; olcRemoteAuthStore = "false"; }; }; }; }; }; }; declarativeContents = { "dc=informatik,dc=hs-fulda,dc=de" = '' dn: dc=informatik,dc=hs-fulda,dc=de objectClass: domain dc: informatik dn: ou=users,dc=informatik,dc=hs-fulda,dc=de objectClass: organizationalUnit ou: users dn: ou=synced,ou=users,dc=informatik,dc=hs-fulda,dc=de objectClass: organizationalUnit ou: users dn: cn=sync,dc=informatik,dc=hs-fulda,dc=de objectClass: applicationProcess objectClass: simpleSecurityObject objectClass: top cn: sync userPassword: {SSHA}Kf5ViggnBdUAPJ3/X5F80Qf/tXOzGI9G dn: cn=login,dc=informatik,dc=hs-fulda,dc=de objectClass: applicationProcess objectClass: simpleSecurityObject objectClass: top cn: login userPassword: {SSHA}esWkdMFThbFD0gSE5tC+jJ1rjwfUuI0p ''; }; }; systemd.services."openldap" = { environment = { SASL_PATH = pkgs.writeTextFile { name = "openldap-sasl-path"; destination = "/slapd.conf"; text = '' pwcheck_method: saslauthd saslauthd_path: /var/run/saslauthd/mux mech_list: GSSAPI EXTERNAL PLAIN NTLM ''; }; }; onSuccess = [ "ldap-sync.service" ]; }; systemd.services."ldap-sync" = { script = "${ldap-sync}/bin/ldap-sync"; startAt = "hourly"; requisite = [ "openldap.service" ]; # Flush caches postStop = '' ${config.services.nscd.package}/bin/nscd --invalidate=group ${config.services.nscd.package}/bin/nscd --invalidate=passwd ''; }; sops.secrets = { "ldap/root/password" = { sopsFile = ./secrets/ldap.yaml; owner = "openldap"; }; "ldap/upstream" = { sopsFile = ./secrets/ldap.yaml; owner = "openldap"; }; "ldap/tls/key" = { sopsFile = ./secrets/ldap.tls.key; format = "binary"; owner = "openldap"; }; "ldap/tls/crt" = { sopsFile = ./secrets/ldap.tls.crt; format = "binary"; owner = "openldap"; }; "ldap/sync/config" = { sopsFile = ./secrets/ldap.yaml; }; }; networking.firewall.allowedTCPPorts = [ 22 389 636 ]; }