activation: Operate on <user-account> and <user-group> records.

* gnu/system/accounts.scm (sexp->user-group, sexp->user-account): New
procedures.
* gnu/system/shadow.scm (account-activation): Call them in the arguments
to 'activate-users+groups'.
(account-shepherd-service): Likewise.
* gnu/build/activation.scm (activate-users+groups): Expect a list of
<user-account> and a list of <user-group>.  Replace uses of 'match' on
tuples with calls to record accessors.
(activate-user-home): Likewise.
master
Ludovic Courtès 2019-03-03 21:57:26 +01:00
parent f6f67b87c0
commit 6061d01512
No known key found for this signature in database
GPG Key ID: 090B11993D9AEBB5
3 changed files with 103 additions and 65 deletions

View File

@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU ;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018 Ludovic Courtès <ludo@gnu.org> ;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2015 Mark H Weaver <mhw@netris.org> ;;; Copyright © 2015 Mark H Weaver <mhw@netris.org>
;;; ;;;
;;; This file is part of GNU Guix. ;;; This file is part of GNU Guix.
@ -18,6 +18,7 @@
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (gnu build activation) (define-module (gnu build activation)
#:use-module (gnu system accounts)
#:use-module (gnu build linux-boot) #:use-module (gnu build linux-boot)
#:use-module (guix build utils) #:use-module (guix build utils)
#:use-module (ice-9 ftw) #:use-module (ice-9 ftw)
@ -212,19 +213,24 @@ logged in."
(apply add-user name group rest))) (apply add-user name group rest)))
(define (activate-users+groups users groups) (define (activate-users+groups users groups)
"Make sure the accounts listed in USERS and the user groups listed in GROUPS "Make sure USERS (a list of user account records) and GROUPS (a list of user
are all available. group records) are all available."
Each item in USERS is a list of all the characteristics of a user account;
each item in GROUPS is a tuple with the group name, group password or #f, and
numeric gid or #f."
(define (touch file) (define (touch file)
(close-port (open-file file "a0b"))) (close-port (open-file file "a0b")))
(define activate-user (define activate-user
(match-lambda (lambda (user)
((name uid group supplementary-groups comment home create-home? (let ((name (user-account-name user))
shell password system?) (uid (user-account-uid user))
(group (user-account-group user))
(supplementary-groups
(user-account-supplementary-groups user))
(comment (user-account-comment user))
(home (user-account-home-directory user))
(create-home? (user-account-create-home-directory? user))
(shell (user-account-shell user))
(password (user-account-password user))
(system? (user-account-system? user)))
(let ((profile-dir (string-append "/var/guix/profiles/per-user/" (let ((profile-dir (string-append "/var/guix/profiles/per-user/"
name))) name)))
(ensure-user name group (ensure-user name group
@ -251,14 +257,14 @@ numeric gid or #f."
(mkdir-p "/var/lib") (mkdir-p "/var/lib")
;; Create the root account so we can use 'useradd' and 'groupadd'. ;; Create the root account so we can use 'useradd' and 'groupadd'.
(activate-user (find (match-lambda (activate-user (find (compose zero? user-account-uid) users))
((name (? zero?) _ ...) #t)
(_ #f))
users))
;; Then create the groups. ;; Then create the groups.
(for-each (match-lambda (for-each (lambda (group)
((name password gid system?) (let ((name (user-group-name group))
(password (user-group-password group))
(gid (user-group-id group))
(system? (user-group-system? group)))
(unless (false-if-exception (getgrnam name)) (unless (false-if-exception (getgrnam name))
(add-group name (add-group name
#:gid gid #:password password #:gid gid #:password password
@ -272,23 +278,21 @@ numeric gid or #f."
(for-each delete-user (for-each delete-user
(lset-difference string=? (lset-difference string=?
(map passwd:name (current-users)) (map passwd:name (current-users))
(match users (map user-account-name users)))
(((names . _) ...)
names))))
(for-each delete-group (for-each delete-group
(lset-difference string=? (lset-difference string=?
(map group:name (current-groups)) (map group:name (current-groups))
(match groups (map user-group-name groups))))
(((names . _) ...)
names)))))
(define (activate-user-home users) (define (activate-user-home users)
"Create and populate the home directory of USERS, a list of tuples, unless "Create and populate the home directory of USERS, a list of tuples, unless
they already exist." they already exist."
(define ensure-user-home (define ensure-user-home
(match-lambda (lambda (user)
((name uid group supplementary-groups comment home create-home? (let ((name (user-account-name user))
shell password system?) (home (user-account-home-directory user))
(create-home? (user-account-create-home-directory? user))
(system? (user-account-system? user)))
;; The home directories of system accounts are created during ;; The home directories of system accounts are created during
;; activation, not here. ;; activation, not here.
(unless (or (not home) (not create-home?) system? (unless (or (not home) (not create-home?) system?

View File

@ -18,6 +18,7 @@
(define-module (gnu system accounts) (define-module (gnu system accounts)
#:use-module (guix records) #:use-module (guix records)
#:use-module (ice-9 match)
#:export (user-account #:export (user-account
user-account? user-account?
user-account-name user-account-name
@ -38,6 +39,9 @@
user-group-id user-group-id
user-group-system? user-group-system?
sexp->user-account
sexp->user-group
default-shell)) default-shell))
@ -79,3 +83,27 @@
(id user-group-id (default #f)) (id user-group-id (default #f))
(system? user-group-system? ; Boolean (system? user-group-system? ; Boolean
(default #f))) (default #f)))
(define (sexp->user-group sexp)
"Take SEXP, a tuple as returned by 'user-group->gexp', and turn it into a
user-group record."
(match sexp
((name password id system?)
(user-group (name name)
(password password)
(id id)
(system? system?)))))
(define (sexp->user-account sexp)
"Take SEXP, a tuple as returned by 'user-account->gexp', and turn it into a
user-account record."
(match sexp
((name uid group supplementary-groups comment home-directory
create-home-directory? shell password system?)
(user-account (name name) (uid uid) (group group)
(supplementary-groups supplementary-groups)
(comment comment)
(home-directory home-directory)
(create-home-directory? create-home-directory?)
(shell shell) (password password)
(system? system?)))))

View File

@ -298,11 +298,14 @@ group."
(assert-valid-users/groups accounts groups) (assert-valid-users/groups accounts groups)
;; Add users and user groups. ;; Add users and user groups.
(with-imported-modules (source-module-closure '((gnu system accounts)))
#~(begin #~(begin
(use-modules (gnu system accounts))
(setenv "PATH" (setenv "PATH"
(string-append #$(@ (gnu packages admin) shadow) "/sbin")) (string-append #$(@ (gnu packages admin) shadow) "/sbin"))
(activate-users+groups (list #$@user-specs) (activate-users+groups (map sexp->user-account (list #$@user-specs))
(list #$@group-specs)))) (map sexp->user-group (list #$@group-specs))))))
(define (account-shepherd-service accounts+groups) (define (account-shepherd-service accounts+groups)
"Return a Shepherd service that creates the home directories for the user "Return a Shepherd service that creates the home directories for the user
@ -322,12 +325,15 @@ accounts among ACCOUNTS+GROUPS."
(list (shepherd-service (list (shepherd-service
(requirement '(file-systems)) (requirement '(file-systems))
(provision '(user-homes)) (provision '(user-homes))
(modules '((gnu build activation))) (modules '((gnu build activation)
(gnu system accounts)))
(start (with-imported-modules (source-module-closure (start (with-imported-modules (source-module-closure
'((gnu build activation))) '((gnu build activation)
(gnu system accounts)))
#~(lambda () #~(lambda ()
(activate-user-home (activate-user-home
(list #$@(map user-account->gexp accounts))) (map sexp->user-account
(list #$@(map user-account->gexp accounts))))
#f))) ;stop #f))) ;stop
(stop #~(const #f)) (stop #~(const #f))
(respawn? #f) (respawn? #f)