From d66f58b03db37e2416ceab79169b22ec36b38c87 Mon Sep 17 00:00:00 2001 From: Marcell Sevcsik <31651557+0sewa0@users.noreply.github.com> Date: Mon, 28 Feb 2022 09:45:08 +0100 Subject: [PATCH] Adds security context to the operator/webhook (#580) (cherry picked from commit ba25ac3680b2f24107bb15821a06f03a25feeda9) --- config/deploy/kubernetes/kubernetes-all.yaml | 29 +++++ config/deploy/openshift/openshift-all.yaml | 29 +++++ .../Common/operator/deployment-operator.yaml | 11 ++ .../Common/webhook/deployment-webhook.yaml | 22 +++- .../operator/deployment-operator_test.yaml | 18 +++ .../webhook/deployment-webhook_test.yaml | 122 ++++++++++++++++++ 6 files changed, 227 insertions(+), 4 deletions(-) diff --git a/config/deploy/kubernetes/kubernetes-all.yaml b/config/deploy/kubernetes/kubernetes-all.yaml index 57dda8291d..0444dcc0a1 100644 --- a/config/deploy/kubernetes/kubernetes-all.yaml +++ b/config/deploy/kubernetes/kubernetes-all.yaml @@ -3546,6 +3546,8 @@ kind: Deployment metadata: name: dynatrace-operator namespace: dynatrace + annotations: + container.apparmor.security.beta.kubernetes.io/dynatrace-operator: runtime/default labels: dynatrace: operator operator: dynakube @@ -3610,6 +3612,15 @@ spec: scheme: HTTP initialDelaySeconds: 15 periodSeconds: 10 + securityContext: + seccompProfile: + type: RuntimeDefault + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + capabilities: + drop: ["all"] affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: @@ -3664,11 +3675,15 @@ spec: metadata: annotations: kubectl.kubernetes.io/default-container: webhook + container.apparmor.security.beta.kubernetes.io/webhook: runtime/default labels: dynatrace.com/operator: oneagent internal.dynatrace.com/component: webhook internal.dynatrace.com/app: webhook spec: + volumes: + - emptyDir: {} + name: certs-dir affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: @@ -3687,6 +3702,8 @@ spec: - name: webhook args: - webhook-server + # OLM mounts the certificates here, so we reuse it for simplicity + - --certs-dir=/tmp/k8s-webhook-server/serving-certs/ image: quay.io/dynatrace/dynatrace-operator:snapshot imagePullPolicy: Always @@ -3718,6 +3735,18 @@ spec: limits: cpu: 300m memory: 128Mi + volumeMounts: + - name: certs-dir + mountPath: /tmp/k8s-webhook-server/serving-certs/ + securityContext: + seccompProfile: + type: RuntimeDefault + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + capabilities: + drop: ["all"] serviceAccountName: dynatrace-webhook --- # Source: dynatrace-operator/templates/Common/webhook/mutatingwebhookconfiguration.yaml diff --git a/config/deploy/openshift/openshift-all.yaml b/config/deploy/openshift/openshift-all.yaml index aac4148fb2..ed3f59fc69 100644 --- a/config/deploy/openshift/openshift-all.yaml +++ b/config/deploy/openshift/openshift-all.yaml @@ -3613,6 +3613,8 @@ kind: Deployment metadata: name: dynatrace-operator namespace: dynatrace + annotations: + container.apparmor.security.beta.kubernetes.io/dynatrace-operator: runtime/default labels: dynatrace: operator operator: dynakube @@ -3677,6 +3679,15 @@ spec: scheme: HTTP initialDelaySeconds: 15 periodSeconds: 10 + securityContext: + seccompProfile: + type: RuntimeDefault + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + capabilities: + drop: ["all"] affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: @@ -3731,11 +3742,15 @@ spec: metadata: annotations: kubectl.kubernetes.io/default-container: webhook + container.apparmor.security.beta.kubernetes.io/webhook: runtime/default labels: dynatrace.com/operator: oneagent internal.dynatrace.com/component: webhook internal.dynatrace.com/app: webhook spec: + volumes: + - emptyDir: {} + name: certs-dir affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: @@ -3754,6 +3769,8 @@ spec: - name: webhook args: - webhook-server + # OLM mounts the certificates here, so we reuse it for simplicity + - --certs-dir=/tmp/k8s-webhook-server/serving-certs/ image: quay.io/dynatrace/dynatrace-operator:snapshot imagePullPolicy: Always @@ -3785,6 +3802,18 @@ spec: limits: cpu: 300m memory: 128Mi + volumeMounts: + - name: certs-dir + mountPath: /tmp/k8s-webhook-server/serving-certs/ + securityContext: + seccompProfile: + type: RuntimeDefault + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + capabilities: + drop: ["all"] serviceAccountName: dynatrace-webhook --- # Source: dynatrace-operator/templates/Common/webhook/mutatingwebhookconfiguration.yaml diff --git a/config/helm/chart/default/templates/Common/operator/deployment-operator.yaml b/config/helm/chart/default/templates/Common/operator/deployment-operator.yaml index df3851830a..d0a0e5ea63 100644 --- a/config/helm/chart/default/templates/Common/operator/deployment-operator.yaml +++ b/config/helm/chart/default/templates/Common/operator/deployment-operator.yaml @@ -18,6 +18,8 @@ kind: Deployment metadata: name: {{ .Release.Name }} namespace: {{ .Release.Namespace }} + annotations: + container.apparmor.security.beta.kubernetes.io/{{ .Release.Name }}: runtime/default labels: {{- include "dynatrace-operator.labels" . | nindent 4 }} spec: @@ -83,6 +85,15 @@ spec: scheme: HTTP initialDelaySeconds: 15 periodSeconds: 10 + securityContext: + seccompProfile: + type: RuntimeDefault + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + capabilities: + drop: ["all"] affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: diff --git a/config/helm/chart/default/templates/Common/webhook/deployment-webhook.yaml b/config/helm/chart/default/templates/Common/webhook/deployment-webhook.yaml index b6d7d07a92..417b4a5dd8 100644 --- a/config/helm/chart/default/templates/Common/webhook/deployment-webhook.yaml +++ b/config/helm/chart/default/templates/Common/webhook/deployment-webhook.yaml @@ -33,11 +33,15 @@ spec: metadata: annotations: kubectl.kubernetes.io/default-container: webhook + container.apparmor.security.beta.kubernetes.io/webhook: runtime/default labels: dynatrace.com/operator: oneagent internal.dynatrace.com/component: webhook internal.dynatrace.com/app: webhook spec: + volumes: + - emptyDir: {} + name: certs-dir affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: @@ -56,10 +60,8 @@ spec: - name: webhook args: - webhook-server - {{- if eq (default false .Values.olm) true }} - # OLM mounts the certificates to a different location + # OLM mounts the certificates here, so we reuse it for simplicity - --certs-dir=/tmp/k8s-webhook-server/serving-certs/ - {{- end}} image: {{- include "dynatrace-operator.image" . | nindent 12 }} imagePullPolicy: Always env: @@ -94,10 +96,22 @@ spec: limits: cpu: {{ default "300m" ((.Values.webhook).limits).cpu }} memory: {{ default "128Mi" ((.Values.webhook).limits).memory }} + volumeMounts: + - name: certs-dir + mountPath: /tmp/k8s-webhook-server/serving-certs/ + securityContext: + seccompProfile: + type: RuntimeDefault + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + capabilities: + drop: ["all"] + serviceAccountName: dynatrace-webhook {{- if (.Values.webhook).hostNetwork }} hostNetwork: true {{- end }} - serviceAccountName: dynatrace-webhook {{- if .Values.operator.customPullSecret }} imagePullSecrets: - name: {{ .Values.operator.customPullSecret }} diff --git a/config/helm/chart/default/tests/Common/operator/deployment-operator_test.yaml b/config/helm/chart/default/tests/Common/operator/deployment-operator_test.yaml index af28acf588..45dad493ef 100644 --- a/config/helm/chart/default/tests/Common/operator/deployment-operator_test.yaml +++ b/config/helm/chart/default/tests/Common/operator/deployment-operator_test.yaml @@ -82,6 +82,15 @@ tests: scheme: HTTP initialDelaySeconds: 15 periodSeconds: 10 + securityContext: + seccompProfile: + type: RuntimeDefault + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + capabilities: + drop: ["all"] affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: @@ -222,6 +231,15 @@ tests: scheme: HTTP initialDelaySeconds: 15 periodSeconds: 10 + securityContext: + seccompProfile: + type: RuntimeDefault + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + capabilities: + drop: ["all"] affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: diff --git a/config/helm/chart/default/tests/Common/webhook/deployment-webhook_test.yaml b/config/helm/chart/default/tests/Common/webhook/deployment-webhook_test.yaml index 018ee89f5e..6f4c0e1dbb 100644 --- a/config/helm/chart/default/tests/Common/webhook/deployment-webhook_test.yaml +++ b/config/helm/chart/default/tests/Common/webhook/deployment-webhook_test.yaml @@ -44,11 +44,15 @@ tests: metadata: annotations: kubectl.kubernetes.io/default-container: webhook + container.apparmor.security.beta.kubernetes.io/webhook: runtime/default labels: dynatrace.com/operator: oneagent internal.dynatrace.com/component: webhook internal.dynatrace.com/app: webhook spec: + volumes: + - emptyDir: {} + name: certs-dir affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: @@ -67,6 +71,7 @@ tests: - name: webhook args: - webhook-server + - --certs-dir=/tmp/k8s-webhook-server/serving-certs/ image: image-name imagePullPolicy: Always env: @@ -97,6 +102,18 @@ tests: limits: cpu: 300m memory: 128Mi + volumeMounts: + - name: certs-dir + mountPath: /tmp/k8s-webhook-server/serving-certs/ + securityContext: + seccompProfile: + type: RuntimeDefault + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + capabilities: + drop: ["all"] serviceAccountName: dynatrace-webhook - it: should have imagePullSecrets defined in spec @@ -112,3 +129,108 @@ tests: asserts: - isNull: path: spec.template.spec.imagePullSecrets + + + - it: should exist on olm (but different) + set: + olm: true + operator.image: image-name + asserts: + - isKind: + of: Deployment + - equal: + path: metadata.name + value: dynatrace-webhook + - equal: + path: metadata.namespace + value: NAMESPACE + - isNotEmpty: + path: metadata.labels + - equal: + path: spec + value: + replicas: 1 + revisionHistoryLimit: 1 + selector: + matchLabels: + internal.dynatrace.com/component: webhook + internal.dynatrace.com/app: webhook + strategy: + type: RollingUpdate + template: + metadata: + annotations: + kubectl.kubernetes.io/default-container: webhook + container.apparmor.security.beta.kubernetes.io/webhook: runtime/default + labels: + dynatrace.com/operator: oneagent + internal.dynatrace.com/component: webhook + internal.dynatrace.com/app: webhook + spec: + volumes: + - emptyDir: {} + name: certs-dir + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: kubernetes.io/arch + operator: In + values: + - amd64 + - arm64 + - key: kubernetes.io/os + operator: In + values: + - linux + containers: + - name: webhook + args: + - webhook-server + - --certs-dir=/tmp/k8s-webhook-server/serving-certs/ + image: image-name + imagePullPolicy: Always + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: DEPLOYED_VIA_OLM + value: "true" + readinessProbe: + httpGet: + path: /healthz + port: server-port + scheme: HTTPS + ports: + - name: metrics + containerPort: 8383 + - name: validation + containerPort: 8384 + - name: server-port + containerPort: 8443 + resources: + requests: + cpu: 300m + memory: 128Mi + limits: + cpu: 300m + memory: 128Mi + volumeMounts: + - name: certs-dir + mountPath: /tmp/k8s-webhook-server/serving-certs/ + securityContext: + seccompProfile: + type: RuntimeDefault + privileged: false + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + capabilities: + drop: ["all"] + serviceAccountName: dynatrace-webhook