| From c4576e56dbf84c0a10a71cb7fd609c2375b3d290 Mon Sep 17 00:00:00 2001 |
| From: Wei Xu <weixugc@google.com> |
| Date: Tue, 21 Jan 2020 18:27:35 -0800 |
| Subject: [PATCH] Make UID generation more stable/predictable. |
| |
| This patch modifies users-groups with the goal of making it behave better in |
| configuration where /etc/passwd is stateless. Specifically it: |
| |
| - adds 'uid' options so that UIDs can be set from cloud-config, that is |
| now recommended and a warning is generated if some users do not have that |
| option; |
| - reserves range [2000, 5000) for UIDs created by cloud-init; |
| - makes sure that users are created in the alphabetical order to provide |
| more predictable and consistent UIDs; |
| - adds a requirement that if homedir already exists the UID assigned to user |
| must be the same as the owner of that directory, this is to protect from |
| assigning incorrect UIDs after config changes. |
| |
| Original Author: Andrey Ulanov <andreyu@google.com> |
| Original Date: Thu Feb 25 18:41:48 2016 -0800 |
| --- |
| cloudinit/config/cc_users_groups.py | 32 +++++++++++++++++++++++++++++ |
| cloudinit/distros/__init__.py | 6 ++++-- |
| 2 files changed, 36 insertions(+), 2 deletions(-) |
| |
| diff --git a/cloudinit/config/cc_users_groups.py b/cloudinit/config/cc_users_groups.py |
| index c32a743a..3bc6d563 100644 |
| --- a/cloudinit/config/cc_users_groups.py |
| +++ b/cloudinit/config/cc_users_groups.py |
| @@ -128,6 +128,9 @@ from cloudinit import log as logging |
| |
| from cloudinit.settings import PER_INSTANCE |
| |
| +import os |
| +import pwd |
| + |
| LOG = logging.getLogger(__name__) |
| |
| frequency = PER_INSTANCE |
| @@ -139,6 +142,8 @@ def handle(name, cfg, cloud, _log, _args): |
| cloud_keys = cloud.get_public_ssh_keys() or [] |
| for (name, members) in groups.items(): |
| cloud.distro.create_group(name, members) |
| + |
| + # First create all users that have UID explicitly specified in cloud-config. |
| for (user, config) in users.items(): |
| ssh_redirect_user = config.pop("ssh_redirect_user", False) |
| if ssh_redirect_user: |
| @@ -162,6 +167,33 @@ def handle(name, cfg, cloud, _log, _args): |
| else: |
| config['ssh_redirect_user'] = default_user |
| config['cloud_public_ssh_keys'] = cloud_keys |
| + if 'uid' in config: |
| + config['uid'] = str(config['uid']) |
| + cloud.distro.create_user(user, **config) |
| + |
| + # dict is an unordered container. To make UIDs assigned to users more |
| + # predictable we sort them by the name and create accounts in that order. |
| + nouids = [] |
| + for user in sorted(users): |
| + config = users[user] |
| + if 'uid' in config: |
| + continue |
| + nouids.append(user) |
| + |
| cloud.distro.create_user(user, **config) |
| |
| + pw = pwd.getpwnam(user) |
| + |
| + homedir = config['homedir'] if 'homedir' in config else ('/home/%s' % user) |
| + if os.path.isdir(homedir): |
| + stats = os.stat(homedir) |
| + if stats.st_uid != pw.pw_uid: |
| + LOG.error('UID %d was assigned to user %s, but homedir %s ' |
| + 'is owned by %d', pw.pw_uid, user, homedir, stats.st_uid) |
| + raise |
| + |
| + if nouids: |
| + LOG.warn('No explicit UID specified for the following users: %s. ' |
| + 'UID may change after reboot.', ', '.join(nouids)) |
| + |
| # vi: ts=4 expandtab |
| diff --git a/cloudinit/distros/__init__.py b/cloudinit/distros/__init__.py |
| index 2b559fe6..02465787 100755 |
| --- a/cloudinit/distros/__init__.py |
| +++ b/cloudinit/distros/__init__.py |
| @@ -396,8 +396,9 @@ class Distro(object): |
| else: |
| create_groups = True |
| |
| - useradd_cmd = ['useradd', name] |
| - log_useradd_cmd = ['useradd', name] |
| + useradd_cmd = ['useradd', name, |
| + '-K', 'UID_MIN=2000', '-K', 'UID_MAX=4999', ] |
| + log_useradd_cmd = useradd_cmd[:] |
| if util.system_is_snappy(): |
| useradd_cmd.append('--extrausers') |
| log_useradd_cmd.append('--extrausers') |
| @@ -416,6 +417,7 @@ class Distro(object): |
| "expiredate": '--expiredate', |
| "inactive": '--inactive', |
| "selinux_user": '--selinux-user', |
| + "uid": '--uid', |
| } |
| |
| useradd_flags = { |
| -- |
| 2.25.1.481.gfbce0eb801-goog |
| |