From 85f986325cf70abb53d2115c297f79013f2b3d8a Mon Sep 17 00:00:00 2001 From: Yongxuan Zhang Date: Sun, 5 Nov 2023 23:34:07 +0000 Subject: [PATCH] [TEP-0142] Add SecurityContext This commit adds SecurityContext to StepAction. Signed-off-by: Yongxuan Zhang yongxuanzhang@google.com --- docs/pipeline-api.md | 34 +++++++++++++++++ docs/stepactions.md | 21 ++++++++++ .../pipeline/v1alpha1/openapi_generated.go | 8 +++- .../pipeline/v1alpha1/stepaction_types.go | 6 +++ pkg/apis/pipeline/v1alpha1/swagger.json | 4 ++ .../v1alpha1/zz_generated.deepcopy.go | 5 +++ pkg/reconciler/taskrun/resources/taskspec.go | 1 + .../taskrun/resources/taskspec_test.go | 38 +++++++++++++++++++ pkg/reconciler/taskrun/taskrun_test.go | 12 ++++-- 9 files changed, 124 insertions(+), 5 deletions(-) diff --git a/docs/pipeline-api.md b/docs/pipeline-api.md index 379383bb642..fd0e5b73880 100644 --- a/docs/pipeline-api.md +++ b/docs/pipeline-api.md @@ -6612,6 +6612,23 @@ Params must be supplied as inputs in Steps unless they declare a defaultvalue.Results are values that this StepAction can output

+ + +securityContext
+ + +Kubernetes core/v1.SecurityContext + + + + +(Optional) +

SecurityContext defines the security options the Step should be run with. +If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. +More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ +The value set in StepAction will take precedence over the value from Task.

+ + @@ -7471,6 +7488,23 @@ Params must be supplied as inputs in Steps unless they declare a defaultvalue.Results are values that this StepAction can output

+ + +securityContext
+ + +Kubernetes core/v1.SecurityContext + + + + +(Optional) +

SecurityContext defines the security options the Step should be run with. +If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. +More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ +The value set in StepAction will take precedence over the value from Task.

+ +

VerificationPolicySpec diff --git a/docs/stepactions.md b/docs/stepactions.md index f7ef86d27fd..85ac1d5e51f 100644 --- a/docs/stepactions.md +++ b/docs/stepactions.md @@ -40,6 +40,7 @@ A `StepAction` definition supports the following fields: - `env` - [`params`](#declaring-params) - [`results`](#declaring-results) + - [`securityContext`](#declaring-securitycontext) The non-functional example below demonstrates the use of most of the above-mentioned fields: @@ -113,6 +114,26 @@ spec: date | tee $(results.current-date-human-readable.path) ``` +### Declaring SecurityContext + +You can declare `securityContext` in a `StepAction`: + +```yaml +apiVersion: tekton.dev/v1alpha1 +kind: StepAction +metadata: + name: example-stepaction-name +spec: + image: gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/git-init:latest + securityContext: + runAsUser: 0 + script: | + # clone the repo + ... +``` + +Note that the `securityContext` from `StepAction` will overwrite the `securityContext` from [`TaskRun`](./taskruns.md/#example-of-running-step-containers-as-a-non-root-user). + ## Referencing a StepAction `StepActions` can be referenced from the `Step` using the `ref` field, as follows: diff --git a/pkg/apis/pipeline/v1alpha1/openapi_generated.go b/pkg/apis/pipeline/v1alpha1/openapi_generated.go index 7638264c094..48b42c1663f 100644 --- a/pkg/apis/pipeline/v1alpha1/openapi_generated.go +++ b/pkg/apis/pipeline/v1alpha1/openapi_generated.go @@ -921,11 +921,17 @@ func schema_pkg_apis_pipeline_v1alpha1_StepActionSpec(ref common.ReferenceCallba }, }, }, + "securityContext": { + SchemaProps: spec.SchemaProps{ + Description: "SecurityContext defines the security options the Step should be run with. If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ The value set in StepAction will take precedence over the value from Task.", + Ref: ref("k8s.io/api/core/v1.SecurityContext"), + }, + }, }, }, }, Dependencies: []string{ - "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1.ParamSpec", "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1.StepActionResult", "k8s.io/api/core/v1.EnvVar"}, + "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1.ParamSpec", "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1.StepActionResult", "k8s.io/api/core/v1.EnvVar", "k8s.io/api/core/v1.SecurityContext"}, } } diff --git a/pkg/apis/pipeline/v1alpha1/stepaction_types.go b/pkg/apis/pipeline/v1alpha1/stepaction_types.go index ce8d0934b6d..4e9efb77714 100644 --- a/pkg/apis/pipeline/v1alpha1/stepaction_types.go +++ b/pkg/apis/pipeline/v1alpha1/stepaction_types.go @@ -121,6 +121,12 @@ type StepActionSpec struct { // +optional // +listType=atomic Results []StepActionResult `json:"results,omitempty"` + // SecurityContext defines the security options the Step should be run with. + // If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. + // More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ + // The value set in StepAction will take precedence over the value from Task. + // +optional + SecurityContext *corev1.SecurityContext `json:"securityContext,omitempty" protobuf:"bytes,15,opt,name=securityContext"` } // StepActionObject is implemented by StepAction diff --git a/pkg/apis/pipeline/v1alpha1/swagger.json b/pkg/apis/pipeline/v1alpha1/swagger.json index 14d777f80ea..aa6a859ecdc 100644 --- a/pkg/apis/pipeline/v1alpha1/swagger.json +++ b/pkg/apis/pipeline/v1alpha1/swagger.json @@ -472,6 +472,10 @@ "script": { "description": "Script is the contents of an executable file to execute.\n\nIf Script is not empty, the Step cannot have an Command and the Args will be passed to the Script.", "type": "string" + }, + "securityContext": { + "description": "SecurityContext defines the security options the Step should be run with. If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/ The value set in StepAction will take precedence over the value from Task.", + "$ref": "#/definitions/v1.SecurityContext" } } }, diff --git a/pkg/apis/pipeline/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/pipeline/v1alpha1/zz_generated.deepcopy.go index 7ee5bef9874..592f5961a91 100644 --- a/pkg/apis/pipeline/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/pipeline/v1alpha1/zz_generated.deepcopy.go @@ -335,6 +335,11 @@ func (in *StepActionSpec) DeepCopyInto(out *StepActionSpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.SecurityContext != nil { + in, out := &in.SecurityContext, &out.SecurityContext + *out = new(v1.SecurityContext) + (*in).DeepCopyInto(*out) + } return } diff --git a/pkg/reconciler/taskrun/resources/taskspec.go b/pkg/reconciler/taskrun/resources/taskspec.go index 66c19f7dde6..0e16a55c11f 100644 --- a/pkg/reconciler/taskrun/resources/taskspec.go +++ b/pkg/reconciler/taskrun/resources/taskspec.go @@ -113,6 +113,7 @@ func GetStepActionsData(ctx context.Context, taskSpec v1.TaskSpec, taskRun *v1.T } stepActionSpec := stepAction.StepActionSpec() s.Image = stepActionSpec.Image + s.SecurityContext = stepActionSpec.SecurityContext if len(stepActionSpec.Command) > 0 { s.Command = stepActionSpec.Command } diff --git a/pkg/reconciler/taskrun/resources/taskspec_test.go b/pkg/reconciler/taskrun/resources/taskspec_test.go index 47a9dd8239c..d40cf1d6e3d 100644 --- a/pkg/reconciler/taskrun/resources/taskspec_test.go +++ b/pkg/reconciler/taskrun/resources/taskspec_test.go @@ -301,6 +301,8 @@ func TestGetTaskData_VerificationResult(t *testing.T) { } func TestGetStepActionsData(t *testing.T) { + taskRunUser := int64(1001) + stepActionUser := int64(1000) tests := []struct { name string tr *v1.TaskRun @@ -454,6 +456,42 @@ func TestGetStepActionsData(t *testing.T) { Image: "foo", Command: []string{"ls"}, }}, + }, { + name: "step-action-with-security-context-overwritten", + tr: &v1.TaskRun{ + ObjectMeta: metav1.ObjectMeta{ + Name: "mytaskrun", + Namespace: "default", + }, + Spec: v1.TaskRunSpec{ + TaskSpec: &v1.TaskSpec{ + Steps: []v1.Step{{ + Ref: &v1.Ref{ + Name: "stepAction", + }, + SecurityContext: &corev1.SecurityContext{RunAsUser: &taskRunUser}, + }}, + }, + }, + }, + stepAction: &v1alpha1.StepAction{ + ObjectMeta: metav1.ObjectMeta{ + Name: "stepAction", + Namespace: "default", + }, + Spec: v1alpha1.StepActionSpec{ + Image: "myimage", + Command: []string{"ls"}, + Args: []string{"-lh"}, + SecurityContext: &corev1.SecurityContext{RunAsUser: &stepActionUser}, + }, + }, + want: []v1.Step{{ + Image: "myimage", + Command: []string{"ls"}, + Args: []string{"-lh"}, + SecurityContext: &corev1.SecurityContext{RunAsUser: &stepActionUser}, + }}, }} for _, tt := range tests { ctx := context.Background() diff --git a/pkg/reconciler/taskrun/taskrun_test.go b/pkg/reconciler/taskrun/taskrun_test.go index 9275b02dc6f..362f3bd9c0b 100644 --- a/pkg/reconciler/taskrun/taskrun_test.go +++ b/pkg/reconciler/taskrun/taskrun_test.go @@ -2956,6 +2956,8 @@ metadata: spec: image: myImage command: ["ls"] + securityContext: + privileged: true `) stepAction2 := parse.MustParseV1alpha1StepAction(t, ` metadata: @@ -2986,11 +2988,13 @@ spec: } getTaskRun, _ := testAssets.Clients.Pipeline.TektonV1().TaskRuns(taskRun.Namespace).Get(testAssets.Ctx, taskRun.Name, metav1.GetOptions{}) got := getTaskRun.Status.TaskSpec.Steps + securityContextPrivileged := true want := []v1.Step{{ - Image: "myImage", - Command: []string{"ls"}, - Name: "step1", - WorkingDir: "/foo", + Image: "myImage", + Command: []string{"ls"}, + Name: "step1", + WorkingDir: "/foo", + SecurityContext: &corev1.SecurityContext{Privileged: &securityContextPrivileged}, }, { Image: "myImage", Script: "echo hi",