Drone

Kube-runner: add runAsUser and runAsGroup to pipeline step definition

Problem: pod containers always run as root, and user can’t be changed.

Solution: add runAsUser and runAsGroup options to step definition.

Implementation: My first though is to add these options on the top level step def:

steps:
  - name: test
    image: gradle:6.3.0-jdk8
    runAsUser: 1000
    runAsGroup: 1000
    commands:
      - gradle test

Let me know what you think!

pod containers always run as root, and user can’t be changed.

to be more accurate, containers run using the default USER that has been defined in the image. This often defaults to root, but is not always root.

add runAsUser and runAsGroup options to step definition.

note that both the docker and kubernetes runtimes support the user parameter which can be used to override the default container user.

- name: foo
  image: bar
  user: baz

however, it is important to remember that when docker creates temporary volumes (e.g. docker volume create) they are owned by root. So if you mount a temporary volume into a container, and the container user is non-root, you may get errors trying to read or write from the volume. This includes the ability to read and write from the workspace (where your code is cloned) which itself is a temporary volume.

to be more accurate, containers run using the default USER that has been defined in the image. This often defaults to root, but is not always root

You’re right, not always root. What I meant was that, currently one can’t change the default user .

note that both the docker and kubernetes runtimes support the user parameter which can be used to override the default container user

Although user option is available in the step definition, it’s not taking effect. I have looked into the https://github.com/drone-runners/drone-runner-kube/blob/master/engine/convert.go#L160, and only privileged is passed to the pod spec:

SecurityContext: &v1.SecurityContext{
				Privileged: boolptr(s.Privileged),
			},

The runAsUser and runAsGroup, which change the default user and group, are not passed to pod spec.

Plus, the user field is of type string. However, in the k8s Pod Spec https://github.com/kubernetes/kubernetes/blob/master/pkg/apis/core/types.go#L2850, the user and group are represented in integers (UID,GID):

	// The UID to run the entrypoint of the container process.
	// Defaults to user specified in image metadata if unspecified.
	// May also be set in SecurityContext.  If set in both SecurityContext and
	// PodSecurityContext, the value specified in SecurityContext takes precedence
	// for that container.
	// +optional
	RunAsUser *int64
	// The GID to run the entrypoint of the container process.
	// Uses runtime default if unset.
	// May also be set in SecurityContext.  If set in both SecurityContext and
	// PodSecurityContext, the value specified in SecurityContext takes precedence
	// for that container.
	// +optional
	RunAsGroup *int64

So I suggest we remove the user field, and replace it with runAsUser and runAsGroup. The reason for this is not to confuse it with docker pipeline options, and keep the semantics of the underlying engine.

Regarding volumes, k8s does not use docker volume API, but rather uses its own API. And kube-runner uses EmptyDir volume type to contain the common workspace. And k8s sets the permissions 777 (RWX for all) on the created directory, you can check here https://github.com/kubernetes/kubernetes/blob/release-1.18/pkg/volume/emptydir/empty_dir.go#L43

So any container can read/write into the dir. Now when it comes to reading files created by a prev container, in most linux distros the default permission is 644 for newly created files, thus the other users can read.

Although user option is available in the step definition, it’s not taking effect […] The runAsUser and runAsGroup, which change the default user and group, are not passed to pod spec.

I would be open to a pull request that populates these values in the spec. Please note that we use snake case in the Drone yaml file so we would recommand user / group as the attribute names.

I see.
So after implementation, this is how a pipeline step def would look like:

kind: pipeline
type: kubernetes
name: java-app

steps:
  - name: build
    image: gradle:6.3.0-jdk8
    user: 1000
    group: 1000
    commands:
      - gradle build

I will open a PR soon.

1 Like

thanks, this is merged and available in the :latest image tag.

2 Likes