| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 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
|
| 59 | parameters of this INF file using the \"{instance_name}\" variable. Note that
|
| 60 | this 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
|
| 64 | started.")
|
| 65 | (group
|
| 66 | (string "dirsrv")
|
| 67 | "Sets the group name the ns-slapd process will use after the service
|
| 68 | started.")
|
| 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
|
| 75 | connections (LDAPS).")
|
| 76 | (root-dn
|
| 77 | (string "cn=Directory Manager")
|
| 78 | "Sets the Distinquished Name (DN) of the administrator account for this
|
| 79 | instance.")
|
| 80 | (root-password
|
| 81 | (string "{invalid}YOU-SHOULD-CHANGE-THIS")
|
| 82 | "Sets the password of the account specified in the \"root-dn\" parameter.
|
| 83 | You can either set this parameter to a plain text password dscreate hashes
|
| 84 | during the installation or to a \"{algorithm}hash\" string generated by the
|
| 85 | pwdhash utility. Note that setting a plain text password can be a security
|
| 86 | risk 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
|
| 90 | encryption during the installation. This is not suitable for production, but
|
| 91 | it enables administrators to use TLS right after the installation. You can
|
| 92 | replace the self-signed certificate with a certificate issued by a certificate
|
| 93 | authority.")
|
| 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)
|
| 103 | database.")
|
| 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
|
| 140 | suffix in the database.")
|
| 141 | (require-index?
|
| 142 | (boolean #false)
|
| 143 | "Set this parameter to #true to refuse unindexed searches in this
|
| 144 | database.")
|
| 145 | (sample-entries
|
| 146 | (string "no")
|
| 147 | "Set this parameter to \"yes\" to add latest version of sample entries to
|
| 148 | this database. Or, use \"001003006\" to use the 1.3.6 version sample entries.
|
| 149 | Use 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
|
| 153 | suffix attribute the install process will not create the backend/suffix. You
|
| 154 | can 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 | |
| 165 | (config-version
|
| 166 | (number 2)
|
| 167 | "Sets the format version of the configuration file. To use the INF file
|
| 168 | with 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
|
| 175 | instance. 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
|
| 180 | authentication 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
|
| 184 | whether 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 | |
| 201 | |
| 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 | |
| 279 | |
| 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))
|