image-account-extension.bbclass 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. # This software is a part of ISAR.
  2. # Copyright (C) Siemens AG, 2019
  3. #
  4. # SPDX-License-Identifier: MIT
  5. #
  6. # This class extends the image.bbclass for creating user accounts and groups.
  7. USERS ??= ""
  8. #USERS += "root"
  9. #USER_root[password] = "" # Encrypted password, or clear-text when [flags] = "clear-text-password"
  10. #USER_root[expire] = ""
  11. #USER_root[inactive] = ""
  12. #USER_root[uid] = ""
  13. #USER_root[gid] = "" # If first character is a number: gid, otherwise groupname
  14. #USER_root[comment] = "The ultimate root user"
  15. #USER_root[home] = "/home/root"
  16. #USER_root[shell] = "/bin/sh"
  17. #USER_root[groups] = "audio video"
  18. #USER_root[flags] = "no-create-home create-home system allow-empty-password clear-text-password"
  19. GROUPS ??= ""
  20. #GROUPS += "root"
  21. #GROUP_root[gid] = ""
  22. #GROUP_root[flags] = "system"
  23. def gen_accounts_array(d, listname, entryname, flags, verb_flags=None):
  24. from itertools import chain
  25. entries = (d.getVar(listname, True) or "").split()
  26. return " ".join(
  27. ":".join(
  28. chain(
  29. (entry,),
  30. (
  31. (",".join(
  32. (
  33. d.getVarFlag(entryname + "_" + entry, flag, True) or ""
  34. ).split()
  35. ) if flag not in (verb_flags or []) else (
  36. d.getVarFlag(entryname + "_" + entry, flag, True) or ""
  37. )).replace(":","=")
  38. for flag in flags
  39. ),
  40. )
  41. )
  42. for entry in entries
  43. )
  44. # List of space separated entries, where each entry has the format:
  45. # username:encryptedpassword:expiredate:inactivenumber:userid:groupid:comment:homedir:shell:group1,group2:flag1,flag2
  46. IMAGE_ACCOUNTS_USERS =+ "${@gen_accounts_array(d, 'USERS', 'USER', ['password', 'expire', 'inactive', 'uid', 'gid', 'comment', 'home', 'shell', 'groups', 'flags'], ['password', 'comment', 'home', 'shell'])}"
  47. # List of space separated entries, where each entry has the format:
  48. # groupname:groupid:flag1,flag2
  49. IMAGE_ACCOUNTS_GROUPS =+ "${@gen_accounts_array(d, 'GROUPS', 'GROUP', ['gid', 'flags'])}"
  50. do_rootfs_install[vardeps] += "${IMAGE_ACCOUNTS_GROUPS} ${IMAGE_ACCOUNTS_USERS}"
  51. ROOTFS_CONFIGURE_COMMAND += "image_configure_accounts"
  52. image_configure_accounts[weight] = "3"
  53. image_configure_accounts() {
  54. # Create groups
  55. # Add space to the end of the list:
  56. list='${@" ".join(d.getVar('IMAGE_ACCOUNTS_GROUPS', True).split())} '
  57. while true; do
  58. # Pop first group entry:
  59. list_rest="${list#*:*:* }"
  60. entry="${list%%${list_rest}}"
  61. list="${list_rest}"
  62. if [ -z "${entry}" ]; then
  63. break
  64. fi
  65. # Add colon to the end of the entry and remove trailing space:
  66. entry="${entry% }:"
  67. # Decode entries:
  68. name="${entry%%:*}"
  69. entry="${entry#${name}:}"
  70. gid="${entry%%:*}"
  71. entry="${entry#${gid}:}"
  72. flags="${entry%%:*}"
  73. entry="${entry#${flags}:}"
  74. flags=",${flags}," # Needed for searching for substrings
  75. # Check if user already exists:
  76. if grep -q "^${name}:" '${ROOTFSDIR}/etc/group'; then
  77. exists="y"
  78. else
  79. exists="n"
  80. fi
  81. # Create arguments:
  82. set -- # clear arguments
  83. if [ -n "$gid" ]; then
  84. set -- "$@" --gid "$gid"
  85. fi
  86. if [ "n" = "$exists" ]; then
  87. if [ "${flags}" != "${flags%*,system,*}" ]; then
  88. set -- "$@" --system
  89. fi
  90. fi
  91. # Create or modify groups:
  92. if [ "y" = "$exists" ]; then
  93. if [ -z "$@" ]; then
  94. echo "Do not execute groupmod (no changes)."
  95. else
  96. echo "Execute groupmod with \"$@\" for \"$name\""
  97. sudo -E chroot '${ROOTFSDIR}' \
  98. /usr/sbin/groupmod "$@" "$name"
  99. fi
  100. else
  101. echo "Execute groupadd with \"$@\" for \"$name\""
  102. sudo -E chroot '${ROOTFSDIR}' \
  103. /usr/sbin/groupadd "$@" "$name"
  104. fi
  105. done
  106. # Create users
  107. list='${@" ".join(d.getVar('IMAGE_ACCOUNTS_USERS', True).split())} '
  108. while true; do
  109. # Pop first user entry:
  110. list_rest="${list#*:*:*:*:*:*:*:*:*:*:* }"
  111. entry="${list%%${list_rest}}"
  112. list="${list_rest}"
  113. if [ -z "${entry}" ]; then
  114. break
  115. fi
  116. # Add colon to the end of the entry and remove trailing space:
  117. entry="${entry% }:"
  118. # Decode entries:
  119. name="${entry%%:*}"
  120. entry="${entry#${name}:}"
  121. password="${entry%%:*}"
  122. entry="${entry#${password}:}"
  123. expire="${entry%%:*}"
  124. entry="${entry#${expire}:}"
  125. inactive="${entry%%:*}"
  126. entry="${entry#${inactive}:}"
  127. uid="${entry%%:*}"
  128. entry="${entry#${uid}:}"
  129. gid="${entry%%:*}"
  130. entry="${entry#${gid}:}"
  131. comment="${entry%%:*}"
  132. entry="${entry#${comment}:}"
  133. home="${entry%%:*}"
  134. entry="${entry#${home}:}"
  135. shell="${entry%%:*}"
  136. entry="${entry#${shell}:}"
  137. groups="${entry%%:*}"
  138. entry="${entry#${groups}:}"
  139. flags="${entry%%:*}"
  140. entry="${entry#${flags}:}"
  141. flags=",${flags}," # Needed for searching for substrings
  142. # Check if user already exists:
  143. if grep -q "^${name}:" '${ROOTFSDIR}/etc/passwd'; then
  144. exists="y"
  145. else
  146. exists="n"
  147. fi
  148. # Create arguments:
  149. set -- # clear arguments
  150. if [ -n "$expire" ]; then
  151. set -- "$@" --expiredate "$expire"
  152. fi
  153. if [ -n "$inactive" ]; then
  154. set -- "$@" --inactive "$inactive"
  155. fi
  156. if [ -n "$uid" ]; then
  157. set -- "$@" --uid "$uid"
  158. fi
  159. if [ -n "$gid" ]; then
  160. set -- "$@" --gid "$gid"
  161. fi
  162. if [ -n "$comment" ]; then
  163. set -- "$@" --comment "$comment"
  164. fi
  165. if [ -n "$home" ]; then
  166. if [ "y" = "$exists" ]; then
  167. set -- "$@" --home "$home" --move-home
  168. else
  169. set -- "$@" --home-dir "$home"
  170. fi
  171. fi
  172. if [ -n "$shell" ]; then
  173. set -- "$@" --shell "$shell"
  174. fi
  175. if [ -n "$groups" ]; then
  176. set -- "$@" --groups "$groups"
  177. fi
  178. if [ "n" = "$exists" ]; then
  179. if [ "${flags}" != "${flags%*,system,*}" ]; then
  180. set -- "$@" --system
  181. fi
  182. if [ "${flags}" != "${flags%*,no-create-home,*}" ]; then
  183. set -- "$@" --no-create-home
  184. else
  185. if [ "${flags}" != "${flags%*,create-home,*}" ]; then
  186. set -- "$@" --create-home
  187. fi
  188. fi
  189. fi
  190. # Create or modify users:
  191. if [ "y" = "$exists" ]; then
  192. if [ -z "$@" ]; then
  193. echo "Do not execute usermod (no changes)."
  194. else
  195. echo "Execute usermod with \"$@\" for \"$name\""
  196. sudo -E chroot '${ROOTFSDIR}' \
  197. /usr/sbin/usermod "$@" "$name"
  198. fi
  199. else
  200. echo "Execute useradd with \"$@\" for \"$name\""
  201. sudo -E chroot '${ROOTFSDIR}' \
  202. /usr/sbin/useradd "$@" "$name"
  203. fi
  204. # Set password:
  205. if [ -n "$password" -o "${flags}" != "${flags%*,allow-empty-password,*}" ]; then
  206. chpasswd_args="-e"
  207. if [ "${flags}" != "${flags%*,clear-text-password,*}" ]; then
  208. chpasswd_args=""
  209. fi
  210. printf '%s:%s' "$name" "$password" | sudo chroot '${ROOTFSDIR}' \
  211. /usr/sbin/chpasswd $chpasswd_args
  212. fi
  213. done
  214. }