ldap.scm 13 KB

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