From 686b0835b46fe20f8567ed1168763d20576110d3 Mon Sep 17 00:00:00 2001 From: David Simansky Date: Mon, 26 Jun 2023 13:25:46 +0200 Subject: [PATCH 1/4] Add default SecurityContext to every new ksvc --- go.mod | 3 ++- pkg/kn/commands/service/create_mock_test.go | 3 +++ .../source/container/container_test.go | 3 +++ pkg/kn/flags/podspec.go | 2 ++ pkg/kn/flags/podspec_helper.go | 22 +++++++++++++++++++ pkg/kn/flags/podspec_test.go | 2 ++ 6 files changed, 34 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 7a57425cb7..863532d560 100644 --- a/go.mod +++ b/go.mod @@ -28,6 +28,8 @@ require ( sigs.k8s.io/yaml v1.3.0 ) +require k8s.io/utils v0.0.0-20221108210102-8e77b1f39fe2 + require ( contrib.go.opencensus.io/exporter/ocagent v0.7.1-0.20200907061046-05415f1de66d // indirect contrib.go.opencensus.io/exporter/prometheus v0.4.2 // indirect @@ -120,7 +122,6 @@ require ( k8s.io/gengo v0.0.0-20221011193443-fad74ee6edd9 // indirect k8s.io/klog/v2 v2.80.2-0.20221028030830-9ae4992afb54 // indirect k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect - k8s.io/utils v0.0.0-20221108210102-8e77b1f39fe2 // indirect sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect sigs.k8s.io/kustomize/api v0.12.1 // indirect sigs.k8s.io/kustomize/kyaml v0.13.9 // indirect diff --git a/pkg/kn/commands/service/create_mock_test.go b/pkg/kn/commands/service/create_mock_test.go index 67a83a6f23..d6af716355 100644 --- a/pkg/kn/commands/service/create_mock_test.go +++ b/pkg/kn/commands/service/create_mock_test.go @@ -18,6 +18,8 @@ import ( "testing" "time" + "knative.dev/client/pkg/kn/flags" + "knative.dev/serving/pkg/apis/autoscaling" "gotest.tools/v3/assert" @@ -477,6 +479,7 @@ func getService(name string) *servingv1.Service { Limits: corev1.ResourceList{}, Requests: corev1.ResourceList{}, }, + SecurityContext: flags.DefaultSecCon(), }} return service diff --git a/pkg/kn/commands/source/container/container_test.go b/pkg/kn/commands/source/container/container_test.go index 10dadf3259..77228d7677 100644 --- a/pkg/kn/commands/source/container/container_test.go +++ b/pkg/kn/commands/source/container/container_test.go @@ -20,6 +20,8 @@ import ( "bytes" "strings" + "knative.dev/client/pkg/kn/flags" + corev1 "k8s.io/api/core/v1" "k8s.io/client-go/tools/clientcmd" v1 "knative.dev/eventing/pkg/apis/sources/v1" @@ -92,6 +94,7 @@ func createContainerSource(name, image string, sink duckv1.Destination, ceo map[ Limits: corev1.ResourceList{}, Requests: corev1.ResourceList{}, }, + SecurityContext: flags.DefaultSecCon(), }}}). Sink(sink). Build() diff --git a/pkg/kn/flags/podspec.go b/pkg/kn/flags/podspec.go index aec09ec494..ed430299dc 100644 --- a/pkg/kn/flags/podspec.go +++ b/pkg/kn/flags/podspec.go @@ -405,5 +405,7 @@ func (p *PodSpecFlags) ResolvePodSpec(podSpec *corev1.PodSpec, flags *pflag.Flag } } + UpdateDefaultSecurityContext(podSpec) + return nil } diff --git a/pkg/kn/flags/podspec_helper.go b/pkg/kn/flags/podspec_helper.go index 97ee7c81b3..10e423d458 100644 --- a/pkg/kn/flags/podspec_helper.go +++ b/pkg/kn/flags/podspec_helper.go @@ -20,6 +20,8 @@ import ( "strconv" "strings" + "k8s.io/utils/pointer" + "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/api/resource" @@ -378,6 +380,26 @@ func UpdateImagePullPolicy(spec *corev1.PodSpec, imagePullPolicy string) error { return nil } +func UpdateDefaultSecurityContext(spec *corev1.PodSpec) { + container := containerOfPodSpec(spec) + if container.SecurityContext == nil { + container.SecurityContext = DefaultSecCon() + } +} + +func DefaultSecCon() *corev1.SecurityContext { + return &corev1.SecurityContext{ + AllowPrivilegeEscalation: pointer.Bool(false), + RunAsNonRoot: pointer.Bool(true), + Capabilities: &corev1.Capabilities{ + Drop: []corev1.Capability{"ALL"}, + }, + SeccompProfile: &corev1.SeccompProfile{ + Type: corev1.SeccompProfileTypeRuntimeDefault, + }, + } +} + func getPolicy(policy string) v1.PullPolicy { var ret v1.PullPolicy switch strings.ToLower(policy) { diff --git a/pkg/kn/flags/podspec_test.go b/pkg/kn/flags/podspec_test.go index 78d78e59b9..ae18200794 100644 --- a/pkg/kn/flags/podspec_test.go +++ b/pkg/kn/flags/podspec_test.go @@ -223,6 +223,7 @@ containers: Limits: corev1.ResourceList{}, Requests: corev1.ResourceList{}, }, + SecurityContext: DefaultSecCon(), }, { Name: "foo", @@ -397,6 +398,7 @@ func TestPodSpecResolveWithEnvFile(t *testing.T) { Limits: v1.ResourceList{}, Requests: v1.ResourceList{}, }, + SecurityContext: DefaultSecCon(), }, }, } From 009b2e7599c9bb856a907db080028f536ab60cd1 Mon Sep 17 00:00:00 2001 From: David Simansky Date: Tue, 27 Jun 2023 15:29:31 +0200 Subject: [PATCH 2/4] Add basic seccon config flag --- docs/cmd/kn_container_add.md | 1 + docs/cmd/kn_service_apply.md | 1 + docs/cmd/kn_service_create.md | 1 + docs/cmd/kn_service_update.md | 1 + docs/cmd/kn_source_container_create.md | 1 + docs/cmd/kn_source_container_update.md | 1 + pkg/kn/commands/service/create_mock_test.go | 2 +- .../source/container/container_test.go | 2 +- pkg/kn/flags/podspec.go | 17 +++++- pkg/kn/flags/podspec_helper.go | 24 +++++++-- pkg/kn/flags/podspec_helper_test.go | 54 +++++++++++++++++++ pkg/kn/flags/podspec_test.go | 32 +++++------ test/e2e/service_export_test.go | 4 +- 13 files changed, 116 insertions(+), 25 deletions(-) diff --git a/docs/cmd/kn_container_add.md b/docs/cmd/kn_container_add.md index c59b1189b0..b5da00cd24 100644 --- a/docs/cmd/kn_container_add.md +++ b/docs/cmd/kn_container_add.md @@ -47,6 +47,7 @@ kn container add NAME --pull-policy string Image pull policy. Valid values (case insensitive): Always | Never | IfNotPresent --pull-secret string Image pull secret to set. An empty argument ("") clears the pull secret. The referenced secret must exist in the service's namespace. --request strings The resource requirement requests for this Service. For example, 'cpu=100m,memory=256Mi'. You can use this flag multiple times. To unset a resource request, append "-" to the resource name, e.g. '--request cpu-'. + --security-context string Security Context definition to be added the service. Accepted values: strict | none. (default "strict") --service-account string Service account name to set. An empty argument ("") clears the service account. The referenced service account must exist in the service's namespace. --user int The user ID to run the container (e.g., 1001). ``` diff --git a/docs/cmd/kn_service_apply.md b/docs/cmd/kn_service_apply.md index 48594fd30a..81221844d8 100644 --- a/docs/cmd/kn_service_apply.md +++ b/docs/cmd/kn_service_apply.md @@ -73,6 +73,7 @@ kn service apply s0 --filename my-svc.yml --scale-target int Recommendation for what metric value the PodAutoscaler should attempt to maintain. Use with --scale-metric flag to configure the metric name for which the target value should be maintained. Default metric name is concurrency. The flag defaults to --concurrency-limit when given. --scale-utilization int Percentage of concurrent requests utilization before scaling up. (default 70) --scale-window string Duration to look back for making auto-scaling decisions. The service is scaled to zero if no request was received in during that time. (eg: 10s) + --security-context string Security Context definition to be added the service. Accepted values: strict | none. (default "strict") --service-account string Service account name to set. An empty argument ("") clears the service account. The referenced service account must exist in the service's namespace. --timeout int Duration in seconds that the request routing layer will wait for a request delivered to a container to begin replying (default 300) --user int The user ID to run the container (e.g., 1001). diff --git a/docs/cmd/kn_service_create.md b/docs/cmd/kn_service_create.md index ba0793ca8f..e2e1c0029b 100644 --- a/docs/cmd/kn_service_create.md +++ b/docs/cmd/kn_service_create.md @@ -98,6 +98,7 @@ kn service create NAME --image IMAGE --scale-target int Recommendation for what metric value the PodAutoscaler should attempt to maintain. Use with --scale-metric flag to configure the metric name for which the target value should be maintained. Default metric name is concurrency. The flag defaults to --concurrency-limit when given. --scale-utilization int Percentage of concurrent requests utilization before scaling up. (default 70) --scale-window string Duration to look back for making auto-scaling decisions. The service is scaled to zero if no request was received in during that time. (eg: 10s) + --security-context string Security Context definition to be added the service. Accepted values: strict | none. (default "strict") --service-account string Service account name to set. An empty argument ("") clears the service account. The referenced service account must exist in the service's namespace. --tag strings Set tag (format: --tag revisionRef=tagName) where revisionRef can be a revision or '@latest' string representing latest ready revision. This flag can be specified multiple times. --target string Work on local directory instead of a remote cluster (experimental) diff --git a/docs/cmd/kn_service_update.md b/docs/cmd/kn_service_update.md index 4d2c97d445..3aa6b2d573 100644 --- a/docs/cmd/kn_service_update.md +++ b/docs/cmd/kn_service_update.md @@ -85,6 +85,7 @@ kn service update NAME --scale-target int Recommendation for what metric value the PodAutoscaler should attempt to maintain. Use with --scale-metric flag to configure the metric name for which the target value should be maintained. Default metric name is concurrency. The flag defaults to --concurrency-limit when given. --scale-utilization int Percentage of concurrent requests utilization before scaling up. (default 70) --scale-window string Duration to look back for making auto-scaling decisions. The service is scaled to zero if no request was received in during that time. (eg: 10s) + --security-context string Security Context definition to be added the service. Accepted values: strict | none. (default "strict") --service-account string Service account name to set. An empty argument ("") clears the service account. The referenced service account must exist in the service's namespace. --tag strings Set tag (format: --tag revisionRef=tagName) where revisionRef can be a revision or '@latest' string representing latest ready revision. This flag can be specified multiple times. --target string Work on local directory instead of a remote cluster (experimental) diff --git a/docs/cmd/kn_source_container_create.md b/docs/cmd/kn_source_container_create.md index be75ad4ccc..952de8dc44 100644 --- a/docs/cmd/kn_source_container_create.md +++ b/docs/cmd/kn_source_container_create.md @@ -37,6 +37,7 @@ kn source container create NAME --image IMAGE --sink SINK --pull-policy string Image pull policy. Valid values (case insensitive): Always | Never | IfNotPresent --pull-secret string Image pull secret to set. An empty argument ("") clears the pull secret. The referenced secret must exist in the service's namespace. --request strings The resource requirement requests for this Service. For example, 'cpu=100m,memory=256Mi'. You can use this flag multiple times. To unset a resource request, append "-" to the resource name, e.g. '--request cpu-'. + --security-context string Security Context definition to be added the service. Accepted values: strict | none. (default "strict") --service-account string Service account name to set. An empty argument ("") clears the service account. The referenced service account must exist in the service's namespace. -s, --sink string Addressable sink for events. You can specify a broker, channel, Knative service or URI. Examples: '--sink broker:nest' for a broker 'nest', '--sink channel:pipe' for a channel 'pipe', '--sink ksvc:mysvc:mynamespace' for a Knative service 'mysvc' in another namespace 'mynamespace', '--sink https://event.receiver.uri' for an URI with an 'http://' or 'https://' schema, '--sink ksvc:receiver' or simply '--sink receiver' for a Knative service 'receiver' in the current namespace. If a prefix is not provided, it is considered as a Knative service in the current namespace. If referring to a Knative service in another namespace, 'ksvc:name:namespace' combination must be provided explicitly. --user int The user ID to run the container (e.g., 1001). diff --git a/docs/cmd/kn_source_container_update.md b/docs/cmd/kn_source_container_update.md index b6c48466fb..5b0ed1abfe 100644 --- a/docs/cmd/kn_source_container_update.md +++ b/docs/cmd/kn_source_container_update.md @@ -37,6 +37,7 @@ kn source container update NAME --image IMAGE --pull-policy string Image pull policy. Valid values (case insensitive): Always | Never | IfNotPresent --pull-secret string Image pull secret to set. An empty argument ("") clears the pull secret. The referenced secret must exist in the service's namespace. --request strings The resource requirement requests for this Service. For example, 'cpu=100m,memory=256Mi'. You can use this flag multiple times. To unset a resource request, append "-" to the resource name, e.g. '--request cpu-'. + --security-context string Security Context definition to be added the service. Accepted values: strict | none. (default "strict") --service-account string Service account name to set. An empty argument ("") clears the service account. The referenced service account must exist in the service's namespace. -s, --sink string Addressable sink for events. You can specify a broker, channel, Knative service or URI. Examples: '--sink broker:nest' for a broker 'nest', '--sink channel:pipe' for a channel 'pipe', '--sink ksvc:mysvc:mynamespace' for a Knative service 'mysvc' in another namespace 'mynamespace', '--sink https://event.receiver.uri' for an URI with an 'http://' or 'https://' schema, '--sink ksvc:receiver' or simply '--sink receiver' for a Knative service 'receiver' in the current namespace. If a prefix is not provided, it is considered as a Knative service in the current namespace. If referring to a Knative service in another namespace, 'ksvc:name:namespace' combination must be provided explicitly. --user int The user ID to run the container (e.g., 1001). diff --git a/pkg/kn/commands/service/create_mock_test.go b/pkg/kn/commands/service/create_mock_test.go index d6af716355..1465428161 100644 --- a/pkg/kn/commands/service/create_mock_test.go +++ b/pkg/kn/commands/service/create_mock_test.go @@ -479,7 +479,7 @@ func getService(name string) *servingv1.Service { Limits: corev1.ResourceList{}, Requests: corev1.ResourceList{}, }, - SecurityContext: flags.DefaultSecCon(), + SecurityContext: flags.DefaultStrictSecCon(), }} return service diff --git a/pkg/kn/commands/source/container/container_test.go b/pkg/kn/commands/source/container/container_test.go index 77228d7677..1f431ee576 100644 --- a/pkg/kn/commands/source/container/container_test.go +++ b/pkg/kn/commands/source/container/container_test.go @@ -94,7 +94,7 @@ func createContainerSource(name, image string, sink duckv1.Destination, ceo map[ Limits: corev1.ResourceList{}, Requests: corev1.ResourceList{}, }, - SecurityContext: flags.DefaultSecCon(), + SecurityContext: flags.DefaultStrictSecCon(), }}}). Sink(sink). Build() diff --git a/pkg/kn/flags/podspec.go b/pkg/kn/flags/podspec.go index ed430299dc..1eed253128 100644 --- a/pkg/kn/flags/podspec.go +++ b/pkg/kn/flags/podspec.go @@ -52,6 +52,8 @@ type PodSpecFlags struct { ServiceAccountName string ImagePullSecrets string User int64 + + SecurityContext string } type ResourceFlags struct { @@ -234,6 +236,10 @@ func (p *PodSpecFlags) AddFlags(flagset *pflag.FlagSet) []string { flagNames = append(flagNames, "pull-secret") flagset.Int64VarP(&p.User, "user", "", 0, "The user ID to run the container (e.g., 1001).") flagNames = append(flagNames, "user") + + flagset.StringVar(&p.SecurityContext, "security-context", "strict", "Security Context definition to be added the service. Accepted values: strict | none.") + flagNames = append(flagNames, "security-context") + return flagNames } @@ -405,7 +411,16 @@ func (p *PodSpecFlags) ResolvePodSpec(podSpec *corev1.PodSpec, flags *pflag.Flag } } - UpdateDefaultSecurityContext(podSpec) + if flags.Changed("security-context") && p.SecurityContext != "" { + if err := UpdateSecurityContext(podSpec, p.SecurityContext); err != nil { + return err + } + } else { + // Set default Security Context + if err := UpdateSecurityContext(podSpec, ""); err != nil { + return err + } + } return nil } diff --git a/pkg/kn/flags/podspec_helper.go b/pkg/kn/flags/podspec_helper.go index 10e423d458..7bdc7b49e1 100644 --- a/pkg/kn/flags/podspec_helper.go +++ b/pkg/kn/flags/podspec_helper.go @@ -380,14 +380,30 @@ func UpdateImagePullPolicy(spec *corev1.PodSpec, imagePullPolicy string) error { return nil } -func UpdateDefaultSecurityContext(spec *corev1.PodSpec) { +// UpdateSecurityContext update the Security Context +func UpdateSecurityContext(spec *corev1.PodSpec, securityContext string) error { container := containerOfPodSpec(spec) - if container.SecurityContext == nil { - container.SecurityContext = DefaultSecCon() + switch strings.ToLower(securityContext) { + case "none": + // Remove any Security Context defined + container.SecurityContext = nil + case "strict": + // Add or update Security Context to default strict + container.SecurityContext = DefaultStrictSecCon() + case "": + // Add default strict SC flag is not used, hence empty value + if container.SecurityContext == nil { + container.SecurityContext = DefaultStrictSecCon() + } + //TODO(dsimansk): add parsing of SC options from the flag value + default: + return fmt.Errorf("invalid --security-context %s. Valid arguments: strict | none", securityContext) } + return nil } -func DefaultSecCon() *corev1.SecurityContext { +// DefaultStrictSecCon helper function to get default strict Security Context +func DefaultStrictSecCon() *corev1.SecurityContext { return &corev1.SecurityContext{ AllowPrivilegeEscalation: pointer.Bool(false), RunAsNonRoot: pointer.Bool(true), diff --git a/pkg/kn/flags/podspec_helper_test.go b/pkg/kn/flags/podspec_helper_test.go index 7671b7df8e..a7ff85a590 100644 --- a/pkg/kn/flags/podspec_helper_test.go +++ b/pkg/kn/flags/podspec_helper_test.go @@ -1487,3 +1487,57 @@ func TestResolveProbeOptions(t *testing.T) { }) } } + +func TestUpdateSecurityContext(t *testing.T) { + testCases := []struct { + name string + + expected *corev1.PodSpec + expectedError error + }{ + { + name: "strict", + expected: &corev1.PodSpec{ + Containers: []corev1.Container{ + {SecurityContext: DefaultStrictSecCon()}}, + }, + expectedError: nil, + }, + { + name: "none", + expected: &corev1.PodSpec{ + Containers: []corev1.Container{{}}, + }, + expectedError: nil, + }, + { + name: "", + expected: &corev1.PodSpec{ + Containers: []corev1.Container{ + {SecurityContext: DefaultStrictSecCon()}}, + }, + expectedError: nil, + }, + { + name: "unknown", + expected: &corev1.PodSpec{ + Containers: []corev1.Container{ + {SecurityContext: DefaultStrictSecCon()}}, + }, + expectedError: errors.New("invalid --security-context unknown. Valid arguments: strict | none"), + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + actual := &corev1.PodSpec{} + err := UpdateSecurityContext(actual, tc.name) + if tc.expectedError != nil { + assert.Error(t, err, tc.expectedError.Error()) + } else { + assert.NilError(t, err) + assert.DeepEqual(t, actual, tc.expected) + } + }) + } +} diff --git a/pkg/kn/flags/podspec_test.go b/pkg/kn/flags/podspec_test.go index ae18200794..a12f478840 100644 --- a/pkg/kn/flags/podspec_test.go +++ b/pkg/kn/flags/podspec_test.go @@ -29,7 +29,6 @@ import ( "github.com/spf13/cobra" "gotest.tools/v3/assert" corev1 "k8s.io/api/core/v1" - v1 "k8s.io/api/core/v1" "knative.dev/client/pkg/util" "knative.dev/pkg/ptr" ) @@ -37,14 +36,15 @@ import ( func TestPodSpecFlags(t *testing.T) { args := []string{"--image", "repo/user/imageID:tag", "--env", "b=c"} wantedPod := &PodSpecFlags{ - Image: "repo/user/imageID:tag", - Env: []string{"b=c"}, - EnvFrom: []string{}, - EnvValueFrom: []string{}, - Mount: []string{}, - Volume: []string{}, - Arg: []string{}, - Command: []string{}, + Image: "repo/user/imageID:tag", + Env: []string{"b=c"}, + EnvFrom: []string{}, + EnvValueFrom: []string{}, + Mount: []string{}, + Volume: []string{}, + Arg: []string{}, + Command: []string{}, + SecurityContext: "strict", } flags := &PodSpecFlags{} testCmd := &cobra.Command{ @@ -86,12 +86,12 @@ func TestPodSpecResolve(t *testing.T) { }, }, ReadinessProbe: &corev1.Probe{ - ProbeHandler: v1.ProbeHandler{ + ProbeHandler: corev1.ProbeHandler{ HTTPGet: &corev1.HTTPGetAction{Port: intstr.Parse("8080"), Path: "/path"}, }, }, LivenessProbe: &corev1.Probe{ - ProbeHandler: v1.ProbeHandler{ + ProbeHandler: corev1.ProbeHandler{ HTTPGet: &corev1.HTTPGetAction{Port: intstr.Parse("8080"), Path: "/path"}, }, }, @@ -223,7 +223,7 @@ containers: Limits: corev1.ResourceList{}, Requests: corev1.ResourceList{}, }, - SecurityContext: DefaultSecCon(), + SecurityContext: DefaultStrictSecCon(), }, { Name: "foo", @@ -394,11 +394,11 @@ func TestPodSpecResolveWithEnvFile(t *testing.T) { }, }, Env: []corev1.EnvVar{{Name: "svcOwner", Value: "James"}, {Name: "svcAuthor", Value: "James"}}, - Resources: v1.ResourceRequirements{ - Limits: v1.ResourceList{}, - Requests: v1.ResourceList{}, + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{}, + Requests: corev1.ResourceList{}, }, - SecurityContext: DefaultSecCon(), + SecurityContext: DefaultStrictSecCon(), }, }, } diff --git a/test/e2e/service_export_test.go b/test/e2e/service_export_test.go index 261a812f4f..9bced1bda0 100644 --- a/test/e2e/service_export_test.go +++ b/test/e2e/service_export_test.go @@ -53,7 +53,7 @@ func TestServiceExport(t *testing.T) { defer r.DumpIfFailed() t.Log("create service with byo revision") - serviceCreateWithOptions(r, "hello", "--revision-name", "rev1") + serviceCreateWithOptions(r, "hello", "--revision-name", "rev1", "--security-context=none") userImage := pkgtest.ImagePath("helloworld") if strings.Contains(userImage, "@") { @@ -233,7 +233,7 @@ func TestServiceExport(t *testing.T) { ), "--with-revisions", "--mode", "export", "-o", "yaml") t.Log("create and export service 'foo' and verify that serviceUID and configurationUID labels are absent") - serviceCreateWithOptions(r, "foo") + serviceCreateWithOptions(r, "foo", "--security-context=none") output := serviceExportOutput(r, "foo", "-o", "json") actSvc := servingv1.Service{} err = json.Unmarshal([]byte(output), &actSvc) From 0fcf8000185bdf24ed98893d8b103b494e846ade Mon Sep 17 00:00:00 2001 From: David Simansky Date: Tue, 27 Jun 2023 17:38:30 +0200 Subject: [PATCH 3/4] Fix export e2e tests --- lib/test/service.go | 2 ++ pkg/kn/flags/podspec.go | 3 +-- pkg/kn/flags/podspec_helper.go | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/test/service.go b/lib/test/service.go index deec4b81db..a61ab046fa 100644 --- a/lib/test/service.go +++ b/lib/test/service.go @@ -259,6 +259,7 @@ func BuildServiceWithOptions(name string, so ...servingtest.ServiceOption) *serv APIVersion: "serving.knative.dev/v1", } svc.Spec.Template.Spec.Containers[0].Resources = corev1.ResourceRequirements{} + svc.Spec.Template.Spec.Containers[0].SecurityContext = &corev1.SecurityContext{} return svc } @@ -301,6 +302,7 @@ func BuildRevision(name string, options ...servingtest.RevisionOption) *servingv rev.ObjectMeta.UID = "" rev.ObjectMeta.Generation = int64(0) rev.Spec.PodSpec.Containers[0].Resources = corev1.ResourceRequirements{} + rev.Spec.PodSpec.Containers[0].SecurityContext = &corev1.SecurityContext{} return rev } diff --git a/pkg/kn/flags/podspec.go b/pkg/kn/flags/podspec.go index 1eed253128..9706771847 100644 --- a/pkg/kn/flags/podspec.go +++ b/pkg/kn/flags/podspec.go @@ -411,12 +411,11 @@ func (p *PodSpecFlags) ResolvePodSpec(podSpec *corev1.PodSpec, flags *pflag.Flag } } - if flags.Changed("security-context") && p.SecurityContext != "" { + if flags.Changed("security-context") { if err := UpdateSecurityContext(podSpec, p.SecurityContext); err != nil { return err } } else { - // Set default Security Context if err := UpdateSecurityContext(podSpec, ""); err != nil { return err } diff --git a/pkg/kn/flags/podspec_helper.go b/pkg/kn/flags/podspec_helper.go index 7bdc7b49e1..0434e753a5 100644 --- a/pkg/kn/flags/podspec_helper.go +++ b/pkg/kn/flags/podspec_helper.go @@ -385,8 +385,8 @@ func UpdateSecurityContext(spec *corev1.PodSpec, securityContext string) error { container := containerOfPodSpec(spec) switch strings.ToLower(securityContext) { case "none": - // Remove any Security Context defined - container.SecurityContext = nil + // Blank any Security Context defined + container.SecurityContext = &corev1.SecurityContext{} case "strict": // Add or update Security Context to default strict container.SecurityContext = DefaultStrictSecCon() From c96dc6c7f62ee2f4ca1daa5bc2a92f5683000c1a Mon Sep 17 00:00:00 2001 From: David Simansky Date: Tue, 27 Jun 2023 19:16:06 +0200 Subject: [PATCH 4/4] Fix unit test --- pkg/kn/flags/podspec_helper_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/kn/flags/podspec_helper_test.go b/pkg/kn/flags/podspec_helper_test.go index a7ff85a590..bb4ef6ebf6 100644 --- a/pkg/kn/flags/podspec_helper_test.go +++ b/pkg/kn/flags/podspec_helper_test.go @@ -1506,7 +1506,8 @@ func TestUpdateSecurityContext(t *testing.T) { { name: "none", expected: &corev1.PodSpec{ - Containers: []corev1.Container{{}}, + Containers: []corev1.Container{{ + SecurityContext: &corev1.SecurityContext{}}}, }, expectedError: nil, },