pipeline: Task fails to run when using runAsNonRoot and runAsUser

This doc shows an example of using runAsNonRoot.

The Pod will also run as a non-root user.

Expected Behavior

Tasks run successfully.

Actual Behavior

Tested this on both GKE and OpenShift 4 (CodeReady Containers, actually). I set runAsNonRoot (or runAsUser) in a TaskRun like this:

spec:
  taskRef:
    name: jib-gradle
  ...
  podTemplate:
    securityContext:
      runAsNonRoot: true

runAsUser

  • When using runAsUser: 12345, the tekton-results-folder-writable container run fails with an error. I think the command chmod 777 /tekton/results doesn’t work due to a permission issue.
  tekton-results-folder-writable:
    Container ID:  cri-o://bfe047e46148846f24efd90608ec31796c2e3359fff23c2905c5f942213bd168
    Image:         busybox
    Image ID:      docker.io/library/busybox@sha256:6915be4043561d64e0ab0f8f098dc2ac48e077fe23f488ac24b665166898115a
    Port:          <none>
    Host Port:     <none>
    Command:
      sh
    Args:
      -c
      chmod 777 /tekton/results
    State:          Terminated
      Reason:       Error
      Exit Code:    1
      Started:      Fri, 06 Mar 2020 12:18:49 -0500
      Finished:     Fri, 06 Mar 2020 12:18:49 -0500
    Ready:          False
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /tekton/home from tekton-internal-home (rw)
      /tekton/results from tekton-internal-results (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-khxck (ro)
      /workspace from tekton-internal-workspace (rw)

runAsNonRoot

  • When using runAsNonRoot: true, I saw slightly different messages on GKE and OpenShfit, but both of them hang indefintely.
    • GKE
    NAME                           READY   STATUS                            RESTARTS   AGE
    pod/jib-gradle-run-pod-kbpp2   0/4     Init:CreateContainerConfigError   0          21m
    
    Events:
      Type     Reason     Age                    From                                               Message
      ----     ------     ----                   ----                                               -------
      Normal   Scheduled  9m2s                   default-scheduler                                  Successfully assigned default/jib-gradle-run-pod-kbpp2 to gke-cluster-2-default-pool-12e48c0a-wwmc
      Normal   Pulled     7m56s (x8 over 9m1s)   kubelet, gke-cluster-2-default-pool-12e48c0a-wwmc  Successfully pulled image "busybox"
      Warning  Failed     7m56s (x8 over 9m1s)   kubelet, gke-cluster-2-default-pool-12e48c0a-wwmc  Error: container has runAsNonRoot and image will run as root
      Normal   Pulling    3m54s (x27 over 9m1s)  kubelet, gke-cluster-2-default-pool-12e48c0a-wwmc  Pulling image "busybox"
    
    • OpenShift
    Events:
      Type     Reason     Age              From                         Message
      ----     ------     ----             ----                         -------
      Normal   Scheduled  <unknown>        default-scheduler            Successfully assigned chanseok/jib-gradle-run-pod-zmzpb to crc-w6th5-master-0
      Normal   Pulled     1s (x3 over 3s)  kubelet, crc-w6th5-master-0  Container image "gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/creds-init@sha256:d1251c017ad8db911f6b459f9cbe94328c962b619b5a6e4ef57524254c1dc30d" already present on machine
      Warning  Failed     1s (x3 over 3s)  kubelet, crc-w6th5-master-0  Error: container has runAsNonRoot and image will run as root
    

Steps to Reproduce the Problem

  1. Set runAsNonRoot: true or runAsUser: 12345 in PodTemplate.
  2. Run a task.

Additional Info

I saw #1872, but I don’t even get to that point.

Tekton version: v0.11.0-rc1

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 19 (14 by maintainers)

Most upvoted comments

Ah, makes sense. Thanks for the explanation. It would have been better if the name were verifyNonRoot or such, because this is inconsistent with runAsUser. (I would expect that runAsUser: 1001 validates that the container runs with UID 1001, not making the container run with UID 1001.)

runAsNonRoot is about validating containers running in the pod, not actually setting the user. See more under the Kubernetes pod documentation:

runAsNonRoot | boolean | Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. If unset or false, no such validation will be performed. May also be set in PodSecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence.

In general, running as a non root user should be built into the container image itself as opposed to relying on a securityContext whenever possible.

So digging further here, Tekton does not account for the securityContext of steps that are defined as part of a Task, such as:

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: echo-task
spec:
  steps:
    - name: echo-first
      image: ubuntu
      command:
        - echo
      args:
        - "Executing first"
      securityContext:
        runAsNonRoot: true
        runAsUser: 1001

The only securityContext that is applied is whatever is applied on the TaskRun or PipelineRun pod template:

https://github.com/tektoncd/pipeline/blob/c30d3aa0230faab3be210fccac19f7bb7ddd658f/pkg/pod/pod.go#L211

So this really comes down to two things:

  1. The documentation should be updated for securityContext through out the project if only runAsNonRoot/runAsUser are being specified for a securityContext
  2. The securityContext of steps should be applied if specified

@chanseokoh @danielhelfand at this point should we consider this a bug in Pipelines, a lack of documentation in Pipelines, or just expected behaviour when using runAsUser/runAsNonRoot? Or maybe all three? I’m not totally clear on the actions that need to be taken to resolve this issue.