root/build-tools/build-docker-images/loci/patches/0002-Don-t-fail-if-user-group-exists-in-base-image.patch
Davlet Panech a885f19aec docker-images: add Loci patches
* 0001-starlingx-wheels-from-filesystem-pkg-repos.patch: allows one to
  specify a local wheels tarfile, rather than a URL.

  This patch was effectively hard-coded in the build script -- converted
  to a proper git patch file.

  This patch has a problem that will be addressed by a separate commit:
  it makes docker images unnecessarily large by embedding the entire
  wheel file in one of the intermediate docker FS layers. While the file
  is deleted at the end, that intermediate layer remains as part of the
  docker image.

* 0002-Don-t-fail-if-user-group-exists-in-base-image.patch: the
  StarlingX base image contains user accounts such as "nova" and
  "keystone", causing Loci to fail when trying to create users &
  groups. This unusual behavior of the base image is a side effect
  of this commit:

    https://review.opendev.org/c/starlingx/integ/+/854246

  which looks necessary for unrelated reasons and can't be reverted.

  This patch adds additional parameters to be used in image build
  recipes that work around this problem:

  - UPDATE_SYSTEM_ACCOUNT: if user exists at build time, update its
    UID/GUID/$HOME if necessary
  - NON_UNIQUE_SYSTEM_ACCOUNT: allow non-unique UID/GID when creating
    user & group.

Story: 2010294
Task: 46282

Signed-off-by: Davlet Panech <davlet.panech@windriver.com>
Change-Id: I213e0401326c8a9b70030f4c4504f8ceb8a63945
2022-09-14 10:56:06 -04:00

123 lines
4.5 KiB
Diff

From e2f044c29b7c5d08113ee633abf7c3b9680d583d Mon Sep 17 00:00:00 2001
From: Davlet Panech <davlet.panech@windriver.com>
Date: Thu, 8 Sep 2022 21:13:35 +0000
Subject: [PATCH 2/2] Don't fail if user/group exists in base image
New parameter NON_UNIQUE_SYSTEM_ACCOUNT: allow creation of user/group
with non-unique IDs
New parameter UPDATE_SYSTEM_ACCOUNT: update UID/GID/HOME if account
already exists and doesn't match what we expect.
Signed-off-by: Davlet Panech <davlet.panech@windriver.com>
---
Dockerfile | 2 ++
scripts/create_user.sh | 77 ++++++++++++++++++++++++++++++++++++++++--
2 files changed, 77 insertions(+), 2 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index 145d284..6567c90 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -20,6 +20,8 @@ ARG EXTRA_PYDEP=""
ARG REGISTRY_PROTOCOL="detect"
ARG REGISTRY_INSECURE="False"
ARG KEEP_ALL_WHEELS="False"
+ARG UPDATE_SYSTEM_ACCOUNT="no"
+ARG NON_UNIQUE_SYSTEM_ACCOUNT="no"
ARG UID=42424
ARG GID=42424
diff --git a/scripts/create_user.sh b/scripts/create_user.sh
index 417875d..fb59bd8 100755
--- a/scripts/create_user.sh
+++ b/scripts/create_user.sh
@@ -1,9 +1,82 @@
#!/bin/bash
+#
+# UPDATE_SYSTEM_ACCOUNT: yes/no, default=no
+# if "yes":
+# if user/group exist, change their UID, GID & home dir
+# else:
+# if user/group exist, and their UID/UID/home dir are not what
+# we expect, then fail
+#
+# NON_UNIQUE_SYSTEM_ACCOUNT: yes/no, default=no
+# if yes: allow non-unique UID/GUID
+
set -ex
-groupadd -g ${GID} ${PROJECT}
-useradd -u ${UID} -g ${PROJECT} -M -d /var/lib/${PROJECT} -s /usr/sbin/nologin -c "${PROJECT} user" ${PROJECT}
+if [[ "$NON_UNIQUE_SYSTEM_ACCOUNT" == "yes" ]] ; then
+ non_unique="-o"
+fi
+
+# Group exists?
+if grent="$(getent group ${PROJECT})" ; then
+ # make sure GID matches
+ gid=$(echo "$grent" | awk -v FS=: '{print $3}')
+ if [[ $gid != $GID ]] ; then
+ if [[ "$UPDATE_SYSTEM_ACCOUNT" != "yes" ]] ; then
+ echo "Group ${PROJECT} already exists and has an unexpected GID $gid (expecting: $GID)" >&2
+ exit 1
+ fi
+ echo "## group ${PROJECT}: changing gid $gid -> $GID" >&2
+ groupmod $non_unique -g "$GID" "${PROJECT}"
+ fi
+# no group: create it
+else
+ echo "## group ${PROJECT}: creating gid=$gid" >&2
+ groupadd $non_unique -g ${GID} ${PROJECT}
+fi
+
+# User exists?
+if pwent="$(getent passwd "${PROJECT}")" ; then
+ # make sure GID, UID & home dir match
+ uid=$(echo "$pwent" | awk -v FS=: '{ print $3 }')
+ gid=$(echo "$pwent" | awk -v FS=: '{ print $4 }')
+ homedir=$(echo "$pwent" | awk -v FS=: '{ print $6 }')
+ # check UID
+ if [[ "$uid" != "$UID" ]] ; then
+ if [[ "$UPDATE_SYSTEM_ACCOUNT" != "yes" ]] ; then
+ echo "User ${PROJECT} already exists and has an unexpected UID $uid (expecting: $UID)" >&2
+ exit 1
+ fi
+ echo "## user ${PROJECT}: changing uid $uid -> $UID" >&2
+ usermod $non_unique -u "$UID" "${PROJECT}"
+ fi
+ # check GID
+ if [[ "$gid" != "$GID" ]] ; then
+ if [[ "$UPDATE_SYSTEM_ACCOUNT" != "yes" ]] ; then
+ echo "User ${PROJECT} already exists and has an unexpected GID $gid (expecting: $GID)" >&2
+ exit 1
+ fi
+ echo "## user ${PROJECT}: changing gid $gid -> $GID" >&2
+ usermod -g "$GID" "${PROJECT}"
+ fi
+ # check home dir
+ # see https://www.gnu.org/software/coreutils/manual/html_node/realpath-invocation.html#realpath-invocation
+ canon_homedir="$(realpath --canonicalize-missing --no-symlinks "$homedir")"
+ canon_ref_homedir="/var/lib/${PROJECT}"
+ if [[ "$canon_homedir" != "$canon_ref_homedir" ]] ; then
+ if [[ "$UPDATE_SYSTEM_ACCOUNT" != "yes" ]] ; then
+ echo "User ${PROJECT} already exists and has an unexpected home directory $homedir (expecting: /var/lib/${PROJECT}" >&2
+ exit 1
+ fi
+ echo "## user ${PROJECT}: changing home $homedir -> /var/lib/${PROJECT}" >&2
+ usermod -d "/var/lib/${PROJECT}" "${PROJECT}"
+ fi
+# no user: create it
+else
+ echo "## user ${PROJECT}: creating uid=$UID gid=$GID home=/var/lib/${PROJECT}" >&2
+ useradd $non_unique -u "${UID}" -g "${PROJECT}" -M -d "/var/lib/${PROJECT}" -s /usr/sbin/nologin -c "${PROJECT} user" "${PROJECT}"
+fi
+# create any missing dirs
mkdir -p /etc/${PROJECT} /var/log/${PROJECT} /var/lib/${PROJECT} /var/cache/${PROJECT}
chown ${PROJECT}:${PROJECT} /etc/${PROJECT} /var/log/${PROJECT} /var/lib/${PROJECT} /var/cache/${PROJECT}
--
2.30.2