Skip to content

Commit

Permalink
Fix using rocker for non-root containers (#50)
Browse files Browse the repository at this point in the history
* Fix using rocker for non-root containers

If the base image given by the user does not have root privileges,
building the rockerized image will fail. Extensions seem to expect that
their Dockerfile snippets are executed with root privileges.

This patch injects a `USER root` instruction right after FROM
base_image.

For similar reasons the `user` extension has to run last, because its
snippet changes the active user again and subsequent snippets from other
extensions might fail.

* Revert redundant reordering of extensions

* Fix user extension for some special cases

- A user with the same UID already exists in the container image.
- A group with the same GID already exists in the container image.
- A user with the same name already exists in the container image.

In all those cases the existing user or group gets deleted before
creating a new one.

Changing the password and adding the user to the sudo group is redundant
to creating /etc/sudoers.d/rocker.

* Suppress mail spool/home directory not found error output of userdel

* tests: Remove obsolete check in UserExtensionTest

* Revert "Suppress mail spool/home directory not found error output of userdel"

This reverts commit c520a4e.

* Create the parent directory of the home directory before calling mkhomedir_helper

The tool fails with exit code 6 if the top-level directory does not exist yet.

    (a39bc32231c8)root@c71fe951b480:/# getent passwd johannes
    johannes:x:1000006:1000:Johannes Meyer:/share/homes/johannes:/bin/bash
    (a39bc32231c8)root@a39bc32231c8:/# rm share -R
    (a39bc32231c8)root@a39bc32231c8:/# mkhomedir_helper johannes; echo $?
    6
    (a39bc32231c8)root@a39bc32231c8:/# mkdir share
    (a39bc32231c8)root@a39bc32231c8:/# mkhomedir_helper johannes; echo $?
    0
  • Loading branch information
meyerj authored Nov 4, 2020
1 parent eef5516 commit 3585298
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 11 deletions.
2 changes: 1 addition & 1 deletion src/rocker/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def main():
print('DEPRECATION Warning: --noexecute is deprecated for --mode dry-run please switch your usage by December 2020')

active_extensions = extension_manager.get_active_extensions(args_dict)
# Force user to end if present otherwise it will
# Force user to end if present otherwise it will break other extensions
active_extensions.sort(key=lambda e:e.get_name().startswith('user'))
print("Active extensions %s" % [e.get_name() for e in active_extensions])

Expand Down
1 change: 1 addition & 0 deletions src/rocker/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ def generate_dockerfile(extensions, args_dict, base_image):
dockerfile_str += '# Preamble from extension [%s]\n' % el.name
dockerfile_str += el.get_preamble(args_dict) + '\n'
dockerfile_str += '\nFROM %s\n' % base_image
dockerfile_str += 'USER root\n'
for el in extensions:
dockerfile_str += '# Snippet from extension [%s]\n' % el.name
dockerfile_str += el.get_snippet(args_dict) + '\n'
Expand Down
20 changes: 13 additions & 7 deletions src/rocker/templates/user_snippet.Dockerfile.em
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,23 @@ RUN if ! command -v sudo >/dev/null; then \
fi

@[if name != 'root']@
RUN groupadd -g "@(gid)" "@name" \
&& useradd --uid "@(uid)" -s "@(shell)" -c "@(gecos)" -g "@(gid)" -d "@(dir)" "@(name)" \
&& echo "@(name):@(name)" | chpasswd \
&& adduser @(name) sudo \
&& echo "@(name) ALL=NOPASSWD: ALL" >> /etc/sudoers.d/rocker
RUN existing_user_by_uid=`getent passwd "@(uid)" | cut -f1 -d: || true` && \
if [ -n "${existing_user_by_uid}" ]; then userdel -r "${existing_user_by_uid}"; fi && \
existing_user_by_name=`getent passwd "@(name)" | cut -f1 -d: || true` && \
if [ -n "${existing_user_by_name}" ]; then userdel -r "${existing_user_by_name}"; fi && \
existing_group_by_gid=`getent group "@(gid)" | cut -f1 -d: || true` && \
if [ -z "${existing_group_by_gid}" ]; then \
groupadd -g "@(gid)" "@name"; \
fi && \
useradd --no-log-init --no-create-home --uid "@(uid)" -s "@(shell)" -c "@(gecos)" -g "@(gid)" -d "@(dir)" "@(name)" && \
echo "@(name) ALL=NOPASSWD: ALL" >> /etc/sudoers.d/rocker

@[if not home_extension_active ]@
# Making sure a home directory exists if we haven't mounted the user's home directory explicitly
RUN mkhomedir_helper @(name)
RUN mkdir -p "$(dirname "@(dir)")" && mkhomedir_helper @(name)
@[end if]@
# Commands below run as the developer user
USER @(name)
@[else]@
# Detected user is root, which already exists so not creating new user.
@[end if]@
@[end if]@
3 changes: 0 additions & 3 deletions test/test_extension.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,6 @@ def test_user_extension(self):
mock_cliargs = {}
snippet = p.get_snippet(mock_cliargs).splitlines()

passwd_line = [l for l in snippet if 'chpasswd' in l][0]
self.assertTrue(getpass.getuser() in passwd_line)

uid_line = [l for l in snippet if '--uid' in l][0]
self.assertTrue(str(os.getuid()) in uid_line)

Expand Down

0 comments on commit 3585298

Please sign in to comment.