{ pkgs, lib, config, ... }: let inherit (builtins) baseNameOf readFile; inherit (lib) types; inherit (pkgs.lib) unlinesAttrs; inherit (config.services) openldap; inherit (config.users) ldap; # FIXME: readFIle ? copyFile = file: pkgs.writeText (baseNameOf file) (readFile file); in { options = { services.openldap.initConfig = lib.mkOption { type = types.lines; description = "The databases' initial config in LDIF."; apply = lines: pkgs.writeText "cn=config.ldif" (lines + "\n" + unlinesAttrs (olcSuffix: {conf, olcDbDirectory, ...}: "include: file://" + pkgs.writeText "config.ldif" (conf + '' olcSuffix: ${olcSuffix} olcDbDirectory: ${olcDbDirectory} '') ) openldap.databases); # sudo ldapsearch -LLL -H ldapi:// -D cn=admin,cn=config -Y EXTERNAL -b "" -s base supportedControl default = '' 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 # 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 include: file://${copyFile openldap/schema/postfix-book.ldif} dn: cn=module{0},cn=config objectClass: olcModuleList # Where the dynamically loaded modules are stored #olcModulePath: /usr/lib/ldap olcModuleLoad: back_mdb ''; }; services.openldap.databases = lib.mkOption { default = {}; type = types.attrsOf (types.submodule ({name, options, config, ...}: { options = { conf = lib.mkOption { type = types.lines; description = "The database's config in LDIF."; }; data = lib.mkOption { type = types.lines; description = "The database's data in LDIF."; }; olcDbDirectory = lib.mkOption { type = types.str; description = "The directory where the database is stored."; default = "${openldap.dataDir}/${name}"; }; resetData = lib.mkOption { type = types.bool; description = "Whether to reset the data at each start of the slapd service."; default = false; }; }; })); }; }; config = lib.mkIf openldap.enable { 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, olcDbDirectory, resetData, ...}: lib.optionalString resetData '' rm -rf "${olcDbDirectory}" '' + '' install -D -d -m 0700 -o "${openldap.user}" -g "${openldap.group}" "${olcDbDirectory}" '') openldap.databases + '' # NOTE: slapd is supposed to have been stopped by systemd # before entering this preStart, # hence slap* commands can safely be used. # # 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. umask 0077 ${pkgs.openldap}/bin/slapadd -n 0 \ -F "${openldap.configDir}" \ -l ${openldap.initConfig} chown -R "${openldap.user}:${openldap.group}" "${openldap.configDir}" '' + unlinesAttrs (olcSuffix: {data, olcDbDirectory, resetData, ...}: lib.optionalString resetData '' ${pkgs.openldap}/bin/slapadd \ -F "${openldap.configDir}" \ -l ${pkgs.writeText "data.ldif" data} '' + '' test ! -e "${olcDbDirectory}" || chown -R "${openldap.user}:${openldap.group}" "${olcDbDirectory}" '') openldap.databases; }; }