Skip to content

Commit

Permalink
Cherry-pick commits from #1576 & #1565 & #1606 to 7.58.x (#1608)
Browse files Browse the repository at this point in the history
* feat: configure workspace security context for container builds

Fix eclipse-che/che#21770

Signed-off-by: Andrew Obuchowicz <[email protected]>

* Set SCC allowPrivilegeEscalation to true when container build enabled (#1596)

* Set SCC allowPrivilegeEscalation to true when container build enabled

Running Podman inside a container in OpenShift requires the pod to have
allowPrivilegeEscalation: true in its security context.

* Fix tests

Signed-off-by: Angel Misevski <[email protected]>

* fix: set scc priority to null

Signed-off-by: Anatolii Bazko <[email protected]>

---------

Signed-off-by: Andrew Obuchowicz <[email protected]>
Signed-off-by: Angel Misevski <[email protected]>
Signed-off-by: Anatolii Bazko <[email protected]>
Co-authored-by: Angel Misevski <[email protected]>
Co-authored-by: Anatolii Bazko <[email protected]>
  • Loading branch information
3 people authored Jan 30, 2023
1 parent c5e6e04 commit ad19924
Show file tree
Hide file tree
Showing 5 changed files with 199 additions and 6 deletions.
15 changes: 15 additions & 0 deletions pkg/common/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@

package constants

import (
corev1 "k8s.io/api/core/v1"
"k8s.io/utils/pointer"
)

const (
// PostgresSQL
DefaultPostgresUser = "pgche"
Expand Down Expand Up @@ -138,4 +143,14 @@ var (
"app": "che",
"component": "che-gateway-config",
}

DefaultWorkspaceContainerSecurityContext = corev1.SecurityContext{
Capabilities: &corev1.Capabilities{
Add: []corev1.Capability{
"SETGID",
"SETUID",
},
},
AllowPrivilegeEscalation: pointer.BoolPtr(true),
}
)
37 changes: 33 additions & 4 deletions pkg/deploy/container-build/container_build.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import (
"context"
"fmt"

"github.com/google/go-cmp/cmp"
"k8s.io/apimachinery/pkg/types"

"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"
Expand Down Expand Up @@ -94,8 +97,36 @@ func (cb *ContainerBuildReconciler) Finalize(ctx *chetypes.DeployContext) bool {
}

func (cb *ContainerBuildReconciler) syncSCC(ctx *chetypes.DeployContext) (bool, error) {
_, err := deploy.CreateIfNotExists(ctx, cb.getSccSpec(ctx))
return err == nil, err
scc := &securityv1.SecurityContextConstraints{}
if exists, err := deploy.Get(ctx,
types.NamespacedName{Name: ctx.CheCluster.Spec.DevEnvironments.ContainerBuildConfiguration.OpenShiftSecurityContextConstraint},
scc); err != nil {
return false, err
} else if exists {
if deploy.IsPartOfEclipseCheResourceAndManagedByOperator(scc.Labels) {
// SCC exists and created by operator (custom SCC won't be updated).
// So, remove priority. See details https://issues.redhat.com/browse/CRW-3894
scc.Priority = nil

// Ensure kind and version set correctly before invoking `Sync`
scc.Kind = "SecurityContextConstraints"
scc.APIVersion = securityv1.GroupVersion.String()

return deploy.Sync(
ctx,
scc,
cmp.Options{
cmp.Comparer(func(x, y securityv1.SecurityContextConstraints) bool {
return pointer.Int32Equal(x.Priority, y.Priority)
}),
})
}
} else {
// Create a new SCC. If custom SCC exists then it won't be touched.
return deploy.Create(ctx, cb.getSccSpec(ctx))
}

return true, nil
}

func (cb *ContainerBuildReconciler) syncRBAC(ctx *chetypes.DeployContext) (bool, error) {
Expand Down Expand Up @@ -259,8 +290,6 @@ func (cb *ContainerBuildReconciler) getSccSpec(ctx *chetypes.DeployContext) *sec
AllowedCapabilities: []corev1.Capability{"SETUID", "SETGID"},
DefaultAddCapabilities: nil,
FSGroup: securityv1.FSGroupStrategyOptions{Type: securityv1.FSGroupStrategyMustRunAs},
// Temporary workaround for https://github.com/devfile/devworkspace-operator/issues/884
Priority: pointer.Int32Ptr(20),
ReadOnlyRootFilesystem: false,
RequiredDropCapabilities: []corev1.Capability{"KILL", "MKNOD"},
RunAsUser: securityv1.RunAsUserStrategyOptions{Type: securityv1.RunAsUserStrategyMustRunAsRange},
Expand Down
10 changes: 8 additions & 2 deletions pkg/deploy/dev-workspace-config/dev_workspace_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func (d *DevWorkspaceConfigReconciler) Reconcile(ctx *chetypes.DeployContext) (r
dwoc.Config = &controllerv1alpha1.OperatorConfiguration{}
}

if err := updateWorkspaceConfig(&ctx.CheCluster.Spec.DevEnvironments, dwoc.Config); err != nil {
if err := updateWorkspaceConfig(ctx.CheCluster, dwoc.Config); err != nil {
return reconcile.Result{}, false, err
}

Expand All @@ -71,7 +71,8 @@ func (d *DevWorkspaceConfigReconciler) Finalize(ctx *chetypes.DeployContext) boo
return true
}

func updateWorkspaceConfig(devEnvironments *chev2.CheClusterDevEnvironments, operatorConfig *controllerv1alpha1.OperatorConfiguration) error {
func updateWorkspaceConfig(cheCluster *chev2.CheCluster, operatorConfig *controllerv1alpha1.OperatorConfiguration) error {
devEnvironments := &cheCluster.Spec.DevEnvironments
if operatorConfig.Workspace == nil {
operatorConfig.Workspace = &controllerv1alpha1.WorkspaceConfig{}
}
Expand All @@ -84,6 +85,11 @@ func updateWorkspaceConfig(devEnvironments *chev2.CheClusterDevEnvironments, ope
return err
}

operatorConfig.Workspace.ContainerSecurityContext = nil
if cheCluster.IsContainerBuildCapabilitiesEnabled() {
operatorConfig.Workspace.ContainerSecurityContext = constants.DefaultWorkspaceContainerSecurityContext.DeepCopy()
}

return nil
}

Expand Down
139 changes: 139 additions & 0 deletions pkg/deploy/dev-workspace-config/dev_workspace_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (

"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
corev1 "k8s.io/api/core/v1"

"github.com/eclipse-che/che-operator/pkg/common/constants"
"k8s.io/apimachinery/pkg/api/resource"
Expand Down Expand Up @@ -318,6 +319,144 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
},
},
},
{
name: "Create DevWorkspaceOperatorConfig without Pod Security Context if container build disabled",
cheCluster: &chev2.CheCluster{
ObjectMeta: metav1.ObjectMeta{
Namespace: "eclipse-che",
Name: "eclipse-che",
},
Spec: chev2.CheClusterSpec{
DevEnvironments: chev2.CheClusterDevEnvironments{
DisableContainerBuildCapabilities: pointer.BoolPtr(true),
},
},
},
expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{
Workspace: &controllerv1alpha1.WorkspaceConfig{},
},
},
{
name: "Create DevWorkspaceOperatorConfig with Pod and Container Security Context if container build enabled",
cheCluster: &chev2.CheCluster{
ObjectMeta: metav1.ObjectMeta{
Namespace: "eclipse-che",
Name: "eclipse-che",
},
Spec: chev2.CheClusterSpec{
DevEnvironments: chev2.CheClusterDevEnvironments{
DisableContainerBuildCapabilities: pointer.BoolPtr(false),
},
},
},
expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{
Workspace: &controllerv1alpha1.WorkspaceConfig{
ContainerSecurityContext: &corev1.SecurityContext{
Capabilities: &corev1.Capabilities{
Add: []corev1.Capability{
"SETGID",
"SETUID",
},
},
AllowPrivilegeEscalation: pointer.BoolPtr(true),
},
},
},
},
{
name: "Update existing DevWorkspaceOperatorConfig by adding Pod and Container Security Context",
cheCluster: &chev2.CheCluster{
ObjectMeta: metav1.ObjectMeta{
Namespace: "eclipse-che",
Name: "eclipse-che",
},
Spec: chev2.CheClusterSpec{
DevEnvironments: chev2.CheClusterDevEnvironments{
DisableContainerBuildCapabilities: pointer.BoolPtr(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{
StorageClassName: pointer.StringPtr("default-storage-class"),
DefaultStorageSize: &controllerv1alpha1.StorageSizes{
Common: &quantity10Gi,
},
},
},
},
},
expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{
Workspace: &controllerv1alpha1.WorkspaceConfig{
StorageClassName: pointer.StringPtr("default-storage-class"),
DefaultStorageSize: &controllerv1alpha1.StorageSizes{
Common: &quantity10Gi,
},
ContainerSecurityContext: &corev1.SecurityContext{
Capabilities: &corev1.Capabilities{
Add: []corev1.Capability{
"SETGID",
"SETUID",
},
},
AllowPrivilegeEscalation: pointer.BoolPtr(true),
},
},
},
},
{
name: "Update existing DevWorkspaceOperatorConfig by removing Pod and Container Security Context",
cheCluster: &chev2.CheCluster{
ObjectMeta: metav1.ObjectMeta{
Namespace: "eclipse-che",
Name: "eclipse-che",
},
Spec: chev2.CheClusterSpec{
DevEnvironments: chev2.CheClusterDevEnvironments{
DisableContainerBuildCapabilities: pointer.BoolPtr(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{
StorageClassName: pointer.StringPtr("default-storage-class"),
DefaultStorageSize: &controllerv1alpha1.StorageSizes{
Common: &quantity10Gi,
},
ContainerSecurityContext: &corev1.SecurityContext{},
},
},
},
},
expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{
Workspace: &controllerv1alpha1.WorkspaceConfig{
StorageClassName: pointer.StringPtr("default-storage-class"),
DefaultStorageSize: &controllerv1alpha1.StorageSizes{
Common: &quantity10Gi,
},
},
},
},
}

for _, testCase := range testCases {
Expand Down
4 changes: 4 additions & 0 deletions pkg/deploy/labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,7 @@ func GetLegacyLabels(component string) map[string]string {
"component": component,
}
}

func IsPartOfEclipseCheResourceAndManagedByOperator(labels map[string]string) bool {
return labels[constants.KubernetesPartOfLabelKey] == constants.CheEclipseOrg && labels[constants.KubernetesManagedByLabelKey] == GetManagedByLabel()
}

0 comments on commit ad19924

Please sign in to comment.