From bea0775bec820569ffc5609869ef327c078c6f5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Carlos=20Ferra=20de=20Almeida?= Date: Wed, 3 Aug 2022 03:28:40 +0100 Subject: [PATCH 01/22] Fix small typo in README (#1687) Changed from `Kuernetes` to `Kubernetes` in the **Multitenancy** chapter. By the way why not use [the vale-action](https://github.com/errata-ai/vale-action) to automate linting in the markdown files? If you'd like I can probably find some time to do it. Just a small token of appreciation for an awesome project! --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d08bbe5096..5e43272df1 100644 --- a/README.md +++ b/README.md @@ -1770,7 +1770,7 @@ Or `spec.template.spec.githubAPICredentialsFrom.secretRef.name` field for the fo Usually, you should have a set of GitHub App credentials per a GitHub organization and you would have a RunnerDeployment and a HorizontalRunnerAutoscaler per an organization runner group. So, you might end up having the following resources for each organization: -- 1 Kuernetes secret that contains GitHub App credentials +- 1 Kubernetes secret that contains GitHub App credentials - 1 RunnerDeployment/RunnerSet and 1 HorizontalRunnerAutoscaler per Runner Group And the RunnerDeployment/RunnerSet and HorizontalRunnerAutoscaler should have the same value for `spec.githubAPICredentialsFrom.secretRef.name`, which refers to the name of the Kubernetes secret. From 37aa1a0b8c59f25b90a4df99c9b65831c7b4c874 Mon Sep 17 00:00:00 2001 From: Natalie Somersall Date: Tue, 2 Aug 2022 20:45:02 -0600 Subject: [PATCH 02/22] Add rootless DinD runner (#1644) * add rootless dind images * add small blurb on rootless dind * Add ToC entry for README section --- README.md | 5 + .../actions-runner-dind-rootless.dockerfile | 139 ++++++++++++++++++ runner/rootless-startup.sh | 27 ++++ 3 files changed, 171 insertions(+) create mode 100644 runner/actions-runner-dind-rootless.dockerfile create mode 100644 runner/rootless-startup.sh diff --git a/README.md b/README.md index 5e43272df1..4e965fcd28 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ ToC: - [Scheduled Overrides](#scheduled-overrides) - [Alternative Runners](#alternative-runners) - [Runner with DinD](#runner-with-dind) + - [Runner with rootless DinD](#runner-with-rootless-dind) - [Runner with k8s jobs](#runner-with-k8s-jobs) - [Additional Tweaks](#additional-tweaks) - [Custom Volume mounts](#custom-volume-mounts) @@ -1163,6 +1164,10 @@ spec: env: [] ``` +#### Runner with rootless DinD + +When using the DinD runner, it assumes that the main runner is rootful, which can be problematic in a regulated or more security-conscious environment, such as co-tenanting across enterprise projects. The `actions-runner-dind-rootless` image runs rootless Docker inside the container as `runner` user. Note that this user does not have sudo access, so anything requiring admin privileges must be built into the runner's base image (like running `apt` to install additional software). + #### Runner with K8s Jobs When using the default runner, jobs that use a container will run in docker. This necessitates privileged mode, either on the runner pod or the sidecar container diff --git a/runner/actions-runner-dind-rootless.dockerfile b/runner/actions-runner-dind-rootless.dockerfile new file mode 100644 index 0000000000..9102b153d4 --- /dev/null +++ b/runner/actions-runner-dind-rootless.dockerfile @@ -0,0 +1,139 @@ +FROM ubuntu:20.04 + +# Target architecture +ARG TARGETPLATFORM=linux/amd64 + +# GitHub runner arguments +ARG RUNNER_VERSION=2.294.0 + +# Docker and Docker Compose arguments +ENV CHANNEL=stable +ARG COMPOSE_VERSION=v2.6.0 + +# Dumb-init version +ARG DUMB_INIT_VERSION=1.2.5 + +# Other arguments +ARG DEBUG=false + +# Set environment variables needed at build +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt update -y \ + && apt-get install -y software-properties-common \ + && add-apt-repository -y ppa:git-core/ppa \ + && apt-get update -y \ + && apt-get install -y --no-install-recommends \ + build-essential \ + curl \ + ca-certificates \ + dnsutils \ + ftp \ + fuse-overlayfs \ + git \ + iproute2 \ + iputils-ping \ + iptables \ + jq \ + libunwind8 \ + locales \ + netcat \ + net-tools \ + openssh-client \ + parallel \ + python3-pip \ + rsync \ + shellcheck \ + supervisor \ + software-properties-common \ + sudo \ + telnet \ + time \ + tzdata \ + uidmap \ + unzip \ + upx \ + wget \ + zip \ + zstd \ + && ln -sf /usr/bin/python3 /usr/bin/python \ + && ln -sf /usr/bin/pip3 /usr/bin/pip \ + && rm -rf /var/lib/apt/lists/* + +# Runner user +RUN adduser --disabled-password --gecos "" --uid 1000 runner + +RUN test -n "$TARGETPLATFORM" || (echo "TARGETPLATFORM must be set" && false) + +# Setup subuid and subgid so that "--userns-remap=default" works +RUN set -eux; \ + addgroup --system dockremap; \ + adduser --system --ingroup dockremap dockremap; \ + echo 'dockremap:165536:65536' >> /etc/subuid; \ + echo 'dockremap:165536:65536' >> /etc/subgid + +ENV RUNNER_ASSETS_DIR=/runnertmp + +# Runner download supports amd64 as x64 +RUN ARCH=$(echo ${TARGETPLATFORM} | cut -d / -f2) \ + && export ARCH \ + && if [ "$ARCH" = "amd64" ]; then export ARCH=x64 ; fi \ + && mkdir -p "$RUNNER_ASSETS_DIR" \ + && cd "$RUNNER_ASSETS_DIR" \ + && curl -L -o runner.tar.gz https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-${ARCH}-${RUNNER_VERSION}.tar.gz \ + && tar xzf ./runner.tar.gz \ + && rm runner.tar.gz \ + && ./bin/installdependencies.sh \ + && apt-get install -y libyaml-dev \ + && rm -rf /var/lib/apt/lists/* + +RUN echo AGENT_TOOLSDIRECTORY=/opt/hostedtoolcache > /runner.env \ + && mkdir /opt/hostedtoolcache \ + && chgrp runner /opt/hostedtoolcache \ + && chmod g+rwx /opt/hostedtoolcache + +# Configure hooks folder structure. +COPY hooks /etc/arc/hooks/ + +# arch command on OS X reports "i386" for Intel CPUs regardless of bitness +RUN export ARCH=$(echo ${TARGETPLATFORM} | cut -d / -f2) \ + && if [ "$ARCH" = "arm64" ]; then export ARCH=aarch64 ; fi \ + && if [ "$ARCH" = "amd64" ] || [ "$ARCH" = "i386" ]; then export ARCH=x86_64 ; fi \ + && curl -f -L -o /usr/local/bin/dumb-init https://github.com/Yelp/dumb-init/releases/download/v${DUMB_INIT_VERSION}/dumb-init_${DUMB_INIT_VERSION}_${ARCH} \ + && chmod +x /usr/local/bin/dumb-init + +COPY entrypoint.sh logger.bash rootless-startup.sh update-status /usr/bin/ + +RUN chmod +x /usr/bin/rootless-startup.sh /usr/bin/entrypoint.sh + +# Make the rootless runner directory executable +RUN mkdir /run/user/1000 \ + && chown runner:runner /run/user/1000 \ + && chmod a+x /run/user/1000 + +# Add the Python "User Script Directory" to the PATH +ENV PATH="${PATH}:${HOME}/.local/bin:/home/runner/bin" +ENV ImageOS=ubuntu20 +ENV DOCKER_HOST=unix:///run/user/1000/docker.sock +ENV XDG_RUNTIME_DIR=/run/user/1000 + +RUN echo "PATH=${PATH}" > /etc/environment \ + && echo "ImageOS=${ImageOS}" >> /etc/environment \ + && echo "DOCKER_HOST=${DOCKER_HOST}" >> /etc/environment \ + && echo "XDG_RUNTIME_DIR=${XDG_RUNTIME_DIR}" >> /etc/environment + +ENV HOME=/home/runner + +# No group definition, as that makes it harder to run docker. +USER runner + +# Docker installation +ENV SKIP_IPTABLES=1 +RUN curl -fsSL https://get.docker.com/rootless | sh + +# Docker-compose installation +RUN curl -L "https://github.com/docker/compose/releases/download/${COMPOSE_VERSION}/docker-compose-Linux-x86_64" -o /home/runner/bin/docker-compose ; \ + chmod +x /home/runner/bin/docker-compose + +ENTRYPOINT ["/usr/local/bin/dumb-init", "--"] +CMD ["rootless-startup.sh"] diff --git a/runner/rootless-startup.sh b/runner/rootless-startup.sh new file mode 100644 index 0000000000..e26f5d58d1 --- /dev/null +++ b/runner/rootless-startup.sh @@ -0,0 +1,27 @@ +#!/bin/bash +source logger.bash + +log.notice "Writing out Docker config file" +/bin/bash <