From d76d650ea479c2dd6772a7ac34a056745a61ba5a Mon Sep 17 00:00:00 2001 From: kabicin Date: Tue, 3 Oct 2023 13:10:59 -0400 Subject: [PATCH 1/5] Add PodSecurityContext fields to .spec.securityContext --- api/v1/runtimecomponent_types.go | 25 +++++++-- api/v1/zz_generated.deepcopy.go | 18 ++++++- .../rc.app.stacks_runtimecomponents.yaml | 52 ++++++++++++++++++- ...ntime-component.clusterserviceversion.yaml | 2 +- common/common.go | 40 ++++++++++++++ common/types.go | 48 ++++++++++++++++- .../rc.app.stacks_runtimecomponents.yaml | 52 ++++++++++++++++++- ...ntime-component.clusterserviceversion.yaml | 2 +- .../deploy/kubectl/runtime-component-crd.yaml | 52 ++++++++++++++++++- .../daily/base/runtime-component-crd.yaml | 52 ++++++++++++++++++- utils/utils.go | 9 +++- 11 files changed, 340 insertions(+), 12 deletions(-) diff --git a/api/v1/runtimecomponent_types.go b/api/v1/runtimecomponent_types.go index cd05e1f9e..506b4d00f 100644 --- a/api/v1/runtimecomponent_types.go +++ b/api/v1/runtimecomponent_types.go @@ -143,9 +143,9 @@ type RuntimeComponentSpec struct { // +operator-sdk:csv:customresourcedefinitions:order=24,type=spec,displayName="Affinity" Affinity *RuntimeComponentAffinity `json:"affinity,omitempty"` - // Security context for the application container. + // Security context for the application pod and container. // +operator-sdk:csv:customresourcedefinitions:order=25,type=spec,displayName="Security Context" - SecurityContext *corev1.SecurityContext `json:"securityContext,omitempty"` + SecurityContext *RuntimeComponentSecurityContext `json:"securityContext,omitempty"` // +operator-sdk:csv:customresourcedefinitions:order=26,type=spec,displayName="Topology Spread Constraints" TopologySpreadConstraints *RuntimeComponentTopologySpreadConstraints `json:"topologySpreadConstraints,omitempty"` @@ -162,6 +162,11 @@ type RuntimeComponentTopologySpreadConstraints struct { DisableOperatorDefaults *bool `json:"disableOperatorDefaults,omitempty"` } +// Define the security context object for the application pod and container +type RuntimeComponentSecurityContext struct { + common.AppSecurityContext `json:",omitempty"` +} + // Defines the service account type RuntimeComponentServiceAccount struct { // Whether the Service Account token should be mounted into the application pods. Defaults to true. @@ -926,8 +931,22 @@ func (a *RuntimeComponentAffinity) GetNodeAffinityLabels() map[string]string { return a.NodeAffinityLabels } +func (sc *RuntimeComponentSecurityContext) GetContainerSecurityContext() *corev1.SecurityContext { + if sc == nil { + return nil + } + return common.GetSecurityContext(&sc.AppSecurityContext) +} + +func (sc *RuntimeComponentSecurityContext) GetPodSecurityContext() *corev1.PodSecurityContext { + if sc == nil { + return nil + } + return common.GetPodSecurityContext(&sc.AppSecurityContext) +} + // GetSecurityContext returns container security context -func (cr *RuntimeComponent) GetSecurityContext() *corev1.SecurityContext { +func (cr *RuntimeComponent) GetSecurityContext() common.BaseComponentSecurityContext { return cr.Spec.SecurityContext } diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index 8c2f73819..3a1f15c51 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -363,6 +363,22 @@ func (in *RuntimeComponentRoute) DeepCopy() *RuntimeComponentRoute { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RuntimeComponentSecurityContext) DeepCopyInto(out *RuntimeComponentSecurityContext) { + *out = *in + in.AppSecurityContext.DeepCopyInto(&out.AppSecurityContext) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RuntimeComponentSecurityContext. +func (in *RuntimeComponentSecurityContext) DeepCopy() *RuntimeComponentSecurityContext { + if in == nil { + return nil + } + out := new(RuntimeComponentSecurityContext) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RuntimeComponentService) DeepCopyInto(out *RuntimeComponentService) { *out = *in @@ -584,7 +600,7 @@ func (in *RuntimeComponentSpec) DeepCopyInto(out *RuntimeComponentSpec) { } if in.SecurityContext != nil { in, out := &in.SecurityContext, &out.SecurityContext - *out = new(corev1.SecurityContext) + *out = new(RuntimeComponentSecurityContext) (*in).DeepCopyInto(*out) } if in.TopologySpreadConstraints != nil { diff --git a/bundle/manifests/rc.app.stacks_runtimecomponents.yaml b/bundle/manifests/rc.app.stacks_runtimecomponents.yaml index cfb0ed833..90ff482ee 100644 --- a/bundle/manifests/rc.app.stacks_runtimecomponents.yaml +++ b/bundle/manifests/rc.app.stacks_runtimecomponents.yaml @@ -3523,7 +3523,7 @@ spec: type: string type: object securityContext: - description: Security context for the application container. + description: Security context for the application pod and container. properties: allowPrivilegeEscalation: description: 'AllowPrivilegeEscalation controls whether a process @@ -3552,6 +3552,28 @@ spec: type: string type: array type: object + fsGroup: + description: "A special supplemental group that applies to all + containers in a pod. Some volume types allow the Kubelet to + change the ownership of that volume to be owned by the pod: + \n 1. The owning GID will be the FSGroup 2. The setgid bit is + set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- \n If unset, + the Kubelet will not modify the ownership and permissions of + any volume. Note that this field cannot be set when spec.os.name + is windows." + format: int64 + type: integer + fsGroupChangePolicy: + description: 'fsGroupChangePolicy defines behavior of changing + ownership and permission of the volume before being exposed + inside Pod. This field will only apply to volume types which + support fsGroup based ownership(and permissions). It will have + no effect on ephemeral volume types such as: secret, configmaps + and emptydir. Valid values are "OnRootMismatch" and "Always". + If not specified, "Always" is used. Note that this field cannot + be set when spec.os.name is windows.' + type: string privileged: description: Run container in privileged mode. Processes in privileged containers are essentially equivalent to root on the host. Defaults @@ -3644,6 +3666,34 @@ spec: required: - type type: object + supplementalGroups: + description: A list of groups applied to the first process run + in each container, in addition to the container's primary GID. If + unspecified, no groups will be added to any container. Note + that this field cannot be set when spec.os.name is windows. + items: + format: int64 + type: integer + type: array + sysctls: + description: Sysctls hold a list of namespaced sysctls used for + the pod. Pods with unsupported sysctls (by the container runtime) + might fail to launch. Note that this field cannot be set when + spec.os.name is windows. + items: + description: Sysctl defines a kernel parameter to be set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array windowsOptions: description: The Windows specific settings applied to all containers. If unspecified, the options from the PodSecurityContext will diff --git a/bundle/manifests/runtime-component.clusterserviceversion.yaml b/bundle/manifests/runtime-component.clusterserviceversion.yaml index 6964d499a..a9347f9d1 100644 --- a/bundle/manifests/runtime-component.clusterserviceversion.yaml +++ b/bundle/manifests/runtime-component.clusterserviceversion.yaml @@ -342,7 +342,7 @@ spec: path: affinity - displayName: Storage path: statefulSet.storage - - description: Security context for the application container. + - description: Security context for the application pod and container. displayName: Security Context path: securityContext - description: A convenient field to set the size of the persisted storage. diff --git a/common/common.go b/common/common.go index a8f750e37..d64cd35e6 100644 --- a/common/common.go +++ b/common/common.go @@ -59,3 +59,43 @@ func GetDefaultMicroProfileLivenessProbe(ba BaseComponent) *corev1.Probe { func GetComponentNameLabel(ba BaseComponent) string { return ba.GetGroupName() + "/name" } + +func GetSecurityContext(asc *AppSecurityContext) *corev1.SecurityContext { + if asc == nil { + return nil + } + sc := asc.SecurityContext + securityContext := &corev1.SecurityContext{} + sc.DeepCopyInto(securityContext) + return securityContext +} + +func GetPodSecurityContext(asc *AppSecurityContext) *corev1.PodSecurityContext { + if asc == nil { + return nil + } + sc := asc.IsolatedPodSecurityContext + podSecurityContext := &corev1.PodSecurityContext{} + podSecurityContext.SupplementalGroups = sc.SupplementalGroups + if sc.FSGroup != nil { + podSecurityContext.FSGroup = sc.FSGroup + } + podSecurityContext.Sysctls = sc.Sysctls + if sc.FSGroupChangePolicy != nil { + podSecurityContext.FSGroupChangePolicy = sc.FSGroupChangePolicy + } + return podSecurityContext +} + +func (in *AppSecurityContext) DeepCopy() *AppSecurityContext { + if in == nil { + return nil + } + out := new(AppSecurityContext) + in.DeepCopyInto(out) + return out +} + +func (in *AppSecurityContext) DeepCopyInto(out *AppSecurityContext) { + *out = *in +} diff --git a/common/types.go b/common/types.go index 8717eceb1..b76aa1724 100644 --- a/common/types.go +++ b/common/types.go @@ -195,6 +195,52 @@ type BaseComponentTopologySpreadConstraints interface { GetDisableOperatorDefaults() *bool } +// Define PodSecurityContext without overlapping fields in SecurityContext +type IsolatedPodSecurityContext struct { + // A list of groups applied to the first process run in each container, in addition + // to the container's primary GID. If unspecified, no groups will be added to + // any container. + // Note that this field cannot be set when spec.os.name is windows. + // +optional + SupplementalGroups []int64 `json:"supplementalGroups,omitempty"` + // A special supplemental group that applies to all containers in a pod. + // Some volume types allow the Kubelet to change the ownership of that volume + // to be owned by the pod: + // + // 1. The owning GID will be the FSGroup + // 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) + // 3. The permission bits are OR'd with rw-rw---- + // + // If unset, the Kubelet will not modify the ownership and permissions of any volume. + // Note that this field cannot be set when spec.os.name is windows. + // +optional + FSGroup *int64 `json:"fsGroup,omitempty"` + // Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported + // sysctls (by the container runtime) might fail to launch. + // Note that this field cannot be set when spec.os.name is windows. + // +optional + Sysctls []corev1.Sysctl `json:"sysctls,omitempty"` + // fsGroupChangePolicy defines behavior of changing ownership and permission of the volume + // before being exposed inside Pod. This field will only apply to + // volume types which support fsGroup based ownership(and permissions). + // It will have no effect on ephemeral volume types such as: secret, configmaps + // and emptydir. + // Valid values are "OnRootMismatch" and "Always". If not specified, "Always" is used. + // Note that this field cannot be set when spec.os.name is windows. + // +optional + FSGroupChangePolicy *corev1.PodFSGroupChangePolicy `json:"fsGroupChangePolicy,omitempty"` +} + +type AppSecurityContext struct { + IsolatedPodSecurityContext `json:",omitempty"` + corev1.SecurityContext `json:",omitempty"` +} + +type BaseComponentSecurityContext interface { + GetContainerSecurityContext() *corev1.SecurityContext + GetPodSecurityContext() *corev1.PodSecurityContext +} + // BaseComponent represents basic kubernetes application type BaseComponent interface { GetApplicationImage() string @@ -228,6 +274,6 @@ type BaseComponent interface { GetRoute() BaseComponentRoute GetAffinity() BaseComponentAffinity GetTopologySpreadConstraints() BaseComponentTopologySpreadConstraints - GetSecurityContext() *corev1.SecurityContext + GetSecurityContext() BaseComponentSecurityContext GetManageTLS() *bool } diff --git a/config/crd/bases/rc.app.stacks_runtimecomponents.yaml b/config/crd/bases/rc.app.stacks_runtimecomponents.yaml index b28faca10..cfa9c5b7b 100644 --- a/config/crd/bases/rc.app.stacks_runtimecomponents.yaml +++ b/config/crd/bases/rc.app.stacks_runtimecomponents.yaml @@ -3520,7 +3520,7 @@ spec: type: string type: object securityContext: - description: Security context for the application container. + description: Security context for the application pod and container. properties: allowPrivilegeEscalation: description: 'AllowPrivilegeEscalation controls whether a process @@ -3549,6 +3549,28 @@ spec: type: string type: array type: object + fsGroup: + description: "A special supplemental group that applies to all + containers in a pod. Some volume types allow the Kubelet to + change the ownership of that volume to be owned by the pod: + \n 1. The owning GID will be the FSGroup 2. The setgid bit is + set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- \n If unset, + the Kubelet will not modify the ownership and permissions of + any volume. Note that this field cannot be set when spec.os.name + is windows." + format: int64 + type: integer + fsGroupChangePolicy: + description: 'fsGroupChangePolicy defines behavior of changing + ownership and permission of the volume before being exposed + inside Pod. This field will only apply to volume types which + support fsGroup based ownership(and permissions). It will have + no effect on ephemeral volume types such as: secret, configmaps + and emptydir. Valid values are "OnRootMismatch" and "Always". + If not specified, "Always" is used. Note that this field cannot + be set when spec.os.name is windows.' + type: string privileged: description: Run container in privileged mode. Processes in privileged containers are essentially equivalent to root on the host. Defaults @@ -3641,6 +3663,34 @@ spec: required: - type type: object + supplementalGroups: + description: A list of groups applied to the first process run + in each container, in addition to the container's primary GID. If + unspecified, no groups will be added to any container. Note + that this field cannot be set when spec.os.name is windows. + items: + format: int64 + type: integer + type: array + sysctls: + description: Sysctls hold a list of namespaced sysctls used for + the pod. Pods with unsupported sysctls (by the container runtime) + might fail to launch. Note that this field cannot be set when + spec.os.name is windows. + items: + description: Sysctl defines a kernel parameter to be set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array windowsOptions: description: The Windows specific settings applied to all containers. If unspecified, the options from the PodSecurityContext will diff --git a/config/manifests/bases/runtime-component.clusterserviceversion.yaml b/config/manifests/bases/runtime-component.clusterserviceversion.yaml index e6351cca2..23fef2b0b 100644 --- a/config/manifests/bases/runtime-component.clusterserviceversion.yaml +++ b/config/manifests/bases/runtime-component.clusterserviceversion.yaml @@ -276,7 +276,7 @@ spec: path: affinity - displayName: Storage path: statefulSet.storage - - description: Security context for the application container. + - description: Security context for the application pod and container. displayName: Security Context path: securityContext - description: A convenient field to set the size of the persisted storage. diff --git a/internal/deploy/kubectl/runtime-component-crd.yaml b/internal/deploy/kubectl/runtime-component-crd.yaml index ded240cc0..51f3425c5 100644 --- a/internal/deploy/kubectl/runtime-component-crd.yaml +++ b/internal/deploy/kubectl/runtime-component-crd.yaml @@ -3522,7 +3522,7 @@ spec: type: string type: object securityContext: - description: Security context for the application container. + description: Security context for the application pod and container. properties: allowPrivilegeEscalation: description: 'AllowPrivilegeEscalation controls whether a process @@ -3551,6 +3551,28 @@ spec: type: string type: array type: object + fsGroup: + description: "A special supplemental group that applies to all + containers in a pod. Some volume types allow the Kubelet to + change the ownership of that volume to be owned by the pod: + \n 1. The owning GID will be the FSGroup 2. The setgid bit is + set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- \n If unset, + the Kubelet will not modify the ownership and permissions of + any volume. Note that this field cannot be set when spec.os.name + is windows." + format: int64 + type: integer + fsGroupChangePolicy: + description: 'fsGroupChangePolicy defines behavior of changing + ownership and permission of the volume before being exposed + inside Pod. This field will only apply to volume types which + support fsGroup based ownership(and permissions). It will have + no effect on ephemeral volume types such as: secret, configmaps + and emptydir. Valid values are "OnRootMismatch" and "Always". + If not specified, "Always" is used. Note that this field cannot + be set when spec.os.name is windows.' + type: string privileged: description: Run container in privileged mode. Processes in privileged containers are essentially equivalent to root on the host. Defaults @@ -3643,6 +3665,34 @@ spec: required: - type type: object + supplementalGroups: + description: A list of groups applied to the first process run + in each container, in addition to the container's primary GID. If + unspecified, no groups will be added to any container. Note + that this field cannot be set when spec.os.name is windows. + items: + format: int64 + type: integer + type: array + sysctls: + description: Sysctls hold a list of namespaced sysctls used for + the pod. Pods with unsupported sysctls (by the container runtime) + might fail to launch. Note that this field cannot be set when + spec.os.name is windows. + items: + description: Sysctl defines a kernel parameter to be set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array windowsOptions: description: The Windows specific settings applied to all containers. If unspecified, the options from the PodSecurityContext will diff --git a/internal/deploy/kustomize/daily/base/runtime-component-crd.yaml b/internal/deploy/kustomize/daily/base/runtime-component-crd.yaml index ded240cc0..51f3425c5 100644 --- a/internal/deploy/kustomize/daily/base/runtime-component-crd.yaml +++ b/internal/deploy/kustomize/daily/base/runtime-component-crd.yaml @@ -3522,7 +3522,7 @@ spec: type: string type: object securityContext: - description: Security context for the application container. + description: Security context for the application pod and container. properties: allowPrivilegeEscalation: description: 'AllowPrivilegeEscalation controls whether a process @@ -3551,6 +3551,28 @@ spec: type: string type: array type: object + fsGroup: + description: "A special supplemental group that applies to all + containers in a pod. Some volume types allow the Kubelet to + change the ownership of that volume to be owned by the pod: + \n 1. The owning GID will be the FSGroup 2. The setgid bit is + set (new files created in the volume will be owned by FSGroup) + 3. The permission bits are OR'd with rw-rw---- \n If unset, + the Kubelet will not modify the ownership and permissions of + any volume. Note that this field cannot be set when spec.os.name + is windows." + format: int64 + type: integer + fsGroupChangePolicy: + description: 'fsGroupChangePolicy defines behavior of changing + ownership and permission of the volume before being exposed + inside Pod. This field will only apply to volume types which + support fsGroup based ownership(and permissions). It will have + no effect on ephemeral volume types such as: secret, configmaps + and emptydir. Valid values are "OnRootMismatch" and "Always". + If not specified, "Always" is used. Note that this field cannot + be set when spec.os.name is windows.' + type: string privileged: description: Run container in privileged mode. Processes in privileged containers are essentially equivalent to root on the host. Defaults @@ -3643,6 +3665,34 @@ spec: required: - type type: object + supplementalGroups: + description: A list of groups applied to the first process run + in each container, in addition to the container's primary GID. If + unspecified, no groups will be added to any container. Note + that this field cannot be set when spec.os.name is windows. + items: + format: int64 + type: integer + type: array + sysctls: + description: Sysctls hold a list of namespaced sysctls used for + the pod. Pods with unsupported sysctls (by the container runtime) + might fail to launch. Note that this field cannot be set when + spec.os.name is windows. + items: + description: Sysctl defines a kernel parameter to be set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array windowsOptions: description: The Windows specific settings applied to all containers. If unspecified, the options from the PodSecurityContext will diff --git a/utils/utils.go b/utils/utils.go index ae9596cd1..70198dd93 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -688,6 +688,7 @@ func CustomizePodSpec(pts *corev1.PodTemplateSpec, ba common.BaseComponent) { pts.Spec.Volumes = ba.GetVolumes() appContainer.SecurityContext = GetSecurityContext(ba) + pts.Spec.SecurityContext = GetPodSecurityContext(ba) if ba.GetManageTLS() == nil || *ba.GetManageTLS() || ba.GetService().GetCertificateSecretRef() != nil { @@ -935,6 +936,7 @@ func CustomizeKnativeService(ksvc *servingv1.Service, ba common.BaseComponent) { ksvc.Spec.Template.Spec.Containers[0].EnvFrom = ba.GetEnvFrom() ksvc.Spec.Template.Spec.Containers[0].SecurityContext = GetSecurityContext(ba) + ksvc.Spec.Template.Spec.SecurityContext = GetPodSecurityContext(ba) ksvc.Spec.Template.Spec.Containers[0].VolumeMounts = ba.GetVolumeMounts() ksvc.Spec.Template.Spec.Volumes = ba.GetVolumes() @@ -1598,7 +1600,7 @@ func ServiceAccountPullSecretExists(ba common.BaseComponent, client client.Clien // Get security context from CR and apply customization to default settings func GetSecurityContext(ba common.BaseComponent) *corev1.SecurityContext { - baSecurityContext := ba.GetSecurityContext() + baSecurityContext := ba.GetSecurityContext().GetContainerSecurityContext() valFalse := false valTrue := true @@ -1639,6 +1641,11 @@ func GetSecurityContext(ba common.BaseComponent) *corev1.SecurityContext { return secContext } +// Get pod security context from CR +func GetPodSecurityContext(ba common.BaseComponent) *corev1.PodSecurityContext { + return ba.GetSecurityContext().GetPodSecurityContext() +} + func AddOCPCertAnnotation(ba common.BaseComponent, svc *corev1.Service) { bao := ba.(metav1.Object) From 5cf4a4b5b3f95be53e339e46fbe070295f153c69 Mon Sep 17 00:00:00 2001 From: kabicin Date: Tue, 3 Oct 2023 13:50:27 -0400 Subject: [PATCH 2/5] Add PodSecurityContext fields to user-guide-v1 --- doc/user-guide-v1.adoc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/user-guide-v1.adoc b/doc/user-guide-v1.adoc index 1d05a4a74..d37440e66 100755 --- a/doc/user-guide-v1.adoc +++ b/doc/user-guide-v1.adoc @@ -106,11 +106,13 @@ Each `RuntimeComponent` CR must at least specify the `.spec.applicationImage` fi | `route.path` | Path to be used for the `Route`. | `route.pathType` | Path type to be used. Required field for Ingress. See link:++https://kubernetes.io/docs/concepts/services-networking/ingress/#path-types++[Ingress path types]. | `route.termination` | TLS termination policy. Can be one of `edge`, `reencrypt` and `passthrough`. -| `securityContext` | A security context to control privilege and permission settings for the application container. For examples, see link:++https://github.com/OpenLiberty/open-liberty-operator/blob/main/doc/user-guide-v1.adoc#set-privileges-and-permissions-for-a-pod-or-container++[Set privileges and permissions for a pod or container]. If set, the fields of `SecurityContext` override the equivalent fields of `PodSecurityContext`. For examples, see link:++https://kubernetes.io/docs/tasks/configure-pod-container/security-context/++[Configure a Security Context for a Pod or Container]. +| `securityContext` | A security context to control privilege and permission settings for the application pod and container. For examples, see link:++https://github.com/OpenLiberty/open-liberty-operator/blob/main/doc/user-guide-v1.adoc#set-privileges-and-permissions-for-a-pod-or-container++[Set privileges and permissions for a pod or container]. If set, the fields of `SecurityContext` override the equivalent fields of `PodSecurityContext`. For examples, see link:++https://kubernetes.io/docs/tasks/configure-pod-container/security-context/++[Configure a Security Context for a Pod or Container]. | `securityContext.allowPrivilegeEscalation` | A Boolean that controls whether a process can gain more privileges than its parent process. This Boolean controls whether the `no_new_privs` flag is set on the container process. `AllowPrivilegeEscalation` is `true` always when the container is run as `Privileged` and has `CAP_SYS_ADMIN`. | `securityContext.capabilities` | The capabilities to add or drop when containers are run. Defaults to the default set of capabilities that the container runtime grants. | `securityContext.capabilities.add` | An array of added capabilities of POSIX capabilities type. | `securityContext.capabilities.drop` | An array of removed capabilities of POSIX capabilities type. +| `securityContext.fsGroup` | A supplemental group that applies to all containers in a pod. For some volume types, the Kubelet may change ownership of that volume to be owned by the pod. In this case, the owning GID will be set to the FSGroup, the setgid bit is set so that new files created in the volume will be owned by FSGroup, and the permission bits are OR'd with `rw-rw----`. If unset, the Kubelet will not modify the ownership and permissions of any volume. +| `securityContext.fsGroupChangePolicy` | For volume types supporting fsGroup, this field defines when ownership and permission of the volume should be modified before being exposed inside the Pod. The field has no effect on ephemeral volumes such as Secret, ConfigMaps and EmptyDir. Valid values are `OnRootMismatch` and `Always`. | `securityContext.privileged` | A Boolean to specify whether to run a container in privileged mode. Processes in privileged containers are equivalent to root on the host. The default is `false`. | `securityContext.procMount` | The type of proc mount to use for the containers. The default is `DefaultProcMount`, which uses the container runtime defaults for read-only paths and masked paths. To use `procMount`, the `ProcMountType` feature flag must be enabled. | `securityContext.readOnlyRootFilesystem` | A Boolean to specify whether this container has a read-only root file system. The default is `false`. @@ -121,6 +123,8 @@ Each `RuntimeComponent` CR must at least specify the `.spec.applicationImage` fi | `securityContext.seccompProfile` | The `seccomp` options to use by this container. If `seccomp` options are set at both the pod and container level, the container options override the pod options. | `securityContext.seccompProfile.localhostProfile` | A profile that is defined in a file on the node. The profile must be preconfigured on the node to work. Specify a descending path, relative to the kubelet configured `seccomp` profile location. Only set `localhostProfile` if `type` is `Localhost`. | `securityContext.seccompProfile.type` | (Required) The kind of `seccomp` profile to use. Valid options are `Localhost` (use a profile that is defined in a file on the node), `RuntimeDefault` (use the container runtime default profile), and `Unconfined` (use no profile). +| `securityContext.supplementalGroups` | A list of groups applied to the first process run in each container, in addition to the container's primary GID. If unspecified, no groups will be added to any container. +| `securityContext.sysctls` | A list of namespaced sysctls used for the pod. Pods with unsupported sysctls (by the container runtime) might fail to launch. | `securityContext.windowsOptions` | The Windows specific settings to apply to all containers. If unset, the options from the `PodSecurityContext` are used. If set in both `SecurityContext` and `PodSecurityContext`, the `SecurityContext` value takes precedence. The `windowsOptions` properties include `gmsaCredentialSpec`, `gmsaCredentialSpecName`, `hostProcess`, and `runAsUserName`. | `service` | Configures parameters for the network service of pods. For an example, see link:++https://github.com/OpenLiberty/open-liberty-operator/blob/main/doc/user-guide-v1.adoc#specify-multiple-service-ports++[Specify multiple service ports]. | `service.annotations` | Annotations to be added to the service. From 6a90c45a7705b91a0d624b2460f858a651446e7b Mon Sep 17 00:00:00 2001 From: kabicin Date: Wed, 4 Oct 2023 15:20:48 -0400 Subject: [PATCH 3/5] Make kubebuilder generate DeepCopy functions --- common/common.go | 13 ------ common/types.go | 2 + common/zz_generated.deepcopy.go | 78 +++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 13 deletions(-) create mode 100644 common/zz_generated.deepcopy.go diff --git a/common/common.go b/common/common.go index d64cd35e6..ffb95f856 100644 --- a/common/common.go +++ b/common/common.go @@ -86,16 +86,3 @@ func GetPodSecurityContext(asc *AppSecurityContext) *corev1.PodSecurityContext { } return podSecurityContext } - -func (in *AppSecurityContext) DeepCopy() *AppSecurityContext { - if in == nil { - return nil - } - out := new(AppSecurityContext) - in.DeepCopyInto(out) - return out -} - -func (in *AppSecurityContext) DeepCopyInto(out *AppSecurityContext) { - *out = *in -} diff --git a/common/types.go b/common/types.go index b76aa1724..48de23142 100644 --- a/common/types.go +++ b/common/types.go @@ -196,6 +196,7 @@ type BaseComponentTopologySpreadConstraints interface { } // Define PodSecurityContext without overlapping fields in SecurityContext +// +kubebuilder:object:generate=true type IsolatedPodSecurityContext struct { // A list of groups applied to the first process run in each container, in addition // to the container's primary GID. If unspecified, no groups will be added to @@ -231,6 +232,7 @@ type IsolatedPodSecurityContext struct { FSGroupChangePolicy *corev1.PodFSGroupChangePolicy `json:"fsGroupChangePolicy,omitempty"` } +// +kubebuilder:object:generate=true type AppSecurityContext struct { IsolatedPodSecurityContext `json:",omitempty"` corev1.SecurityContext `json:",omitempty"` diff --git a/common/zz_generated.deepcopy.go b/common/zz_generated.deepcopy.go new file mode 100644 index 000000000..95abd0f16 --- /dev/null +++ b/common/zz_generated.deepcopy.go @@ -0,0 +1,78 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* + + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package common + +import ( + "k8s.io/api/core/v1" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AppSecurityContext) DeepCopyInto(out *AppSecurityContext) { + *out = *in + in.IsolatedPodSecurityContext.DeepCopyInto(&out.IsolatedPodSecurityContext) + in.SecurityContext.DeepCopyInto(&out.SecurityContext) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppSecurityContext. +func (in *AppSecurityContext) DeepCopy() *AppSecurityContext { + if in == nil { + return nil + } + out := new(AppSecurityContext) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IsolatedPodSecurityContext) DeepCopyInto(out *IsolatedPodSecurityContext) { + *out = *in + if in.SupplementalGroups != nil { + in, out := &in.SupplementalGroups, &out.SupplementalGroups + *out = make([]int64, len(*in)) + copy(*out, *in) + } + if in.FSGroup != nil { + in, out := &in.FSGroup, &out.FSGroup + *out = new(int64) + **out = **in + } + if in.Sysctls != nil { + in, out := &in.Sysctls, &out.Sysctls + *out = make([]v1.Sysctl, len(*in)) + copy(*out, *in) + } + if in.FSGroupChangePolicy != nil { + in, out := &in.FSGroupChangePolicy, &out.FSGroupChangePolicy + *out = new(v1.PodFSGroupChangePolicy) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IsolatedPodSecurityContext. +func (in *IsolatedPodSecurityContext) DeepCopy() *IsolatedPodSecurityContext { + if in == nil { + return nil + } + out := new(IsolatedPodSecurityContext) + in.DeepCopyInto(out) + return out +} From bfd4145c2a2f900a14ffa58d0e56b825195bd5f6 Mon Sep 17 00:00:00 2001 From: kabicin Date: Thu, 5 Oct 2023 11:46:30 -0400 Subject: [PATCH 4/5] Cite PodSecurityContext source --- common/types.go | 1 + 1 file changed, 1 insertion(+) diff --git a/common/types.go b/common/types.go index 48de23142..7a5b7fb73 100644 --- a/common/types.go +++ b/common/types.go @@ -196,6 +196,7 @@ type BaseComponentTopologySpreadConstraints interface { } // Define PodSecurityContext without overlapping fields in SecurityContext +// This struct is based upon the PodSecurityContext specification in https://github.com/kubernetes/api/blob/v0.24.2/core/v1/types.go // +kubebuilder:object:generate=true type IsolatedPodSecurityContext struct { // A list of groups applied to the first process run in each container, in addition From 1af5bfba430d0459714460fec31c20b80eb42e6a Mon Sep 17 00:00:00 2001 From: kabicin Date: Thu, 8 Feb 2024 12:20:51 -0500 Subject: [PATCH 5/5] Patch instead of replace PodSecurityContext --- api/v1/runtimecomponent_types.go | 6 +++--- common/common.go | 16 +++++++++++----- common/types.go | 2 +- utils/utils.go | 8 ++++---- 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/api/v1/runtimecomponent_types.go b/api/v1/runtimecomponent_types.go index 506b4d00f..4a67cfc2d 100644 --- a/api/v1/runtimecomponent_types.go +++ b/api/v1/runtimecomponent_types.go @@ -938,11 +938,11 @@ func (sc *RuntimeComponentSecurityContext) GetContainerSecurityContext() *corev1 return common.GetSecurityContext(&sc.AppSecurityContext) } -func (sc *RuntimeComponentSecurityContext) GetPodSecurityContext() *corev1.PodSecurityContext { +func (sc *RuntimeComponentSecurityContext) PatchPodSecurityContext(podSecurityContext *corev1.PodSecurityContext) *corev1.PodSecurityContext { if sc == nil { - return nil + return podSecurityContext } - return common.GetPodSecurityContext(&sc.AppSecurityContext) + return common.PatchPodSecurityContext(&sc.AppSecurityContext, podSecurityContext) } // GetSecurityContext returns container security context diff --git a/common/common.go b/common/common.go index ffb95f856..2aa177964 100644 --- a/common/common.go +++ b/common/common.go @@ -70,17 +70,23 @@ func GetSecurityContext(asc *AppSecurityContext) *corev1.SecurityContext { return securityContext } -func GetPodSecurityContext(asc *AppSecurityContext) *corev1.PodSecurityContext { +func PatchPodSecurityContext(asc *AppSecurityContext, podSecurityContext *corev1.PodSecurityContext) *corev1.PodSecurityContext { if asc == nil { - return nil + return podSecurityContext + } + if podSecurityContext == nil { + podSecurityContext = &corev1.PodSecurityContext{} } sc := asc.IsolatedPodSecurityContext - podSecurityContext := &corev1.PodSecurityContext{} - podSecurityContext.SupplementalGroups = sc.SupplementalGroups + if len(sc.SupplementalGroups) > 0 { + podSecurityContext.SupplementalGroups = sc.SupplementalGroups + } if sc.FSGroup != nil { podSecurityContext.FSGroup = sc.FSGroup } - podSecurityContext.Sysctls = sc.Sysctls + if len(sc.Sysctls) > 0 { + podSecurityContext.Sysctls = sc.Sysctls + } if sc.FSGroupChangePolicy != nil { podSecurityContext.FSGroupChangePolicy = sc.FSGroupChangePolicy } diff --git a/common/types.go b/common/types.go index 7a5b7fb73..96bfc7b68 100644 --- a/common/types.go +++ b/common/types.go @@ -241,7 +241,7 @@ type AppSecurityContext struct { type BaseComponentSecurityContext interface { GetContainerSecurityContext() *corev1.SecurityContext - GetPodSecurityContext() *corev1.PodSecurityContext + PatchPodSecurityContext(*corev1.PodSecurityContext) *corev1.PodSecurityContext } // BaseComponent represents basic kubernetes application diff --git a/utils/utils.go b/utils/utils.go index 70198dd93..c82af39c8 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -688,7 +688,7 @@ func CustomizePodSpec(pts *corev1.PodTemplateSpec, ba common.BaseComponent) { pts.Spec.Volumes = ba.GetVolumes() appContainer.SecurityContext = GetSecurityContext(ba) - pts.Spec.SecurityContext = GetPodSecurityContext(ba) + pts.Spec.SecurityContext = PatchPodSecurityContext(ba, pts.Spec.SecurityContext) if ba.GetManageTLS() == nil || *ba.GetManageTLS() || ba.GetService().GetCertificateSecretRef() != nil { @@ -936,7 +936,7 @@ func CustomizeKnativeService(ksvc *servingv1.Service, ba common.BaseComponent) { ksvc.Spec.Template.Spec.Containers[0].EnvFrom = ba.GetEnvFrom() ksvc.Spec.Template.Spec.Containers[0].SecurityContext = GetSecurityContext(ba) - ksvc.Spec.Template.Spec.SecurityContext = GetPodSecurityContext(ba) + ksvc.Spec.Template.Spec.SecurityContext = PatchPodSecurityContext(ba, ksvc.Spec.Template.Spec.SecurityContext) ksvc.Spec.Template.Spec.Containers[0].VolumeMounts = ba.GetVolumeMounts() ksvc.Spec.Template.Spec.Volumes = ba.GetVolumes() @@ -1642,8 +1642,8 @@ func GetSecurityContext(ba common.BaseComponent) *corev1.SecurityContext { } // Get pod security context from CR -func GetPodSecurityContext(ba common.BaseComponent) *corev1.PodSecurityContext { - return ba.GetSecurityContext().GetPodSecurityContext() +func PatchPodSecurityContext(ba common.BaseComponent, podSecurityContext *corev1.PodSecurityContext) *corev1.PodSecurityContext { + return ba.GetSecurityContext().PatchPodSecurityContext(podSecurityContext) } func AddOCPCertAnnotation(ba common.BaseComponent, svc *corev1.Service) {