From e4e62f825598f40659083096118102a4e239abca Mon Sep 17 00:00:00 2001 From: Owais Lone Date: Fri, 2 Jul 2021 00:20:40 +0530 Subject: [PATCH] Container Security Context Allow setting a custom security context on containers. --- PROJECT | 1 - api/v1alpha1/opentelemetrycollector_types.go | 5 + api/v1alpha1/zz_generated.deepcopy.go | 1 + ...emetry-operator.clusterserviceversion.yaml | 2 +- ...ntelemetry.io_opentelemetrycollectors.yaml | 139 ++++++++++++++++++ ...ntelemetry.io_opentelemetrycollectors.yaml | 139 ++++++++++++++++++ pkg/collector/container.go | 13 +- pkg/collector/container_test.go | 29 ++++ 8 files changed, 321 insertions(+), 8 deletions(-) diff --git a/PROJECT b/PROJECT index 89485dd8ce..948fffc49b 100644 --- a/PROJECT +++ b/PROJECT @@ -12,4 +12,3 @@ resources: version: "3" plugins: manifests.sdk.operatorframework.io/v2: {} - scorecard.sdk.operatorframework.io/v2: {} diff --git a/api/v1alpha1/opentelemetrycollector_types.go b/api/v1alpha1/opentelemetrycollector_types.go index 48c53b6fc1..7cf236ab70 100644 --- a/api/v1alpha1/opentelemetrycollector_types.go +++ b/api/v1alpha1/opentelemetrycollector_types.go @@ -51,6 +51,11 @@ type OpenTelemetryCollectorSpec struct { // +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors=true ServiceAccount string `json:"serviceAccount,omitempty"` + // SecurityContext will be set as the container security context + // +optional + // +operator-sdk:gen-csv:customresourcedefinitions.specDescriptors=true + SecurityContext v1.SecurityContext `json:"securityContext,omitempty"` + // VolumeClaimTemplates will provide stable storage using PersistentVolumes. Only available when the mode=statefulset. // +optional // +listType=atomic diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index caee6f0b02..a3fe81cec0 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -97,6 +97,7 @@ func (in *OpenTelemetryCollectorSpec) DeepCopyInto(out *OpenTelemetryCollectorSp *out = new(int32) **out = **in } + in.SecurityContext.DeepCopyInto(&out.SecurityContext) if in.VolumeClaimTemplates != nil { in, out := &in.VolumeClaimTemplates, &out.VolumeClaimTemplates *out = make([]v1.PersistentVolumeClaim, len(*in)) diff --git a/bundle/manifests/opentelemetry-operator.clusterserviceversion.yaml b/bundle/manifests/opentelemetry-operator.clusterserviceversion.yaml index 1f0d528533..651f8041a3 100644 --- a/bundle/manifests/opentelemetry-operator.clusterserviceversion.yaml +++ b/bundle/manifests/opentelemetry-operator.clusterserviceversion.yaml @@ -21,7 +21,7 @@ metadata: containerImage: quay.io/opentelemetry/opentelemetry-operator createdAt: "2020-12-16T13:37:00+00:00" description: Provides the OpenTelemetry components, including the Collector - operators.operatorframework.io/builder: operator-sdk-v1.8.0+git + operators.operatorframework.io/builder: operator-sdk-v1.9.0 operators.operatorframework.io/project_layout: go.kubebuilder.io/v2 repository: github.com/open-telemetry/opentelemetry-operator support: OpenTelemetry Community diff --git a/bundle/manifests/opentelemetry.io_opentelemetrycollectors.yaml b/bundle/manifests/opentelemetry.io_opentelemetrycollectors.yaml index b4f7d902e1..52fd3cf1c0 100644 --- a/bundle/manifests/opentelemetry.io_opentelemetrycollectors.yaml +++ b/bundle/manifests/opentelemetry.io_opentelemetrycollectors.yaml @@ -288,6 +288,145 @@ spec: to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext will be set as the container security + context + 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' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the container + runtime. + 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. + 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. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. + 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. + 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. + 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. + 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. + 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. + 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 + 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 serviceAccount: description: ServiceAccount indicates the name of an existing service account to use with this instance. diff --git a/config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml b/config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml index 15ce2e9b80..07b605e509 100644 --- a/config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml +++ b/config/crd/bases/opentelemetry.io_opentelemetrycollectors.yaml @@ -276,6 +276,145 @@ spec: to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + securityContext: + description: SecurityContext will be set as the container security + context + 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' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the container + runtime. + 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. + 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. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. + 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. + 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. + 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. + 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. + 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. + 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 + 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 serviceAccount: description: ServiceAccount indicates the name of an existing service account to use with this instance. diff --git a/pkg/collector/container.go b/pkg/collector/container.go index 3384b0b8e9..9bed540576 100644 --- a/pkg/collector/container.go +++ b/pkg/collector/container.go @@ -69,11 +69,12 @@ func Container(cfg config.Config, logger logr.Logger, otelcol v1alpha1.OpenTelem } return corev1.Container{ - Name: naming.Container(), - Image: image, - VolumeMounts: volumeMounts, - Args: args, - Env: envVars, - Resources: otelcol.Spec.Resources, + Name: naming.Container(), + Image: image, + VolumeMounts: volumeMounts, + Args: args, + Env: envVars, + Resources: otelcol.Spec.Resources, + SecurityContext: &otelcol.Spec.SecurityContext, } } diff --git a/pkg/collector/container_test.go b/pkg/collector/container_test.go index 172d13c131..f682dd24f8 100644 --- a/pkg/collector/container_test.go +++ b/pkg/collector/container_test.go @@ -98,6 +98,35 @@ func TestContainerCustomVolumes(t *testing.T) { assert.Equal(t, "custom-volume-mount", c.VolumeMounts[1].Name) } +func TestContainerCustomSecurityContext(t *testing.T) { + // default config without security context + c1 := Container(config.New(), logger, v1alpha1.OpenTelemetryCollector{Spec: v1alpha1.OpenTelemetryCollectorSpec{}}) + + // verify + assert.NotNil(t, c1.SecurityContext) + assert.Nil(t, c1.SecurityContext.Privileged) + assert.Nil(t, c1.SecurityContext.RunAsUser) + + // prepare + isPrivileged := true + uid := int64(1234) + + // test + c2 := Container(config.New(), logger, v1alpha1.OpenTelemetryCollector{ + Spec: v1alpha1.OpenTelemetryCollectorSpec{ + SecurityContext: corev1.SecurityContext{ + Privileged: &isPrivileged, + RunAsUser: &uid, + }, + }, + }) + + // verify + assert.NotNil(t, c2.SecurityContext) + assert.True(t, *c2.SecurityContext.Privileged) + assert.Nil(t, c1.SecurityContext.RunAsUser, uid) +} + func TestContainerEnvVarsOverridden(t *testing.T) { otelcol := v1alpha1.OpenTelemetryCollector{ Spec: v1alpha1.OpenTelemetryCollectorSpec{