services: admin: Refactor and renaming of doas-service-type

main
Luis Guilherme Coelho 2024-09-22 13:56:39 -03:00
parent f6aab460c7
commit eb862f370b
No known key found for this signature in database
GPG Key ID: 1F2E76ACE3F531C8
1 changed files with 72 additions and 52 deletions

View File

@ -2,33 +2,20 @@
#:use-module (gnu packages admin) #:use-module (gnu packages admin)
#:use-module (gnu services configuration) #:use-module (gnu services configuration)
#:use-module ((gnu services) #:hide (delete)) #:use-module ((gnu services) #:hide (delete))
#:use-module (gnu system privilege)
#:use-module (guix gexp) #:use-module (guix gexp)
#:use-module (guix packages)
#:use-module (guix records) #:use-module (guix records)
#:use-module (ice-9 format) #:use-module (ice-9 format)
#:use-module (ice-9 match) #:use-module (ice-9 match)
#:use-module (srfi srfi-1) #:use-module (srfi srfi-1)
#:use-module (srfi srfi-26) #:use-module (srfi srfi-26)
#:export (doas-service-type #:export (opendoas-service-type
opendoas-configuration
opendoas-rule-extension
permit permit
make-permit-statement deny))
permit-statement?
permit-statement-args
permit-statement-as-user
permit-statement-command
permit-statement-identity
permit-statement-keepenv?
permit-statement-nolog?
permit-statement-nopass?
permit-statement-persist?
permit-statement-setenv
deny
make-deny-statement
deny-statement?
deny-statement-args
deny-statement-as-user
deny-statement-command))
;; Dummy serializers, just to avoid warnings ;; Dummy serializers, just to avoid warnings
(define empty-serializer (define empty-serializer
@ -47,7 +34,7 @@
(define-maybe assoc-list) (define-maybe assoc-list)
(define-maybe string) (define-maybe string)
(define-configuration/no-serialization permit-statement (define-configuration/no-serialization permit-rule
(nopass? (nopass?
(boolean #f) (boolean #f)
"Whether the user should be permitted to run the command without a password.") "Whether the user should be permitted to run the command without a password.")
@ -85,8 +72,8 @@ without arguments.")
to #f, or simply exported, by setting them to #t. If the first character of the to #f, or simply exported, by setting them to #t. If the first character of the
value is $ then the value to be set is taken from the existing environment value is $ then the value to be set is taken from the existing environment
variable with the given name.")) variable with the given name."))
(define-syntax-rule (permit entry ...) (define-syntax-rule (permit field ...)
(permit-statement entry ...)) (permit-rule field ...))
(define (unset? val) (define (unset? val)
"Tests if VAL is unset." "Tests if VAL is unset."
@ -97,8 +84,8 @@ variable with the given name."))
"Apply PROC to VAL if VAL is not unset, otherwise returns #f." "Apply PROC to VAL if VAL is not unset, otherwise returns #f."
(if (not (unset? val)) (proc val) #f)) (if (not (unset? val)) (proc val) #f))
(define serialize-permit-statement (define serialize-permit-rule
(match-record-lambda <permit-statement> (match-record-lambda <permit-rule>
(identity as-user command args setenv keepenv? nopass? nolog? persist?) (identity as-user command args setenv keepenv? nopass? nolog? persist?)
(format #f "permit ~:[~;keepenv ~]~ (format #f "permit ~:[~;keepenv ~]~
~:[~;nopass ~]~ ~:[~;nopass ~]~
@ -118,7 +105,7 @@ variable with the given name."))
(if-set command) (if-set command)
(if-set args)))) (if-set args))))
(define-configuration/no-serialization deny-statement (define-configuration/no-serialization deny-rule
(identity (identity
string string
"The username to match. Groups may be specified by prepending a colon ':'.") "The username to match. Groups may be specified by prepending a colon ':'.")
@ -136,11 +123,11 @@ path is specified, only a restricted PATH will be searched.")
"Arguments to command. The command arguments provided by the user need to "Arguments to command. The command arguments provided by the user need to
match those specified. The keyword args alone means that command must be run match those specified. The keyword args alone means that command must be run
without arguments.")) without arguments."))
(define-syntax-rule (deny entry ...) (define-syntax-rule (deny field ...)
(deny-statement entry ...)) (deny-rule field ...))
(define serialize-deny-statement (define serialize-deny-rule
(match-record-lambda <deny-statement> (match-record-lambda <deny-rule>
(identity as-user command args) (identity as-user command args)
(format #f "deny ~a~@[ as ~a~]~@[ cmd ~a~]~@[ args~{ ~a~}~]~%" (format #f "deny ~a~@[ as ~a~]~@[ cmd ~a~]~@[ args~{ ~a~}~]~%"
identity identity
@ -148,30 +135,63 @@ without arguments."))
(if-set command) (if-set command)
(if-set args)))) (if-set args))))
(define (doas-config-file config) (define (rule? x)
(plain-file "doas.conf" (or (permit-rule? x)
(deny-rule? x)))
(define list-of-rules?
(list-of rule?))
(define-configuration/no-serialization opendoas-configuration
(opendoas
(package opendoas)
"The doas package to be used.")
(rules
(list-of-rules '())
"The list of permit and/or deny rules used by doas."))
(define-configuration/no-serialization opendoas-rule-extension
(rules
(list-of-rules '())
"The list of permit and/or deny rules used by doas."))
(define (opendoas-extensions original-config extension-configs)
(opendoas-configuration
(inherit original-config)
(rules (append (opendoas-configuration-rules original-config)
(reverse (append-map opendoas-rule-extension-rules
extension-configs))))))
(define (opendoas-config-file config)
`(("doas.conf"
,(plain-file "doas.conf"
(apply string-append (apply string-append
(map (lambda (s) (map (lambda (s)
(cond ((permit-statement? s) (cond ((permit-rule? s)
(serialize-permit-statement s)) (serialize-permit-rule s))
((deny-statement? s) ((deny-rule? s)
(serialize-deny-statement s)))) (serialize-deny-rule s))))
config)))) (opendoas-configuration-rules config)))))))
(define (doas-etc-service config) (define (opendoas-privileged-programs config)
`(("doas.conf" ,(doas-config-file config)))) (let ((opendoas (opendoas-configuration-opendoas config)))
(list (privileged-program
(program (file-append opendoas "/bin/doas"))
(setuid? #t)))))
(define doas-service-type (define (opendoas-packages config)
(service-type (name 'doas) (list (opendoas-configuration-opendoas config)))
(define opendoas-service-type
(service-type (name 'opendoas)
(extensions (extensions
(list (service-extension (list (service-extension etc-service-type
etc-service-type opendoas-config-file)
doas-etc-service))) (service-extension profile-service-type
(compose (compose concatenate reverse)) opendoas-packages)
(extend append) (service-extension privileged-program-service-type
(default-value '()) opendoas-privileged-programs)))
(compose identity)
(extend opendoas-extensions)
(default-value (opendoas-configuration))
(description "Set /etc/doas.conf"))) (description "Set /etc/doas.conf")))
(define (generate-documentation)
(configuration->documentation 'permit-statement)
(configuration->documentation 'deny-statement))