1 { lib, pkgs, config, openldap, ... }:
3 cfg = config.myServices.databases.openldap;
6 options.myServices.databases = {
8 enable = lib.mkOption {
11 description = "Whether to enable ldap";
12 type = lib.types.bool;
14 baseDn = lib.mkOption {
20 rootDn = lib.mkOption {
26 rootPw = lib.mkOption {
29 Root (Hashed) password
32 accessFile = lib.mkOption {
33 type = lib.types.path;
35 The file path that defines the access
38 dataDir = lib.mkOption {
39 type = lib.types.path;
40 default = "/var/lib/openldap/mdb";
42 The directory where Openldap stores its data.
45 socketsDir = lib.mkOption {
46 type = lib.types.path;
47 default = "/run/openldap";
49 The directory where Openldap puts sockets and pid files.
54 type = lib.types.attrsOf lib.types.path;
56 pid = "${cfg.socketsDir}/slapd.pid";
57 args = "${cfg.socketsDir}/slapd.args";
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;
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" ];
78 }).overrideAttrs (old: {
79 configureFlags = old.configureFlags ++ [ "--with-cyrus-sasl" "--enable-spasswd" ];
89 text = "${cfg.rootPw}";
95 text = builtins.readFile cfg.accessFile;
104 users.users.openldap.extraGroups = [ "keys" ];
105 networking.firewall.allowedTCPPorts = [ 636 389 ];
107 security.acme.certs."ldap" = {
109 domain = "ldap.immae.eu";
111 systemctl restart openldap.service
115 services.filesWatcher.openldap = {
117 paths = [ config.secrets.fullPaths."ldap" ];
120 services.openldap = {
122 urlList = [ "ldap://" "ldaps://" ];
123 package = pkgs.openldap_libressl_cyrus;
126 olcPidFile = cfg.pids.pid;
127 olcArgsFile = cfg.pids.args;
128 olcLogLevel = "none";
129 olcTLSCertificateFile = "${config.security.acme.certs.ldap.directory}/cert.pem";
130 olcTLSCertificateKeyFile = "${config.security.acme.certs.ldap.directory}/key.pem";
131 olcTLSCACertificateFile = "${config.security.acme.certs.ldap.directory}/fullchain.pem";
132 olcTLSCACertificatePath = "${pkgs.cacert.unbundled}/etc/ssl/certs/";
133 # This makes openldap crash
134 # olcTLSCipherSuite = "DEFAULT";
135 #olcSaslHost = "kerberos.immae.eu";
136 # Map sasl "dn" to ldap dn
137 #olcAuthzRegexp = ''{0}"uid=([^,]*)(,cn=IMMAE.EU)?,cn=(gssapi|gss-spnego),cn=auth" "uid=$1,ou=users,dc=immae,dc=eu"'';
143 objectClass = [ "olcModuleList" ];
144 olcModuleLoad = [ "{0}back_mdb" "{1}memberof" "{2}syncprov" ];
147 "cn=schema".includes = map (schema:
148 "${config.services.openldap.package}/etc/schema/${schema}.ldif"
149 ) [ "core" "cosine" "inetorgperson" "nis" ] ++ [
150 "${openldap.immae-ldif}"
152 "olcDatabase={0}config" = {
154 objectClass = "olcDatabaseConfig";
155 olcDatabase = "{0}config";
156 olcAccess = ["{0}to * by * none"];
159 "olcDatabase={1}mdb" = {
161 objectClass = [ "olcDatabaseConfig" "olcMdbConfig" ];
162 olcDatabase = "{1}mdb";
174 join = builtins.replaceStrings ["\n"] [" "];
176 # First matching "to" + "by" wins
177 #### Replication needs full access
179 by dn.base="uid=ldap_replication,cn=ldap,ou=services,dc=immae,dc=eu" read
182 #### Prevent modification of SASL passwords
183 (join ''{1}to attrs=userPassword val.regex="^.SASL..+"
188 #### Oneself needs access to users password
189 (join ''{2}to attrs=userPassword,shadowLastChange
194 #### Should be write, but disabled during migration to psql
195 (join ''{3}to attrs=immaeSshKey
200 #### Anyone can auth, and I can see myself
207 #### Specific access for phpldapadmin
208 (join ''{5}to filter="(uid=*)" attrs=entry,uid
209 by dn.base="cn=phpldapadmin,ou=services,dc=immae,dc=eu" read
214 # The attributes are available to every host
215 (join ''{6}to dn.one="ou=hosts,dc=immae,dc=eu"
216 by dn.subtree="ou=hosts,dc=immae,dc=eu" read
217 by dn.base="dc=immae,dc=eu" search
223 # this/-* & user : all your ancestors have access to you
224 # this/memberOf/-* & user : all those whom you belong to (in a group),
225 # and their ancestors, have access to you
226 # user/immaeAccessWriteDn*/member & this : you have write access to the
227 # members of your immaeAccessDn
229 # user/immaeAccessDn*/member & this : you have access to the members
230 # of your immaeAccessDn attributes
231 # user/immaeAccessReadSubtree* & this/-* : you have access to the
232 # childrens of your immaeAccessReadSubtree
234 # this/memberOf/-* & user/immaeAccessReadSubtree*: you have access to
235 # the members of the childrens of your
236 # immaeAccessReadSubtree attributes
237 # http://www.openldap.org/faq/data/cache/1133.html
238 (join ''{7}to dn.subtree="dc=immae,dc=eu"
239 by dn.subtree="ou=external_services,dc=immae,dc=eu" break
240 by set.exact="this/-* & user" read
241 by set.exact="this/memberOf/-* & user" read
242 by set.exact="user/immaeAccessWriteDn*/member & this" write
243 by set.exact="user/immaeAccessDn*/member & this" read
244 by set.exact="user/immaeAccessReadSubtree* & this/-*" read
245 by set.exact="this/memberOf/-* & user/immaeAccessReadSubtree*" read
251 #### External services
252 # http://www.openldap.org/faq/data/cache/429.html
253 # FIXME: Find a way to whitelist?
254 (join ''{8}to attrs=immaeSshKey
255 by dn.subtree="ou=external_services,dc=immae,dc=eu" none
257 (join ''{9}to dn.subtree="dc=immae,dc=eu"
258 by set.exact="this/-* & user" read
259 by set.exact="this/memberOf/-* & user" read
260 by set.exact="user/immaeAccessDn*/member & this/-*" read
264 #### /External services
266 olcDbDirectory = cfg.dataDir;
267 olcRootDN = cfg.rootDn;
268 olcRootPW.path = config.secrets.fullPaths."ldap/password";
269 olcSuffix = cfg.baseDn;
272 "olcOverlay={0}memberof" = {
274 objectClass = [ "olcOverlayConfig" "olcMemberOf" ];
275 olcOverlay = "{0}memberof";
278 "olcOverlay={1}syncprov" = {
280 objectClass = [ "olcOverlayConfig" "olcSyncProvConfig" ];
281 olcOverlay = "{1}syncprov";
282 olcSpCheckpoint = "100 10";
290 myServices.monitoring.fromMasterActivatedPlugins = [ "tcp" ];
291 myServices.monitoring.fromMasterObjects.service = [
293 service_description = "ldap SSL is up to date";
294 host_name = config.hostEnv.fqdn;
295 use = "external-service";
296 check_command = ["check_tcp_ssl" "636"];
298 servicegroups = "webstatus-ssl";
299 _webstatus_name = "LDAP";
300 _webstatus_url = "ldap.immae.eu";