projects/guix·blob master · refs

317 lines · 13.0 KiB

1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2018, 2019, 2022 Ricardo Wurmus <[email protected]>
3;;;
4;;; This file is part of GNU Guix.
5;;;
6;;; GNU Guix is free software; you can redistribute it and/or modify it
7;;; under the terms of the GNU General Public License as published by
8;;; the Free Software Foundation; either version 3 of the License, or (at
9;;; your option) any later version.
10;;;
11;;; GNU Guix is distributed in the hope that it will be useful, but
12;;; WITHOUT ANY WARRANTY; without even the implied warranty of
13;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14;;; GNU General Public License for more details.
15;;;
16;;; You should have received a copy of thye GNU General Public License
17;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
18
19(define-module (gnu services ldap)
20 #:use-module (gnu packages admin)
21 #:use-module (gnu packages openldap)
22 #:use-module (gnu services)
23 #:use-module (gnu services configuration)
24 #:use-module (gnu services shepherd)
25 #:use-module (gnu system shadow)
26 #:use-module (guix gexp)
27 #:use-module (srfi srfi-1)
28 #:use-module (ice-9 match)
29 #:use-module (ice-9 string-fun)
30 #:export (directory-server-service-type
31 directory-server-shepherd-service
32
33 directory-server-instance-configuration
34 slapd-configuration
35 backend-userroot-configuration))
36
37(define (uglify-field-name name)
38 (let ((str (string-map (match-lambda
39 (#\- #\_)
40 (chr chr))
41 (symbol->string name))))
42 (if (string-suffix? "?" str)
43 (substring str 0 (1- (string-length str)))
44 str)))
45(define (serialize-field field-name val)
46 (format #t "~a = ~a\n" (uglify-field-name field-name) val))
47(define serialize-string serialize-field)
48(define-maybe string)
49(define (serialize-boolean field-name val)
50 (serialize-field field-name (if val "True" "False")))
51(define (serialize-number field-name val)
52 (serialize-field field-name (number->string val)))
53
54
55(define-configuration slapd-configuration
56 (instance-name
57 (string "localhost")
58 "Sets the name of the instance. You can refer to this value in other
59parameters of this INF file using the \"{instance_name}\" variable. Note that
60this name cannot be changed after the installation!")
61 (user
62 (string "dirsrv")
63 "Sets the user name the ns-slapd process will use after the service
64started.")
65 (group
66 (string "dirsrv")
67 "Sets the group name the ns-slapd process will use after the service
68started.")
69 (port
70 (number 389)
71 "Sets the TCP port the instance uses for LDAP connections.")
72 (secure-port
73 (number 636)
74 "Sets the TCP port the instance uses for TLS-secured LDAP
75connections (LDAPS).")
76 (root-dn
77 (string "cn=Directory Manager")
78 "Sets the Distinquished Name (DN) of the administrator account for this
79instance.")
80 (root-password
81 (string "{invalid}YOU-SHOULD-CHANGE-THIS")
82 "Sets the password of the account specified in the \"root-dn\" parameter.
83You can either set this parameter to a plain text password dscreate hashes
84during the installation or to a \"{algorithm}hash\" string generated by the
85pwdhash utility. Note that setting a plain text password can be a security
86risk if unprivileged users can read this INF file!")
87 (self-sign-cert
88 (boolean #t)
89 "Sets whether the setup creates a self-signed certificate and enables TLS
90encryption during the installation. This is not suitable for production, but
91it enables administrators to use TLS right after the installation. You can
92replace the self-signed certificate with a certificate issued by a certificate
93authority.")
94 (self-sign-cert-valid-months
95 (number 24)
96 "Set the number of months the issued self-signed certificate will be valid.")
97 (backup-dir
98 (string "/var/lib/dirsrv/slapd-{instance_name}/bak")
99 "Set the backup directory of the instance.")
100 (cert-dir
101 (string "/etc/dirsrv/slapd-{instance_name}")
102 "Sets the directory of the instance's Network Security Services (NSS)
103database.")
104 (config-dir
105 (string "/etc/dirsrv/slapd-{instance_name}")
106 "Sets the configuration directory of the instance.")
107 (db-dir
108 (string "/var/lib/dirsrv/slapd-{instance_name}/db")
109 "Sets the database directory of the instance.")
110 (initconfig-dir
111 (string "/etc/dirsrv/registry")
112 "Sets the directory of the operating system's rc configuration directory.")
113 (ldif-dir
114 (string "/var/lib/dirsrv/slapd-{instance_name}/ldif")
115 "Sets the LDIF export and import directory of the instance.")
116 (lock-dir
117 (string "/var/lock/dirsrv/slapd-{instance_name}")
118 "Sets the lock directory of the instance.")
119 (log-dir
120 (string "/var/log/dirsrv/slapd-{instance_name}")
121 "Sets the log directory of the instance.")
122 (run-dir
123 (string "/run/dirsrv")
124 "Sets PID directory of the instance.")
125 (schema-dir
126 (string "/etc/dirsrv/slapd-{instance_name}/schema")
127 "Sets schema directory of the instance.")
128 (tmp-dir
129 (string "/tmp")
130 "Sets the temporary directory of the instance."))
131
132(define (serialize-slapd-configuration field-name val)
133 #t)
134
135
136(define-configuration backend-userroot-configuration
137 (create-suffix-entry?
138 (boolean #false)
139 "Set this parameter to #true to create a generic root node entry for the
140suffix in the database.")
141 (require-index?
142 (boolean #false)
143 "Set this parameter to #true to refuse unindexed searches in this
144database.")
145 (sample-entries
146 (string "no")
147 "Set this parameter to \"yes\" to add latest version of sample entries to
148this database. Or, use \"001003006\" to use the 1.3.6 version sample entries.
149Use this option, for example, to create a database for testing purposes.")
150 (suffix
151 maybe-string
152 "Sets the root suffix stored in this database. If you do not set the
153suffix attribute the install process will not create the backend/suffix. You
154can also create multiple backends/suffixes by duplicating this section."))
155
156(define (serialize-backend-userroot-configuration field-name val)
157 #t)
158
159
160(define-configuration directory-server-instance-configuration
161 (package
162 (file-like 389-ds-base)
163 "The 389-ds-base package.")
164 ;; General settings
165 (config-version
166 (number 2)
167 "Sets the format version of the configuration file. To use the INF file
168with dscreate, this parameter must be 2.")
169 (full-machine-name
170 (string "localhost")
171 "Sets the fully qualified hostname (FQDN) of this system.")
172 (selinux
173 (boolean #false)
174 "Enables SELinux detection and integration during the installation of this
175instance. If set to #T, dscreate auto-detects whether SELinux is enabled.")
176 (strict-host-checking
177 (boolean #t)
178 "Sets whether the server verifies the forward and reverse record set in the
179\"full-machine-name\" parameter. When installing this instance with GSSAPI
180authentication behind a load balancer, set this parameter to #F.")
181 (systemd
182 (boolean #false)
183 "Enables systemd platform features. If set to #T, dscreate auto-detects
184whether systemd is installed.")
185 (slapd
186 (slapd-configuration (slapd-configuration))
187 "Configuration of slapd.")
188 (backend-userroot
189 (backend-userroot-configuration (backend-userroot-configuration))
190 "Configuration of the userroot backend."))
191
192(define (serialize-directory-server-instance-configuration x)
193 (format #t "[general]\n")
194 (serialize-configuration
195 x
196 (filter (lambda (field)
197 (not (member (configuration-field-name field)
198 '(package slapd backend-userroot))))
199 directory-server-instance-configuration-fields))
200 ;; Do not start instance while running dscreate. Do this later with
201 ;; shepherd.
202 (format #t "start = False\n")
203 (format #t "\n[slapd]\n")
204 (serialize-configuration
205 (directory-server-instance-configuration-slapd x)
206 slapd-configuration-fields)
207 (format #t "\n[backend-userroot]\n")
208 (serialize-configuration
209 (directory-server-instance-configuration-backend-userroot x)
210 backend-userroot-configuration-fields))
211
212(define (directory-server-instance-config-file config)
213 "Return an LDAP directory server instance configuration file."
214 (let* ((slapd (directory-server-instance-configuration-slapd config))
215 (instance-name (slapd-configuration-instance-name slapd)))
216 (plain-file
217 (string-append "dirsrv-" instance-name ".inf")
218 (with-output-to-string
219 (lambda ()
220 (serialize-directory-server-instance-configuration config))))))
221
222(define (directory-server-shepherd-service config)
223 "Return a shepherd service for an LDAP directory server with CONFIG."
224 (let* ((389-ds-base (directory-server-instance-configuration-package config))
225 (slapd (directory-server-instance-configuration-slapd config))
226 (instance-name
227 (slapd-configuration-instance-name slapd)))
228 (list (shepherd-service
229 (documentation "Run an 389 directory server instance.")
230 (provision (list (symbol-append 'directory-server-
231 (string->symbol instance-name))))
232 (requirement '(user-processes))
233 (start #~(make-forkexec-constructor
234 (list #$(file-append 389-ds-base "/sbin/dsctl")
235 #$instance-name "start")
236 #:pid-file
237 (string-append
238 #$(slapd-configuration-run-dir slapd)
239 "/slapd-" #$instance-name ".pid")))
240 (stop #~(make-kill-destructor))))))
241
242(define (directory-server-accounts config)
243 (let* ((slapd (directory-server-instance-configuration-slapd config))
244 (user (slapd-configuration-user slapd))
245 (group (slapd-configuration-group slapd)))
246 (list (user-group
247 (name group)
248 (system? #true))
249 (user-account
250 (name user)
251 (group group)
252 (system? #true)
253 (comment "System user for the 389 directory server")
254 (home-directory "/var/empty")
255 (shell (file-append shadow "/sbin/nologin"))))))
256
257(define (directory-server-activation config)
258 (let* ((389-ds-base (directory-server-instance-configuration-package config))
259 (config-file (directory-server-instance-config-file config))
260 (slapd (directory-server-instance-configuration-slapd config))
261 (instance-name (slapd-configuration-instance-name slapd))
262 (user (slapd-configuration-user slapd))
263 (group (slapd-configuration-group slapd))
264 (instantiate (lambda (proc)
265 (string-replace-substring
266 (proc slapd) "{instance_name}" instance-name)))
267 (config-dir (instantiate slapd-configuration-config-dir))
268 (all-dirs (delete-duplicates
269 (map (compose dirname instantiate)
270 (list slapd-configuration-backup-dir
271 slapd-configuration-cert-dir
272 slapd-configuration-db-dir
273 slapd-configuration-ldif-dir
274 slapd-configuration-lock-dir
275 slapd-configuration-log-dir
276 slapd-configuration-run-dir
277 slapd-configuration-schema-dir)))))
278 ;; 389-ds-base doesn't let us update an instance configuration, so bail
279 ;; out when the configuration directory already exists.
280 #~(begin
281 (use-modules (ice-9 match)
282 (guix build utils))
283 (if (file-exists? #$config-dir)
284 (format #t
285 "directory-server: Instance configuration for `~a' already exists. Skipping.\n"
286 #$instance-name)
287 (let ((owner (getpwnam #$user)))
288 (for-each (lambda (dir)
289 (mkdir-p dir)
290 (chown dir (passwd:uid owner) (passwd:gid owner)))
291 (sort '#$all-dirs string<=))
292 (system* #$(file-append 389-ds-base "/sbin/dscreate")
293 "from-file" #$config-file))))))
294
295(define directory-server-service-type
296 (service-type (name 'directory-server)
297 (extensions
298 (list (service-extension shepherd-root-service-type
299 directory-server-shepherd-service)
300 (service-extension activation-service-type
301 directory-server-activation)
302 (service-extension account-service-type
303 directory-server-accounts)))
304 (default-value (directory-server-instance-configuration))
305 (description
306 "Run a directory server instance.")))
307
308(define (generate-directory-server-documentation)
309 (generate-documentation
310 `((directory-server-instance-configuration
311 ,directory-server-instance-configuration-fields
312 (slapd slapd-configuration)
313 (backend-userroot backend-userroot-configuration))
314 (slapd-configuration ,slapd-configuration-fields)
315 (backend-userroot-configuration
316 ,backend-userroot-configuration-fields))
317 'directory-server-instance-configuration))