-
-
Notifications
You must be signed in to change notification settings - Fork 539
Description
Clear and concise description of the problem
Hi, thanks for this project! The Kubernetes integration appears to be much better thought out than most other CI systems we've used.
Unfortunately, as far as we can tell, cloning a repo using the Woodpecker-provided netrc credentials isn't possible without root privileges, short of marking the project as "Trusted:Security", which is probably worse overall, from a security perspective:
- The default clone step runs as the root user, so the runner namespace must be privileged. On security-conscious Kubernetes distributions like Talos, namespaces are not privileged by default, so the runner namespace needs the
pod-security.kubernetes.io/enforce: privilegedlabel on these distributions. In our clusters, we prefer to add this label only when the app absolutely requires elevated privileges; e.g., because it needs to use host networking. - Because the default clone step runs as the root user, the otherwise very handy
WOODPECKER_BACKEND_K8S_SECCTX_NONROOToption is incompatible with it. The default clone step pod will always fail to start if this option is set. - As far as I can tell, the only reason that Woodpecker runs the default clone step as the root user is to set the filesystem permissions on the workspace directory. However, unless I'm missing something, that could easily be addressed by using the
fsGroupChangePolicypod security context setting, without any need for root privileges.
Initially, #4151 had support for fsGroupChangePolicy (e.g., 3c7e071), but that appears to have been removed at some stage before the merge, though it's not clear to me why.
Suggested solution
Unless there's some other reason why the default clone step needs to run as root, adding support for fsGroupChangePolicy in the Kubernetes backend_options and de-privileging the default clone step would be a major security posture improvement for the Kubernetes backend.
Alternative
Run the clone step manually
Because the woodpeckerci/plugin-git plugin is trusted, Woodpecker provides it with the netrc creds when run as a plugin. Therefore, we tried running a manual clone step, first like this:
skip_clone: true
steps:
- name: clone
image: quay.io/woodpeckerci/plugin-git:2.6.5
backend_options:
kubernetes:
securityContext:
runAsUser: 405 # `guest` user in Alpine
runAsGroup: 100 # `users` group in Alpine
fsGroup: 100
privileged: false
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
However, that failed because the default HOME is /app, and the pod couldn't access /app/.netrc.
We then tried this:
skip_clone: true
steps:
- name: clone
image: quay.io/woodpeckerci/plugin-git:2.6.5
settings:
home: /tmp
backend_options:
kubernetes:
securityContext:
runAsUser: 405
runAsGroup: 100
fsGroup: 100
privileged: false
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
Then the pod was able to read /tmp/.netrc, but that failed due to permissions on the mounted workspace, which leads us to the need for fsGroupChangePolicy:
+ git init --object-format sha1 -b main
/woodpecker/src/forgejo.hackworth-corp.com/hackworth/hops/.git: Permission denied
exit status 1
User namespaces
Since v1.30, Kubernetes supports user namespaces: https://kubernetes.io/docs/concepts/workloads/pods/user-namespaces/
The feature is currently in beta. When it's enabled, and pod.spec.hostUsers is false, Kubernetes creates a separate UID/GID namespace, so that, e.g., UID 0 in the pod is not the same as UID 0 outside the pod; i.e., it has no privileges outside the pod. If a Woodpecker Kubernetes backend option to disable hostUsers were available, we'd be more comfortable with the default clone step running as UID 0. (For starters, based on our testing of the feature with other apps, it's not necessary to privilege the namespace when running containers as UID 0 and hostUsers disabled.) However, we'd still feel much better if the default clone step ran as non-root.
Irrespective of this particular issue, user namespaces would be a useful feature for other CI workloads that need to run as root, but don't require actual system-level privileges.
Additional context
No response