blob: b047f2aeb13c668ed4645b25d58d95b030d04f49 [file] [log] [blame]
From 00243896aa249f8db2a965f61b66d452effcaab5 Mon Sep 17 00:00:00 2001
From: vaibhavrustagi <vaibhavrustagi@google.com>
Date: Thu, 20 Jun 2019 12:26:56 -0800
Subject: [PATCH] When creating users try to derive the UID/GID from the
homedir
It's possible that when a new user is being created that the home
directory for that user already exists. When this happens account
manager will now try to find the UID and GID of the user from that
directory and reuse it.
This fixes potential problems if for some reason the new accounts that
were previously added into passwd/group were not preserved after reboot,
but the correspondinghome directory was.
---
.../accounts/accounts_utils.py | 70 +++++++++++++++++--
1 file changed, 65 insertions(+), 5 deletions(-)
diff --git a/packages/python-google-compute-engine/google_compute_engine/accounts/accounts_utils.py b/packages/python-google-compute-engine/google_compute_engine/accounts/accounts_utils.py
index 56732c5..60ad005 100644
--- a/packages/python-google-compute-engine/google_compute_engine/accounts/accounts_utils.py
+++ b/packages/python-google-compute-engine/google_compute_engine/accounts/accounts_utils.py
@@ -30,7 +30,8 @@ USER_REGEX = re.compile(r'\A[A-Za-z0-9._][A-Za-z0-9._-]{0,31}\Z')
DEFAULT_GPASSWD_ADD_CMD = 'gpasswd -a {user} {group}'
DEFAULT_GPASSWD_REMOVE_CMD = 'gpasswd -d {user} {group}'
DEFAULT_GROUPADD_CMD = 'groupadd {group}'
-DEFAULT_USERADD_CMD = 'useradd -m -s /bin/bash -p * {user}'
+DEFAULT_GROUPADD_WITH_GID_CMD = 'groupadd -g {gid} {group}'
+DEFAULT_USERADD_CMD = 'useradd -s /bin/bash -p * {user}'
DEFAULT_USERDEL_CMD = 'userdel -r {user}'
DEFAULT_USERMOD_CMD = 'usermod -G {groups} {user}'
@@ -60,6 +61,7 @@ class AccountsUtils(object):
self.gpasswd_add_cmd = gpasswd_add_cmd or DEFAULT_GPASSWD_ADD_CMD
self.gpasswd_remove_cmd = gpasswd_remove_cmd or DEFAULT_GPASSWD_REMOVE_CMD
self.groupadd_cmd = groupadd_cmd or DEFAULT_GROUPADD_CMD
+ self.groupadd_with_gid_cmd = DEFAULT_GROUPADD_WITH_GID_CMD
self.useradd_cmd = useradd_cmd or DEFAULT_USERADD_CMD
self.userdel_cmd = userdel_cmd or DEFAULT_USERDEL_CMD
self.usermod_cmd = usermod_cmd or DEFAULT_USERMOD_CMD
@@ -113,6 +115,29 @@ class AccountsUtils(object):
file_utils.SetPermissions(
self.google_sudoers_file, mode=0o440, uid=0, gid=0)
+ def _CreateGroupWithGID(self, group, gid):
+ """Create a Linux group with specific gid.
+
+ Args:
+ group: string, the name of the Linux group to create.
+ gid: string, derived from user's home directory.
+
+ Returns:
+ bool, True if group created with gid succeeded.
+ """
+ self.logger.info('Creating a group for %s with gid %s.', group, gid)
+
+ command = self.groupadd_with_gid_cmd.format(gid=gid, group=group)
+ try:
+ subprocess.check_call(command.split(' '))
+ except subprocess.CalledProcessError as e:
+ self.logger.warning('Could not create group %s with gid %s . %s.',
+ group, gid, str(e))
+ return False
+ else:
+ self.logger.info('Created group %s with gid %s.', group, gid)
+ return True
+
def _GetUser(self, user):
"""Retrieve a Linux user account.
@@ -127,18 +152,31 @@ class AccountsUtils(object):
except KeyError:
return None
- def _AddUser(self, user):
+ def _AddUser(self, user, uid=None, gid=None, homedir=None):
"""Configure a Linux user account.
Args:
user: string, the name of the Linux user account to create.
+ uid: string, derived from 'new' user's home directory.
+ gid: string, derived from 'new' user's home directory.
+ homedir: string, home directory for 'new' user.
Returns:
bool, True if user creation succeeded.
"""
self.logger.info('Creating a new user account for %s.', user)
- command = self.useradd_cmd.format(user=user)
+ extra_flags = ''
+ if homedir:
+ extra_flags += ' -d %s' % homedir
+ else:
+ extra_flags += ' -m'
+ if uid:
+ extra_flags += ' -u %s' % str(uid)
+ if gid:
+ extra_flags += ' -g %s' % str(gid)
+
+ command = self.useradd_cmd.format(user=user) + extra_flags
try:
subprocess.check_call(command.split(' '))
except subprocess.CalledProcessError as e:
@@ -342,9 +380,31 @@ class AccountsUtils(object):
if not self._GetUser(user):
# User does not exist. Attempt to create the user and add them to the
# appropriate user groups.
- if not (self._AddUser(user)
- and self._UpdateUserGroups(user, self.groups)):
+ user_created = False
+
+ # Check if the homedir already exists and if yes try to derive UID
+ # and GID from that directory.
+ homedir = '/home/%s' % user
+ if os.path.isdir(homedir):
+ stats = os.stat(homedir)
+ if stats.st_uid > 1000:
+ self.logger.info('Using UID %d, GID %d and homedir %s for account %s',
+ stats.st_uid, stats.st_gid, homedir, user)
+
+ if not self._CreateGroupWithGID(user, stats.st_gid):
+ return False
+
+ if not self._AddUser(user, uid=stats.st_uid,
+ gid=stats.st_gid, homedir=homedir):
+ return False
+ user_created = True
+
+ if not user_created and not self._AddUser(user):
+ return False
+
+ if not self._UpdateUserGroups(user, self.groups):
return False
+
# Add the user to the google sudoers group.
if not self._UpdateSudoer(user, sudoer=True):
return False
--
2.22.0.410.gd8fdbe21b5-goog