]> git.immae.eu Git - perso/Immae/Config/Nix.git/blame - modules/private/databases/openldap/default.nix
WIP upgrade
[perso/Immae/Config/Nix.git] / modules / private / databases / openldap / default.nix
CommitLineData
4aac110f 1{ lib, pkgs, config, ... }:
182ae57f
IB
2let
3 cfg = config.myServices.databases.openldap;
182ae57f
IB
4in
5{
6 options.myServices.databases = {
7 openldap = {
8 enable = lib.mkOption {
8415083e 9 default = false;
182ae57f
IB
10 example = true;
11 description = "Whether to enable ldap";
12 type = lib.types.bool;
13 };
4aac110f
IB
14 baseDn = lib.mkOption {
15 type = lib.types.str;
16 description = ''
17 Base DN for LDAP
18 '';
19 };
20 rootDn = lib.mkOption {
21 type = lib.types.str;
22 description = ''
23 Root DN
24 '';
25 };
26 rootPw = lib.mkOption {
27 type = lib.types.str;
28 description = ''
29 Root (Hashed) password
30 '';
31 };
32 accessFile = lib.mkOption {
33 type = lib.types.path;
34 description = ''
35 The file path that defines the access
36 '';
37 };
182ae57f
IB
38 dataDir = lib.mkOption {
39 type = lib.types.path;
40 default = "/var/lib/openldap";
41 description = ''
42 The directory where Openldap stores its data.
43 '';
44 };
45 socketsDir = lib.mkOption {
46 type = lib.types.path;
47 default = "/run/slapd";
48 description = ''
49 The directory where Openldap puts sockets and pid files.
50 '';
51 };
52 # Output variables
53 pids = lib.mkOption {
54 type = lib.types.attrsOf lib.types.path;
55 default = {
56 pid = "${cfg.socketsDir}/slapd.pid";
57 args = "${cfg.socketsDir}/slapd.args";
58 };
59 readOnly = true;
60 description = ''
61 Slapd pid files
62 '';
63 };
64 };
65 };
66
67 config = lib.mkIf cfg.enable {
4c4652aa
IB
68 secrets.keys = {
69 "ldap/password" = {
182ae57f
IB
70 permissions = "0400";
71 user = "openldap";
72 group = "openldap";
e34b3079 73 text = "${cfg.rootPw}";
4c4652aa
IB
74 };
75 "ldap/access" = {
182ae57f
IB
76 permissions = "0400";
77 user = "openldap";
78 group = "openldap";
da30ae4f 79 text = builtins.readFile cfg.accessFile;
4c4652aa
IB
80 };
81 "ldap" = {
da30ae4f
IB
82 permissions = "0500";
83 user = "openldap";
84 group = "openldap";
85 isDir = true;
4c4652aa
IB
86 };
87 };
182ae57f
IB
88 users.users.openldap.extraGroups = [ "keys" ];
89 networking.firewall.allowedTCPPorts = [ 636 389 ];
90
5400b9b6 91 security.acme.certs."ldap" = config.myServices.databasesCerts // {
182ae57f 92 group = "openldap";
182ae57f
IB
93 domain = "ldap.immae.eu";
94 postRun = ''
95 systemctl restart openldap.service
96 '';
97 };
98
17f6eae9
IB
99 services.filesWatcher.openldap = {
100 restart = true;
da30ae4f 101 paths = [ config.secrets.fullPaths."ldap" ];
17f6eae9
IB
102 };
103
182ae57f
IB
104 services.openldap = {
105 enable = true;
182ae57f 106 urlList = [ "ldap://" "ldaps://" ];
e34b3079
IB
107 settings = {
108 attrs = {
109 olcPidFile = cfg.pids.pid;
110 olcArgsFile = cfg.pids.args;
111 olcLogLevel = "none";
112 olcTLSCertificateFile = "${config.security.acme.certs.ldap.directory}/cert.pem";
113 olcTLSCertificateKeyFile = "${config.security.acme.certs.ldap.directory}/key.pem";
114 olcTLSCACertificateFile = "${config.security.acme.certs.ldap.directory}/fullchain.pem";
115 olcTLSCACertificatePath = "${pkgs.cacert.unbundled}/etc/ssl/certs/";
116 # This makes openldap crash
117 # olcTLSCipherSuite = "DEFAULT";
118 olcSaslHost = "kerberos.immae.eu";
119 # Map sasl "dn" to ldap dn
120 olcAuthzRegexp = ''{0}"uid=([^,]*)(,cn=IMMAE.EU)?,cn=(gssapi|gss-spnego),cn=auth" "uid=$1,ou=users,dc=immae,dc=eu"'';
121 };
122 children = {
123 "cn=module{0}" = {
124 attrs = {
125 cn = "module{0}";
126 objectClass = [ "olcModuleList" ];
127 olcModuleLoad = [ "{0}back_hdb" "{1}memberof" "{2}syncprov" ];
128 };
129 };
130 "cn=schema".includes = map (schema:
131 "${config.services.openldap.package}/etc/schema/${schema}.ldif"
132 ) [ "core" "cosine" "inetorgperson" "nis" ] ++ [
133 "${./immae.ldif}"
134 ];
135 "olcDatabase={0}config" = {
136 attrs = {
137 objectClass = "olcDatabaseConfig";
138 olcDatabase = "{0}config";
139 olcAccess = ["{0}to * by * none"];
140 };
141 };
142 "olcDatabase={1}hdb" = {
143 attrs = {
144 objectClass = [ "olcDatabaseConfig" "olcHdbConfig" ];
145 olcDatabase = "{1}hdb";
146 olcDbIndex = [
147 "objectClass eq"
148 "uid pres,eq"
149 "mail pres,eq,sub"
150 "cn pres,eq,sub"
151 "sn pres,eq,sub"
152 "dc eq"
153 "member eq"
154 "memberOf eq"
155 ];
156 olcAccess = let
157 join = builtins.replaceStrings ["\n"] [" "];
158 in [
159 # First matching "to" + "by" wins
160 #### Replication needs full access
161 (join ''{0}to *
162 by dn.base="uid=ldap_replication,cn=ldap,ou=services,dc=immae,dc=eu" read
163 by * break
164 '')
165 #### Kerberos needs access to users password
166 (join ''{1}to attrs=userPassword,shadowLastChange
167 by self write
168 by anonymous auth
169 by * none
170 '')
171 ####
172 (join ''{2}to attrs=immaeSshKey
173 by self write
174 by * break
175 '')
5400b9b6 176
e34b3079
IB
177 #### Anyone can auth, and I can see myself
178 (join ''{3}to *
179 by self read
180 by anonymous auth
181 by * break
182 '')
5400b9b6 183
e34b3079
IB
184 #### Specific access for phpldapadmin
185 (join ''{4}to filter="(uid=*)" attrs=entry,uid
186 by dn.base="cn=phpldapadmin,ou=services,dc=immae,dc=eu" read
187 by * break
188 '')
189
190 #### Hosts
191 # The attributes are available to every host
192 (join ''{5}to dn.one="ou=hosts,dc=immae,dc=eu"
193 by dn.subtree="ou=hosts,dc=immae,dc=eu" read
194 by dn.base="dc=immae,dc=eu" search
195 by * break
196 '')
197 #### /Hosts
198
199 #### Local services
200 # this/-* & user : all your ancestors have access to you
201 # this/memberOf/-* & user : all those whom you belong to (in a group),
202 # and their ancestors, have access to you
203 # user/immaeAccessWriteDn*/member & this : you have write access to the
204 # members of your immaeAccessDn
205 # attributes
206 # user/immaeAccessDn*/member & this : you have access to the members
207 # of your immaeAccessDn attributes
208 # user/immaeAccessReadSubtree* & this/-* : you have access to the
209 # childrens of your immaeAccessReadSubtree
210 # attributes
211 # this/memberOf/-* & user/immaeAccessReadSubtree*: you have access to
212 # the members of the childrens of your
213 # immaeAccessReadSubtree attributes
214 # http://www.openldap.org/faq/data/cache/1133.html
215 (join ''{6}to dn.subtree="dc=immae,dc=eu"
216 by dn.subtree="ou=external_services,dc=immae,dc=eu" break
217 by set.exact="this/-* & user" read
218 by set.exact="this/memberOf/-* & user" read
219 by set.exact="user/immaeAccessWriteDn*/member & this" write
220 by set.exact="user/immaeAccessDn*/member & this" read
221 by set.exact="user/immaeAccessReadSubtree* & this/-*" read
222 by set.exact="this/memberOf/-* & user/immaeAccessReadSubtree*" read
223 by users search
224 by * break
225 '')
226 #### /Local services
227
228 #### External services
229 # http://www.openldap.org/faq/data/cache/429.html
230 # FIXME: Find a way to whitelist?
231 (join ''{7}to attrs=immaeSshKey
232 by dn.subtree="ou=external_services,dc=immae,dc=eu" none
233 '')
234 (join ''{8}to dn.subtree="dc=immae,dc=eu"
235 by set.exact="this/-* & user" read
236 by set.exact="this/memberOf/-* & user" read
237 by set.exact="user/immaeAccessDn*/member & this/-*" read
238 by users search
239 by * none
240 '')
241 #### /External services
242 ];
243 olcDbDirectory = cfg.dataDir;
244 olcRootDN = cfg.rootDn;
245 olcRootPW.path = config.secrets.fullPaths."ldap/password";
246 olcSuffix = cfg.baseDn;
247 };
248 children = {
249 "olcOverlay={0}memberof" = {
250 attrs = {
251 objectClass = [ "olcOverlayConfig" "olcMemberOf" ];
252 olcOverlay = "{0}memberof";
253 };
254 };
255 "olcOverlay={1}syncprov" = {
256 attrs = {
257 objectClass = [ "olcOverlayConfig" "olcSyncProvConfig" ];
258 olcOverlay = "{1}syncprov";
259 olcSpCheckpoint = "100 10";
260 };
261 };
262 };
263 };
264 };
265 };
182ae57f
IB
266 };
267 };
268}