From f53475879a54aa43fda07b0444e8735a561514cc Mon Sep 17 00:00:00 2001 From: Charles Coggins Date: Thu, 26 Dec 2024 13:58:24 -0600 Subject: [PATCH] feat: operate with non-root container user This change updates the `phylum-ci` Docker images to operate with a non- root user. This works (assuming the changes from #518) for most of the CI environments but GitHub directly contradicts this course of actions, specifying that: > Docker actions must be run by the default Docker user (root). Do not > use the USER instruction in your Dockerfile, because you won't be able > to access the GITHUB_WORKSPACE directory. It is possible to work around this restriction albeit in a hacky manner. Creating an image with the same `runner` user, with the same UID, will satisfy GitHub and ensure the user information matches between the running container and the host OS (which is also in a container). This is not fool-proof because the UID for the `runner` user is different depending on the GitHub-hosted runner in use (e.g., standard vs. large) and there is no guarantee that the user name or ID will remain consistent. The `docker` group is used to further match the configuration from the `actions-runner-dind` image. References: https://support.atlassian.com/bitbucket-cloud/docs/use-docker-images-as-build-environments/ https://docs.github.com/en/actions/sharing-automations/creating-actions/dockerfile-support-for-github-actions#user https://github.com/orgs/community/discussions/26811 https://github.com/actions/runner-images/issues/6930 https://github.com/actions/runner/issues/2411 https://github.com/actions/actions-runner-controller/blob/1e10417be8341df564a11abc970fe8f41a3b102c/runner/actions-runner-dind.ubuntu-22.04.dockerfile#L36 Needs #518 BREAKING CHANGE: GitHub container jobs will not work until the container options are updated to specify `options: --user=root` BREAKING CHANGE: The GitHub action and GitHub container steps no longer support providing analysis results of just the newly added dependencies. The `--all-deps` flag must be specified for these CI environments. --- Dockerfile | 20 ++++++++++++++++++++ Dockerfile.slim | 20 ++++++++++++++++++++ docs/integrations/github_actions.md | 7 +++++++ src/phylum/ci/ci_base.py | 3 +++ 4 files changed, 50 insertions(+) diff --git a/Dockerfile b/Dockerfile index 68229af..6619f73 100644 --- a/Dockerfile +++ b/Dockerfile @@ -205,6 +205,25 @@ COPY --from=builder ${PHYLUM_VENV} ${PHYLUM_VENV} # Ref: https://github.com/hadolint/hadolint/wiki/DL4006 SHELL ["/bin/bash", "-euxo", "pipefail", "-c"] RUN \ + # Create a non-root user/group, with a home directory (required by some CI environments). + # GitHub specifies that: + # "Docker actions must be run by the default Docker user (root). Do not use the USER instruction + # in your Dockerfile, because you won't be able to access the GITHUB_WORKSPACE directory." + # It is possible to work around this restriction, albeit in a hacky manner. Creating an image with + # the same `runner` user, with the same UID, will satisfy GitHub and ensure the user information + # matches between the running container and the host OS (which is also in a container). This is not + # fool-proof because the UID for the `runner` user is different depending on the GitHub-hosted runner in + # use (e.g., standard vs. large) and there is no guarantee that the user name or ID will remain consistent. + # The `docker` group is used to further match the configuration from the `actions-runner-dind` image. + # References: + # https://support.atlassian.com/bitbucket-cloud/docs/use-docker-images-as-build-environments/ + # https://docs.github.com/en/actions/sharing-automations/creating-actions/dockerfile-support-for-github-actions#user + # https://github.com/orgs/community/discussions/26811 + # https://github.com/actions/runner-images/issues/6930 + # https://github.com/actions/runner/issues/2411 + # https://github.com/actions/actions-runner-controller/blob/1e10417be8341df564a11abc970fe8f41a3b102c/runner/actions-runner-dind.ubuntu-22.04.dockerfile#L36 + groupadd --system docker; \ + useradd --create-home --no-log-init --system --uid 1001 --gid docker runner; \ # Install prerequisites and package manager versions for `npm`, `bundle`, and `mvn` tools apt-get update; \ apt-get upgrade --yes; \ @@ -301,4 +320,5 @@ RUN \ rm -rf /tmp/*; \ find / -type f -name '*.pyc' -delete; +USER runner:docker CMD ["phylum-ci"] diff --git a/Dockerfile.slim b/Dockerfile.slim index 7382805..9c0b23b 100644 --- a/Dockerfile.slim +++ b/Dockerfile.slim @@ -177,6 +177,25 @@ ENV XDG_CACHE_HOME="${INSTALL_DIR}/.cache" COPY --from=builder ${PHYLUM_VENV} ${PHYLUM_VENV} RUN set -eux; \ + # Create a non-root user/group, with a home directory (required by some CI environments). + # GitHub specifies that: + # "Docker actions must be run by the default Docker user (root). Do not use the USER instruction + # in your Dockerfile, because you won't be able to access the GITHUB_WORKSPACE directory." + # It is possible to work around this restriction, albeit in a hacky manner. Creating an image with + # the same `runner` user, with the same UID, will satisfy GitHub and ensure the user information + # matches between the running container and the host OS (which is also in a container). This is not + # fool-proof because the UID for the `runner` user is different depending on the GitHub-hosted runner in + # use (e.g., standard vs. large) and there is no guarantee that the user name or ID will remain consistent. + # The `docker` group is used to further match the configuration from the `actions-runner-dind` image. + # References: + # https://support.atlassian.com/bitbucket-cloud/docs/use-docker-images-as-build-environments/ + # https://docs.github.com/en/actions/sharing-automations/creating-actions/dockerfile-support-for-github-actions#user + # https://github.com/orgs/community/discussions/26811 + # https://github.com/actions/runner-images/issues/6930 + # https://github.com/actions/runner/issues/2411 + # https://github.com/actions/actions-runner-controller/blob/1e10417be8341df564a11abc970fe8f41a3b102c/runner/actions-runner-dind.ubuntu-22.04.dockerfile#L36 + groupadd --system docker; \ + useradd --create-home --no-log-init --system --uid 1001 --gid docker runner; \ # Install prerequisites apt-get update; \ apt-get upgrade --yes; \ @@ -199,4 +218,5 @@ RUN set -eux; \ rm -rf /tmp/*; \ find / -type f -name '*.pyc' -delete; +USER runner:docker CMD ["phylum-ci"] diff --git a/docs/integrations/github_actions.md b/docs/integrations/github_actions.md index c67f953..2b5cd5a 100644 --- a/docs/integrations/github_actions.md +++ b/docs/integrations/github_actions.md @@ -60,6 +60,8 @@ jobs: # lockfile generation. If that is desired, use the # `phylum-dev/phylum-analyze-pr-action` action instead. image: docker://ghcr.io/phylum-dev/phylum-ci:slim + # Container jobs only work for the `root` user + options: --user=root env: GITHUB_TOKEN: ${{ github.token }} PHYLUM_API_KEY: ${{ secrets.PHYLUM_TOKEN }} @@ -80,9 +82,14 @@ The `GITHUB_TOKEN` and `PHYLUM_API_KEY` environment variables are required to ha Those environment variables and the rest of the options are more fully documented in the [Phylum Analyze PR action repository][repo]. +Container jobs [do not work when a non-root user is specified][1], like in the default `phylum-ci` image. +[They will work][2] after specifying `options: --user=root` with the container options. + [container_job]: https://docs.github.com/actions/using-jobs/running-jobs-in-a-container [ghcr_tags]: https://github.com/phylum-dev/phylum-ci/pkgs/container/phylum-ci [docker_hub_tags]: https://hub.docker.com/r/phylumio/phylum-ci/tags +[1]: https://docs.github.com/en/actions/sharing-automations/creating-actions/dockerfile-support-for-github-actions#user +[2]: https://github.com/orgs/community/discussions/26811 ### Container Steps diff --git a/src/phylum/ci/ci_base.py b/src/phylum/ci/ci_base.py index 6bf34d3..17448d1 100644 --- a/src/phylum/ci/ci_base.py +++ b/src/phylum/ci/ci_base.py @@ -977,6 +977,9 @@ def _get_base_packages(self) -> Packages: return [] base_packages: set[Package] = set() + # Use something other than worktrees here (e.g., git clone, checkout, unpack-file, etc.)? + # The git worktree can't be created due to not having permissions to write/create the `.git/worktree` + # directory. It might also be possible to automatically set the `--all-deps` flag when this happens. with git_worktree(self.common_ancestor_commit, env=self._env) as temp_dir: for depfile in self.depfiles: prev_depfile_path = temp_dir / depfile.path.relative_to(self._git_root_dir)