]> git.immae.eu Git - perso/Immae/Config/Nix.git/blob - systems/eldiron/databases/openldap/default.nix
Move backup directory to host subdir
[perso/Immae/Config/Nix.git] / systems / eldiron / databases / openldap / default.nix
1 { lib, pkgs, config, openldap, ... }:
2 let
3 cfg = config.myServices.databases.openldap;
4 in
5 {
6 options.myServices.databases = {
7 openldap = {
8 enable = lib.mkOption {
9 default = false;
10 example = true;
11 description = "Whether to enable ldap";
12 type = lib.types.bool;
13 };
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 };
38 dataDir = lib.mkOption {
39 type = lib.types.path;
40 default = "/var/lib/openldap/mdb";
41 description = ''
42 The directory where Openldap stores its data.
43 '';
44 };
45 socketsDir = lib.mkOption {
46 type = lib.types.path;
47 default = "/run/openldap";
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 {
68 myServices.dns.zones."immae.eu".subdomains.ldap =
69 with config.myServices.dns.helpers; ips servers.eldiron.ips.main;
70
71 nixpkgs.overlays = [
72 (self: super: {
73 openldap_libressl_cyrus = (self.openldap.override {
74 openssl = self.libressl;
75 cyrus_sasl = self.cyrus_sasl.overrideAttrs (old: {
76 configureFlags = old.configureFlags ++ [ "--with-configdir=/etc/sasl2" ];
77 });
78 }).overrideAttrs (old: {
79 configureFlags = old.configureFlags ++ [ "--with-cyrus-sasl" "--enable-spasswd" ];
80 });
81 })
82 ];
83
84 secrets.keys = {
85 "ldap/password" = {
86 permissions = "0400";
87 user = "openldap";
88 group = "openldap";
89 text = "${cfg.rootPw}";
90 };
91 "ldap/access" = {
92 permissions = "0400";
93 user = "openldap";
94 group = "openldap";
95 text = builtins.readFile cfg.accessFile;
96 };
97 "ldap" = {
98 permissions = "0500";
99 user = "openldap";
100 group = "openldap";
101 isDir = true;
102 };
103 };
104 users.users.openldap.extraGroups = [ "keys" ];
105 networking.firewall.allowedTCPPorts = [ 636 389 ];
106 services.borgBackup.profiles.global.includedPaths = [
107 "openldap"
108 ];
109
110 security.acme.certs."ldap" = {
111 group = "openldap";
112 domain = "ldap.immae.eu";
113 postRun = ''
114 systemctl restart openldap.service
115 '';
116 };
117
118 services.filesWatcher.openldap = {
119 restart = true;
120 paths = [ config.secrets.fullPaths."ldap" ];
121 };
122
123 services.openldap = {
124 enable = true;
125 urlList = [ "ldap://" "ldaps://" ];
126 package = pkgs.openldap_libressl_cyrus;
127 settings = {
128 attrs = {
129 olcPidFile = cfg.pids.pid;
130 olcArgsFile = cfg.pids.args;
131 olcLogLevel = "none";
132 olcTLSCertificateFile = "${config.security.acme.certs.ldap.directory}/cert.pem";
133 olcTLSCertificateKeyFile = "${config.security.acme.certs.ldap.directory}/key.pem";
134 olcTLSCACertificateFile = "${config.security.acme.certs.ldap.directory}/fullchain.pem";
135 olcTLSCACertificatePath = "${pkgs.cacert.unbundled}/etc/ssl/certs/";
136 # This makes openldap crash
137 # olcTLSCipherSuite = "DEFAULT";
138 #olcSaslHost = "kerberos.immae.eu";
139 # Map sasl "dn" to ldap dn
140 #olcAuthzRegexp = ''{0}"uid=([^,]*)(,cn=IMMAE.EU)?,cn=(gssapi|gss-spnego),cn=auth" "uid=$1,ou=users,dc=immae,dc=eu"'';
141 };
142 children = {
143 "cn=module{0}" = {
144 attrs = {
145 cn = "module{0}";
146 objectClass = [ "olcModuleList" ];
147 olcModuleLoad = [ "{0}back_mdb" "{1}memberof" "{2}syncprov" ];
148 };
149 };
150 "cn=schema".includes = map (schema:
151 "${config.services.openldap.package}/etc/schema/${schema}.ldif"
152 ) [ "core" "cosine" "inetorgperson" "nis" ] ++ [
153 "${openldap.immae-ldif}"
154 ];
155 "olcDatabase={0}config" = {
156 attrs = {
157 objectClass = "olcDatabaseConfig";
158 olcDatabase = "{0}config";
159 olcAccess = ["{0}to * by * none"];
160 };
161 };
162 "olcDatabase={1}mdb" = {
163 attrs = {
164 objectClass = [ "olcDatabaseConfig" "olcMdbConfig" ];
165 olcDatabase = "{1}mdb";
166 olcDbIndex = [
167 "objectClass eq"
168 "uid pres,eq"
169 "mail pres,eq,sub"
170 "cn pres,eq,sub"
171 "sn pres,eq,sub"
172 "dc eq"
173 "member eq"
174 "memberOf eq"
175 ];
176 olcAccess = let
177 join = builtins.replaceStrings ["\n"] [" "];
178 in [
179 # First matching "to" + "by" wins
180 #### Replication needs full access
181 (join ''{0}to *
182 by dn.base="uid=ldap_replication,cn=ldap,ou=services,dc=immae,dc=eu" read
183 by * break
184 '')
185 #### Prevent modification of SASL passwords
186 (join ''{1}to attrs=userPassword val.regex="^.SASL..+"
187 by self read
188 by anonymous auth
189 by * none
190 '')
191 #### Oneself needs access to users password
192 (join ''{2}to attrs=userPassword,shadowLastChange
193 by self write
194 by anonymous auth
195 by * none
196 '')
197 #### Should be write, but disabled during migration to psql
198 (join ''{3}to attrs=immaeSshKey
199 by self read
200 by * break
201 '')
202
203 #### Anyone can auth, and I can see myself
204 (join ''{4}to *
205 by self read
206 by anonymous auth
207 by * break
208 '')
209
210 #### Specific access for phpldapadmin
211 (join ''{5}to filter="(uid=*)" attrs=entry,uid
212 by dn.base="cn=phpldapadmin,ou=services,dc=immae,dc=eu" read
213 by * break
214 '')
215
216 #### Hosts
217 # The attributes are available to every host
218 (join ''{6}to dn.one="ou=hosts,dc=immae,dc=eu"
219 by dn.subtree="ou=hosts,dc=immae,dc=eu" read
220 by dn.base="dc=immae,dc=eu" search
221 by * break
222 '')
223 #### /Hosts
224
225 #### Local services
226 # this/-* & user : all your ancestors have access to you
227 # this/memberOf/-* & user : all those whom you belong to (in a group),
228 # and their ancestors, have access to you
229 # user/immaeAccessWriteDn*/member & this : you have write access to the
230 # members of your immaeAccessDn
231 # attributes
232 # user/immaeAccessDn*/member & this : you have access to the members
233 # of your immaeAccessDn attributes
234 # user/immaeAccessReadSubtree* & this/-* : you have access to the
235 # childrens of your immaeAccessReadSubtree
236 # attributes
237 # this/memberOf/-* & user/immaeAccessReadSubtree*: you have access to
238 # the members of the childrens of your
239 # immaeAccessReadSubtree attributes
240 # http://www.openldap.org/faq/data/cache/1133.html
241 (join ''{7}to dn.subtree="dc=immae,dc=eu"
242 by dn.subtree="ou=external_services,dc=immae,dc=eu" break
243 by set.exact="this/-* & user" read
244 by set.exact="this/memberOf/-* & user" read
245 by set.exact="user/immaeAccessWriteDn*/member & this" write
246 by set.exact="user/immaeAccessDn*/member & this" read
247 by set.exact="user/immaeAccessReadSubtree* & this/-*" read
248 by set.exact="this/memberOf/-* & user/immaeAccessReadSubtree*" read
249 by users search
250 by * break
251 '')
252 #### /Local services
253
254 #### External services
255 # http://www.openldap.org/faq/data/cache/429.html
256 # FIXME: Find a way to whitelist?
257 (join ''{8}to attrs=immaeSshKey
258 by dn.subtree="ou=external_services,dc=immae,dc=eu" none
259 '')
260 (join ''{9}to dn.subtree="dc=immae,dc=eu"
261 by set.exact="this/-* & user" read
262 by set.exact="this/memberOf/-* & user" read
263 by set.exact="user/immaeAccessDn*/member & this/-*" read
264 by users search
265 by * none
266 '')
267 #### /External services
268 ];
269 olcDbDirectory = cfg.dataDir;
270 olcRootDN = cfg.rootDn;
271 olcRootPW.path = config.secrets.fullPaths."ldap/password";
272 olcSuffix = cfg.baseDn;
273 };
274 children = {
275 "olcOverlay={0}memberof" = {
276 attrs = {
277 objectClass = [ "olcOverlayConfig" "olcMemberOf" ];
278 olcOverlay = "{0}memberof";
279 };
280 };
281 "olcOverlay={1}syncprov" = {
282 attrs = {
283 objectClass = [ "olcOverlayConfig" "olcSyncProvConfig" ];
284 olcOverlay = "{1}syncprov";
285 olcSpCheckpoint = "100 10";
286 };
287 };
288 };
289 };
290 };
291 };
292 };
293 myServices.monitoring.fromMasterActivatedPlugins = [ "tcp" ];
294 myServices.monitoring.fromMasterObjects.service = [
295 {
296 service_description = "ldap SSL is up to date";
297 host_name = config.hostEnv.fqdn;
298 use = "external-service";
299 check_command = ["check_tcp_ssl" "636"];
300
301 servicegroups = "webstatus-ssl";
302 _webstatus_name = "LDAP";
303 _webstatus_url = "ldap.immae.eu";
304 }
305 ];
306 };
307 }