]> Git — Sourcephile - sourcephile-nix.git/blob - install/logical/friot/openldap.nix
openldap: support multiple databases.
[sourcephile-nix.git] / install / logical / friot / openldap.nix
1 {pkgs, lib, config, ...}:
2 let inherit (builtins) baseNameOf readFile;
3 inherit (lib) types;
4 inherit (config.services) openldap;
5 inherit (config.users) ldap;
6 unlines = lib.concatStringsSep "\n";
7 copyFile = file: pkgs.writeText (baseNameOf file) (readFile file);
8 configLDIF = pkgs.writeText "cn=config.ldif" (''
9 dn: cn=config
10 objectClass: olcGlobal
11 #olcPidFile: /run/slapd/slapd.pid
12 # List of arguments that were passed to the server
13 #olcArgsFile: /run/slapd/slapd.args
14 # Read slapd-config(5) for possible values
15 olcLogLevel: none
16 # The tool-threads parameter sets the actual amount of cpu's
17 # that is used for indexing.
18 olcToolThreads: 1
19
20 dn: olcDatabase={-1}frontend,cn=config
21 objectClass: olcDatabaseConfig
22 objectClass: olcFrontendConfig
23 # The maximum number of entries that is returned for a search operation
24 olcSizeLimit: 500
25 # Allow unlimited access to local connection from the local root user
26 olcAccess: to *
27 by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage
28 by * break
29 # Allow unauthenticated read access for schema and base DN autodiscovery
30 olcAccess: to dn.exact=""
31 by * read
32 olcAccess: to dn.base="cn=Subschema"
33 by * read
34
35 dn: olcDatabase=config,cn=config
36 objectClass: olcDatabaseConfig
37 olcRootDN: cn=admin,cn=config
38 # Access to cn=config, system root can be manager
39 # with SASL mechanism (-Y EXTERNAL) over unix socket (-H ldapi://)
40 olcAccess: to *
41 by dn.exact="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" manage
42 by * break
43
44 dn: cn=schema,cn=config
45 objectClass: olcSchemaConfig
46
47 include: file://${pkgs.openldap}/etc/schema/core.ldif
48 include: file://${pkgs.openldap}/etc/schema/cosine.ldif
49 include: file://${pkgs.openldap}/etc/schema/nis.ldif
50 include: file://${pkgs.openldap}/etc/schema/inetorgperson.ldif
51 include: file://${copyFile openldap/schema/postfix-book.ldif}
52 include: file://${copyFile openldap/schema/postfix2.ldif}
53
54 dn: cn=module{0},cn=config
55 objectClass: olcModuleList
56 # Where the dynamically loaded modules are stored
57 #olcModulePath: /usr/lib/ldap
58 olcModuleLoad: back_mdb
59
60 '' + unlines (lib.mapAttrsToList (olcSuffix: {conf, olcDbDirectory, ...}:
61 "include: file://" + pkgs.writeText "config.ldif" (conf + ''
62 olcSuffix: ${olcSuffix}
63 olcDbDirectory: ${olcDbDirectory}
64 '')
65 ) openldap.databases));
66 in
67 {
68 imports = [
69 openldap/commonsoft.coop.nix
70 ];
71 options.services.openldap.domainSuffix = lib.mkOption {
72 type = types.str;
73 default = "dc=${lib.concatStringsSep ",dc=" (lib.splitString "." config.networking.domain)}";
74 description = ''
75 LDAP suffix for config.networking.domain.
76 '';
77 };
78 options.services.openldap.databases = lib.mkOption {
79 type = types.attrsOf (types.submodule ({name, options, config, ...}: {
80 options = {
81 conf = lib.mkOption {
82 type = types.lines;
83 description = "The database's config in LDIF.";
84 };
85 data = lib.mkOption {
86 type = types.lines;
87 description = "The database's data in LDIF.";
88 };
89 olcDbDirectory = lib.mkOption {
90 type = types.str;
91 description = "The directory where the database is stored.";
92 default = "${openldap.dataDir}/${name}";
93 };
94 resetData = lib.mkOption {
95 type = types.bool;
96 description = "Whether to reset the data at each start of the slapd service.";
97 default = false;
98 };
99 };
100 }));
101 };
102 config = {
103 users.ldap = {
104 enable = true;
105 # FIXME: even with the correct LD_LIBRARY_PATH to libnss_ldap.so,
106 # passwd still does not work on LDAP accounts.
107 daemon = {
108 enable = true;
109 extraConfig = ''
110 sasl_mech EXTERNAL
111 '';
112 };
113 server = "ldapi:///";
114 base = "ou=posix,${openldap.domainSuffix}";
115 bind = {
116 #distinguishedName = "cn=admin,${openldap.domainSuffix}";
117 };
118 };
119 services.openldap = {
120 enable = true;
121 dataDir = "/var/db/ldap";
122 configDir = "/var/db/slapd";
123 urlList = [ "ldapi:///" ]; # UNIX socket
124 };
125 systemd.services.openldap = {
126 preStart = ''
127 # NOTE: slapd's config is always re-initialized.
128 rm -rf "${openldap.configDir}"/cn=config \
129 "${openldap.configDir}"/cn=config.ldif
130 install -D -d -m 0700 -o "${openldap.user}" -g "${openldap.group}" "${openldap.configDir}"
131 # NOTE: olcDbDirectory must be created before adding the config.
132 '' + unlines (lib.mapAttrsToList (olcSuffix: {data, olcDbDirectory, resetData, ...}:
133 lib.optionalString resetData ''
134 rm -rf "${olcDbDirectory}"
135 '' + ''
136 install -D -d -m 0700 -o "${openldap.user}" -g "${openldap.group}" "${olcDbDirectory}"
137 '') openldap.databases
138 ) + ''
139 # NOTE: slapd is supposed to be stopped while in preStart,
140 # hence slap* commands can safely be used.
141 umask 0077
142 ${pkgs.openldap}/bin/slapadd -n 0 \
143 -F "${openldap.configDir}" \
144 -l ${configLDIF}
145 chown -R "${openldap.user}:${openldap.group}" "${openldap.configDir}"
146 # NOTE: slapadd(8): To populate the config database slapd-config(5),
147 # use -n 0 as it is always the first database.
148 # It must physically exist on the filesystem prior to this, however.
149 '' +
150 unlines (lib.mapAttrsToList (olcSuffix: {data, olcDbDirectory, resetData, ...}:
151 lib.optionalString resetData ''
152 ${pkgs.openldap}/bin/slapadd \
153 -F "${openldap.configDir}" \
154 -l ${pkgs.writeText "data.ldif" data}
155 '' + ''
156 test ! -e "${olcDbDirectory}" ||
157 chown -R "${openldap.user}:${openldap.group}" "${olcDbDirectory}"
158 '') openldap.databases);
159 };
160 };
161 }