diff --git a/api/v2/checluster_types.go b/api/v2/checluster_types.go index 61313d33d..149f6208b 100644 --- a/api/v2/checluster_types.go +++ b/api/v2/checluster_types.go @@ -125,8 +125,21 @@ type CheClusterDevEnvironments struct { // +kubebuilder:default:=-1 SecondsOfRunBeforeIdling *int32 `json:"secondsOfRunBeforeIdling,omitempty"` // Disables the container build capabilities. + // When set to `false` (the default value), the devEnvironments.security.containerSecurityContext + // field is ignored, and the following container SecurityContext is applied: + // + // containerSecurityContext: + // allowPrivilegeEscalation: true + // capabilities: + // add: + // - SETGID + // - SETUID + // // +optional DisableContainerBuildCapabilities *bool `json:"disableContainerBuildCapabilities,omitempty"` + // Workspace security configuration. + // +optional + Security WorkspaceSecurityConfig `json:"security,omitempty"` // Container build configuration. // +optional ContainerBuildConfiguration *ContainerBuildConfiguration `json:"containerBuildConfiguration,omitempty"` @@ -456,6 +469,19 @@ type WorkspaceDefaultPlugins struct { Plugins []string `json:"plugins,omitempty"` } +// Workspace security configuration +type WorkspaceSecurityConfig struct { + // PodSecurityContext used by all workspace-related pods. + // If set, defined values are merged into the default PodSecurityContext configuration. + // +optional + PodSecurityContext *corev1.PodSecurityContext `json:"podSecurityContext,omitempty"` + // Container SecurityContext used by all workspace-related containers. + // If set, defined values are merged into the default Container SecurityContext configuration. + // Requires devEnvironments.disableContainerBuildCapabilities to be set to `true` in order to take effect. + // +optional + ContainerSecurityContext *corev1.SecurityContext `json:"containerSecurityContext,omitempty"` +} + // Authentication settings. type Auth struct { // Public URL of the Identity Provider server. diff --git a/api/v2/zz_generated.deepcopy.go b/api/v2/zz_generated.deepcopy.go index 3eabf49a2..602d543e2 100644 --- a/api/v2/zz_generated.deepcopy.go +++ b/api/v2/zz_generated.deepcopy.go @@ -232,6 +232,7 @@ func (in *CheClusterDevEnvironments) DeepCopyInto(out *CheClusterDevEnvironments *out = new(bool) **out = **in } + in.Security.DeepCopyInto(&out.Security) if in.ContainerBuildConfiguration != nil { in, out := &in.ContainerBuildConfiguration, &out.ContainerBuildConfiguration *out = new(ContainerBuildConfiguration) @@ -977,6 +978,31 @@ func (in *WorkspaceDefaultPlugins) DeepCopy() *WorkspaceDefaultPlugins { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WorkspaceSecurityConfig) DeepCopyInto(out *WorkspaceSecurityConfig) { + *out = *in + if in.PodSecurityContext != nil { + in, out := &in.PodSecurityContext, &out.PodSecurityContext + *out = new(v1.PodSecurityContext) + (*in).DeepCopyInto(*out) + } + if in.ContainerSecurityContext != nil { + in, out := &in.ContainerSecurityContext, &out.ContainerSecurityContext + *out = new(v1.SecurityContext) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WorkspaceSecurityConfig. +func (in *WorkspaceSecurityConfig) DeepCopy() *WorkspaceSecurityConfig { + if in == nil { + return nil + } + out := new(WorkspaceSecurityConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WorkspaceStorage) DeepCopyInto(out *WorkspaceStorage) { *out = *in diff --git a/bundle/next/eclipse-che/manifests/che-operator.clusterserviceversion.yaml b/bundle/next/eclipse-che/manifests/che-operator.clusterserviceversion.yaml index db04e7306..266974205 100644 --- a/bundle/next/eclipse-che/manifests/che-operator.clusterserviceversion.yaml +++ b/bundle/next/eclipse-che/manifests/che-operator.clusterserviceversion.yaml @@ -77,7 +77,7 @@ metadata: operators.operatorframework.io/project_layout: go.kubebuilder.io/v3 repository: https://github.com/eclipse-che/che-operator support: Eclipse Foundation - name: eclipse-che.v7.72.0-805.next + name: eclipse-che.v7.72.0-806.next namespace: placeholder spec: apiservicedefinitions: {} @@ -952,6 +952,9 @@ spec: value: https://open-vsx.org - name: CHE_DEFAULT_SPEC_DEVENVIRONMENTS_DISABLECONTAINERBUILDCAPABILITIES value: "false" + - name: CHE_DEFAULT_SPEC_DEVENVIRONMENTS_CONTAINERSECURITYCONTEXT + value: '{"allowPrivilegeEscalation": true,"capabilities": + {"add": ["SETGID", "SETUID"]}}' image: quay.io/eclipse/che-operator:next imagePullPolicy: Always livenessProbe: @@ -1231,7 +1234,7 @@ spec: minKubeVersion: 1.19.0 provider: name: Eclipse Foundation - version: 7.72.0-805.next + version: 7.72.0-806.next webhookdefinitions: - admissionReviewVersions: - v1 diff --git a/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml b/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml index ddbf8f5f1..e6f233ee5 100644 --- a/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml +++ b/bundle/next/eclipse-che/manifests/org.eclipse.che_checlusters.yaml @@ -6797,7 +6797,11 @@ spec: - RollingUpdate type: string disableContainerBuildCapabilities: - description: Disables the container build capabilities. + description: "Disables the container build capabilities. When\ + \ set to `false` (the default value), the devEnvironments.security.containerSecurityContext\ + \ field is ignored, and the following container SecurityContext\ + \ is applied: \n containerSecurityContext: allowPrivilegeEscalation:\ + \ true capabilities: add: - SETGID - SETUID" type: boolean gatewayContainer: description: GatewayContainer configuration. @@ -7234,6 +7238,374 @@ spec: run timeout, set this value to -1. format: int32 type: integer + security: + description: Workspace security configuration. + properties: + containerSecurityContext: + description: Container SecurityContext used by all workspace-related + containers. If set, defined values are merged into the + default Container SecurityContext configuration. Requires + devEnvironments.disableContainerBuildCapabilities to be + set to `true` in order to take effect. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent + process. This bool directly controls if the no_new_privs + flag will be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be + set when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running + containers. Defaults to the default set of capabilities + granted by the container runtime. Note that this field + cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent + to root on the host. Defaults to false. Note that + this field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount + to use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. Note that this field cannot + be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only + root filesystem. Default is false. Note that this + field cannot be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: 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. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the + container. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in PodSecurityContext. If set in both + SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is + windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & + container level, the container options override the + pod options. Note that this field cannot be set when + spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. + The profile must be preconfigured on the node + to work. Must be a descending path, relative to + the kubelet's configured seccomp profile location. + Must only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp\ + \ profile will be applied. Valid options are:\ + \ \n Localhost - a profile defined in a file on\ + \ the node should be used. RuntimeDefault - the\ + \ container runtime default profile should be\ + \ used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to + all containers. If unspecified, the options from the + PodSecurityContext will be used. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name + of the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. This + field is alpha-level and will only be honored + by components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the + Pod. All of a Pod's containers must have the same + effective HostProcess value (it is not allowed + to have a mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true + then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the + entrypoint of the container process. Defaults + to the user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set + in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + type: string + type: object + type: object + podSecurityContext: + description: PodSecurityContext used by all workspace-related + pods. If set, defined values are merged into the default + PodSecurityContext configuration. + properties: + 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 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 + runAsGroup: + description: 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. Note that this + field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: 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 SecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: 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. Note that this field cannot be + set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all + containers. If unspecified, the container runtime + will allocate a random SELinux context for each container. May + also be set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this + field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by the containers + in this pod. Note that this field cannot be set when + spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. + The profile must be preconfigured on the node + to work. Must be a descending path, relative to + the kubelet's configured seccomp profile location. + Must only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp\ + \ profile will be applied. Valid options are:\ + \ \n Localhost - a profile defined in a file on\ + \ the node should be used. RuntimeDefault - the\ + \ container runtime default profile should be\ + \ used. Unconfined - no profile should be applied." + type: string + 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, the fsGroup (if specified), and group + memberships defined in the container image for the + uid of the container process. If unspecified, no additional + groups are added to any container. Note that group + memberships defined in the container image for the + uid of the container process are still effective, + even if they are not included in this list. 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 within + a container's SecurityContext will be used. If set + in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name + of the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. This + field is alpha-level and will only be honored + by components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the + Pod. All of a Pod's containers must have the same + effective HostProcess value (it is not allowed + to have a mix of HostProcess containers and non-HostProcess + containers). In addition, if HostProcess is true + then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the + entrypoint of the container process. Defaults + to the user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set + in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + type: string + type: object + type: object + type: object serviceAccount: description: ServiceAccount to use by the DevWorkspace operator when starting the workspaces. diff --git a/config/crd/bases/org.eclipse.che_checlusters.yaml b/config/crd/bases/org.eclipse.che_checlusters.yaml index c938e2524..c6dc5b206 100644 --- a/config/crd/bases/org.eclipse.che_checlusters.yaml +++ b/config/crd/bases/org.eclipse.che_checlusters.yaml @@ -6605,7 +6605,11 @@ spec: - RollingUpdate type: string disableContainerBuildCapabilities: - description: Disables the container build capabilities. + description: "Disables the container build capabilities. When + set to `false` (the default value), the devEnvironments.security.containerSecurityContext + field is ignored, and the following container SecurityContext + is applied: \n containerSecurityContext: allowPrivilegeEscalation: + true capabilities: add: - SETGID - SETUID" type: boolean gatewayContainer: description: GatewayContainer configuration. @@ -7033,6 +7037,370 @@ spec: run timeout, set this value to -1. format: int32 type: integer + security: + description: Workspace security configuration. + properties: + containerSecurityContext: + description: Container SecurityContext used by all workspace-related + containers. If set, defined values are merged into the default + Container SecurityContext configuration. Requires devEnvironments.disableContainerBuildCapabilities + to be set to `true` in order to take effect. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag + will be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be + set when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running + containers. Defaults to the default set of capabilities + granted by the container runtime. Note that this field + cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent + to root on the host. Defaults to false. Note that this + field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount + to use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. Note that this field cannot + be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root + filesystem. Default is false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: 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. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the + container. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. + Note that this field cannot be set when spec.os.name + is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. The + profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's + configured seccomp profile location. Must only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n Localhost + - a profile defined in a file on the node should + be used. RuntimeDefault - the container runtime + default profile should be used. Unconfined - no + profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to + all containers. If unspecified, the options from the + PodSecurityContext will be used. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of + the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. This + field is alpha-level and will only be honored by + components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the Pod. + All of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a mix + of HostProcess containers and non-HostProcess containers). In + addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + podSecurityContext: + description: PodSecurityContext used by all workspace-related + pods. If set, defined values are merged into the default + PodSecurityContext configuration. + properties: + 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 + 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 + runAsGroup: + description: 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. Note that this + field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: 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 SecurityContext. If set + in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: 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. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all + containers. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this + field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by the containers + in this pod. Note that this field cannot be set when + spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. The + profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's + configured seccomp profile location. Must only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n Localhost + - a profile defined in a file on the node should + be used. RuntimeDefault - the container runtime + default profile should be used. Unconfined - no + profile should be applied." + type: string + 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, the fsGroup (if specified), and group memberships + defined in the container image for the uid of the container + process. If unspecified, no additional groups are added + to any container. Note that group memberships defined + in the container image for the uid of the container + process are still effective, even if they are not included + in this list. 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 within a + container's SecurityContext will be used. If set in + both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of + the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. This + field is alpha-level and will only be honored by + components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the Pod. + All of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a mix + of HostProcess containers and non-HostProcess containers). In + addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + type: object serviceAccount: description: ServiceAccount to use by the DevWorkspace operator when starting the workspaces. diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index f29202103..ba9c94d7c 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -107,6 +107,8 @@ spec: value: https://open-vsx.org - name: CHE_DEFAULT_SPEC_DEVENVIRONMENTS_DISABLECONTAINERBUILDCAPABILITIES value: 'false' + - name: CHE_DEFAULT_SPEC_DEVENVIRONMENTS_CONTAINERSECURITYCONTEXT + value: '{"allowPrivilegeEscalation": true,"capabilities": {"add": ["SETGID", "SETUID"]}}' livenessProbe: httpGet: path: /healthz diff --git a/deploy/deployment/kubernetes/combined.yaml b/deploy/deployment/kubernetes/combined.yaml index 40486e30f..4ed9ea9f0 100644 --- a/deploy/deployment/kubernetes/combined.yaml +++ b/deploy/deployment/kubernetes/combined.yaml @@ -6624,7 +6624,11 @@ spec: - RollingUpdate type: string disableContainerBuildCapabilities: - description: Disables the container build capabilities. + description: "Disables the container build capabilities. When + set to `false` (the default value), the devEnvironments.security.containerSecurityContext + field is ignored, and the following container SecurityContext + is applied: \n containerSecurityContext: allowPrivilegeEscalation: + true capabilities: add: - SETGID - SETUID" type: boolean gatewayContainer: description: GatewayContainer configuration. @@ -7052,6 +7056,370 @@ spec: run timeout, set this value to -1. format: int32 type: integer + security: + description: Workspace security configuration. + properties: + containerSecurityContext: + description: Container SecurityContext used by all workspace-related + containers. If set, defined values are merged into the default + Container SecurityContext configuration. Requires devEnvironments.disableContainerBuildCapabilities + to be set to `true` in order to take effect. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag + will be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be + set when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running + containers. Defaults to the default set of capabilities + granted by the container runtime. Note that this field + cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent + to root on the host. Defaults to false. Note that this + field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount + to use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. Note that this field cannot + be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root + filesystem. Default is false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: 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. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the + container. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. + Note that this field cannot be set when spec.os.name + is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. The + profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's + configured seccomp profile location. Must only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n Localhost + - a profile defined in a file on the node should + be used. RuntimeDefault - the container runtime + default profile should be used. Unconfined - no + profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to + all containers. If unspecified, the options from the + PodSecurityContext will be used. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of + the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. This + field is alpha-level and will only be honored by + components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the Pod. + All of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a mix + of HostProcess containers and non-HostProcess containers). In + addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + podSecurityContext: + description: PodSecurityContext used by all workspace-related + pods. If set, defined values are merged into the default + PodSecurityContext configuration. + properties: + 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 + 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 + runAsGroup: + description: 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. Note that this + field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: 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 SecurityContext. If set + in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: 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. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all + containers. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this + field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by the containers + in this pod. Note that this field cannot be set when + spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. The + profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's + configured seccomp profile location. Must only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n Localhost + - a profile defined in a file on the node should + be used. RuntimeDefault - the container runtime + default profile should be used. Unconfined - no + profile should be applied." + type: string + 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, the fsGroup (if specified), and group memberships + defined in the container image for the uid of the container + process. If unspecified, no additional groups are added + to any container. Note that group memberships defined + in the container image for the uid of the container + process are still effective, even if they are not included + in this list. 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 within a + container's SecurityContext will be used. If set in + both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of + the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. This + field is alpha-level and will only be honored by + components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the Pod. + All of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a mix + of HostProcess containers and non-HostProcess containers). In + addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + type: object serviceAccount: description: ServiceAccount to use by the DevWorkspace operator when starting the workspaces. @@ -8502,6 +8870,9 @@ spec: value: https://open-vsx.org - name: CHE_DEFAULT_SPEC_DEVENVIRONMENTS_DISABLECONTAINERBUILDCAPABILITIES value: "false" + - name: CHE_DEFAULT_SPEC_DEVENVIRONMENTS_CONTAINERSECURITYCONTEXT + value: '{"allowPrivilegeEscalation": true,"capabilities": {"add": ["SETGID", + "SETUID"]}}' image: quay.io/eclipse/che-operator:next imagePullPolicy: Always livenessProbe: diff --git a/deploy/deployment/kubernetes/objects/che-operator.Deployment.yaml b/deploy/deployment/kubernetes/objects/che-operator.Deployment.yaml index 60aa5820c..04ffe3c44 100644 --- a/deploy/deployment/kubernetes/objects/che-operator.Deployment.yaml +++ b/deploy/deployment/kubernetes/objects/che-operator.Deployment.yaml @@ -101,6 +101,9 @@ spec: value: https://open-vsx.org - name: CHE_DEFAULT_SPEC_DEVENVIRONMENTS_DISABLECONTAINERBUILDCAPABILITIES value: "false" + - name: CHE_DEFAULT_SPEC_DEVENVIRONMENTS_CONTAINERSECURITYCONTEXT + value: '{"allowPrivilegeEscalation": true,"capabilities": {"add": ["SETGID", + "SETUID"]}}' image: quay.io/eclipse/che-operator:next imagePullPolicy: Always livenessProbe: diff --git a/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml b/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml index a5c33846d..d29a3c5da 100644 --- a/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml +++ b/deploy/deployment/kubernetes/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml @@ -6619,7 +6619,11 @@ spec: - RollingUpdate type: string disableContainerBuildCapabilities: - description: Disables the container build capabilities. + description: "Disables the container build capabilities. When + set to `false` (the default value), the devEnvironments.security.containerSecurityContext + field is ignored, and the following container SecurityContext + is applied: \n containerSecurityContext: allowPrivilegeEscalation: + true capabilities: add: - SETGID - SETUID" type: boolean gatewayContainer: description: GatewayContainer configuration. @@ -7047,6 +7051,370 @@ spec: run timeout, set this value to -1. format: int32 type: integer + security: + description: Workspace security configuration. + properties: + containerSecurityContext: + description: Container SecurityContext used by all workspace-related + containers. If set, defined values are merged into the default + Container SecurityContext configuration. Requires devEnvironments.disableContainerBuildCapabilities + to be set to `true` in order to take effect. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag + will be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be + set when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running + containers. Defaults to the default set of capabilities + granted by the container runtime. Note that this field + cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent + to root on the host. Defaults to false. Note that this + field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount + to use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. Note that this field cannot + be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root + filesystem. Default is false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: 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. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the + container. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. + Note that this field cannot be set when spec.os.name + is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. The + profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's + configured seccomp profile location. Must only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n Localhost + - a profile defined in a file on the node should + be used. RuntimeDefault - the container runtime + default profile should be used. Unconfined - no + profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to + all containers. If unspecified, the options from the + PodSecurityContext will be used. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of + the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. This + field is alpha-level and will only be honored by + components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the Pod. + All of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a mix + of HostProcess containers and non-HostProcess containers). In + addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + podSecurityContext: + description: PodSecurityContext used by all workspace-related + pods. If set, defined values are merged into the default + PodSecurityContext configuration. + properties: + 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 + 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 + runAsGroup: + description: 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. Note that this + field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: 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 SecurityContext. If set + in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: 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. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all + containers. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this + field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by the containers + in this pod. Note that this field cannot be set when + spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. The + profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's + configured seccomp profile location. Must only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n Localhost + - a profile defined in a file on the node should + be used. RuntimeDefault - the container runtime + default profile should be used. Unconfined - no + profile should be applied." + type: string + 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, the fsGroup (if specified), and group memberships + defined in the container image for the uid of the container + process. If unspecified, no additional groups are added + to any container. Note that group memberships defined + in the container image for the uid of the container + process are still effective, even if they are not included + in this list. 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 within a + container's SecurityContext will be used. If set in + both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of + the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. This + field is alpha-level and will only be honored by + components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the Pod. + All of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a mix + of HostProcess containers and non-HostProcess containers). In + addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + type: object serviceAccount: description: ServiceAccount to use by the DevWorkspace operator when starting the workspaces. diff --git a/deploy/deployment/openshift/combined.yaml b/deploy/deployment/openshift/combined.yaml index be00e9f23..562172381 100644 --- a/deploy/deployment/openshift/combined.yaml +++ b/deploy/deployment/openshift/combined.yaml @@ -6624,7 +6624,11 @@ spec: - RollingUpdate type: string disableContainerBuildCapabilities: - description: Disables the container build capabilities. + description: "Disables the container build capabilities. When + set to `false` (the default value), the devEnvironments.security.containerSecurityContext + field is ignored, and the following container SecurityContext + is applied: \n containerSecurityContext: allowPrivilegeEscalation: + true capabilities: add: - SETGID - SETUID" type: boolean gatewayContainer: description: GatewayContainer configuration. @@ -7052,6 +7056,370 @@ spec: run timeout, set this value to -1. format: int32 type: integer + security: + description: Workspace security configuration. + properties: + containerSecurityContext: + description: Container SecurityContext used by all workspace-related + containers. If set, defined values are merged into the default + Container SecurityContext configuration. Requires devEnvironments.disableContainerBuildCapabilities + to be set to `true` in order to take effect. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag + will be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be + set when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running + containers. Defaults to the default set of capabilities + granted by the container runtime. Note that this field + cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent + to root on the host. Defaults to false. Note that this + field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount + to use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. Note that this field cannot + be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root + filesystem. Default is false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: 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. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the + container. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. + Note that this field cannot be set when spec.os.name + is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. The + profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's + configured seccomp profile location. Must only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n Localhost + - a profile defined in a file on the node should + be used. RuntimeDefault - the container runtime + default profile should be used. Unconfined - no + profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to + all containers. If unspecified, the options from the + PodSecurityContext will be used. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of + the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. This + field is alpha-level and will only be honored by + components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the Pod. + All of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a mix + of HostProcess containers and non-HostProcess containers). In + addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + podSecurityContext: + description: PodSecurityContext used by all workspace-related + pods. If set, defined values are merged into the default + PodSecurityContext configuration. + properties: + 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 + 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 + runAsGroup: + description: 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. Note that this + field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: 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 SecurityContext. If set + in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: 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. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all + containers. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this + field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by the containers + in this pod. Note that this field cannot be set when + spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. The + profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's + configured seccomp profile location. Must only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n Localhost + - a profile defined in a file on the node should + be used. RuntimeDefault - the container runtime + default profile should be used. Unconfined - no + profile should be applied." + type: string + 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, the fsGroup (if specified), and group memberships + defined in the container image for the uid of the container + process. If unspecified, no additional groups are added + to any container. Note that group memberships defined + in the container image for the uid of the container + process are still effective, even if they are not included + in this list. 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 within a + container's SecurityContext will be used. If set in + both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of + the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. This + field is alpha-level and will only be honored by + components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the Pod. + All of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a mix + of HostProcess containers and non-HostProcess containers). In + addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + type: object serviceAccount: description: ServiceAccount to use by the DevWorkspace operator when starting the workspaces. @@ -8504,6 +8872,9 @@ spec: value: https://open-vsx.org - name: CHE_DEFAULT_SPEC_DEVENVIRONMENTS_DISABLECONTAINERBUILDCAPABILITIES value: "false" + - name: CHE_DEFAULT_SPEC_DEVENVIRONMENTS_CONTAINERSECURITYCONTEXT + value: '{"allowPrivilegeEscalation": true,"capabilities": {"add": ["SETGID", + "SETUID"]}}' image: quay.io/eclipse/che-operator:next imagePullPolicy: Always livenessProbe: diff --git a/deploy/deployment/openshift/objects/che-operator.Deployment.yaml b/deploy/deployment/openshift/objects/che-operator.Deployment.yaml index 8fe68ec41..40897a34a 100644 --- a/deploy/deployment/openshift/objects/che-operator.Deployment.yaml +++ b/deploy/deployment/openshift/objects/che-operator.Deployment.yaml @@ -101,6 +101,9 @@ spec: value: https://open-vsx.org - name: CHE_DEFAULT_SPEC_DEVENVIRONMENTS_DISABLECONTAINERBUILDCAPABILITIES value: "false" + - name: CHE_DEFAULT_SPEC_DEVENVIRONMENTS_CONTAINERSECURITYCONTEXT + value: '{"allowPrivilegeEscalation": true,"capabilities": {"add": ["SETGID", + "SETUID"]}}' image: quay.io/eclipse/che-operator:next imagePullPolicy: Always livenessProbe: diff --git a/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml b/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml index 025e79b37..d9d644510 100644 --- a/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml +++ b/deploy/deployment/openshift/objects/checlusters.org.eclipse.che.CustomResourceDefinition.yaml @@ -6619,7 +6619,11 @@ spec: - RollingUpdate type: string disableContainerBuildCapabilities: - description: Disables the container build capabilities. + description: "Disables the container build capabilities. When + set to `false` (the default value), the devEnvironments.security.containerSecurityContext + field is ignored, and the following container SecurityContext + is applied: \n containerSecurityContext: allowPrivilegeEscalation: + true capabilities: add: - SETGID - SETUID" type: boolean gatewayContainer: description: GatewayContainer configuration. @@ -7047,6 +7051,370 @@ spec: run timeout, set this value to -1. format: int32 type: integer + security: + description: Workspace security configuration. + properties: + containerSecurityContext: + description: Container SecurityContext used by all workspace-related + containers. If set, defined values are merged into the default + Container SecurityContext configuration. Requires devEnvironments.disableContainerBuildCapabilities + to be set to `true` in order to take effect. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag + will be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be + set when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running + containers. Defaults to the default set of capabilities + granted by the container runtime. Note that this field + cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent + to root on the host. Defaults to false. Note that this + field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount + to use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. Note that this field cannot + be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root + filesystem. Default is false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: 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. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the + container. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. + Note that this field cannot be set when spec.os.name + is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. The + profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's + configured seccomp profile location. Must only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n Localhost + - a profile defined in a file on the node should + be used. RuntimeDefault - the container runtime + default profile should be used. Unconfined - no + profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to + all containers. If unspecified, the options from the + PodSecurityContext will be used. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of + the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. This + field is alpha-level and will only be honored by + components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the Pod. + All of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a mix + of HostProcess containers and non-HostProcess containers). In + addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + podSecurityContext: + description: PodSecurityContext used by all workspace-related + pods. If set, defined values are merged into the default + PodSecurityContext configuration. + properties: + 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 + 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 + runAsGroup: + description: 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. Note that this + field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: 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 SecurityContext. If set + in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: 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. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all + containers. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this + field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by the containers + in this pod. Note that this field cannot be set when + spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. The + profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's + configured seccomp profile location. Must only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n Localhost + - a profile defined in a file on the node should + be used. RuntimeDefault - the container runtime + default profile should be used. Unconfined - no + profile should be applied." + type: string + 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, the fsGroup (if specified), and group memberships + defined in the container image for the uid of the container + process. If unspecified, no additional groups are added + to any container. Note that group memberships defined + in the container image for the uid of the container + process are still effective, even if they are not included + in this list. 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 within a + container's SecurityContext will be used. If set in + both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of + the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. This + field is alpha-level and will only be honored by + components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the Pod. + All of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a mix + of HostProcess containers and non-HostProcess containers). In + addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + type: object serviceAccount: description: ServiceAccount to use by the DevWorkspace operator when starting the workspaces. diff --git a/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml b/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml index a5c33846d..d29a3c5da 100644 --- a/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml +++ b/helmcharts/next/crds/checlusters.org.eclipse.che.CustomResourceDefinition.yaml @@ -6619,7 +6619,11 @@ spec: - RollingUpdate type: string disableContainerBuildCapabilities: - description: Disables the container build capabilities. + description: "Disables the container build capabilities. When + set to `false` (the default value), the devEnvironments.security.containerSecurityContext + field is ignored, and the following container SecurityContext + is applied: \n containerSecurityContext: allowPrivilegeEscalation: + true capabilities: add: - SETGID - SETUID" type: boolean gatewayContainer: description: GatewayContainer configuration. @@ -7047,6 +7051,370 @@ spec: run timeout, set this value to -1. format: int32 type: integer + security: + description: Workspace security configuration. + properties: + containerSecurityContext: + description: Container SecurityContext used by all workspace-related + containers. If set, defined values are merged into the default + Container SecurityContext configuration. Requires devEnvironments.disableContainerBuildCapabilities + to be set to `true` in order to take effect. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag + will be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be + set when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running + containers. Defaults to the default set of capabilities + granted by the container runtime. Note that this field + cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent + to root on the host. Defaults to false. Note that this + field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount + to use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. Note that this field cannot + be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root + filesystem. Default is false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: 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. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the + container. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. + Note that this field cannot be set when spec.os.name + is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. The + profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's + configured seccomp profile location. Must only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n Localhost + - a profile defined in a file on the node should + be used. RuntimeDefault - the container runtime + default profile should be used. Unconfined - no + profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to + all containers. If unspecified, the options from the + PodSecurityContext will be used. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of + the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. This + field is alpha-level and will only be honored by + components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the Pod. + All of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a mix + of HostProcess containers and non-HostProcess containers). In + addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + podSecurityContext: + description: PodSecurityContext used by all workspace-related + pods. If set, defined values are merged into the default + PodSecurityContext configuration. + properties: + 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 + 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 + runAsGroup: + description: 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. Note that this + field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: 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 SecurityContext. If set + in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: 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. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all + containers. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this + field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by the containers + in this pod. Note that this field cannot be set when + spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. The + profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's + configured seccomp profile location. Must only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n Localhost + - a profile defined in a file on the node should + be used. RuntimeDefault - the container runtime + default profile should be used. Unconfined - no + profile should be applied." + type: string + 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, the fsGroup (if specified), and group memberships + defined in the container image for the uid of the container + process. If unspecified, no additional groups are added + to any container. Note that group memberships defined + in the container image for the uid of the container + process are still effective, even if they are not included + in this list. 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 within a + container's SecurityContext will be used. If set in + both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of + the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. This + field is alpha-level and will only be honored by + components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the Pod. + All of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a mix + of HostProcess containers and non-HostProcess containers). In + addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + type: object serviceAccount: description: ServiceAccount to use by the DevWorkspace operator when starting the workspaces. diff --git a/helmcharts/next/templates/che-operator.Deployment.yaml b/helmcharts/next/templates/che-operator.Deployment.yaml index 60aa5820c..04ffe3c44 100644 --- a/helmcharts/next/templates/che-operator.Deployment.yaml +++ b/helmcharts/next/templates/che-operator.Deployment.yaml @@ -101,6 +101,9 @@ spec: value: https://open-vsx.org - name: CHE_DEFAULT_SPEC_DEVENVIRONMENTS_DISABLECONTAINERBUILDCAPABILITIES value: "false" + - name: CHE_DEFAULT_SPEC_DEVENVIRONMENTS_CONTAINERSECURITYCONTEXT + value: '{"allowPrivilegeEscalation": true,"capabilities": {"add": ["SETGID", + "SETUID"]}}' image: quay.io/eclipse/che-operator:next imagePullPolicy: Always livenessProbe: diff --git a/pkg/common/constants/constants.go b/pkg/common/constants/constants.go index 771940f9e..382f4c35d 100644 --- a/pkg/common/constants/constants.go +++ b/pkg/common/constants/constants.go @@ -12,11 +12,6 @@ package constants -import ( - corev1 "k8s.io/api/core/v1" - "k8s.io/utils/pointer" -) - const ( // Dashboard DefaultDashboardMemoryLimit = "256Mi" @@ -144,14 +139,4 @@ var ( "app": "che", "component": "che-gateway-config", } - - DefaultWorkspaceContainerSecurityContext = corev1.SecurityContext{ - Capabilities: &corev1.Capabilities{ - Add: []corev1.Capability{ - "SETGID", - "SETUID", - }, - }, - AllowPrivilegeEscalation: pointer.BoolPtr(true), - } ) diff --git a/pkg/common/operator-defaults/defaults.go b/pkg/common/operator-defaults/defaults.go index 205e7849f..5cf953b55 100644 --- a/pkg/common/operator-defaults/defaults.go +++ b/pkg/common/operator-defaults/defaults.go @@ -44,6 +44,7 @@ var ( defaultDevEnvironmentsDefaultEditor string defaultDevEnvironmentsDefaultComponents string defaultDevEnvironmentsDisableContainerBuildCapabilities string + defaultDevEnvironmentsContainerSecurityContext string defaultPluginRegistryOpenVSXURL string defaultDashboardHeaderMessageText string @@ -74,6 +75,7 @@ func Initialize() { defaultsConsoleLinkImage = ensureEnv("CONSOLE_LINK_IMAGE") defaultDevEnvironmentsDisableContainerBuildCapabilities = ensureEnv("CHE_DEFAULT_SPEC_DEVENVIRONMENTS_DISABLECONTAINERBUILDCAPABILITIES") + defaultDevEnvironmentsContainerSecurityContext = ensureEnv(("CHE_DEFAULT_SPEC_DEVENVIRONMENTS_CONTAINERSECURITYCONTEXT")) defaultDevEnvironmentsDefaultComponents = ensureEnv("CHE_DEFAULT_SPEC_DEVENVIRONMENTS_DEFAULTCOMPONENTS") // can be empty @@ -261,6 +263,14 @@ func GetDevEnvironmentsDefaultComponents() string { return defaultDevEnvironmentsDefaultComponents } +func GetDevEnvironmentsContainerSecurityContext() string { + if !initialized { + logrus.Fatalf("Operator defaults are not initialized.") + } + + return defaultDevEnvironmentsContainerSecurityContext +} + func GetDevEnvironmentsDisableContainerBuildCapabilities() string { if !initialized { logrus.Fatalf("Operator defaults are not initialized.") diff --git a/pkg/deploy/dashboard/dashboard_deployment_test.go b/pkg/deploy/dashboard/dashboard_deployment_test.go index cfed5eae1..5a9a5dec9 100644 --- a/pkg/deploy/dashboard/dashboard_deployment_test.go +++ b/pkg/deploy/dashboard/dashboard_deployment_test.go @@ -204,6 +204,10 @@ func TestDashboardDeploymentEnvVars(t *testing.T) { Name: "CHE_DEFAULT_SPEC_DEVENVIRONMENTS_DISABLECONTAINERBUILDCAPABILITIES", Value: defaults.GetDevEnvironmentsDisableContainerBuildCapabilities(), }, + { + Name: "CHE_DEFAULT_SPEC_DEVENVIRONMENTS_CONTAINERSECURITYCONTEXT", + Value: defaults.GetDevEnvironmentsContainerSecurityContext(), + }, }, cheCluster: &chev2.CheCluster{ ObjectMeta: metav1.ObjectMeta{ @@ -281,6 +285,10 @@ func TestDashboardDeploymentEnvVars(t *testing.T) { Name: "CHE_DEFAULT_SPEC_DEVENVIRONMENTS_DISABLECONTAINERBUILDCAPABILITIES", Value: defaults.GetDevEnvironmentsDisableContainerBuildCapabilities(), }, + { + Name: "CHE_DEFAULT_SPEC_DEVENVIRONMENTS_CONTAINERSECURITYCONTEXT", + Value: defaults.GetDevEnvironmentsContainerSecurityContext(), + }, }, cheCluster: &chev2.CheCluster{ ObjectMeta: metav1.ObjectMeta{ diff --git a/pkg/deploy/dev-workspace-config/dev_workspace_config.go b/pkg/deploy/dev-workspace-config/dev_workspace_config.go index 99d12857c..f060bc676 100644 --- a/pkg/deploy/dev-workspace-config/dev_workspace_config.go +++ b/pkg/deploy/dev-workspace-config/dev_workspace_config.go @@ -13,12 +13,14 @@ package devworkspaceconfig import ( + "encoding/json" "fmt" controllerv1alpha1 "github.com/devfile/devworkspace-operator/apis/controller/v1alpha1" chev2 "github.com/eclipse-che/che-operator/api/v2" "github.com/eclipse-che/che-operator/pkg/common/chetypes" "github.com/eclipse-che/che-operator/pkg/common/constants" + defaults "github.com/eclipse-che/che-operator/pkg/common/operator-defaults" "github.com/eclipse-che/che-operator/pkg/common/utils" "github.com/eclipse-che/che-operator/pkg/deploy" v1 "k8s.io/api/apps/v1" @@ -88,15 +90,12 @@ func updateWorkspaceConfig(cheCluster *chev2.CheCluster, operatorConfig *control updateWorkspaceServiceAccountConfig(devEnvironments, operatorConfig.Workspace) - if err := updateWorkspacePodSchedulerNameConfig(devEnvironments, operatorConfig.Workspace); err != nil { - return err - } + updateWorkspacePodSchedulerNameConfig(devEnvironments, operatorConfig.Workspace) updateProjectCloneConfig(devEnvironments, operatorConfig.Workspace) - operatorConfig.Workspace.ContainerSecurityContext = nil - if cheCluster.IsContainerBuildCapabilitiesEnabled() { - operatorConfig.Workspace.ContainerSecurityContext = constants.DefaultWorkspaceContainerSecurityContext.DeepCopy() + if err := updateSecurityContext(operatorConfig, cheCluster); err != nil { + return err } updateStartTimeout(operatorConfig, devEnvironments.StartTimeoutSeconds) @@ -107,6 +106,25 @@ func updateWorkspaceConfig(cheCluster *chev2.CheCluster, operatorConfig *control return nil } +func updateSecurityContext(operatorConfig *controllerv1alpha1.OperatorConfiguration, cheCluster *chev2.CheCluster) error { + operatorConfig.Workspace.ContainerSecurityContext = nil + if cheCluster.IsContainerBuildCapabilitiesEnabled() { + defaultContainerSecurityContext, err := getDefaultContainerSecurityContext() + if err != nil { + return err + } + operatorConfig.Workspace.ContainerSecurityContext = defaultContainerSecurityContext + } else if cheCluster.Spec.DevEnvironments.Security.ContainerSecurityContext != nil { + operatorConfig.Workspace.ContainerSecurityContext = cheCluster.Spec.DevEnvironments.Security.ContainerSecurityContext + } + + operatorConfig.Workspace.PodSecurityContext = nil + if cheCluster.Spec.DevEnvironments.Security.PodSecurityContext != nil { + operatorConfig.Workspace.PodSecurityContext = cheCluster.Spec.DevEnvironments.Security.PodSecurityContext + } + return nil +} + func updateStartTimeout(operatorConfig *controllerv1alpha1.OperatorConfiguration, startTimeoutSeconds *int32) { if startTimeoutSeconds == nil { // Allow the default start timeout of 5 minutes to be used if devEnvironments.StartTimeoutSeconds is unset @@ -169,9 +187,8 @@ func updateWorkspaceServiceAccountConfig(devEnvironments *chev2.CheClusterDevEnv } } -func updateWorkspacePodSchedulerNameConfig(devEnvironments *chev2.CheClusterDevEnvironments, workspaceConfig *controllerv1alpha1.WorkspaceConfig) error { +func updateWorkspacePodSchedulerNameConfig(devEnvironments *chev2.CheClusterDevEnvironments, workspaceConfig *controllerv1alpha1.WorkspaceConfig) { workspaceConfig.SchedulerName = devEnvironments.PodSchedulerName - return nil } func updateProjectCloneConfig(devEnvironments *chev2.CheClusterDevEnvironments, workspaceConfig *controllerv1alpha1.WorkspaceConfig) { @@ -190,6 +207,17 @@ func updateProjectCloneConfig(devEnvironments *chev2.CheClusterDevEnvironments, workspaceConfig.ProjectCloneConfig.Resources = cheResourcesToCoreV1Resources(container.Resources) } +// Returns the default container security context required for container builds. +// Returns an error if the default container security context could not be retrieved. +func getDefaultContainerSecurityContext() (*corev1.SecurityContext, error) { + containerSecurityContext := &corev1.SecurityContext{} + err := json.Unmarshal([]byte(defaults.GetDevEnvironmentsContainerSecurityContext()), &containerSecurityContext) + if err != nil { + return nil, err + } + return containerSecurityContext, nil +} + // cheResourcesToCoreV1Resources converts a Che resources struct to the usual Kubernetes object by directly copying fields. // It does not set any default values or include logic for removing requests/limits that are set to "0" as it is intended // to prepare resources for the DevWorkspace Operator, which has its own defaults and handling of "0" values. diff --git a/pkg/deploy/dev-workspace-config/dev_workspace_config_test.go b/pkg/deploy/dev-workspace-config/dev_workspace_config_test.go index 1f50be996..54b70abc7 100644 --- a/pkg/deploy/dev-workspace-config/dev_workspace_config_test.go +++ b/pkg/deploy/dev-workspace-config/dev_workspace_config_test.go @@ -14,7 +14,9 @@ package devworkspaceconfig import ( "context" + "fmt" "regexp" + "sort" "testing" controllerv1alpha1 "github.com/devfile/devworkspace-operator/apis/controller/v1alpha1" @@ -33,7 +35,7 @@ import ( "k8s.io/utils/pointer" ) -func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { +func TestReconcileDevWorkspaceConfigStorage(t *testing.T) { type testCase struct { name string cheCluster *chev2.CheCluster @@ -50,8 +52,6 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { var quantity15Gi = resource.MustParse("15Gi") var quantity10Gi = resource.MustParse("10Gi") - var quantity1CPU = resource.MustParse("1000m") - var quantity500mCPU = resource.MustParse("500m") var expectedErrorTestCases = []errorTestCase{ { @@ -94,7 +94,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{Workspace: &controllerv1alpha1.WorkspaceConfig{DeploymentStrategy: "Recreate"}}, }, { - name: "Create DevWorkspaceOperatorConfig with ephemeral strategy", + name: "Create DevWorkspaceOperatorConfig with ephemeral storage strategy", cheCluster: &chev2.CheCluster{ ObjectMeta: metav1.ObjectMeta{ Namespace: "eclipse-che", @@ -146,7 +146,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { }, }, { - name: "Create DevWorkspaceOperatorConfig with per-user strategy", + name: "Create DevWorkspaceOperatorConfig with per-user storage strategy", cheCluster: &chev2.CheCluster{ ObjectMeta: metav1.ObjectMeta{ Namespace: "eclipse-che", @@ -176,7 +176,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { }, }, { - name: "Create DevWorkspaceOperatorConfig with per-workspace strategy", + name: "Create DevWorkspaceOperatorConfig with per-workspace storage strategy", cheCluster: &chev2.CheCluster{ ObjectMeta: metav1.ObjectMeta{ Namespace: "eclipse-che", @@ -206,7 +206,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { }, }, { - name: "Update DevWorkspaceOperatorConfig with per-workspace strategy", + name: "Update DevWorkspaceOperatorConfig with per-workspace storage strategy", cheCluster: &chev2.CheCluster{ ObjectMeta: metav1.ObjectMeta{ Namespace: "eclipse-che", @@ -256,7 +256,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { }, }, { - name: "Update DevWorkspaceOperatorConfig with per-user strategy", + name: "Update DevWorkspaceOperatorConfig with per-user storage strategy", cheCluster: &chev2.CheCluster{ ObjectMeta: metav1.ObjectMeta{ Namespace: "eclipse-che", @@ -306,7 +306,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { }, }, { - name: "Update populated DevWorkspaceOperatorConfig", + name: "Update populated DevWorkspaceOperatorConfig with storage class name, storage strategy and storage size", cheCluster: &chev2.CheCluster{ ObjectMeta: metav1.ObjectMeta{ Namespace: "eclipse-che", @@ -359,8 +359,50 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { }, }, }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + deployContext := test.GetDeployContext(testCase.cheCluster, testCase.existedObjects) + infrastructure.InitializeForTesting(infrastructure.OpenShiftv4) + + devWorkspaceConfigReconciler := NewDevWorkspaceConfigReconciler() + _, _, err := devWorkspaceConfigReconciler.Reconcile(deployContext) + assert.NoError(t, err) + + dwoc := &controllerv1alpha1.DevWorkspaceOperatorConfig{} + err = deployContext.ClusterAPI.Client.Get(context.TODO(), types.NamespacedName{Name: devWorkspaceConfigName, Namespace: testCase.cheCluster.Namespace}, dwoc) + assert.NoError(t, err) + + diff := cmp.Diff(testCase.expectedOperatorConfig, dwoc.Config, cmp.Options{cmpopts.IgnoreFields(controllerv1alpha1.WorkspaceConfig{}, "ServiceAccount")}) + assert.Empty(t, diff) + }) + } + + for _, testCase := range expectedErrorTestCases { + t.Run(testCase.name, func(t *testing.T) { + deployContext := test.GetDeployContext(testCase.cheCluster, testCase.existedObjects) + infrastructure.InitializeForTesting(infrastructure.OpenShiftv4) + + devWorkspaceConfigReconciler := NewDevWorkspaceConfigReconciler() + _, _, err := devWorkspaceConfigReconciler.Reconcile(deployContext) + assert.Error(t, err) + assert.Regexp(t, regexp.MustCompile(testCase.expectedErrorMessage), err.Error(), "error message must match") + }) + } +} + +func TestReconcileDevWorkspaceConfigForContainerBuilds(t *testing.T) { + type testCase struct { + name string + cheCluster *chev2.CheCluster + existedObjects []runtime.Object + expectedOperatorConfig *controllerv1alpha1.OperatorConfiguration + } + + var testCases = []testCase{ { - name: "Create DevWorkspaceOperatorConfig without Pod Security Context if container build disabled", + name: "Create DevWorkspaceOperatorConfig without Container Security Context if container build disabled", cheCluster: &chev2.CheCluster{ ObjectMeta: metav1.ObjectMeta{ Namespace: "eclipse-che", @@ -373,13 +415,11 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { }, }, expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{ - Workspace: &controllerv1alpha1.WorkspaceConfig{ - DeploymentStrategy: "Recreate", - }, + Workspace: &controllerv1alpha1.WorkspaceConfig{}, }, }, { - name: "Create DevWorkspaceOperatorConfig with Pod and Container Security Context if container build enabled", + name: "Create DevWorkspaceOperatorConfig with Container Security Context if container build enabled", cheCluster: &chev2.CheCluster{ ObjectMeta: metav1.ObjectMeta{ Namespace: "eclipse-che", @@ -402,12 +442,11 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { }, AllowPrivilegeEscalation: pointer.Bool(true), }, - DeploymentStrategy: "Recreate", }, }, }, { - name: "Update existing DevWorkspaceOperatorConfig by adding Pod and Container Security Context", + name: "Update existing DevWorkspaceOperatorConfig by adding Container Security Context", cheCluster: &chev2.CheCluster{ ObjectMeta: metav1.ObjectMeta{ Namespace: "eclipse-che", @@ -430,21 +469,12 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { APIVersion: controllerv1alpha1.GroupVersion.String(), }, Config: &controllerv1alpha1.OperatorConfiguration{ - Workspace: &controllerv1alpha1.WorkspaceConfig{ - StorageClassName: pointer.String("default-storage-class"), - DefaultStorageSize: &controllerv1alpha1.StorageSizes{ - Common: &quantity10Gi, - }, - }, + Workspace: &controllerv1alpha1.WorkspaceConfig{}, }, }, }, expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{ Workspace: &controllerv1alpha1.WorkspaceConfig{ - StorageClassName: pointer.String("default-storage-class"), - DefaultStorageSize: &controllerv1alpha1.StorageSizes{ - Common: &quantity10Gi, - }, ContainerSecurityContext: &corev1.SecurityContext{ Capabilities: &corev1.Capabilities{ Add: []corev1.Capability{ @@ -454,12 +484,11 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { }, AllowPrivilegeEscalation: pointer.Bool(true), }, - DeploymentStrategy: "Recreate", }, }, }, { - name: "Update existing DevWorkspaceOperatorConfig by removing Pod and Container Security Context", + name: "Update existing DevWorkspaceOperatorConfig by removing Container Security Context", cheCluster: &chev2.CheCluster{ ObjectMeta: metav1.ObjectMeta{ Namespace: "eclipse-che", @@ -483,26 +512,53 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { }, Config: &controllerv1alpha1.OperatorConfiguration{ Workspace: &controllerv1alpha1.WorkspaceConfig{ - StorageClassName: pointer.String("default-storage-class"), - DefaultStorageSize: &controllerv1alpha1.StorageSizes{ - Common: &quantity10Gi, + ContainerSecurityContext: &corev1.SecurityContext{Capabilities: &corev1.Capabilities{ + Add: []corev1.Capability{ + "SETGID", + "SETUID", + }, + }, + AllowPrivilegeEscalation: pointer.Bool(true), }, - ContainerSecurityContext: &corev1.SecurityContext{}, - DeploymentStrategy: "Recreate", }, }, }, }, expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{ - Workspace: &controllerv1alpha1.WorkspaceConfig{ - StorageClassName: pointer.String("default-storage-class"), - DefaultStorageSize: &controllerv1alpha1.StorageSizes{ - Common: &quantity10Gi, - }, - DeploymentStrategy: "Recreate", - }, + Workspace: &controllerv1alpha1.WorkspaceConfig{}, }, }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + deployContext := test.GetDeployContext(testCase.cheCluster, testCase.existedObjects) + infrastructure.InitializeForTesting(infrastructure.OpenShiftv4) + + devWorkspaceConfigReconciler := NewDevWorkspaceConfigReconciler() + _, _, err := devWorkspaceConfigReconciler.Reconcile(deployContext) + assert.NoError(t, err) + + dwoc := &controllerv1alpha1.DevWorkspaceOperatorConfig{} + err = deployContext.ClusterAPI.Client.Get(context.TODO(), types.NamespacedName{Name: devWorkspaceConfigName, Namespace: testCase.cheCluster.Namespace}, dwoc) + assert.NoError(t, err) + + diff := cmp.Diff(testCase.expectedOperatorConfig, dwoc.Config, + cmp.Options{cmpopts.IgnoreFields(controllerv1alpha1.WorkspaceConfig{}, "ServiceAccount", "ProjectCloneConfig", "DeploymentStrategy", "DefaultStorageSize", "StorageClassName")}) + assert.Empty(t, diff) + }) + } +} + +func TestReconcileDevWorkspaceConfigProgressTimeout(t *testing.T) { + type testCase struct { + name string + cheCluster *chev2.CheCluster + existedObjects []runtime.Object + expectedOperatorConfig *controllerv1alpha1.OperatorConfiguration + } + + var testCases = []testCase{ { name: "Create DevWorkspaceOperatorConfig with progressTimeout", cheCluster: &chev2.CheCluster{ @@ -549,23 +605,13 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { APIVersion: controllerv1alpha1.GroupVersion.String(), }, Config: &controllerv1alpha1.OperatorConfiguration{ - Workspace: &controllerv1alpha1.WorkspaceConfig{ - StorageClassName: pointer.String("default-storage-class"), - DefaultStorageSize: &controllerv1alpha1.StorageSizes{ - Common: &quantity10Gi, - }, - }, + Workspace: &controllerv1alpha1.WorkspaceConfig{}, }, }, }, expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{ Workspace: &controllerv1alpha1.WorkspaceConfig{ - StorageClassName: pointer.String("default-storage-class"), - DefaultStorageSize: &controllerv1alpha1.StorageSizes{ - Common: &quantity10Gi, - }, - ProgressTimeout: "600s", - DeploymentStrategy: "Recreate", + ProgressTimeout: "600s", }, }, }, @@ -595,10 +641,6 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { }, Config: &controllerv1alpha1.OperatorConfiguration{ Workspace: &controllerv1alpha1.WorkspaceConfig{ - StorageClassName: pointer.String("default-storage-class"), - DefaultStorageSize: &controllerv1alpha1.StorageSizes{ - Common: &quantity10Gi, - }, ProgressTimeout: "1h30m", }, }, @@ -606,12 +648,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { }, expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{ Workspace: &controllerv1alpha1.WorkspaceConfig{ - StorageClassName: pointer.String("default-storage-class"), - DefaultStorageSize: &controllerv1alpha1.StorageSizes{ - Common: &quantity10Gi, - }, - ProgressTimeout: "420s", - DeploymentStrategy: "Recreate", + ProgressTimeout: "420s", }, }, }, @@ -640,104 +677,13 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { }, Config: &controllerv1alpha1.OperatorConfiguration{ Workspace: &controllerv1alpha1.WorkspaceConfig{ - StorageClassName: pointer.String("default-storage-class"), - DefaultStorageSize: &controllerv1alpha1.StorageSizes{ - Common: &quantity10Gi, - }, ProgressTimeout: "1h30m", }, }, }, }, expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{ - Workspace: &controllerv1alpha1.WorkspaceConfig{ - StorageClassName: pointer.String("default-storage-class"), - DefaultStorageSize: &controllerv1alpha1.StorageSizes{ - Common: &quantity10Gi, - }, - DeploymentStrategy: "Recreate", - }, - }, - }, - { - name: "Configures ProjectCloneConfig in DevWorkspaceOperatorConfig", - cheCluster: &chev2.CheCluster{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "eclipse-che", - Name: "eclipse-che", - }, - Spec: chev2.CheClusterSpec{ - DevEnvironments: chev2.CheClusterDevEnvironments{ - DisableContainerBuildCapabilities: pointer.Bool(true), - ProjectCloneContainer: &chev2.Container{ - Name: "project-clone", - Image: "test-image", - ImagePullPolicy: "IfNotPresent", - Env: []corev1.EnvVar{ - {Name: "test-env-1", Value: "test-val-1"}, - {Name: "test-env-2", Value: "test-val-2"}, - }, - Resources: &chev2.ResourceRequirements{ - Requests: &chev2.ResourceList{ - Memory: &quantity10Gi, - Cpu: &quantity500mCPU, - }, - Limits: &chev2.ResourceList{ - Memory: &quantity15Gi, - Cpu: &quantity1CPU, - }, - }, - }, - }, - }, - }, - existedObjects: []runtime.Object{ - &controllerv1alpha1.DevWorkspaceOperatorConfig{ - ObjectMeta: metav1.ObjectMeta{ - Name: devWorkspaceConfigName, - Namespace: "eclipse-che", - }, - TypeMeta: metav1.TypeMeta{ - Kind: "DevWorkspaceOperatorConfig", - APIVersion: controllerv1alpha1.GroupVersion.String(), - }, - Config: &controllerv1alpha1.OperatorConfiguration{ - Workspace: &controllerv1alpha1.WorkspaceConfig{ - StorageClassName: pointer.String("default-storage-class"), - DefaultStorageSize: &controllerv1alpha1.StorageSizes{ - Common: &quantity10Gi, - }, - ProgressTimeout: "1h30m", - }, - }, - }, - }, - expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{ - Workspace: &controllerv1alpha1.WorkspaceConfig{ - StorageClassName: pointer.String("default-storage-class"), - DefaultStorageSize: &controllerv1alpha1.StorageSizes{ - Common: &quantity10Gi, - }, - DeploymentStrategy: "Recreate", - ProjectCloneConfig: &controllerv1alpha1.ProjectCloneConfig{ - Image: "test-image", - ImagePullPolicy: "IfNotPresent", - Env: []corev1.EnvVar{ - {Name: "test-env-1", Value: "test-val-1"}, - {Name: "test-env-2", Value: "test-val-2"}, - }, - Resources: &corev1.ResourceRequirements{ - Requests: corev1.ResourceList{ - corev1.ResourceMemory: quantity10Gi, - corev1.ResourceCPU: quantity500mCPU, - }, - Limits: corev1.ResourceList{ - corev1.ResourceMemory: quantity15Gi, - corev1.ResourceCPU: quantity1CPU, - }, - }, - }, - }, + Workspace: &controllerv1alpha1.WorkspaceConfig{}, }, }, } @@ -755,22 +701,11 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) { err = deployContext.ClusterAPI.Client.Get(context.TODO(), types.NamespacedName{Name: devWorkspaceConfigName, Namespace: testCase.cheCluster.Namespace}, dwoc) assert.NoError(t, err) - diff := cmp.Diff(testCase.expectedOperatorConfig, dwoc.Config, cmp.Options{cmpopts.IgnoreFields(controllerv1alpha1.WorkspaceConfig{}, "ServiceAccount")}) + diff := cmp.Diff(testCase.expectedOperatorConfig, dwoc.Config, + cmp.Options{cmpopts.IgnoreFields(controllerv1alpha1.WorkspaceConfig{}, "ServiceAccount", "DefaultStorageSize", "StorageClassName", "ProjectCloneConfig", "DeploymentStrategy")}) assert.Empty(t, diff) }) } - - for _, testCase := range expectedErrorTestCases { - t.Run(testCase.name, func(t *testing.T) { - deployContext := test.GetDeployContext(testCase.cheCluster, testCase.existedObjects) - infrastructure.InitializeForTesting(infrastructure.OpenShiftv4) - - devWorkspaceConfigReconciler := NewDevWorkspaceConfigReconciler() - _, _, err := devWorkspaceConfigReconciler.Reconcile(deployContext) - assert.Error(t, err) - assert.Regexp(t, regexp.MustCompile(testCase.expectedErrorMessage), err.Error(), "error message must match") - }) - } } func TestReconcileServiceAccountConfig(t *testing.T) { @@ -1410,7 +1345,7 @@ func TestReconcileDevWorkspaceConfigDeploymentStrategy(t *testing.T) { } } -func TestReconcileDevWorkspaceProjectCloneCOnfig(t *testing.T) { +func TestReconcileDevWorkspaceProjectCloneConfig(t *testing.T) { const testNamespace = "eclipse-che" testMemLimit := resource.MustParse("2Gi") testCpuLimit := resource.MustParse("1000m") @@ -1805,3 +1740,450 @@ func TestReconcileDevWorkspaceConfigPersistUserHome(t *testing.T) { }) } } + +func TestReconcileDevWorkspaceContainerSecurityContext(t *testing.T) { + type testCase struct { + name string + cheCluster *chev2.CheCluster + existedObjects []runtime.Object + expectedOperatorConfig *controllerv1alpha1.OperatorConfiguration + } + + var testCases = []testCase{ + { + name: "Create DevWorkspaceOperatorConfig with Container security context", + cheCluster: &chev2.CheCluster{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "eclipse-che", + Name: "eclipse-che", + }, + Spec: chev2.CheClusterSpec{ + DevEnvironments: chev2.CheClusterDevEnvironments{ + // We disable container build capabilities so that it does not override the container security context we configured + DisableContainerBuildCapabilities: pointer.Bool(true), + Security: chev2.WorkspaceSecurityConfig{ + ContainerSecurityContext: &corev1.SecurityContext{ + Capabilities: &corev1.Capabilities{ + Add: []corev1.Capability{ + "SYS_TIME", + "SETGID", + "SETUID", + }, + Drop: []corev1.Capability{ + "CHOWN", + "KILL", + }, + }, + AllowPrivilegeEscalation: pointer.Bool(false), + }, + }, + }, + }, + }, + expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{ + Workspace: &controllerv1alpha1.WorkspaceConfig{ + ContainerSecurityContext: &corev1.SecurityContext{ + Capabilities: &corev1.Capabilities{ + Add: []corev1.Capability{ + "SYS_TIME", + "SETGID", + "SETUID", + }, + Drop: []corev1.Capability{ + "CHOWN", + "KILL", + }, + }, + AllowPrivilegeEscalation: pointer.Bool(false), + }, + }, + }, + }, + { + name: "Updates existing DevWorkspaceOperatorConfig when Container security context is added", + cheCluster: &chev2.CheCluster{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "eclipse-che", + Name: "eclipse-che", + }, + Spec: chev2.CheClusterSpec{ + DevEnvironments: chev2.CheClusterDevEnvironments{ + DisableContainerBuildCapabilities: pointer.Bool(true), + Security: chev2.WorkspaceSecurityConfig{ + ContainerSecurityContext: &corev1.SecurityContext{ + Capabilities: &corev1.Capabilities{ + Add: []corev1.Capability{ + "SYS_TIME", + "SETGID", + "SETUID", + }, + Drop: []corev1.Capability{ + "CHOWN", + "KILL", + }, + }, + AllowPrivilegeEscalation: pointer.Bool(false), + }}, + }, + }, + }, + existedObjects: []runtime.Object{ + &controllerv1alpha1.DevWorkspaceOperatorConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: devWorkspaceConfigName, + Namespace: "eclipse-che", + }, + TypeMeta: metav1.TypeMeta{ + Kind: "DevWorkspaceOperatorConfig", + APIVersion: controllerv1alpha1.GroupVersion.String(), + }, + }, + }, + expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{ + Workspace: &controllerv1alpha1.WorkspaceConfig{ + ContainerSecurityContext: &corev1.SecurityContext{ + Capabilities: &corev1.Capabilities{ + Add: []corev1.Capability{ + "SYS_TIME", + "SETGID", + "SETUID", + }, + Drop: []corev1.Capability{ + "CHOWN", + "KILL", + }, + }, + AllowPrivilegeEscalation: pointer.Bool(false), + }, + }, + }, + }, + { + name: "Updates existing DevWorkspaceOperatorConfig when Container security is changed", + cheCluster: &chev2.CheCluster{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "eclipse-che", + Name: "eclipse-che", + }, + Spec: chev2.CheClusterSpec{ + DevEnvironments: chev2.CheClusterDevEnvironments{ + DisableContainerBuildCapabilities: pointer.Bool(true), + Security: chev2.WorkspaceSecurityConfig{ + ContainerSecurityContext: &corev1.SecurityContext{ + Capabilities: &corev1.Capabilities{ + Add: []corev1.Capability{ + "SYS_TIME", + "SETGID", + "SETUID", + }, + Drop: []corev1.Capability{ + "CHOWN", + "KILL", + }, + }, + AllowPrivilegeEscalation: pointer.Bool(false), + }, + }, + }, + }, + }, + existedObjects: []runtime.Object{ + &controllerv1alpha1.DevWorkspaceOperatorConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: devWorkspaceConfigName, + Namespace: "eclipse-che", + }, + TypeMeta: metav1.TypeMeta{ + Kind: "DevWorkspaceOperatorConfig", + APIVersion: controllerv1alpha1.GroupVersion.String(), + }, + Config: &controllerv1alpha1.OperatorConfiguration{ + Workspace: &controllerv1alpha1.WorkspaceConfig{ + ContainerSecurityContext: &corev1.SecurityContext{ + Capabilities: &corev1.Capabilities{ + Add: []corev1.Capability{ + "KILL", + }, + Drop: []corev1.Capability{ + "SYS_TIME", + }, + }, + AllowPrivilegeEscalation: pointer.Bool(true), + }, + }, + }, + }, + }, + expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{ + Workspace: &controllerv1alpha1.WorkspaceConfig{ + ContainerSecurityContext: &corev1.SecurityContext{ + Capabilities: &corev1.Capabilities{ + Add: []corev1.Capability{ + "SYS_TIME", + "SETGID", + "SETUID", + }, + Drop: []corev1.Capability{ + "CHOWN", + "KILL", + }, + }, + AllowPrivilegeEscalation: pointer.Bool(false), + }, + }, + }, + }, + { + name: "Updates existing DevWorkspaceOperatorConfig when Container security is removed", + cheCluster: &chev2.CheCluster{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "eclipse-che", + Name: "eclipse-che", + }, + Spec: chev2.CheClusterSpec{ + DevEnvironments: chev2.CheClusterDevEnvironments{ + DisableContainerBuildCapabilities: pointer.Bool(true), + }, + }, + }, + existedObjects: []runtime.Object{ + &controllerv1alpha1.DevWorkspaceOperatorConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: devWorkspaceConfigName, + Namespace: "eclipse-che", + }, + TypeMeta: metav1.TypeMeta{ + Kind: "DevWorkspaceOperatorConfig", + APIVersion: controllerv1alpha1.GroupVersion.String(), + }, + Config: &controllerv1alpha1.OperatorConfiguration{ + Workspace: &controllerv1alpha1.WorkspaceConfig{ + ContainerSecurityContext: &corev1.SecurityContext{ + Capabilities: &corev1.Capabilities{ + Add: []corev1.Capability{ + "KILL", + }, + Drop: []corev1.Capability{ + "SYS_TIME", + }, + }, + AllowPrivilegeEscalation: pointer.Bool(true), + }, + }, + }, + }, + }, + expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{ + Workspace: &controllerv1alpha1.WorkspaceConfig{}, + }, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + deployContext := test.GetDeployContext(testCase.cheCluster, []runtime.Object{}) + infrastructure.InitializeForTesting(infrastructure.OpenShiftv4) + + devWorkspaceConfigReconciler := NewDevWorkspaceConfigReconciler() + _, _, err := devWorkspaceConfigReconciler.Reconcile(deployContext) + assert.NoError(t, err) + + dwoc := &controllerv1alpha1.DevWorkspaceOperatorConfig{} + err = deployContext.ClusterAPI.Client.Get(context.TODO(), types.NamespacedName{Name: devWorkspaceConfigName, Namespace: testCase.cheCluster.Namespace}, dwoc) + assert.NoError(t, err) + + sortCapabilities := func(capabilites []corev1.Capability) func(i, j int) bool { + return func(i, j int) bool { + return capabilites[i] > capabilites[j] + } + } + expectedContainerSecurityContext := testCase.expectedOperatorConfig.Workspace.ContainerSecurityContext + actualContainerSecurityContext := dwoc.Config.Workspace.ContainerSecurityContext + if expectedContainerSecurityContext != nil { + sort.Slice(expectedContainerSecurityContext.Capabilities.Add, sortCapabilities(expectedContainerSecurityContext.Capabilities.Add)) + sort.Slice(expectedContainerSecurityContext.Capabilities.Drop, sortCapabilities(expectedContainerSecurityContext.Capabilities.Drop)) + } + if actualContainerSecurityContext != nil { + sort.Slice(actualContainerSecurityContext.Capabilities.Add, sortCapabilities(actualContainerSecurityContext.Capabilities.Add)) + sort.Slice(actualContainerSecurityContext.Capabilities.Drop, sortCapabilities(actualContainerSecurityContext.Capabilities.Drop)) + + } + + assert.Equal(t, expectedContainerSecurityContext, actualContainerSecurityContext, + fmt.Sprintf("Did not get expected ContainerSecurityContext.\nDiff:%s", cmp.Diff(expectedContainerSecurityContext, actualContainerSecurityContext))) + }) + } +} + +func TestReconcileDevWorkspacePodSecurityContext(t *testing.T) { + type testCase struct { + name string + cheCluster *chev2.CheCluster + existedObjects []runtime.Object + expectedOperatorConfig *controllerv1alpha1.OperatorConfiguration + } + + configuredPodSecurityContext := &corev1.PodSecurityContext{ + RunAsUser: pointer.Int64(0), + RunAsGroup: pointer.Int64(0), + RunAsNonRoot: pointer.Bool(false), + } + + var testCases = []testCase{ + { + name: "Create DevWorkspaceOperatorConfig with Pod security context", + cheCluster: &chev2.CheCluster{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "eclipse-che", + Name: "eclipse-che", + }, + Spec: chev2.CheClusterSpec{ + DevEnvironments: chev2.CheClusterDevEnvironments{ + Security: chev2.WorkspaceSecurityConfig{ + PodSecurityContext: configuredPodSecurityContext, + }, + }, + }, + }, + expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{ + Workspace: &controllerv1alpha1.WorkspaceConfig{ + PodSecurityContext: configuredPodSecurityContext, + }, + }, + }, + { + name: "Updates existing DevWorkspaceOperatorConfig with Pod security context", + cheCluster: &chev2.CheCluster{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "eclipse-che", + Name: "eclipse-che", + }, + Spec: chev2.CheClusterSpec{ + DevEnvironments: chev2.CheClusterDevEnvironments{ + Security: chev2.WorkspaceSecurityConfig{ + PodSecurityContext: configuredPodSecurityContext, + }, + }, + }, + }, + existedObjects: []runtime.Object{ + &controllerv1alpha1.DevWorkspaceOperatorConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: devWorkspaceConfigName, + Namespace: "eclipse-che", + }, + TypeMeta: metav1.TypeMeta{ + Kind: "DevWorkspaceOperatorConfig", + APIVersion: controllerv1alpha1.GroupVersion.String(), + }, + }, + }, + expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{ + Workspace: &controllerv1alpha1.WorkspaceConfig{ + PodSecurityContext: configuredPodSecurityContext, + }, + }, + }, + { + name: "Updates existing DevWorkspaceOperatorConfig when Pod security context is changed", + cheCluster: &chev2.CheCluster{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "eclipse-che", + Name: "eclipse-che", + }, + Spec: chev2.CheClusterSpec{ + DevEnvironments: chev2.CheClusterDevEnvironments{ + Security: chev2.WorkspaceSecurityConfig{ + PodSecurityContext: configuredPodSecurityContext, + }, + }, + }, + }, + existedObjects: []runtime.Object{ + &controllerv1alpha1.DevWorkspaceOperatorConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: devWorkspaceConfigName, + Namespace: "eclipse-che", + }, + TypeMeta: metav1.TypeMeta{ + Kind: "DevWorkspaceOperatorConfig", + APIVersion: controllerv1alpha1.GroupVersion.String(), + }, + Config: &controllerv1alpha1.OperatorConfiguration{ + Workspace: &controllerv1alpha1.WorkspaceConfig{ + PodSecurityContext: &corev1.PodSecurityContext{ + RunAsUser: pointer.Int64(1000), + RunAsGroup: pointer.Int64(10001), + RunAsNonRoot: pointer.Bool(true), + SupplementalGroups: []int64{ + 5, + }, + }, + }, + }, + }, + }, + expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{ + Workspace: &controllerv1alpha1.WorkspaceConfig{ + PodSecurityContext: configuredPodSecurityContext, + }, + }, + }, + { + name: "Updates existing DevWorkspaceOperatorConfig when Pod security context is removed", + cheCluster: &chev2.CheCluster{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "eclipse-che", + Name: "eclipse-che", + }, + Spec: chev2.CheClusterSpec{ + DevEnvironments: chev2.CheClusterDevEnvironments{}, + }, + }, + existedObjects: []runtime.Object{ + &controllerv1alpha1.DevWorkspaceOperatorConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: devWorkspaceConfigName, + Namespace: "eclipse-che", + }, + TypeMeta: metav1.TypeMeta{ + Kind: "DevWorkspaceOperatorConfig", + APIVersion: controllerv1alpha1.GroupVersion.String(), + }, + Config: &controllerv1alpha1.OperatorConfiguration{ + Workspace: &controllerv1alpha1.WorkspaceConfig{ + PodSecurityContext: &corev1.PodSecurityContext{ + RunAsUser: pointer.Int64(1000), + RunAsGroup: pointer.Int64(10001), + RunAsNonRoot: pointer.Bool(true), + SupplementalGroups: []int64{ + 5, + }, + }, + }, + }, + }, + }, + expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{ + Workspace: &controllerv1alpha1.WorkspaceConfig{}, + }, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + deployContext := test.GetDeployContext(testCase.cheCluster, []runtime.Object{}) + infrastructure.InitializeForTesting(infrastructure.OpenShiftv4) + + devWorkspaceConfigReconciler := NewDevWorkspaceConfigReconciler() + _, _, err := devWorkspaceConfigReconciler.Reconcile(deployContext) + assert.NoError(t, err) + + dwoc := &controllerv1alpha1.DevWorkspaceOperatorConfig{} + err = deployContext.ClusterAPI.Client.Get(context.TODO(), types.NamespacedName{Name: devWorkspaceConfigName, Namespace: testCase.cheCluster.Namespace}, dwoc) + assert.NoError(t, err) + assert.Equal(t, testCase.expectedOperatorConfig.Workspace.PodSecurityContext, dwoc.Config.Workspace.PodSecurityContext, + fmt.Sprintf("Did not get expected PodSecurityContext.\nDiff:%s", cmp.Diff(testCase.expectedOperatorConfig.Workspace.PodSecurityContext, dwoc.Config.Workspace.PodSecurityContext))) + }) + } +}