{ 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);
+let
+ inherit (builtins) baseNameOf readFile;
+ inherit (lib) types;
+ inherit (config.services) openldap;
+ inherit (config.users) ldap;
+ unlines = lib.concatStringsSep "\n";
+ unlinesAttrs = f: as: unlines (lib.mapAttrsToList f as);
in
{
options = {
- services.openldap.domainSuffix = lib.mkOption {
- type = types.str;
- default = "dc=${lib.concatStringsSep ",dc=" (lib.splitString "." config.networking.domain)}";
- description = ''LDAP suffix for config.networking.domain.'';
- };
- services.openldap.initConfig = lib.mkOption {
- type = types.lines;
- description = "The databases' initial config in LDIF.";
- apply = lines: pkgs.writeText "cn=config.ldif.nix"
- (lines + "\n" + unlinesAttrs (olcSuffix: {conf, olcDbDirectory, ...}:
- "include: file://" + pkgs.writeText "config.ldif" (conf + ''
- olcSuffix: ${olcSuffix}
- olcDbDirectory: ${olcDbDirectory}
- '')
- ) openldap.databases);
- 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
+services.openldap.cnConfig = lib.mkOption {
+ type = types.lines;
+ description = "The cn=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);
+ default = ''
+ dn: cn=config
+ objectClass: olcGlobal
+ olcLogLevel: none
+ 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: cn={0}module,cn=config
+ objectClass: olcModuleList
+ olcModulePath: ${pkgs.openldap}/lib/modules
+ #olcModuleLoad: pw-sha2
+ #olcModuleLoad: pw-pbkdf2
+ olcModuleLoad: back_mdb
- 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: olcDatabase={-1}frontend,cn=config
+ objectClass: olcDatabaseConfig
+ objectClass: olcFrontendConfig
+ 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
+ # Hash algorithm to be used by LDAP Password Modify Extended Operation or the ppolicy overlay
+ #olcPasswordHash: {PBKDF2-SHA256}
+ olcPasswordHash: {SSHA}
- dn: cn=schema,cn=config
- objectClass: olcSchemaConfig
+ dn: olcDatabase={0}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
- 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=schema,cn=config
+ objectClass: olcSchemaConfig
- 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;
- };
+ 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
+ '';
+};
+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.nullOr 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}";
+ };
+ };
+ }));
+};
};
-config = {
- 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;
- };
+config = lib.mkIf openldap.enable {
+systemd.services.openldap.preStart =
+ # olcDbDirectory must be created before adding the config.
+ ''
+ set -e
+ install -D -d -m 0700 -o "${openldap.user}" -g "${openldap.group}" "${openldap.configDir}"
+ '' +
+ unlinesAttrs (olcSuffix: {data, olcDbDirectory, ...}: lib.optionalString (data != null) ''
+ rm -rf "${olcDbDirectory}"
+ install -D -d -m 0700 -o "${openldap.user}" -g "${openldap.group}" "${olcDbDirectory}"
+ '') openldap.databases
+ # slapd is supposed to have been stopped by systemd
+ # before entering this preStart,
+ # hence slap* commands can safely be used.
+ #
+ # 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
+ rm -rf "${openldap.configDir}"/cn=config \
+ "${openldap.configDir}"/cn=config.ldif
+ ${pkgs.openldap}/bin/slapadd -n 0 \
+ -F "${openldap.configDir}" \
+ -l ${openldap.cnConfig}
+ chown -R "${openldap.user}:${openldap.group}" "${openldap.configDir}"
+ '' +
+ unlinesAttrs (olcSuffix: {data, olcDbDirectory, ...}: lib.optionalString (data != null) ''
+ ${pkgs.openldap}/bin/slapadd \
+ -F "${openldap.configDir}" \
+ -b ${olcSuffix} \
+ -l ${pkgs.writeText "data.ldif" data}
+ '' + ''
+ test ! -e "${olcDbDirectory}" ||
+ chown -R "${openldap.user}:${openldap.group}" "${olcDbDirectory}"
+ '') openldap.databases;
};
}