Merge pull request #94610 from kwohlfahrt/openldap

This commit is contained in:
Jörg Thalheim 2020-11-21 23:09:40 +01:00 committed by GitHub
commit 258903e725
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 424 additions and 264 deletions

View File

@ -185,6 +185,32 @@
which is the new stable release. OpenAFS 1.6 was removed. which is the new stable release. OpenAFS 1.6 was removed.
</para> </para>
</listitem> </listitem>
<listitem>
<para>
The <literal>openldap</literal> module now has support for OLC-style
configuration, users of the <literal>configDir</literal> option may wish
to migrate. If you continue to use <literal>configDir</literal>, ensure that
<literal>olcPidFile</literal> is set to <literal>/run/slapd/slapd.pid</literal>.
</para>
<para>
As a result, <literal>extraConfig</literal> and <literal>extraDatabaseConfig</literal>
are removed. To help with migration, you can convert your <literal>slapd.conf</literal>
file to OLC configuration with the following script (find the location of this
configuration file by running <literal>systemctl status openldap</literal>, it is the
<literal>-f</literal> option.
</para>
<programlisting>
TMPDIR=$(mktemp -d)
slaptest -f /path/to/slapd.conf $TMPDIR
slapcat -F $TMPDIR -n0 -H 'ldap:///???(!(objectClass=olcSchemaConfig))'
</programlisting>
<para>
This will dump your current configuration in LDIF format, which should be
straightforward to convert into Nix settings. This does not show your schema
configuration, as this is unnecessarily verbose for users of the default schemas
and <literal>slaptest</literal> is buggy with schemas directly in the config file.
</para>
</listitem>
</itemizedlist> </itemizedlist>
</section> </section>

View File

@ -135,7 +135,7 @@ in
#keys = 96; # unused #keys = 96; # unused
#haproxy = 97; # dynamically allocated as of 2020-03-11 #haproxy = 97; # dynamically allocated as of 2020-03-11
mongodb = 98; mongodb = 98;
openldap = 99; #openldap = 99; # dynamically allocated as of PR#94610
#users = 100; # unused #users = 100; # unused
cgminer = 101; cgminer = 101;
munin = 102; munin = 102;
@ -451,7 +451,7 @@ in
keys = 96; keys = 96;
#haproxy = 97; # dynamically allocated as of 2020-03-11 #haproxy = 97; # dynamically allocated as of 2020-03-11
#mongodb = 98; # unused #mongodb = 98; # unused
openldap = 99; #openldap = 99; # dynamically allocated as of PR#94610
munin = 102; munin = 102;
#logcheck = 103; # unused #logcheck = 103; # unused
#nix-ssh = 104; # unused #nix-ssh = 104; # unused

View File

@ -1,43 +1,121 @@
{ config, lib, pkgs, ... }: { config, lib, pkgs, ... }:
with lib; with lib;
let let
cfg = config.services.openldap; cfg = config.services.openldap;
legacyOptions = [ "rootpwFile" "suffix" "dataDir" "rootdn" "rootpw" ];
openldap = cfg.package; openldap = cfg.package;
configDir = if cfg.configDir != null then cfg.configDir else "/etc/openldap/slapd.d";
dataFile = pkgs.writeText "ldap-contents.ldif" cfg.declarativeContents; ldapValueType = let
configFile = pkgs.writeText "slapd.conf" ((optionalString cfg.defaultSchemas '' # Can't do types.either with multiple non-overlapping submodules, so define our own
include ${openldap.out}/etc/schema/core.schema singleLdapValueType = lib.mkOptionType rec {
include ${openldap.out}/etc/schema/cosine.schema name = "LDAP";
include ${openldap.out}/etc/schema/inetorgperson.schema description = "LDAP value";
include ${openldap.out}/etc/schema/nis.schema check = x: lib.isString x || (lib.isAttrs x && (x ? path || x ? base64));
'') + '' merge = lib.mergeEqualOption;
${cfg.extraConfig} };
database ${cfg.database} # We don't coerce to lists of single values, as some values must be unique
suffix ${cfg.suffix} in types.either singleLdapValueType (types.listOf singleLdapValueType);
rootdn ${cfg.rootdn}
${if (cfg.rootpw != null) then ''
rootpw ${cfg.rootpw}
'' else ''
include ${cfg.rootpwFile}
''}
directory ${cfg.dataDir}
${cfg.extraDatabaseConfig}
'');
configOpts = if cfg.configDir == null then "-f ${configFile}"
else "-F ${cfg.configDir}";
in
{ ldapAttrsType =
let
options = {
attrs = mkOption {
type = types.attrsOf ldapValueType;
default = {};
description = "Attributes of the parent entry.";
};
children = mkOption {
# Hide the child attributes, to avoid infinite recursion in e.g. documentation
# Actual Nix evaluation is lazy, so this is not an issue there
type = let
hiddenOptions = lib.mapAttrs (name: attr: attr // { visible = false; }) options;
in types.attrsOf (types.submodule { options = hiddenOptions; });
default = {};
description = "Child entries of the current entry, with recursively the same structure.";
example = lib.literalExample ''
{
"cn=schema" = {
# The attribute used in the DN must be defined
attrs = { cn = "schema"; };
children = {
# This entry's DN is expanded to "cn=foo,cn=schema"
"cn=foo" = { ... };
};
# These includes are inserted after "cn=schema", but before "cn=foo,cn=schema"
includes = [ ... ];
};
}
'';
};
includes = mkOption {
type = types.listOf types.path;
default = [];
description = ''
LDIF files to include after the parent's attributes but before its children.
'';
};
};
in types.submodule { inherit options; };
###### interface valueToLdif = attr: values: let
listValues = if lib.isList values then values else lib.singleton values;
in map (value:
if lib.isAttrs value then
if lib.hasAttr "path" value
then "${attr}:< file://${value.path}"
else "${attr}:: ${value.base64}"
else "${attr}: ${lib.replaceStrings [ "\n" ] [ "\n " ] value}"
) listValues;
attrsToLdif = dn: { attrs, children, includes, ... }: [''
dn: ${dn}
${lib.concatStringsSep "\n" (lib.flatten (lib.mapAttrsToList valueToLdif attrs))}
''] ++ (map (path: "include: file://${path}\n") includes) ++ (
lib.flatten (lib.mapAttrsToList (name: value: attrsToLdif "${name},${dn}" value) children)
);
in {
imports = let
deprecationNote = "This option is removed due to the deprecation of `slapd.conf` upstream. Please migrate to `services.openldap.settings`, see the release notes for advice with this process.";
mkDatabaseOption = old: new:
lib.mkChangedOptionModule [ "services" "openldap" old ] [ "services" "openldap" "settings" "children" ]
(config: let
database = lib.getAttrFromPath [ "services" "openldap" "database" ] config;
value = lib.getAttrFromPath [ "services" "openldap" old ] config;
in lib.setAttrByPath ([ "olcDatabase={1}${database}" "attrs" ] ++ new) value);
in [
(lib.mkRemovedOptionModule [ "services" "openldap" "extraConfig" ] deprecationNote)
(lib.mkRemovedOptionModule [ "services" "openldap" "extraDatabaseConfig" ] deprecationNote)
(lib.mkChangedOptionModule [ "services" "openldap" "logLevel" ] [ "services" "openldap" "settings" "attrs" "olcLogLevel" ]
(config: lib.splitString " " (lib.getAttrFromPath [ "services" "openldap" "logLevel" ] config)))
(lib.mkChangedOptionModule [ "services" "openldap" "defaultSchemas" ] [ "services" "openldap" "settings" "children" "cn=schema" "includes"]
(config: lib.optionals (lib.getAttrFromPath [ "services" "openldap" "defaultSchemas" ] config) (
map (schema: "${openldap}/etc/schema/${schema}.ldif") [ "core" "cosine" "inetorgperson" "nis" ])))
(lib.mkChangedOptionModule [ "services" "openldap" "database" ] [ "services" "openldap" "settings" "children" ]
(config: let
database = lib.getAttrFromPath [ "services" "openldap" "database" ] config;
in {
"olcDatabase={1}${database}".attrs = {
# objectClass is case-insensitive, so don't need to capitalize ${database}
objectClass = [ "olcdatabaseconfig" "olc${database}config" ];
olcDatabase = "{1}${database}";
olcDbDirectory = lib.mkDefault "/var/db/openldap";
};
"cn=schema".includes = lib.mkDefault (
map (schema: "${openldap}/etc/schema/${schema}.ldif") [ "core" "cosine" "inetorgperson" "nis" ]
);
}))
(mkDatabaseOption "rootpwFile" [ "olcRootPW" "path" ])
(mkDatabaseOption "suffix" [ "olcSuffix" ])
(mkDatabaseOption "dataDir" [ "olcDbDirectory" ])
(mkDatabaseOption "rootdn" [ "olcRootDN" ])
(mkDatabaseOption "rootpw" [ "olcRootPW" ])
];
options = { options = {
services.openldap = { services.openldap = {
enable = mkOption { enable = mkOption {
type = types.bool; type = types.bool;
default = false; default = false;
@ -77,224 +155,170 @@ in
example = [ "ldaps:///" ]; example = [ "ldaps:///" ];
}; };
dataDir = mkOption { settings = mkOption {
type = types.path; type = ldapAttrsType;
default = "/var/db/openldap"; description = "Configuration for OpenLDAP, in OLC format";
description = "The database directory."; example = lib.literalExample ''
}; {
attrs.olcLogLevel = [ "stats" ];
defaultSchemas = mkOption { children = {
type = types.bool; "cn=schema".includes = [
default = true; "\${pkgs.openldap}/etc/schema/core.ldif"
description = '' "\${pkgs.openldap}/etc/schema/cosine.ldif"
Include the default schemas core, cosine, inetorgperson and nis. "\${pkgs.openldap}/etc/schema/inetorgperson.ldif"
This setting will be ignored if configDir is set. ];
"olcDatabase={-1}frontend" = {
attrs = {
objectClass = "olcDatabaseConfig";
olcDatabase = "{-1}frontend";
olcAccess = [ "{0}to * by dn.exact=uidNumber=0+gidNumber=0,cn=peercred,cn=external,cn=auth manage stop by * none stop" ];
};
};
"olcDatabase={0}config" = {
attrs = {
objectClass = "olcDatabaseConfig";
olcDatabase = "{0}config";
olcAccess = [ "{0}to * by * none break" ];
};
};
"olcDatabase={1}mdb" = {
attrs = {
objectClass = [ "olcDatabaseConfig" "olcMdbConfig" ];
olcDatabase = "{1}mdb";
olcDbDirectory = "/var/db/ldap";
olcDbIndex = [
"objectClass eq"
"cn pres,eq"
"uid pres,eq"
"sn pres,eq,subany"
];
olcSuffix = "dc=example,dc=com";
olcAccess = [ "{0}to * by * read break" ];
};
};
};
};
''; '';
}; };
database = mkOption { # This option overrides settings
type = types.str;
default = "mdb";
description = ''
Database type to use for the LDAP.
This setting will be ignored if configDir is set.
'';
};
suffix = mkOption {
type = types.str;
example = "dc=example,dc=org";
description = ''
Specify the DN suffix of queries that will be passed to this backend
database.
This setting will be ignored if configDir is set.
'';
};
rootdn = mkOption {
type = types.str;
example = "cn=admin,dc=example,dc=org";
description = ''
Specify the distinguished name that is not subject to access control
or administrative limit restrictions for operations on this database.
This setting will be ignored if configDir is set.
'';
};
rootpw = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Password for the root user.
This setting will be ignored if configDir is set.
Using this option will store the root password in plain text in the
world-readable nix store. To avoid this the <literal>rootpwFile</literal> can be used.
'';
};
rootpwFile = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
Password file for the root user.
The file should contain the string <literal>rootpw</literal> followed by the password.
e.g.: <literal>rootpw mysecurepassword</literal>
'';
};
logLevel = mkOption {
type = types.str;
default = "0";
example = "acl trace";
description = "The log level selector of slapd.";
};
configDir = mkOption { configDir = mkOption {
type = types.nullOr types.path; type = types.nullOr types.path;
default = null; default = null;
description = "Use this optional config directory instead of using slapd.conf"; description = ''
Use this config directory instead of generating one from the
<literal>settings</literal> option. Overrides all NixOS settings. If
you use this option,ensure `olcPidFile` is set to `/run/slapd/slapd.conf`.
'';
example = "/var/db/slapd.d"; example = "/var/db/slapd.d";
}; };
extraConfig = mkOption {
type = types.lines;
default = "";
description = "
slapd.conf configuration
";
example = literalExample ''
'''
include ${openldap.out}/etc/schema/core.schema
include ${openldap.out}/etc/schema/cosine.schema
include ${openldap.out}/etc/schema/inetorgperson.schema
include ${openldap.out}/etc/schema/nis.schema
database bdb
suffix dc=example,dc=org
rootdn cn=admin,dc=example,dc=org
# NOTE: change after first start
rootpw secret
directory /var/db/openldap
'''
'';
};
declarativeContents = mkOption { declarativeContents = mkOption {
type = with types; nullOr lines; type = with types; attrsOf lines;
default = null; default = {};
description = '' description = ''
Declarative contents for the LDAP database, in LDIF format. Declarative contents for the LDAP database, in LDIF format by suffix.
Note a few facts when using it. First, the database All data will be erased when starting the LDAP server. Modifications
<emphasis>must</emphasis> be stored in the directory defined by to the database are not prevented, they are just dropped on the next
<code>dataDir</code>. Second, all <code>dataDir</code> will be erased reboot of the server. Performance-wise the database and indexes are
when starting the LDAP server. Third, modifications to the database rebuilt on each server startup, so this will slow down server startup,
are not prevented, they are just dropped on the next reboot of the
server. Finally, performance-wise the database and indexes are rebuilt
on each server startup, so this will slow down server startup,
especially with large databases. especially with large databases.
''; '';
example = '' example = lib.literalExample ''
dn: dc=example,dc=org {
objectClass: domain "dc=example,dc=org" = '''
dc: example dn= dn: dc=example,dc=org
objectClass: domain
dc: example
dn: ou=users,dc=example,dc=org dn: ou=users,dc=example,dc=org
objectClass = organizationalUnit objectClass = organizationalUnit
ou: users ou: users
# ... # ...
''';
}
''; '';
}; };
extraDatabaseConfig = mkOption {
type = types.lines;
default = "";
description = ''
slapd.conf configuration after the database option.
This setting will be ignored if configDir is set.
'';
example = ''
# Indices to maintain for this directory
# unique id so equality match only
index uid eq
# allows general searching on commonname, givenname and email
index cn,gn,mail eq,sub
# allows multiple variants on surname searching
index sn eq,sub
# sub above includes subintial,subany,subfinal
# optimise department searches
index ou eq
# if searches will include objectClass uncomment following
# index objectClass eq
# shows use of default index parameter
index default eq,sub
# indices missing - uses default eq,sub
index telephonenumber
# other database parameters
# read more in slapd.conf reference section
cachesize 10000
checkpoint 128 15
'';
};
}; };
}; };
meta = { meta.maintainers = with lib.maintainters; [ mic92 kwohlfahrt ];
maintainers = [ lib.maintainers.mic92 ];
};
###### implementation
config = mkIf cfg.enable { config = mkIf cfg.enable {
assertions = [ assertions = map (opt: {
{ assertion = ((getAttr opt cfg) != "_mkMergedOptionModule") -> (cfg.database != "_mkMergedOptionModule");
assertion = cfg.configDir != null || cfg.rootpwFile != null || cfg.rootpw != null; message = "Legacy OpenLDAP option `services.openldap.${opt}` requires `services.openldap.database` (use value \"mdb\" if unsure)";
message = "services.openldap: Unless configDir is set, either rootpw or rootpwFile must be set"; }) legacyOptions;
}
];
environment.systemPackages = [ openldap ]; environment.systemPackages = [ openldap ];
# Literal attributes must always be set
services.openldap.settings = {
attrs = {
objectClass = "olcGlobal";
cn = "config";
olcPidFile = "/run/slapd/slapd.pid";
};
children."cn=schema".attrs = {
cn = "schema";
objectClass = "olcSchemaConfig";
};
};
systemd.services.openldap = { systemd.services.openldap = {
description = "LDAP server"; description = "LDAP server";
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
after = [ "network.target" ]; after = [ "network.target" ];
preStart = '' preStart = let
settingsFile = pkgs.writeText "config.ldif" (lib.concatStringsSep "\n" (attrsToLdif "cn=config" cfg.settings));
dbSettings = lib.filterAttrs (name: value: lib.hasPrefix "olcDatabase=" name) cfg.settings.children;
dataDirs = lib.mapAttrs' (name: value: lib.nameValuePair value.attrs.olcSuffix value.attrs.olcDbDirectory)
(lib.filterAttrs (_: value: value.attrs ? olcDbDirectory) dbSettings);
dataFiles = lib.mapAttrs (dn: contents: pkgs.writeText "${dn}.ldif" contents) cfg.declarativeContents;
mkLoadScript = dn: let
dataDir = lib.escapeShellArg (getAttr dn dataDirs);
in ''
rm -rf ${dataDir}/*
${openldap}/bin/slapadd -F ${lib.escapeShellArg configDir} -b ${dn} -l ${getAttr dn dataFiles}
chown -R "${cfg.user}:${cfg.group}" ${dataDir}
'';
in ''
mkdir -p /run/slapd mkdir -p /run/slapd
chown -R "${cfg.user}:${cfg.group}" /run/slapd chown -R "${cfg.user}:${cfg.group}" /run/slapd
${optionalString (cfg.declarativeContents != null) ''
rm -Rf "${cfg.dataDir}"
''}
mkdir -p "${cfg.dataDir}"
${optionalString (cfg.declarativeContents != null) ''
${openldap.out}/bin/slapadd ${configOpts} -l ${dataFile}
''}
chown -R "${cfg.user}:${cfg.group}" "${cfg.dataDir}"
${openldap}/bin/slaptest ${configOpts} mkdir -p ${lib.escapeShellArg configDir} ${lib.escapeShellArgs (lib.attrValues dataDirs)}
chown "${cfg.user}:${cfg.group}" ${lib.escapeShellArg configDir} ${lib.escapeShellArgs (lib.attrValues dataDirs)}
${lib.optionalString (cfg.configDir == null) (''
rm -Rf ${configDir}/*
${openldap}/bin/slapadd -F ${configDir} -bcn=config -l ${settingsFile}
'')}
chown -R "${cfg.user}:${cfg.group}" ${lib.escapeShellArg configDir}
${lib.concatStrings (map mkLoadScript (lib.attrNames cfg.declarativeContents))}
${openldap}/bin/slaptest -u -F ${lib.escapeShellArg configDir}
''; '';
serviceConfig.ExecStart = serviceConfig = {
"${openldap.out}/libexec/slapd -d '${cfg.logLevel}' " + ExecStart = lib.escapeShellArgs ([
"-u '${cfg.user}' -g '${cfg.group}' " + "${openldap}/libexec/slapd" "-u" cfg.user "-g" cfg.group "-F" configDir
"-h '${concatStringsSep " " cfg.urlList}' " + "-h" (lib.concatStringsSep " " cfg.urlList)
"${configOpts}"; ]);
Type = "forking";
PIDFile = cfg.settings.attrs.olcPidFile;
};
}; };
users.users.openldap = users.users = lib.optionalAttrs (cfg.user == "openldap") {
{ name = cfg.user; openldap = {
group = cfg.group; group = cfg.group;
uid = config.ids.uids.openldap; isSystemUser = true;
};
users.groups.openldap =
{ name = cfg.group;
gid = config.ids.gids.openldap;
}; };
};
users.groups = lib.optionalAttrs (cfg.group == "openldap") {
openldap = {};
};
}; };
} }

View File

@ -1,33 +1,125 @@
import ./make-test-python.nix { { pkgs, system ? builtins.currentSystem, ... }: let
name = "openldap"; dbContents = ''
dn: dc=example
machine = { pkgs, ... }: { objectClass: domain
services.openldap = { dc: example
enable = true;
suffix = "dc=example";
rootdn = "cn=root,dc=example";
rootpw = "notapassword";
database = "bdb";
extraDatabaseConfig = ''
directory /var/db/openldap
'';
declarativeContents = ''
dn: dc=example
objectClass: domain
dc: example
dn: ou=users,dc=example
objectClass: organizationalUnit
ou: users
'';
};
};
dn: ou=users,dc=example
objectClass: organizationalUnit
ou: users
'';
testScript = '' testScript = ''
machine.wait_for_unit("openldap.service") machine.wait_for_unit("openldap.service")
machine.succeed( machine.succeed(
"systemctl status openldap.service",
'ldapsearch -LLL -D "cn=root,dc=example" -w notapassword -b "dc=example"', 'ldapsearch -LLL -D "cn=root,dc=example" -w notapassword -b "dc=example"',
) )
''; '';
in {
# New-style configuration
current = import ./make-test-python.nix {
inherit testScript;
name = "openldap";
machine = { pkgs, ... }: {
environment.etc."openldap/root_password".text = "notapassword";
services.openldap = {
enable = true;
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"
];
"olcDatabase={1}mdb" = {
# This tests string, base64 and path values, as well as lists of string values
attrs = {
objectClass = [ "olcDatabaseConfig" "olcMdbConfig" ];
olcDatabase = "{1}mdb";
olcDbDirectory = "/var/db/openldap";
olcSuffix = "dc=example";
olcRootDN = {
# cn=root,dc=example
base64 = "Y249cm9vdCxkYz1leGFtcGxl";
};
olcRootPW = {
path = "/etc/openldap/root_password";
};
};
};
};
};
declarativeContents."dc=example" = dbContents;
};
};
};
# Old-style configuration
oldOptions = import ./make-test-python.nix {
inherit testScript;
name = "openldap";
machine = { pkgs, ... }: {
services.openldap = {
enable = true;
logLevel = "stats acl";
defaultSchemas = true;
database = "mdb";
suffix = "dc=example";
rootdn = "cn=root,dc=example";
rootpw = "notapassword";
declarativeContents."dc=example" = dbContents;
};
};
};
# Manually managed configDir, for example if dynamic config is essential
manualConfigDir = import ./make-test-python.nix {
name = "openldap";
machine = { pkgs, ... }: {
services.openldap = {
enable = true;
configDir = "/var/db/slapd.d";
};
};
testScript = let
contents = pkgs.writeText "data.ldif" dbContents;
config = pkgs.writeText "config.ldif" ''
dn: cn=config
cn: config
objectClass: olcGlobal
olcLogLevel: stats
olcPidFile: /run/slapd/slapd.pid
dn: cn=schema,cn=config
cn: schema
objectClass: olcSchemaConfig
include: file://${pkgs.openldap}/etc/schema/core.ldif
include: file://${pkgs.openldap}/etc/schema/cosine.ldif
include: file://${pkgs.openldap}/etc/schema/inetorgperson.ldif
dn: olcDatabase={1}mdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcMdbConfig
olcDatabase: {1}mdb
olcDbDirectory: /var/db/openldap
olcDbIndex: objectClass eq
olcSuffix: dc=example
olcRootDN: cn=root,dc=example
olcRootPW: notapassword
'';
in ''
machine.succeed(
"mkdir -p /var/db/slapd.d /var/db/openldap",
"slapadd -F /var/db/slapd.d -n0 -l ${config}",
"slapadd -F /var/db/slapd.d -n1 -l ${contents}",
"chown -R openldap:openldap /var/db/slapd.d /var/db/openldap",
"systemctl restart openldap",
)
'' + testScript;
};
} }

View File

@ -1,4 +1,4 @@
import ./make-test-python.nix ({ pkgs, ... }: ({ pkgs, ... }:
let let
dbDomain = "example.org"; dbDomain = "example.org";
dbSuffix = "dc=example,dc=org"; dbSuffix = "dc=example,dc=org";
@ -7,8 +7,7 @@ import ./make-test-python.nix ({ pkgs, ... }:
ldapRootPassword = "foobar"; ldapRootPassword = "foobar";
testUser = "alice"; testUser = "alice";
in in import ./make-test-python.nix {
{
name = "sssd-ldap"; name = "sssd-ldap";
meta = with pkgs.stdenv.lib.maintainers; { meta = with pkgs.stdenv.lib.maintainers; {
@ -18,34 +17,53 @@ import ./make-test-python.nix ({ pkgs, ... }:
machine = { pkgs, ... }: { machine = { pkgs, ... }: {
services.openldap = { services.openldap = {
enable = true; enable = true;
rootdn = "cn=${ldapRootUser},${dbSuffix}"; settings = {
rootpw = ldapRootPassword; children = {
suffix = dbSuffix; "cn=schema".includes = [
declarativeContents = '' "${pkgs.openldap}/etc/schema/core.ldif"
dn: ${dbSuffix} "${pkgs.openldap}/etc/schema/cosine.ldif"
objectClass: top "${pkgs.openldap}/etc/schema/inetorgperson.ldif"
objectClass: dcObject "${pkgs.openldap}/etc/schema/nis.ldif"
objectClass: organization ];
o: ${dbDomain} "olcDatabase={1}mdb" = {
attrs = {
objectClass = [ "olcDatabaseConfig" "olcMdbConfig" ];
olcDatabase = "{1}mdb";
olcDbDirectory = "/var/db/openldap";
olcSuffix = dbSuffix;
olcRootDN = "cn=${ldapRootUser},${dbSuffix}";
olcRootPW = ldapRootPassword;
};
};
};
};
declarativeContents = {
${dbSuffix} = ''
dn: ${dbSuffix}
objectClass: top
objectClass: dcObject
objectClass: organization
o: ${dbDomain}
dn: ou=posix,${dbSuffix} dn: ou=posix,${dbSuffix}
objectClass: top objectClass: top
objectClass: organizationalUnit objectClass: organizationalUnit
dn: ou=accounts,ou=posix,${dbSuffix} dn: ou=accounts,ou=posix,${dbSuffix}
objectClass: top objectClass: top
objectClass: organizationalUnit objectClass: organizationalUnit
dn: uid=${testUser},ou=accounts,ou=posix,${dbSuffix} dn: uid=${testUser},ou=accounts,ou=posix,${dbSuffix}
objectClass: person objectClass: person
objectClass: posixAccount objectClass: posixAccount
# userPassword: somePasswordHash # userPassword: somePasswordHash
homeDirectory: /home/${testUser} homeDirectory: /home/${testUser}
uidNumber: 1234 uidNumber: 1234
gidNumber: 1234 gidNumber: 1234
cn: "" cn: ""
sn: "" sn: ""
''; '';
};
}; };
services.sssd = { services.sssd = {