1 |
A GLEP 81-compliant eclass to create user account packages. |
2 |
--- |
3 |
eclass/acct-user.eclass | 249 ++++++++++++++++++++++++++++++++++++++++ |
4 |
1 file changed, 249 insertions(+) |
5 |
create mode 100644 eclass/acct-user.eclass |
6 |
|
7 |
diff --git a/eclass/acct-user.eclass b/eclass/acct-user.eclass |
8 |
new file mode 100644 |
9 |
index 000000000000..b856a350083d |
10 |
--- /dev/null |
11 |
+++ b/eclass/acct-user.eclass |
12 |
@@ -0,0 +1,249 @@ |
13 |
+# Copyright 2019 Gentoo Authors |
14 |
+# Distributed under the terms of the GNU General Public License v2 |
15 |
+ |
16 |
+# @ECLASS: acct-user.eclass |
17 |
+# @MAINTAINER: |
18 |
+# Michał Górny <mgorny@g.o> |
19 |
+# @AUTHOR: |
20 |
+# Michael Orlitzky <mjo@g.o> |
21 |
+# Michał Górny <mgorny@g.o> |
22 |
+# @BLURB: Eclass used to create and maintain a single user entry |
23 |
+# @DESCRIPTION: |
24 |
+# This eclass represents and creates a single user entry. The name |
25 |
+# of the user is derived from ${PN}, while (preferred) UID needs to |
26 |
+# be specified via ACCT_USER_ID. Additional variables are provided |
27 |
+# to override the default home directory, shell and add group |
28 |
+# membership. Packages needing the user in question should depend |
29 |
+# on the package providing it. |
30 |
+# |
31 |
+# The ebuild needs to call acct-user_add_deps after specifying |
32 |
+# ACCT_USER_GROUPS. |
33 |
+# |
34 |
+# Example: |
35 |
+# If your package needs user 'foo' belonging to same-named group, you |
36 |
+# create 'acct-user/foo' package and add an ebuild with the following |
37 |
+# contents: |
38 |
+# |
39 |
+# @CODE |
40 |
+# EAPI=7 |
41 |
+# inherit acct-user |
42 |
+# ACCT_USER_ID=200 |
43 |
+# ACCT_USER_GROUPS=( foo ) |
44 |
+# acct-user_add_deps |
45 |
+# @CODE |
46 |
+# |
47 |
+# Then you add appropriate dependency to your package. The dependency |
48 |
+# type(s) should be: |
49 |
+# - DEPEND (+ RDEPEND) if the user is already needed at build time, |
50 |
+# - RDEPEND if it is needed at install time (e.g. you 'fowners' files |
51 |
+# in pkg_preinst) or run time. |
52 |
+ |
53 |
+if [[ -z ${_ACCT_USER_ECLASS} ]]; then |
54 |
+_ACCT_USER_ECLASS=1 |
55 |
+ |
56 |
+case ${EAPI:-0} in |
57 |
+ 7) ;; |
58 |
+ *) die "EAPI=${EAPI} not supported";; |
59 |
+esac |
60 |
+ |
61 |
+inherit user |
62 |
+ |
63 |
+[[ ${CATEGORY} == acct-user ]] || |
64 |
+ die "Ebuild error: this eclass can be used only in acct-user category!" |
65 |
+ |
66 |
+ |
67 |
+# << Eclass variables >> |
68 |
+ |
69 |
+# @ECLASS-VARIABLE: ACCT_USER_NAME |
70 |
+# @INTERNAL |
71 |
+# @DESCRIPTION: |
72 |
+# The name of the user. This is forced to ${PN} and the policy prohibits |
73 |
+# it from being changed. |
74 |
+ACCT_USER_NAME=${PN} |
75 |
+readonly ACCT_USER_NAME |
76 |
+ |
77 |
+# @ECLASS-VARIABLE: ACCT_USER_ID |
78 |
+# @REQUIRED |
79 |
+# @DESCRIPTION: |
80 |
+# Preferred UID for the new user. This variable is obligatory, and its |
81 |
+# value must be unique across all user packages. |
82 |
+ |
83 |
+# @ECLASS-VARIABLE: ACCT_USER_ENFORCE_ID |
84 |
+# @DESCRIPTION: |
85 |
+# If set to a non-null value, the eclass will require the user to have |
86 |
+# specified UID. If the user already exists with another UID, or |
87 |
+# the UID is taken by another user, the install will fail. |
88 |
+: ${ACCT_USER_ENFORCE_ID:=} |
89 |
+ |
90 |
+# @ECLASS-VARIABLE: ACCT_USER_SHELL |
91 |
+# @DESCRIPTION: |
92 |
+# The shell to use for the user. If not specified, a 'nologin' variant |
93 |
+# for the system is used. |
94 |
+: ${ACCT_USER_SHELL:=-1} |
95 |
+ |
96 |
+# @ECLASS-VARIABLE: ACCT_USER_HOME |
97 |
+# @DESCRIPTION: |
98 |
+# The home directory for the user. If not specified, /dev/null is used. |
99 |
+# The directory will be created with appropriate permissions if it does |
100 |
+# not exist. When updating, existing home directory will not be moved. |
101 |
+: ${ACCT_USER_HOME:=/dev/null} |
102 |
+ |
103 |
+# @ECLASS-VARIABLE: ACCT_USER_HOME_OWNER |
104 |
+# @DEFAULT_UNSET |
105 |
+# @DESCRIPTION: |
106 |
+# The ownership to use for the home directory, in chown ([user][:group]) |
107 |
+# syntax. Defaults to the newly created user, and its primary group. |
108 |
+ |
109 |
+# @ECLASS-VARIABLE: ACCT_USER_HOME_PERMS |
110 |
+# @DESCRIPTION: |
111 |
+# The permissions to use for the home directory, in chmod (octal |
112 |
+# or verbose) form. |
113 |
+: ${ACCT_USER_HOME_PERMS:=0755} |
114 |
+ |
115 |
+# @ECLASS-VARIABLE: ACCT_USER_GROUPS |
116 |
+# @REQUIRED |
117 |
+# @DESCRIPTION: |
118 |
+# List of groups the user should belong to. This must be a bash |
119 |
+# array. |
120 |
+ |
121 |
+ |
122 |
+# << Boilerplate ebuild variables >> |
123 |
+: ${DESCRIPTION:="Service user: ${ACCT_USER_NAME}"} |
124 |
+: ${HOMEPAGE:=https://www.gentoo.org/} |
125 |
+: ${SLOT:=0} |
126 |
+: ${KEYWORDS:=alpha amd64 arm arm64 hppa ia64 m68k ~mips ppc ppc64 ~riscv s390 sh sparc x86 ~ppc-aix ~x64-cygwin ~amd64-fbsd ~x86-fbsd ~amd64-linux ~x86-linux ~ppc-macos ~x64-macos ~x86-macos ~m68k-mint ~sparc-solaris ~sparc64-solaris ~x64-solaris ~x86-solaris} |
127 |
+S=${WORKDIR} |
128 |
+ |
129 |
+ |
130 |
+# << API functions >> |
131 |
+ |
132 |
+# @FUNCTION: acct-user_add_deps |
133 |
+# @DESCRIPTION: |
134 |
+# Generate appropriate RDEPEND from ACCT_USER_GROUPS. This must be |
135 |
+# called if ACCT_USER_GROUPS are set. |
136 |
+acct-user_add_deps() { |
137 |
+ debug-print-function ${FUNCNAME} "${@}" |
138 |
+ |
139 |
+ # ACCT_USER_GROUPS sanity check |
140 |
+ if ! declare -p ACCT_USER_GROUPS &>/dev/null; then |
141 |
+ die 'ACCT_USER_GROUPS must be specified.' |
142 |
+ elif [[ $(declare -p ACCT_USER_GROUPS) != "declare -a"* ]]; then |
143 |
+ die 'ACCT_USER_GROUPS must be an array.' |
144 |
+ fi |
145 |
+ |
146 |
+ RDEPEND+=${ACCT_USER_GROUPS[*]/#/ acct-group/} |
147 |
+ _ACCT_USER_ADD_DEPS_CALLED=1 |
148 |
+} |
149 |
+ |
150 |
+ |
151 |
+# << Phase functions >> |
152 |
+EXPORT_FUNCTIONS pkg_pretend src_install pkg_preinst pkg_postinst \ |
153 |
+ pkg_prerm |
154 |
+ |
155 |
+# @FUNCTION: acct-user_pkg_pretend |
156 |
+# @DESCRIPTION: |
157 |
+# Performs sanity checks for correct eclass usage, and early-checks |
158 |
+# whether requested UID can be enforced. |
159 |
+acct-user_pkg_pretend() { |
160 |
+ debug-print-function ${FUNCNAME} "${@}" |
161 |
+ |
162 |
+ # verify that acct-user_add_deps() has been called |
163 |
+ # (it verifies ACCT_USER_GROUPS itself) |
164 |
+ if [[ -z ${_ACCT_USER_ADD_DEPS_CALLED} ]]; then |
165 |
+ die "Ebuild error: acct-user_add_deps must have been called in global scope!" |
166 |
+ fi |
167 |
+ |
168 |
+ # verify ACCT_USER_ID |
169 |
+ [[ -n ${ACCT_USER_ID} ]] || die "Ebuild error: ACCT_USER_ID must be set!" |
170 |
+ [[ ${ACCT_USER_ID} -ge 0 ]] || die "Ebuild errors: ACCT_USER_ID=${ACCT_USER_ID} invalid!" |
171 |
+ |
172 |
+ # check for ACCT_USER_ID collisions early |
173 |
+ if [[ -n ${ACCT_USER_ENFORCE_ID} ]]; then |
174 |
+ local user_by_id=$(egetusername "${ACCT_USER_ID}") |
175 |
+ local user_by_name=$(egetent passwd "${ACCT_USER_NAME}") |
176 |
+ if [[ -n ${user_by_id} ]]; then |
177 |
+ if [[ ${user_by_id} != ${ACCT_USER_NAME} ]]; then |
178 |
+ eerror "The required UID is already taken by another user." |
179 |
+ eerror " UID: ${ACCT_USER_ID}" |
180 |
+ eerror " needed for: ${ACCT_USER_NAME}" |
181 |
+ eerror " current user: ${user_by_id}" |
182 |
+ die "UID ${ACCT_USER_ID} taken already" |
183 |
+ fi |
184 |
+ elif [[ -n ${user_by_name} ]]; then |
185 |
+ eerror "The requested user exists already with wrong UID." |
186 |
+ eerror " username: ${ACCT_USER_NAME}" |
187 |
+ eerror " requested UID: ${ACCT_USER_ID}" |
188 |
+ eerror " current entry: ${user_by_name}" |
189 |
+ die "Username ${ACCT_USER_NAME} exists with wrong UID" |
190 |
+ fi |
191 |
+ fi |
192 |
+} |
193 |
+ |
194 |
+# @FUNCTION: acct-user_src_install |
195 |
+# @DESCRIPTION: |
196 |
+# Installs a keep-file into the user's home directory to ensure it is |
197 |
+# owned by the package. |
198 |
+acct-user_src_install() { |
199 |
+ debug-print-function ${FUNCNAME} "${@}" |
200 |
+ |
201 |
+ if [[ ${ACCT_USER_HOME} != /dev/null ]]; then |
202 |
+ # note: we can't set permissions here since the user isn't |
203 |
+ # created yet |
204 |
+ keepdir "${ACCT_USER_HOME}" |
205 |
+ fi |
206 |
+} |
207 |
+ |
208 |
+# @FUNCTION: acct-user_pkg_preinst |
209 |
+# @DESCRIPTION: |
210 |
+# Creates the user if it does not exist yet. Sets permissions |
211 |
+# of the home directory in install image. |
212 |
+acct-user_pkg_preinst() { |
213 |
+ debug-print-function ${FUNCNAME} "${@}" |
214 |
+ |
215 |
+ local groups=${ACCT_USER_GROUPS[*]} |
216 |
+ enewuser -F -M "${ACCT_USER_NAME}" "${ACCT_USER_ID}" \ |
217 |
+ "${ACCT_USER_SHELL}" "${ACCT_USER_HOME}" "${groups// /,}" |
218 |
+ |
219 |
+ if [[ ${ACCT_USER_HOME} != /dev/null ]]; then |
220 |
+ # default ownership to user:group |
221 |
+ if [[ -z ${ACCT_USER_HOME_OWNER} ]]; then |
222 |
+ ACCT_USER_HOME_OWNER=${ACCT_USER_NAME} |
223 |
+ if [[ -n ${ACCT_USER_GROUPS[0]} ]]; then |
224 |
+ ACCT_USER_HOME_OWNER+=":${ACCT_USER_GROUPS[0]}" |
225 |
+ fi |
226 |
+ fi |
227 |
+ fowners "${ACCT_USER_HOME_OWNER}" "${ACCT_USER_HOME}" |
228 |
+ fperms "${ACCT_USER_HOME_PERMS}" "${ACCT_USER_HOME}" |
229 |
+ fi |
230 |
+} |
231 |
+ |
232 |
+# @FUNCTION: acct-user_pkg_postinst |
233 |
+# @DESCRIPTION: |
234 |
+# Updates user properties if necessary. This needs to be done after |
235 |
+# new home directory is installed. |
236 |
+acct-user_pkg_postinst() { |
237 |
+ debug-print-function ${FUNCNAME} "${@}" |
238 |
+ |
239 |
+ # NB: eset* functions check current value |
240 |
+ esethome "${ACCT_USER_NAME}" "${ACCT_USER_HOME}" |
241 |
+ esetshell "${ACCT_USER_NAME}" "${ACCT_USER_SHELL}" |
242 |
+ local groups=${ACCT_USER_GROUPS[*]} |
243 |
+ esetgroups "${ACCT_USER_NAME}" "${groups// /,}" |
244 |
+ # comment field can not contain colons |
245 |
+ esetcomment "${ACCT_USER_NAME}" "${DESCRIPTION//[:,=]/;}" |
246 |
+} |
247 |
+ |
248 |
+# @FUNCTION: acct-user_pkg_prerm |
249 |
+# @DESCRIPTION: |
250 |
+# Ensures that the user account is locked out when it is removed. |
251 |
+acct-user_pkg_prerm() { |
252 |
+ debug-print-function ${FUNCNAME} "${@}" |
253 |
+ |
254 |
+ if [[ -z ${REPLACED_BY_VERSION} ]]; then |
255 |
+ esetshell "${ACCT_USER_NAME}" -1 |
256 |
+ esetcomment "${ACCT_USER_NAME}" \ |
257 |
+ "$(egetcomment "${ACCT_USER_NAME}"); user account removed @ $(date +%Y-%m-%d)" |
258 |
+ fi |
259 |
+} |
260 |
+ |
261 |
+fi |
262 |
-- |
263 |
2.22.0.rc3 |