public inbox for isar-users@googlegroups.com
 help / color / mirror / Atom feed
From: claudius.heine.ext@siemens.com
To: isar-users@googlegroups.com
Cc: Claudius Heine <ch@denx.de>
Subject: [PATCH v4 4/8] meta/classes: add image-account-extension class
Date: Thu, 23 May 2019 16:55:17 +0200	[thread overview]
Message-ID: <20190523145521.23050-5-claudius.heine.ext@siemens.com> (raw)
In-Reply-To: <20190523145521.23050-1-claudius.heine.ext@siemens.com>

From: Claudius Heine <ch@denx.de>

This class allows to configure user and group accounts of the image.

Groups or users that should be configured/created are added into the
`GROUPS` or `USERS` variable.

The configuration itself is then added to each groups or users
`GROUP_<groupname>` or `USER_<username>` flags.

The flags available for groups are `gid` and `flags`. The `flags`
variable contains some additional options for the group. With this patch
only `system` is supported for groups, allowing to create groups with
`groupadd` with the `--system` parameter.

The flags available for users are `password`, `expire`, `inactive`,
`uid`, `gid`, `comment`, `home`, `shell`, `groups` and `flags`. The
additional flags for users are `no-create-home`, `create-home`, `system`
and `allow-empty-password`.

Signed-off-by: Claudius Heine <ch@denx.de>
---
 meta/classes/image-account-extension.bbclass | 257 +++++++++++++++++++
 meta/classes/image.bbclass                   |   1 +
 2 files changed, 258 insertions(+)
 create mode 100644 meta/classes/image-account-extension.bbclass

diff --git a/meta/classes/image-account-extension.bbclass b/meta/classes/image-account-extension.bbclass
new file mode 100644
index 0000000..22754da
--- /dev/null
+++ b/meta/classes/image-account-extension.bbclass
@@ -0,0 +1,257 @@
+# This software is a part of ISAR.
+# Copyright (C) Siemens AG, 2019
+#
+# SPDX-License-Identifier: MIT
+#
+# This class extends the image.bbclass for creating user accounts and groups.
+
+USERS ??= ""
+
+#USERS += "root"
+#USER_root[password] = "" # Encrypted password
+#USER_root[expire] = ""
+#USER_root[inactive] = ""
+#USER_root[uid] = ""
+#USER_root[gid] = "" # If first character is a number: gid, otherwise groupname
+#USER_root[comment] = "The ultimate root user"
+#USER_root[home] = "/home/root"
+#USER_root[shell] = "/bin/sh"
+#USER_root[groups] = "audio video"
+#USER_root[flags] = "no-create-home create-home system allow-empty-password"
+
+GROUPS ??= ""
+
+#GROUPS += "root"
+#GROUP_root[gid] = ""
+#GROUP_root[flags] = "system"
+
+def gen_accounts_array(d, listname, entryname, flags, verb_flags=None):
+    from itertools import chain
+
+    entries = (d.getVar(listname, True) or "").split()
+    return " ".join(
+        ":".join(
+            chain(
+                (entry,),
+                (
+                    (",".join(
+                        (
+                            d.getVarFlag(entryname + "_" + entry, flag, True) or ""
+                        ).split()
+                    ) if flag not in (verb_flags or []) else (
+                        d.getVarFlag(entryname + "_" + entry, flag, True) or ""
+                    )).replace(":","=")
+                    for flag in flags
+                ),
+            )
+        )
+        for entry in entries
+    )
+
+# List of space separated entries, where each entry has the format:
+# username:encryptedpassword:expiredate:inactivenumber:userid:groupid:comment:homedir:shell:group1,group2:flag1,flag2
+IMAGE_ACCOUNTS_USERS =+ "${@gen_accounts_array(d, 'USERS', 'USER', ['password',  'expire', 'inactive', 'uid', 'gid', 'comment', 'home', 'shell', 'groups', 'flags'], ['password', 'comment', 'home', 'shell'])}"
+
+# List of space separated entries, where each entry has the format:
+# groupname:groupid:flag1,flag2
+IMAGE_ACCOUNTS_GROUPS =+ "${@gen_accounts_array(d, 'GROUPS', 'GROUP', ['gid', 'flags'])}"
+
+ROOTFS_CONFIGURE_COMMAND += "image_configure_accounts"
+image_configure_accounts[weight] = "3"
+image_configure_accounts() {
+    # Create groups
+    # Add space to the end of the list:
+    list='${@" ".join(d.getVar('IMAGE_ACCOUNTS_GROUPS', True).split())} '
+    while true; do
+        # Pop first group entry:
+        list_rest="${list#*:*:* }"
+        entry="${list%%${list_rest}}"
+        list="${list_rest}"
+
+        if [ -z "${entry}" ]; then
+            break
+        fi
+
+        # Add colon to the end of the entry and remove trailing space:
+        entry="${entry% }:"
+
+        # Decode entries:
+        name="${entry%%:*}"
+        entry="${entry#${name}:}"
+
+        gid="${entry%%:*}"
+        entry="${entry#${gid}:}"
+
+        flags="${entry%%:*}"
+        entry="${entry#${flags}:}"
+
+        flags=",${flags}," # Needed for searching for substrings
+
+        # Check if user already exists:
+        if grep -q "^${name}:" '${ROOTFSDIR}/etc/group'; then
+            exists="y"
+        else
+            exists="n"
+        fi
+
+        # Create arguments:
+        set -- # clear arguments
+
+        if [ -n "$gid" ]; then
+            set -- "$@" --gid "$gid"
+        fi
+
+        if [ "n" = "$exists" ]; then
+            if [ "${flags}" != "${flags%*,system,*}" ]; then
+                set -- "$@" --system
+            fi
+        fi
+
+        # Create or modify groups:
+        if [ "y" = "$exists" ]; then
+            if [ -z "$@" ]; then
+                echo "Do not execute groupmod (no changes)."
+            else
+                echo "Execute groupmod with \"$@\" for \"$name\""
+                sudo -E chroot '${ROOTFSDIR}' \
+                    /usr/sbin/groupmod "$@" "$name"
+            fi
+        else
+            echo "Execute groupadd with \"$@\" for \"$name\""
+            sudo -E chroot '${ROOTFSDIR}' \
+                /usr/sbin/groupadd "$@" "$name"
+        fi
+    done
+
+    # Create users
+    list='${@" ".join(d.getVar('IMAGE_ACCOUNTS_USERS', True).split())} '
+    while true; do
+        # Pop first user entry:
+        list_rest="${list#*:*:*:*:*:*:*:*:*:*:* }"
+        entry="${list%%${list_rest}}"
+        list="${list_rest}"
+
+        if [ -z "${entry}" ]; then
+            break
+        fi
+
+        # Add colon to the end of the entry and remove trailing space:
+        entry="${entry% }:"
+
+        # Decode entries:
+        name="${entry%%:*}"
+        entry="${entry#${name}:}"
+
+        password="${entry%%:*}"
+        entry="${entry#${password}:}"
+
+        expire="${entry%%:*}"
+        entry="${entry#${expire}:}"
+
+        inactive="${entry%%:*}"
+        entry="${entry#${inactive}:}"
+
+        uid="${entry%%:*}"
+        entry="${entry#${uid}:}"
+
+        gid="${entry%%:*}"
+        entry="${entry#${gid}:}"
+
+        comment="${entry%%:*}"
+        entry="${entry#${comment}:}"
+
+        home="${entry%%:*}"
+        entry="${entry#${home}:}"
+
+        shell="${entry%%:*}"
+        entry="${entry#${shell}:}"
+
+        groups="${entry%%:*}"
+        entry="${entry#${groups}:}"
+
+        flags="${entry%%:*}"
+        entry="${entry#${flags}:}"
+
+        flags=",${flags}," # Needed for searching for substrings
+
+        # Check if user already exists:
+        if grep -q "^${name}:" '${ROOTFSDIR}/etc/passwd'; then
+            exists="y"
+        else
+            exists="n"
+        fi
+
+        # Create arguments:
+        set -- # clear arguments
+
+        if [ -n "$expire" ]; then
+            set -- "$@" --expiredate "$expire"
+        fi
+
+        if [ -n "$inactive" ]; then
+            set -- "$@" --inactive "$inactive"
+        fi
+
+        if [ -n "$uid" ]; then
+            set -- "$@" --uid "$uid"
+        fi
+
+        if [ -n "$gid" ]; then
+            set -- "$@" --gid "$gid"
+        fi
+
+        if [ -n "$comment" ]; then
+            set -- "$@" --comment "$comment"
+        fi
+
+        if [ -n "$home" ]; then
+            if [ "y" = "$exists" ]; then
+                set -- "$@" --home "$home" --move-home
+            else
+                set -- "$@" --home-dir "$home"
+            fi
+        fi
+
+        if [ -n "$shell" ]; then
+            set -- "$@" --shell "$shell"
+        fi
+
+        if [ -n "$groups" ]; then
+            set -- "$@" --groups "$groups"
+        fi
+
+        if [ "n" = "$exists" ]; then
+            if [ "${flags}" != "${flags%*,system,*}" ]; then
+                set -- "$@" --system
+            fi
+            if [ "${flags}" != "${flags%*,no-create-home,*}" ]; then
+                set -- "$@" --no-create-home
+            else
+                if [ "${flags}" != "${flags%*,create-home,*}" ]; then
+                    set -- "$@" --create-home
+                fi
+            fi
+        fi
+
+        # Create or modify users:
+        if [ "y" = "$exists" ]; then
+            if [ -z "$@" ]; then
+                echo "Do not execute usermod (no changes)."
+            else
+                echo "Execute usermod with \"$@\" for \"$name\""
+                sudo -E chroot '${ROOTFSDIR}' \
+                    /usr/sbin/usermod "$@" "$name"
+            fi
+        else
+            echo "Execute useradd with \"$@\" for \"$name\""
+            sudo -E chroot '${ROOTFSDIR}' \
+                /usr/sbin/useradd "$@" "$name"
+        fi
+
+        # Set password:
+        if [ -n "$password" -o "${flags}" != "${flags%*,allow-empty-password,*}" ]; then
+            printf '%s:%s' "$name" "$password" | sudo chroot '${ROOTFSDIR}' \
+                /usr/sbin/chpasswd -e
+        fi
+    done
+}
diff --git a/meta/classes/image.bbclass b/meta/classes/image.bbclass
index dce6638..ef7983b 100644
--- a/meta/classes/image.bbclass
+++ b/meta/classes/image.bbclass
@@ -61,6 +61,7 @@ inherit image-cache-extension
 inherit image-tools-extension
 inherit image-postproc-extension
 inherit image-locales-extension
+inherit image-account-extension
 
 # Extra space for rootfs in MB
 ROOTFS_EXTRA ?= "64"
-- 
2.20.1


  parent reply	other threads:[~2019-05-23 14:55 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-05-23 14:55 [PATCH v4 0/8] pre-processing pipeline and transient package replacement claudius.heine.ext
2019-05-23 14:55 ` [PATCH v4 1/8] meta: remove transient package support claudius.heine.ext
2019-05-23 14:55 ` [PATCH v4 2/8] split up isar-bootstrap helper and implement pre-process pipeline claudius.heine.ext
2019-05-24 12:49   ` Maxim Yu. Osipov
2019-05-27  6:55     ` Claudius Heine
2019-05-27  7:20       ` Maxim Yu. Osipov
2019-05-27  7:36         ` Maxim Yu. Osipov
2019-05-27  8:30           ` Claudius Heine
2019-05-27  9:03         ` Claudius Heine
2019-05-27  9:49           ` Maxim Yu. Osipov
2019-05-27 10:44             ` [PATCH] rootfs.bbclass: add comment about task weights claudius.heine.ext
2019-05-29 12:38               ` Maxim Yu. Osipov
2019-08-14 16:00   ` [PATCH v4 2/8] split up isar-bootstrap helper and implement pre-process pipeline Jan Kiszka
2019-08-19  6:59     ` Claudius Heine
2019-08-19  7:02       ` Jan Kiszka
2019-08-19  7:09         ` Claudius Heine
2019-05-23 14:55 ` [PATCH v4 3/8] meta/classes: add image-locales-extension class claudius.heine.ext
2019-05-23 14:55 ` claudius.heine.ext [this message]
2019-05-31  7:29   ` [PATCH v4 4/8] meta/classes: add image-account-extension class Jan Kiszka
2019-06-03  9:14     ` Claudius Heine
2019-05-23 14:55 ` [PATCH v4 5/8] doc: update description of image customization claudius.heine.ext
2019-05-23 14:55 ` [PATCH v4 6/8] doc: some fixes claudius.heine.ext
2019-05-23 14:55 ` [PATCH v4 7/8] meta-isar: local.conf.sample: update root password and isar user creation claudius.heine.ext
2019-05-23 14:55 ` [PATCH v4 8/8] RECIPE-API-CHANGELOG: update transient package removal + root password claudius.heine.ext
2019-05-24 12:56 ` [PATCH v4 0/8] pre-processing pipeline and transient package replacement Maxim Yu. Osipov
2019-05-27  7:56   ` Claudius Heine
2019-05-27  8:10     ` Maxim Yu. Osipov
2019-05-27  8:24       ` Claudius Heine
2019-05-27  9:28         ` Maxim Yu. Osipov
2019-05-27 15:22 ` Maxim Yu. Osipov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190523145521.23050-5-claudius.heine.ext@siemens.com \
    --to=claudius.heine.ext@siemens.com \
    --cc=ch@denx.de \
    --cc=isar-users@googlegroups.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox