]> Git — Sourcephile - sourcephile-nix.git/blob - servers/mermet/openldap/sourcephile.nix
x509: send the key once for root, not one per service
[sourcephile-nix.git] / servers / mermet / openldap / sourcephile.nix
1 { pkgs, lib, config, ... }:
2 let
3 inherit (builtins) hasAttr;
4 inherit (builtins.extraBuiltins) pass-chomp;
5 inherit (config) networking;
6 inherit (config.services) openldap;
7 inherit (config.users) users groups;
8 inherit (pkgs.lib) unlines;
9 domainSuffix = openldap.domainSuffix;
10 posixAccount =
11 { uid
12 , uidNumber
13 , gidNumber ? uidNumber
14 , cn ? ""
15 , sn ? ""
16 , userPassword ? null # NOTE: doveadm pw -s SSHA -u $user -p $pass
17 , mailAlias ? []
18 , homeDirectory ? ""
19 , mailStorageDirectory ? null
20 , loginShell ? "/run/current-system/sw/bin/bash"
21 , mailEnabled ? true
22 , mailForwardingAddress ? []
23 , domain ? networking.domain
24 }: "\n" + lib.concatStringsSep "\n\n" [
25 (unlines ([ ''
26 dn: uid=${uid},ou=accounts,ou=posix,${domainSuffix}
27 objectClass: person
28 objectClass: posixAccount
29 objectClass: shadowAccount
30 objectClass: PostfixBookMailAccount
31 objectClass: PostfixBookMailForward
32 cn: ${cn}
33 sn: ${sn}
34 mail: ${uid}${lib.optionalString (networking.domain != "") "@${networking.domain}"}
35 mailEnabled: ${if mailEnabled then "TRUE" else "FALSE"}
36 #mailGroupMember: ${networking.domainBase}'']
37 ++ [ "uidNumber: ${toString uidNumber}" ]
38 ++ [ "gidNumber: ${toString gidNumber}" ]
39 ++ [ "homeDirectory: ${homeDirectory}" ]
40 ++ lib.optional (loginShell != null) "loginShell: ${loginShell}"
41 ++ lib.optional (userPassword != null) "userPassword: ${userPassword}"
42 ++ lib.optional (mailStorageDirectory != null) "mailStorageDirectory: ${mailStorageDirectory}"
43 ++ map (forward: "mailForwardingAddress: ${forward}") mailForwardingAddress
44 ++ map (alias: "mailAlias: ${alias}@${networking.domain}") mailAlias
45 ++ lib.optional (mailAlias == []) "mailAlias:"
46 # NOTE: required by PostfixBookMailForward
47 ))
48 ''
49 dn: cn=${uid},ou=groups,ou=posix,${domainSuffix}
50 objectClass: top
51 objectClass: posixGroup
52 gidNumber: ${toString gidNumber}
53 memberUid: ${uid}
54 ''
55 ];
56 in
57 {
58 config = lib.mkIf config.users.ldap.enable {
59 services.openldap = {
60 databases = {
61 # DEBUG: echo "$(nixops show-option mermet -d production services.openldap.databases."dc=sourcephile,dc=fr".data)"
62 "${domainSuffix}" = {
63 #
64 #
65 # WARNING: this deletes data.
66 #
67 #
68 resetData = true;
69
70 # DEBUG: sudo ldapsearch -LLL -H ldapi:// -D cn=admin,cn=config -Y EXTERNAL -b 'olcDatabase={1}mdb,cn=config' -s sub
71 # WARNING: newlines matter
72 conf = ''
73 dn: olcBackend={1}mdb,cn=config
74 objectClass: olcBackendConfig
75
76 dn: olcDatabase={1}mdb,cn=config
77 objectClass: olcDatabaseConfig
78 objectClass: olcMdbConfig
79 # NOTE: checkpoint the database periodically in case of system failure
80 # and to speed slapd shutdown.
81 olcDbCheckpoint: 512 30
82 # Database max size is 1G
83 olcDbMaxSize: 1073741824
84 olcLastMod: TRUE
85 # NOTE: database superuser. Needed for syncrepl.
86 olcRootDN: cn=admin,${domainSuffix}
87 # NOTE: superuser password, generated with slappasswd -h "{SSHA}" -s "$password"
88 #olcRootPW: {SSHA}COkATGNe7rs/g8vWcYP5rqt4u5sWdMgP
89 #
90 olcDbIndex: objectClass eq
91 olcDbIndex: cn,uid eq
92 olcDbIndex: uidNumber,gidNumber eq
93 olcDbIndex: member,memberUid eq
94 olcDbIndex: mail eq
95 olcDbIndex: mailAlias eq
96 olcDbIndex: mailEnabled eq
97 #
98 olcAccess: to attrs=userPassword
99 by self write
100 by anonymous auth
101 by dn="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" write
102 by * none
103 olcAccess: to attrs=shadowLastChange
104 by self write
105 by dn="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" write
106 by * none
107 olcAccess: to dn.sub="ou=posix,${domainSuffix}"
108 by self read
109 by dn="gidNumber=${toString groups.nslcd.gid}+uidNumber=${toString users.nslcd.uid},cn=peercred,cn=external,cn=auth" read
110 ${lib.optionalString (hasAttr "postfix" users) ''by dn="gidNumber=${toString groups.postfix.gid}+uidNumber=${toString users.postfix.uid},cn=peercred,cn=external,cn=auth" read''}
111 by dn="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" read
112 # NOTE: dovecot/auth runs as root, hence the gidNumber=0+uidNumber=0
113 olcAccess: to *
114 by self read
115 by * none
116 '';
117 data = ''
118 dn: ${domainSuffix}
119 objectClass: top
120 objectClass: dcObject
121 objectClass: organization
122 o: ${networking.domainBase}
123
124 dn: cn=admin,${domainSuffix}
125 objectClass: simpleSecurityObject
126 objectClass: organizationalRole
127 description: ${networking.domainBase} LDAP administrator
128 roleOccupant: ${domainSuffix}
129 userPassword:
130 #userPassword: {SSHA}NONVwwKnKsCBmFxkMqTCFekdu3SJQHc9
131
132 dn: ou=posix,${domainSuffix}
133 objectClass: top
134 objectClass: organizationalUnit
135
136 dn: ou=accounts,ou=posix,${domainSuffix}
137 objectClass: top
138 objectClass: organizationalUnit
139
140 dn: ou=groups,ou=posix,${domainSuffix}
141 objectClass: top
142 objectClass: organizationalUnit
143
144 dn: cn=${networking.domainBase},ou=groups,ou=posix,${domainSuffix}
145 objectClass: top
146 objectClass: posixGroup
147 gidNumber: 20000
148 memberUid: julm
149 memberUid: sevy
150
151 ''
152 + lib.concatMapStrings posixAccount [ rec
153 { uid = "julm";
154 cn = "Julien Moutinho";
155 sn = uid;
156 uidNumber = users.julm.uid;
157 gidNumber = groups.julm.gid;
158 mailAlias = [ "julien.moutinho" ];
159 userPassword = pass-chomp "members/julm/mail/hashedPassword";
160 mailStorageDirectory =
161 let stateDir = "/var/lib/dovecot";
162 d="sourcephile.fr";
163 in
164 # I'm personnaly using "maildir:" instead of "sdbox:" to be able to use a local (neo)mutt on it,
165 # bypassing IMAP because (neo)mutt support of IMAP is very bad
166 # (can't even have a decent $folder_format (with %n or %m) working,
167 # neither sorting them by date).
168 "maildir:${stateDir}/mail/${d}/${uid}/mail.d:LAYOUT=maildir++:UTF-8:CONTROL=${stateDir}/control/${d}/${uid}:INDEX=${stateDir}/index/${d}/${uid}";
169 }
170 #{ uid="sevy"; uidNumber=10001; cn="Séverine Popek"; sn="sévy";
171 # mailAlias = ["severine.popek" "ouais-ouais"]; }
172 #{ uid="nomail"; uidNumber=10002; mailAlias = ["noalias"]; mailEnabled = false; }
173 #{ uid="post"; domain="friot"; mailForwardingAddress = ["ju@${networking.domain}"]; }
174 #{ uid="host"; mailForwardingAddress = ["ju@${networking.domain}"]; }
175 ];
176 };
177 };
178 };
179 };
180 }