diff --git a/charts/cluster-shield/Chart.yaml b/charts/cluster-shield/Chart.yaml index 97c0d593c..2306c04bb 100644 --- a/charts/cluster-shield/Chart.yaml +++ b/charts/cluster-shield/Chart.yaml @@ -2,8 +2,8 @@ apiVersion: v2 name: cluster-shield description: Cluster Shield Helm Chart for Kubernetes type: application -version: 1.1.2 -appVersion: "1.1.2" +version: 1.2.0 +appVersion: "1.2.0" maintainers: - name: AlbertoBarba email: alberto.barba@sysdig.com diff --git a/charts/cluster-shield/README.md b/charts/cluster-shield/README.md index 2dd239dc7..c3a5e5072 100644 --- a/charts/cluster-shield/README.md +++ b/charts/cluster-shield/README.md @@ -23,7 +23,7 @@ $ pre-commit run -a $ helm repo add sysdig https://charts.sysdig.com $ helm repo update $ helm upgrade --install sysdig-sysdig-cluster-shield sysdig/cluster-shield \ - --create-namespace -n sysdig-agent --version=1.1.2 \ + --create-namespace -n sysdig-agent --version=1.2.0 \ --set global.clusterConfig.name=CLUSTER_NAME \ --set global.sysdig.region=SYSDIG_REGION \ --set global.sysdig.accessKey=YOUR-KEY-HERE @@ -144,11 +144,9 @@ The following table lists the configurable parameters of the `cluster-shield` ch | cluster_shield.features.container_vulnerability_management.enabled | Enable the container vulnerability management feature | false | | cluster_shield.features.container_vulnerability_management.in_use.enabled | Allows to retrieve the list of running packages. | true | | cluster_shield.features.container_vulnerability_management.in_use.integration_enabled | Allows to store the list of running packages to Sysdig backend. | false | -| cluster_shield.features.container_vulnerability_management.local_cluster.enabled | Enable to scan the cluster where the cluster-shield is running. | true | | cluster_shield.features.container_vulnerability_management.local_cluster.registry_secrets | Restrict access to specific Docker secrets when Cluster Scanner is running. The default behavior is listing all secrets. | [] | | cluster_shield.features.container_vulnerability_management.platform_services_enabled | Define if the platform services are enabled | true | | cluster_shield.features.container_vulnerability_management.registry_ssl.verify | If set to false it allows insecure connections to registries, Such as for registries with self-signed or private certificates. | true | -| cluster_shield.features.container_vulnerability_management.remote_clusters.enabled | | false | | cluster_shield.features.kubernetes_metadata.enabled | Enable the Kubernetes Metadata feature | false | | ca.certs | A PEM-encoded x509 certificate. This can also be a bundle with multiple certificates. | [] | | ca.keyName | Filename that is used when creating the secret. Required if certs is provided. | null | @@ -157,7 +155,8 @@ The following table lists the configurable parameters of the `cluster-shield` ch | ca.existingCaConfigMap | Provide the name of an existing ConfigMap that contains the CA required | null | | ca.existingCaConfigMapKeyName | Provide the filename that is defined inside the existing ConfigMap | null | | run_command | The command executed by the Cluster Shield POD | "run-all-namespaced" | -| image.repository | The Cluster Shield container image repository | quay.io/sysdig/cluster-shield | +| image.registry | The Sysdig Registry Scanner image registry. | quay.io | +| image.repository | The Cluster Shield container image repository | sysdig/cluster-shield | | image.pullPolicy | The Cluster Shield container image pull policy | | | proxy.httpProxy | Sets the HTTP Proxy address. | | | proxy.httpsProxy | Sets the HTTPS Proxy address. | | @@ -188,6 +187,8 @@ The following table lists the configurable parameters of the `cluster-shield` ch | updateStrategy.type | The update strategy for the Cluster Shield deployment | RollingUpdate | | updateStrategy.rollingUpdate | The rolling update strategy for the Cluster Shield deployment | {} | | onPremCompatibilityVersion | Optional parameter used to check the compatibility of cluster-shield component versions with the on-premised backend version. If you are running an on-prem version of the Sysdig backend, you MUST set this parameter with the version of Sysdig backend you are using. If you are runinng on SaaS, do NOT provide this parameter. | | +| hostNetwork | Specifies if Cluster Shield should be started in hostNetwork mode. This field is required if you are using a custom CNI where the control plane nodes are unable to initiate network connections to the pods, for example, using Calico CNI plugin on EKS. | false | +| dnsPolicy | Define Cluster Shield Pods DNS Policy | | ## Running helm unit tests diff --git a/charts/cluster-shield/templates/_helpers.tpl b/charts/cluster-shield/templates/_helpers.tpl index 071a96b28..38cdf2e8c 100644 --- a/charts/cluster-shield/templates/_helpers.tpl +++ b/charts/cluster-shield/templates/_helpers.tpl @@ -50,59 +50,62 @@ Adds kubernetes related keys to the configuration. */}} {{- define "cluster-shield.configMap" -}} {{- $conf := deepCopy .Values.cluster_shield -}} -{{- $_ := set $conf "kubernetes" (include "cluster-shield.configurationKubernetes" . | fromYaml) }} -{{- if eq "true" (include "cluster-shield.containerVulnerabilityManagementEnabled" .) }} -{{- if regexMatch "^v?([0-9]+)(\\.[0-9]+)?(\\.[0-9]+)?(-([0-9A-Za-z\\-]+(\\.[0-9A-Za-z\\-]+)*))?(\\+([0-9A-Za-z\\-]+(\\.[0-9A-Za-z\\-]+)*))?$" (.Values.onPremCompatibilityVersion | default "") }} +{{- $_ := set $conf "kubernetes" (include "cluster-shield.configurationKubernetes" . | fromYaml) -}} +{{- if eq "true" (include "cluster-shield.containerVulnerabilityManagementEnabled" .) -}} +{{- if regexMatch "^v?([0-9]+)(\\.[0-9]+)?(\\.[0-9]+)?(-([0-9A-Za-z\\-]+(\\.[0-9A-Za-z\\-]+)*))?(\\+([0-9A-Za-z\\-]+(\\.[0-9A-Za-z\\-]+)*))?$" (.Values.onPremCompatibilityVersion | default "") -}} {{- if semverCompare "< 7.0.0" .Values.onPremCompatibilityVersion -}} -{{- $_ := set $conf.features.container_vulnerability_management "platform_services_enabled" false }} +{{- $_ := set $conf.features.container_vulnerability_management "platform_services_enabled" false -}} {{- end -}} {{- end -}} -{{- $_ := set $conf "cluster_scanner" (merge (include "cluster-shield.configurationClusterScanner" . | fromYaml) (.Values.cluster_shield.cluster_scanner | default dict)) }} -{{- end }} +{{- $_ := set $conf "cluster_scanner" (merge (include "cluster-shield.configurationClusterScanner" . | fromYaml) (.Values.cluster_shield.cluster_scanner | default dict)) -}} +{{- end -}} {{- if and (.Values.cluster_shield.features.admission_control.enabled) (.Values.cluster_shield.features.admission_control.container_vulnerability_management.enabled)}} -{{- $_ := set $conf "admission_controller_secure" (include "cluster-shield.configurationAdmissionControllerSecure" . | fromYaml) }} +{{- $_ := set $conf "admission_controller_secure" (include "cluster-shield.configurationAdmissionControllerSecure" . | fromYaml) -}} {{- end}} -{{- $_ := unset $conf.sysdig_endpoint "access_key" }} -{{- $_ := unset $conf.sysdig_endpoint "secure_api_token" }} +{{- $_ := unset $conf.sysdig_endpoint "access_key" -}} +{{- $_ := unset $conf.sysdig_endpoint "secure_api_token" -}} {{/* sysdig-deploy support start */}} -{{- if not .Values.cluster_shield.cluster_config.name }} -{{- if .Values.global.clusterConfig.name }} -{{- $_ := set $conf "cluster_config" (dict "name" .Values.global.clusterConfig.name) }} -{{- else }} +{{- if not .Values.cluster_shield.cluster_config.name -}} +{{- if .Values.global.clusterConfig.name -}} +{{- $_ := set $conf "cluster_config" (dict "name" .Values.global.clusterConfig.name) -}} +{{- else -}} {{- fail "One of global.clusterConfig.name and cluster_shield.cluster_config.name must be defined." -}} -{{- end }} -{{- end }} -{{- if not .Values.cluster_shield.sysdig_endpoint.region }} -{{- if .Values.global.sysdig.region }} -{{- $_ := set $conf.sysdig_endpoint "region" .Values.global.sysdig.region }} -{{- else }} +{{- end -}} +{{- end -}} +{{- if not .Values.cluster_shield.sysdig_endpoint.region -}} +{{- if .Values.global.sysdig.region -}} +{{- $_ := set $conf.sysdig_endpoint "region" .Values.global.sysdig.region -}} +{{- else -}} {{- fail "One of global.sysdig.region and cluster_shield.sysdig_endpoint.region must be defined." -}} -{{- end }} -{{- end }} -{{- if eq $conf.sysdig_endpoint.region "custom" }} -{{- if and (not .Values.cluster_shield.sysdig_endpoint.api_url) .Values.global.sysdig.apiHost }} -{{- $_ := set $conf.sysdig_endpoint "api_url" .Values.global.sysdig.apiHost }} -{{- if not (or (hasPrefix "https://" .Values.global.sysdig.apiHost) (hasPrefix "http://" .Values.global.sysdig.apiHost)) }} -{{- $_ := set $conf.sysdig_endpoint "api_url" (printf "https://%s" .Values.global.sysdig.apiHost) }} -{{- end }} -{{- end }} -{{- if not $conf.sysdig_endpoint.api_url }} +{{- end -}} +{{- end -}} +{{- if eq $conf.sysdig_endpoint.region "custom" -}} +{{- if and (not .Values.cluster_shield.sysdig_endpoint.api_url) .Values.global.sysdig.apiHost -}} +{{- $_ := set $conf.sysdig_endpoint "api_url" .Values.global.sysdig.apiHost -}} +{{- if not (or (hasPrefix "https://" .Values.global.sysdig.apiHost) (hasPrefix "http://" .Values.global.sysdig.apiHost)) -}} +{{- $_ := set $conf.sysdig_endpoint "api_url" (printf "https://%s" .Values.global.sysdig.apiHost) -}} +{{- end -}} +{{- end -}} +{{- if not $conf.sysdig_endpoint.api_url -}} {{- fail "Custom region requires one of global.sysdig.apiHost or cluster_shield.sysdig_endpoint.api_url to be defined." -}} -{{- end }} -{{- end }} -{{- if not (hasKey (default .Values.cluster_shield.ssl dict) "verify") }} -{{- $_ := set $conf "ssl" (dict "verify" .Values.global.sslVerifyCertificate) }} -{{- end }} -{{- if not .Values.cluster_shield.cluster_config.name }} -{{- if .Values.global.clusterConfig.name }} -{{- $_ := set $conf.cluster_config "name" .Values.global.clusterConfig.name }} -{{- else }} +{{- end -}} +{{- if and ($conf.features.kubernetes_metadata.enabled) (not $conf.sysdig_endpoint.collector) -}} +{{- fail "Custom region requires cluster_shield.sysdig_endpoint.collector to be defined." -}} +{{- end -}} +{{- end -}} +{{- if not (hasKey (default .Values.cluster_shield.ssl dict) "verify") -}} +{{- $_ := set $conf "ssl" (dict "verify" .Values.global.sslVerifyCertificate) -}} +{{- end -}} +{{- if not .Values.cluster_shield.cluster_config.name -}} +{{- if .Values.global.clusterConfig.name -}} +{{- $_ := set $conf.cluster_config "name" .Values.global.clusterConfig.name -}} +{{- else -}} {{- fail "One of global.clusterConfig.name and cluster_shield.cluster_config.name must be defined." -}} -{{- end }} -{{- end }} +{{- end -}} +{{- end -}} {{/* sysdig-deploy support end */}} {{- $conf | toYaml -}} -{{- end }} +{{- end -}} {{/* Adds kubernetes related keys to the configuration. @@ -192,6 +195,13 @@ Verify if certs needs to be generated and mounted inside the pod {{- or .Values.cluster_shield.features.audit.enabled .Values.cluster_shield.features.admission_control.enabled (eq "true" (include "cluster-shield.containerVulnerabilityManagementEnabled" .)) }} {{- end -}} +{{/* +Verify if ValidatingWebhookConfiguration needs to be generated +*/}} +{{- define "cluster-shield.needWebhooks"}} +{{- or .Values.cluster_shield.features.audit.enabled .Values.cluster_shield.features.admission_control.enabled }} +{{- end -}} + {{/* Custom CA */}} @@ -210,7 +220,7 @@ Custom CA {{- define "cluster-shield.custom_ca.useExistingConfigMap" -}} {{- if or (and .Values.ca.existingCaSecretKeyName .Values.ca.existingCaSecret) (and .Values.global.ssl.ca.existingCaSecretKeyName .Values.global.ssl.ca.existingCaSecret) -}} {{- false -}} - {{- else if (and .Values.ca.existingCaConfigMapKeyName .Values.ca.existingCaConfigMap) -}} + {{- else if or (and .Values.ca.existingCaConfigMapKeyName .Values.ca.existingCaConfigMap) (and .Values.global.ssl.ca.existingCaConfigMapKeyName .Values.global.ssl.ca.existingCaConfigMap) -}} {{- true -}} {{- else -}} {{- false -}} @@ -222,7 +232,7 @@ Custom CA {{- false -}} {{- else if (and .Values.ca.existingCaConfigMapKeyName .Values.ca.existingCaConfigMap) -}} {{- false -}} - {{- else if (and .Values.ca.certs .Values.ca.keyName) -}} + {{- else if or (and .Values.ca.certs .Values.ca.keyName) (and .Values.global.ssl.ca.keyName .Values.global.ssl.ca.certs) -}} {{- true -}} {{- else -}} {{- false -}} @@ -377,11 +387,7 @@ Proxy Secret Name Define the proper image repository to use for cluster-shield */}} {{- define "cluster-shield.repository" -}} - {{- if .Values.global.imageRegistry -}} - {{- printf "%s/%s" .Values.global.imageRegistry "sysdig/cluster-shield" -}} - {{- else -}} - {{- .Values.image.repository -}} - {{- end -}} + {{- printf "%s/%s" (default .Values.image.registry .Values.global.imageRegistry) .Values.image.repository -}} {{- end -}} {{- define "cluster-shield.serviceMonitoringPort" -}} diff --git a/charts/cluster-shield/templates/configmap.yaml b/charts/cluster-shield/templates/configmap.yaml index 67a27bf8a..0175e4930 100644 --- a/charts/cluster-shield/templates/configmap.yaml +++ b/charts/cluster-shield/templates/configmap.yaml @@ -6,4 +6,5 @@ metadata: labels: {{- include "cluster-shield.labels" . | nindent 4 }} data: - cluster-shield.yaml: {{ include "cluster-shield.configMap" . | quote }} + cluster-shield.yaml: | + {{- include "cluster-shield.configMap" . | nindent 4 }} diff --git a/charts/cluster-shield/templates/deployment.yaml b/charts/cluster-shield/templates/deployment.yaml index 4c214158d..b6bc449b6 100644 --- a/charts/cluster-shield/templates/deployment.yaml +++ b/charts/cluster-shield/templates/deployment.yaml @@ -35,6 +35,12 @@ spec: {{- toYaml .Values.global.image.pullSecrets | nindent 8 }} {{- end }} {{/* sysdig-deploy support end */}} + {{- if .Values.hostNetwork }} + hostNetwork: true + dnsPolicy: {{ default "ClusterFirstWithHostNet" .Values.dnsPolicy }} + {{- else if .Values.dnsPolicy }} + dnsPolicy: {{ .Values.dnsPolicy }} + {{- end }} serviceAccountName: {{ include "cluster-shield.serviceAccountName" . }} containers: - name: "cluster-shield" @@ -163,11 +169,11 @@ spec: {{- else if eq (include "cluster-shield.custom_ca.useExistingSecret" .) "true" }} - name: ca-cert secret: - secretName: {{ .Values.ca.existingCaSecret }} + secretName: {{ .Values.ca.existingCaSecret | default .Values.global.ssl.ca.existingCaSecret }} {{- else if eq (include "cluster-shield.custom_ca.useExistingConfigMap" .) "true" }} - name: ca-cert configMap: - name: {{ .Values.ca.existingCaConfigMap }} + name: {{ .Values.ca.existingCaConfigMap | default .Values.global.ssl.ca.existingCaConfigMap }} {{- end }} {{- with .Values.nodeSelector }} nodeSelector: diff --git a/charts/cluster-shield/templates/validatingwebhookconfiguration.yaml b/charts/cluster-shield/templates/validatingwebhookconfiguration.yaml index 0e618760b..feb1521b8 100644 --- a/charts/cluster-shield/templates/validatingwebhookconfiguration.yaml +++ b/charts/cluster-shield/templates/validatingwebhookconfiguration.yaml @@ -6,11 +6,11 @@ so the template is executed just once {{- if eq (include "cluster-shield.needCerts" .) "true" }} {{- $certString := include "cluster-shield.tlsGenCerts" . -}} {{- $certList := split "$" $certString }} +{{- if eq (include "cluster-shield.needWebhooks" .) "true" }} apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: name: {{ include "cluster-shield.fullname" . }}-audit - namespace: {{ .Release.Namespace }} webhooks: {{- if .Values.cluster_shield.features.audit.enabled }} - name: audit.secure.sysdig.com @@ -59,6 +59,9 @@ webhooks: apiVersions: [ "v1" ] operations: [ "CREATE", "UPDATE" ] resources: + {{- if .Values.cluster_shield.features.admission_control.container_vulnerability_management.enabled }} + - "pods" + {{- end }} - "deployments" - "replicasets" - "statefulsets" @@ -82,6 +85,7 @@ webhooks: failurePolicy: Ignore {{- end }} {{- end }} +{{- end }} --- apiVersion: v1 kind: Secret diff --git a/charts/cluster-shield/tests/configmap_test.yaml b/charts/cluster-shield/tests/configmap_test.yaml index 3e1e43015..a945eed62 100644 --- a/charts/cluster-shield/tests/configmap_test.yaml +++ b/charts/cluster-shield/tests/configmap_test.yaml @@ -4,6 +4,26 @@ templates: values: - ../ci/base-values.yaml tests: + + - it: Check configmap does not contain leading/trailing whitespaces + asserts: + - hasDocuments: + count: 1 + - containsDocument: + kind: ConfigMap + apiVersion: v1 + - isNotEmpty: + path: data + - notMatchRegex: + path: data['cluster-shield.yaml'] + pattern: ^\n + - notMatchRegex: + path: data['cluster-shield.yaml'] + pattern: \n\n$ + - matchRegex: + path: data['cluster-shield.yaml'] + pattern: \n$ + - it: Sets the correct log level in configmap set: cluster_shield: @@ -166,3 +186,77 @@ tests: pattern: | ssl: verify: true + + + - it: Local custom region requires Collector when kubernetes_metadata feature is enabled + set: + cluster_shield: + sysdig_endpoint: + region: "custom" + api_url: "https://www.example.com" + collector: null + features: + kubernetes_metadata: + enabled: true + asserts: + - failedTemplate: + errorMessage: Custom region requires cluster_shield.sysdig_endpoint.collector to be defined. + + - it: Global custom region requires Collector when kubernetes_metadata feature is enabled + set: + global: + sysdig: + region: "custom" + cluster_shield: + sysdig_endpoint: + api_url: "https://www.example.com" + collector: null + features: + kubernetes_metadata: + enabled: true + asserts: + - failedTemplate: + errorMessage: Custom region requires cluster_shield.sysdig_endpoint.collector to be defined. + + + - it: Local custom region requires Collector when kubernetes_metadata feature is enabled + set: + cluster_shield: + sysdig_endpoint: + region: "custom" + api_url: "https://www.example.com" + collector: "collector.example.com:6443" + features: + kubernetes_metadata: + enabled: true + asserts: + - notFailedTemplate: {} + - matchRegex: + path: data['cluster-shield.yaml'] + pattern: |- + sysdig_endpoint: + api_url: https://www.example.com + collector: collector.example.com:6443 + region: custom + + - it: Global custom region requires Collector when kubernetes_metadata feature is enabled + set: + global: + sysdig: + region: "custom" + cluster_shield: + sysdig_endpoint: + api_url: "https://www.example.com" + collector: "collector.example.com:6443" + features: + kubernetes_metadata: + enabled: true + asserts: + - notFailedTemplate: {} + - matchRegex: + path: data['cluster-shield.yaml'] + pattern: |- + sysdig_endpoint: + api_url: https://www.example.com + collector: collector.example.com:6443 + region: custom diff --git a/charts/cluster-shield/tests/custom_ca_test.yaml b/charts/cluster-shield/tests/custom_ca_test.yaml new file mode 100644 index 000000000..ba012fa35 --- /dev/null +++ b/charts/cluster-shield/tests/custom_ca_test.yaml @@ -0,0 +1,264 @@ +suite: Test Custom CA +templates: + - templates/deployment.yaml + - templates/secrets.yaml +values: + - ../ci/base-values.yaml +release: + name: shield-release + namespace: shield-namespace +tests: + - it: Test without Custom CA Settings + asserts: + - hasDocuments: + count: 1 + template: templates/secrets.yaml + - containsDocument: + kind: Secret + apiVersion: v1 + name: cluster-shield-ca + not: true + template: templates/secrets.yaml + - notExists: + path: spec.template.spec.containers[?(@.name == "cluster-shield")].env[?(@.name == "SSL_CERT_FILE")] + template: templates/deployment.yaml + - notContains: + path: spec.template.spec.containers[?(@.name == "cluster-shield")].volumeMounts + content: + name: ca-cert + mountPath: /ca-certs + readOnly: true + template: templates/deployment.yaml + - notExists: + path: spec.template.spec.volumes[?(@.name == "ca-cert")] + template: templates/deployment.yaml + + - it: Test with Local Custom CA Settings (values) + set: + ca: + certs: + - "test certificate" + keyName: "custom-ca-from-values.crt" + asserts: + - hasDocuments: + count: 2 + template: templates/secrets.yaml + - containsDocument: + kind: Secret + apiVersion: v1 + name: cluster-shield-ca + template: templates/secrets.yaml + documentIndex: 1 + - equal: + path: data["custom-ca-from-values.crt"] + decodeBase64: true + value: "test certificate" + template: templates/secrets.yaml + documentIndex: 1 + - isSubset: + path: spec.template.spec.volumes[?(@.name == "ca-cert")] + content: + secret: + secretName: cluster-shield-ca + template: templates/deployment.yaml + - contains: + path: spec.template.spec.containers[?(@.name == "cluster-shield")].volumeMounts + content: + name: ca-cert + mountPath: /ca-certs + readOnly: true + template: templates/deployment.yaml + - equal: + path: spec.template.spec.containers[?(@.name == "cluster-shield")].env[?(@.name == "SSL_CERT_FILE")] + value: + name: SSL_CERT_FILE + value: /ca-certs/custom-ca-from-values.crt + template: templates/deployment.yaml + + - it: Test with Local Custom CA Settings (configmap) + set: + ca: + existingCaConfigMap: fake-configmap-name + existingCaConfigMapKeyName: custom-ca-from-configmap.crt + asserts: + - hasDocuments: + count: 1 + template: templates/secrets.yaml + - containsDocument: + kind: Secret + apiVersion: v1 + name: cluster-shield-ca + template: templates/secrets.yaml + not: true + - isSubset: + path: spec.template.spec.volumes[?(@.name == "ca-cert")] + content: + configMap: + name: fake-configmap-name + template: templates/deployment.yaml + - contains: + path: spec.template.spec.containers[?(@.name == "cluster-shield")].volumeMounts + content: + name: ca-cert + mountPath: /ca-certs + readOnly: true + template: templates/deployment.yaml + - equal: + path: spec.template.spec.containers[?(@.name == "cluster-shield")].env[?(@.name == "SSL_CERT_FILE")] + value: + name: SSL_CERT_FILE + value: /ca-certs/custom-ca-from-configmap.crt + template: templates/deployment.yaml + + - it: Test with Local Custom CA Settings (secret) + set: + ca: + existingCaSecret: fake-secret-name + existingCaSecretKeyName: custom-ca-from-secret.crt + asserts: + - hasDocuments: + count: 1 + template: templates/secrets.yaml + - containsDocument: + kind: Secret + apiVersion: v1 + name: cluster-shield-ca + template: templates/secrets.yaml + not: true + - isSubset: + path: spec.template.spec.volumes[?(@.name == "ca-cert")] + content: + secret: + secretName: fake-secret-name + template: templates/deployment.yaml + - contains: + path: spec.template.spec.containers[?(@.name == "cluster-shield")].volumeMounts + content: + name: ca-cert + mountPath: /ca-certs + readOnly: true + template: templates/deployment.yaml + - equal: + path: spec.template.spec.containers[?(@.name == "cluster-shield")].env[?(@.name == "SSL_CERT_FILE")] + value: + name: SSL_CERT_FILE + value: /ca-certs/custom-ca-from-secret.crt + template: templates/deployment.yaml + + - it: Test with Global Custom CA Settings (values) + set: + global: + ssl: + ca: + certs: + - "test certificate" + keyName: "custom-ca-from-values.crt" + asserts: + - hasDocuments: + count: 2 + template: templates/secrets.yaml + - containsDocument: + kind: Secret + apiVersion: v1 + name: cluster-shield-ca + template: templates/secrets.yaml + documentIndex: 1 + - equal: + path: data["custom-ca-from-values.crt"] + decodeBase64: true + value: "test certificate" + template: templates/secrets.yaml + documentIndex: 1 + - isSubset: + path: spec.template.spec.volumes[?(@.name == "ca-cert")] + content: + secret: + secretName: cluster-shield-ca + template: templates/deployment.yaml + - contains: + path: spec.template.spec.containers[?(@.name == "cluster-shield")].volumeMounts + content: + name: ca-cert + mountPath: /ca-certs + readOnly: true + template: templates/deployment.yaml + - equal: + path: spec.template.spec.containers[?(@.name == "cluster-shield")].env[?(@.name == "SSL_CERT_FILE")] + value: + name: SSL_CERT_FILE + value: /ca-certs/custom-ca-from-values.crt + template: templates/deployment.yaml + + - it: Test with Global Custom CA Settings (configmap) + set: + global: + ssl: + ca: + existingCaConfigMap: fake-configmap-name + existingCaConfigMapKeyName: custom-ca-from-configmap.crt + asserts: + - hasDocuments: + count: 1 + template: templates/secrets.yaml + - containsDocument: + kind: Secret + apiVersion: v1 + name: cluster-shield-ca + template: templates/secrets.yaml + not: true + - isSubset: + path: spec.template.spec.volumes[?(@.name == "ca-cert")] + content: + configMap: + name: fake-configmap-name + template: templates/deployment.yaml + - contains: + path: spec.template.spec.containers[?(@.name == "cluster-shield")].volumeMounts + content: + name: ca-cert + mountPath: /ca-certs + readOnly: true + template: templates/deployment.yaml + - equal: + path: spec.template.spec.containers[?(@.name == "cluster-shield")].env[?(@.name == "SSL_CERT_FILE")] + value: + name: SSL_CERT_FILE + value: /ca-certs/custom-ca-from-configmap.crt + template: templates/deployment.yaml + + - it: Test with Global Custom CA Settings (secret) + set: + global: + ssl: + ca: + existingCaSecret: fake-secret-name + existingCaSecretKeyName: custom-ca-from-secret.crt + asserts: + - hasDocuments: + count: 1 + template: templates/secrets.yaml + - containsDocument: + kind: Secret + apiVersion: v1 + name: cluster-shield-ca + template: templates/secrets.yaml + not: true + - isSubset: + path: spec.template.spec.volumes[?(@.name == "ca-cert")] + content: + secret: + secretName: fake-secret-name + template: templates/deployment.yaml + - contains: + path: spec.template.spec.containers[?(@.name == "cluster-shield")].volumeMounts + content: + name: ca-cert + mountPath: /ca-certs + readOnly: true + template: templates/deployment.yaml + - equal: + path: spec.template.spec.containers[?(@.name == "cluster-shield")].env[?(@.name == "SSL_CERT_FILE")] + value: + name: SSL_CERT_FILE + value: /ca-certs/custom-ca-from-secret.crt + template: templates/deployment.yaml diff --git a/charts/cluster-shield/tests/deployment_test.yaml b/charts/cluster-shield/tests/deployment_test.yaml index f3e8bb442..3b204757d 100644 --- a/charts/cluster-shield/tests/deployment_test.yaml +++ b/charts/cluster-shield/tests/deployment_test.yaml @@ -19,6 +19,10 @@ tests: - equal: path: metadata.namespace value: shield-namespace + - isNull: + path: spec.template.spec.hostNetwork + - isNull: + path: spec.template.spec.dnsPolicy - isNotNull: path: spec.template.spec.containers[?(@.name == "cluster-shield")] - isNotNull: @@ -42,6 +46,10 @@ tests: - equal: path: metadata.namespace value: shield-namespace + - isNull: + path: spec.template.spec.hostNetwork + - isNull: + path: spec.template.spec.dnsPolicy - isNotNull: path: spec.template.spec.containers[?(@.name == "cluster-shield")] - isNull: @@ -296,3 +304,63 @@ tests: - equal: path: spec.template.spec.serviceAccountName value: custom-service-account + + - it: Use image.registry, image.repository and image.tag to build the pullString + set: + image: + registry: "test-registry.io" + repository: "sysdig/cluster-shield" + tag: "0.0.0" + asserts: + - equal: + path: spec.template.spec.containers[?(@.name == "cluster-shield")].image + value: test-registry.io/sysdig/cluster-shield:0.0.0 + + - it: Use global.imageRegistry,image.repository and image.tag to build the pullString + set: + global: + imageRegistry: "test-global-registry.io" + image: + registry: "test-registry.io" + repository: "sysdig/cluster-shield" + tag: "0.0.0" + asserts: + - equal: + path: spec.template.spec.containers[?(@.name == "cluster-shield")].image + value: test-global-registry.io/sysdig/cluster-shield:0.0.0 + + - it: Default DNS Policy + asserts: + - notExists: + path: spec.template.spec.dnsPolicy + + - it: Test hostNetwork + set: + hostNetwork: true + asserts: + - equal: + path: spec.template.spec.hostNetwork + value: true + - equal: + path: spec.template.spec.dnsPolicy + value: ClusterFirstWithHostNet + + - it: Custom DNS Policy + set: + dnsPolicy: "None" + asserts: + - equal: + path: spec.template.spec.dnsPolicy + value: None + + - it: Custom DNS Policy with hostNetwork + set: + hostNetwork: true + dnsPolicy: "None" + asserts: + - equal: + path: spec.template.spec.hostNetwork + value: true + - equal: + path: spec.template.spec.dnsPolicy + value: None diff --git a/charts/cluster-shield/tests/schema_test.yaml b/charts/cluster-shield/tests/schema_test.yaml index d59981edd..e77caf4f6 100644 --- a/charts/cluster-shield/tests/schema_test.yaml +++ b/charts/cluster-shield/tests/schema_test.yaml @@ -59,7 +59,7 @@ tests: errorMessage: | values don't meet the specifications of the schema(s) in the following chart(s): cluster-shield: - - cluster_shield.sysdig_endpoint.region: cluster_shield.sysdig_endpoint.region must be one of the following: "custom", "au-syd-monitor", "au-syd-private-monitor", "au-syd-private-secure", "au-syd-secure", "au1", "br-sao-monitor", "br-sao-private-monitor", "br-sao-private-secure", "br-sao-secure", "ca-tor-monitor", "ca-tor-private-monitor", "ca-tor-private-secure", "ca-tor-secure", "eu-de-monitor", "eu-de-private-monitor", "eu-de-private-secure", "eu-de-secure", "eu-gb-monitor", "eu-gb-private-monitor", "eu-gb-private-secure", "eu-gb-secure", "eu1", "jp-osa-monitor", "jp-osa-private-monitor", "jp-osa-private-secure", "jp-osa-secure", "jp-tok-monitor", "jp-tok-private-monitor", "jp-tok-private-secure", "jp-tok-secure", "me2", "us-east-monitor", "us-east-private-monitor", "us-east-private-secure", "us-east-secure", "us-south-monitor", "us-south-private-monitor", "us-south-private-secure", "us-south-secure", "us1", "us2", "us3", "us4", null + - cluster_shield.sysdig_endpoint.region: cluster_shield.sysdig_endpoint.region must be one of the following: "custom", "au-syd-monitor", "au-syd-private-monitor", "au-syd-private-secure", "au-syd-secure", "au1", "br-sao-monitor", "br-sao-private-monitor", "br-sao-private-secure", "br-sao-secure", "ca-tor-monitor", "ca-tor-private-monitor", "ca-tor-private-secure", "ca-tor-secure", "eu-de-monitor", "eu-de-private-monitor", "eu-de-private-secure", "eu-de-secure", "eu-gb-monitor", "eu-gb-private-monitor", "eu-gb-private-secure", "eu-gb-secure", "eu1", "in1", "jp-osa-monitor", "jp-osa-private-monitor", "jp-osa-private-secure", "jp-osa-secure", "jp-tok-monitor", "jp-tok-private-monitor", "jp-tok-private-secure", "jp-tok-secure", "me2", "us-east-monitor", "us-east-private-monitor", "us-east-private-secure", "us-east-secure", "us-south-monitor", "us-south-private-monitor", "us-south-private-secure", "us-south-secure", "us1", "us2", "us3", "us4", null - it: Global - Custom Region requires API URL set: @@ -118,3 +118,43 @@ tests: api_url: asserts: - notFailedTemplate: { } + + - it: Accept null as dnsPolicy + set: + dnsPolicy: null + asserts: + - notFailedTemplate: { } + + - it: Accept ClusterFirst as dnsPolicy + set: + dnsPolicy: ClusterFirst + asserts: + - notFailedTemplate: { } + + - it: Accept ClusterFirstWithHostNet as dnsPolicy + set: + dnsPolicy: ClusterFirstWithHostNet + asserts: + - notFailedTemplate: { } + + - it: Accept Default as dnsPolicy + set: + dnsPolicy: Default + asserts: + - notFailedTemplate: { } + + - it: Accept None as dnsPolicy + set: + dnsPolicy: None + asserts: + - notFailedTemplate: { } + + - it: Does not Accept incorrect dnsPolicy + set: + dnsPolicy: CustomDNSPolicy + asserts: + - failedTemplate: + errorMessage: | + values don't meet the specifications of the schema(s) in the following chart(s): + cluster-shield: + - dnsPolicy: dnsPolicy must be one of the following: null, "ClusterFirst", "ClusterFirstWithHostNet", "Default", "None" diff --git a/charts/cluster-shield/tests/validatingwebhookconfiguration_test.yaml b/charts/cluster-shield/tests/validatingwebhookconfiguration_test.yaml index 7e294edf8..6023c551b 100644 --- a/charts/cluster-shield/tests/validatingwebhookconfiguration_test.yaml +++ b/charts/cluster-shield/tests/validatingwebhookconfiguration_test.yaml @@ -31,7 +31,13 @@ tests: asserts: - hasDocuments: count: 2 - - isNotNull: + - containsDocument: + kind: ValidatingWebhookConfiguration + apiVersion: admissionregistration.k8s.io/v1 + name: shield-release-cluster-shield-audit + - notExists: + path: metadata.namespace + - exists: path: .webhooks[?(@.name == "vac.secure.sysdig.com")] - equal: path: .webhooks[?(@.name == "vac.secure.sysdig.com")].failurePolicy @@ -65,7 +71,13 @@ tests: asserts: - hasDocuments: count: 2 - - isNotNull: + - containsDocument: + kind: ValidatingWebhookConfiguration + apiVersion: admissionregistration.k8s.io/v1 + name: shield-release-cluster-shield-audit + - notExists: + path: metadata.namespace + - exists: path: .webhooks[?(@.name == "vac.secure.sysdig.com")] - equal: path: .webhooks[?(@.name == "vac.secure.sysdig.com")].failurePolicy @@ -95,7 +107,11 @@ tests: asserts: - hasDocuments: count: 2 - - isNotNull: + - containsDocument: + kind: ValidatingWebhookConfiguration + apiVersion: admissionregistration.k8s.io/v1 + name: shield-release-cluster-shield-audit + - exists: path: .webhooks[?(@.name == "audit.secure.sysdig.com")] - equal: path: .webhooks[?(@.name == "audit.secure.sysdig.com")].clientConfig.service.namespace @@ -130,9 +146,13 @@ tests: asserts: - hasDocuments: count: 2 - - isNotNull: + - containsDocument: + kind: ValidatingWebhookConfiguration + apiVersion: admissionregistration.k8s.io/v1 + name: shield-release-cluster-shield-audit + - exists: path: .webhooks[?(@.name == "vac.secure.sysdig.com")] - - isNotNull: + - exists: path: .webhooks[?(@.name == "audit.secure.sysdig.com")] - equal: path: .webhooks[?(@.name == "vac.secure.sysdig.com")].clientConfig.service.namespace @@ -186,9 +206,9 @@ tests: asserts: - hasDocuments: count: 2 - - isNotNull: + - exists: path: .webhooks[?(@.name == "vac.secure.sysdig.com")] - - isNotNull: + - exists: path: .webhooks[?(@.name == "audit.secure.sysdig.com")] - equal: path: .webhooks[?(@.name == "vac.secure.sysdig.com")].clientConfig.service.namespace @@ -229,9 +249,13 @@ tests: asserts: - hasDocuments: count: 2 - - isNotNull: + - containsDocument: + kind: ValidatingWebhookConfiguration + apiVersion: admissionregistration.k8s.io/v1 + name: shield-release-cluster-shield-audit + - exists: path: .webhooks[?(@.name == "vac.secure.sysdig.com")] - - isNotNull: + - exists: path: .webhooks[?(@.name == "audit.secure.sysdig.com")] - equal: path: .webhooks[?(@.name == "vac.secure.sysdig.com")].clientConfig.service.namespace @@ -274,9 +298,38 @@ tests: kind: Secret apiVersion: v1 name: sysdig-cluster-shield-tls-certs - - isNotNull: + - isNotNullOrEmpty: + path: data["tls.crt"] + - isNotNullOrEmpty: + path: data["tls.key"] + - isNotNullOrEmpty: + path: data["ca.crt"] + + - it: Does create only the TLS secret if admission control and audit features are disabled but container_vulnerability_management is enabled + set: + cluster_shield: + features: + container_vulnerability_management: + enabled: true + admission_control: + enabled: false + audit: + enabled: false + asserts: + - hasDocuments: + count: 1 + - containsDocument: + kind: Secret + apiVersion: v1 + name: sysdig-cluster-shield-tls-certs + - containsDocument: + kind: ValidatingWebhookConfiguration + apiVersion: admissionregistration.k8s.io/v1 + name: shield-release-cluster-shield-audit + not: true + - isNotNullOrEmpty: path: data["tls.crt"] - - isNotNull: + - isNotNullOrEmpty: path: data["tls.key"] - - isNotNull: + - isNotNullOrEmpty: path: data["ca.crt"] diff --git a/charts/cluster-shield/values.schema.json b/charts/cluster-shield/values.schema.json index 786a596b9..4b067f769 100644 --- a/charts/cluster-shield/values.schema.json +++ b/charts/cluster-shield/values.schema.json @@ -61,6 +61,7 @@ "eu-gb-private-secure", "eu-gb-secure", "eu1", + "in1", "jp-osa-monitor", "jp-osa-private-monitor", "jp-osa-private-secure", @@ -172,6 +173,21 @@ }, "cluster_shield": { "$ref": "#/$defs/ClusterShieldConfiguration" + }, + "dnsPolicy": { + "type": [ + "null", + "string" + ], + "description": "Define Cluster Shield Pods DNS Policy", + "default": null, + "enum": [ + null, + "ClusterFirst", + "ClusterFirstWithHostNet", + "Default", + "None" + ] } }, "allOf": [ @@ -417,32 +433,6 @@ "description": "Kubernetes configurations" } }, - "allOf": [ - { - "description": "Sets sysdig_endpoint required properties based on features configuration.", - "if": { - "properties": { - "sysdig_endpoint": { - "$ref": "#/$defs/ClusterShieldConfiguration/$defs/SysdigEndpoint/$defs/IsCustomRegion" - }, - "features": { - "properties": { - "kubernetes_metadata": { - "$ref": "#/$defs/ClusterShieldConfiguration/$defs/KubernetesMetadata/$defs/IsEnabled" - } - } - } - } - }, - "then": { - "properties": { - "sysdig_endpoint": { - "$ref": "#/$defs/ClusterShieldConfiguration/$defs/SysdigEndpoint/$defs/SetCollectorRequired" - } - } - } - } - ], "$defs": { "Audit": { "type": "object", @@ -576,6 +566,7 @@ "eu-gb-private-secure", "eu-gb-secure", "eu1", + "in1", "jp-osa-monitor", "jp-osa-private-monitor", "jp-osa-private-secure", @@ -658,51 +649,28 @@ "local_cluster": { "$ref": "#/$defs/ClusterShieldConfiguration/$defs/ContainerVulnerabilityManagementLocal" }, - "remote_clusters": { - "$ref": "#/$defs/ClusterShieldConfiguration/$defs/ContainerVulnerabilityManagementRemote" - } - }, - "if": { - "properties": { - "enabled": { - "const": true - } + "parallel_files_analysis_count": { + "type": "integer", + "description": "Maximum number of files that are analyzed in parallel", + "default": 5 + }, + "max_file_size_bytes": { + "type": "integer", + "description": "Maximum size in bytes for a file to be analyzed", + "default": 104857600 + }, + "max_file_size_bytes_in_memory": { + "type": "integer", + "description": "Maximum size in bytes for a file to be analyzed in memory; file whose size is bigger than this are temporarily copied on to the filesystem", + "default": 26214400 } }, - "then": { - "oneOf": [ - { - "properties": { - "local_cluster": { - "properties": { - "enabled": { - "const": true - } - } - } - } - }, - { - "properties": { - "remote_clusters": { - "properties": { - "enabled": { - "const": true - } - } - } - } - } - ] - }, "required": [ "enabled", "local_cluster", - "remote_clusters", "in_use", "registry_ssl" ], - "additionalProperties": false, "$defs": { "IsEnabled": { "properties": { @@ -736,11 +704,6 @@ "ContainerVulnerabilityManagementLocal": { "type": "object", "properties": { - "enabled": { - "type": "boolean", - "description": "Specify if should scan only the local cluster", - "default": true - }, "registry_secrets": { "type": "array", "items": { @@ -757,8 +720,7 @@ ] ] } - }, - "additionalProperties": false + } }, "ContainerVulnerabilityManagementLocalRegistrySecret": { "type": "object", @@ -779,36 +741,6 @@ ], "additionalProperties": false }, - "ContainerVulnerabilityManagementRemote": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean", - "description": "Specify if it should scan remote clusters", - "default": false - }, - "kubeconfig_path": { - "type": "string", - "description": "Path to the kubeconfig file", - "examples": [ - "/path/to/kubeconfig" - ] - } - }, - "if": { - "properties": { - "enabled": { - "const": true - } - } - }, - "then": { - "required": [ - "kubeconfig_path" - ] - }, - "additionalProperties": false - }, "Kubernetes": { "type": "object", "properties": { diff --git a/charts/cluster-shield/values.yaml b/charts/cluster-shield/values.yaml index c464d5731..bde15d407 100644 --- a/charts/cluster-shield/values.yaml +++ b/charts/cluster-shield/values.yaml @@ -115,8 +115,6 @@ cluster_shield: # Allows to store the list of running packages to Sysdig backend. integration_enabled: false local_cluster: - # Enable to scan the cluster where the cluster-shield is running. - enabled: true # Restrict access to specific Docker secrets when Cluster Scanner is running. # The default behavior is listing all secrets. registry_secrets: [] @@ -134,8 +132,6 @@ cluster_shield: # If set to false it allows insecure connections to registries, # Such as for registries with self-signed or private certificates. verify: true - remote_clusters: - enabled: false kubernetes_metadata: # Enable the Kubernetes Metadata feature enabled: false @@ -163,8 +159,10 @@ ca: # The command executed by the Cluster Shield POD run_command: "run-all-namespaced" image: + # The Sysdig Registry Scanner image registry. + registry: quay.io # The Cluster Shield container image repository - repository: quay.io/sysdig/cluster-shield + repository: sysdig/cluster-shield # The Cluster Shield container image pull policy pullPolicy: proxy: @@ -250,3 +248,9 @@ updateStrategy: # # If you are runinng on SaaS, do NOT provide this parameter. onPremCompatibilityVersion: +# Specifies if Cluster Shield should be started in hostNetwork mode. +# This field is required if you are using a custom CNI where the control plane nodes are unable to initiate +# network connections to the pods, for example, using Calico CNI plugin on EKS. +hostNetwork: false +# Define Cluster Shield Pods DNS Policy +dnsPolicy: diff --git a/charts/sysdig-deploy/Chart.yaml b/charts/sysdig-deploy/Chart.yaml index 1f9e06d92..812846bee 100644 --- a/charts/sysdig-deploy/Chart.yaml +++ b/charts/sysdig-deploy/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: sysdig-deploy description: A chart with various Sysdig components for Kubernetes type: application -version: 1.61.6 +version: 1.61.7 maintainers: - name: AlbertoBarba email: alberto.barba@sysdig.com @@ -60,6 +60,6 @@ dependencies: - name: cluster-shield # repository: https://charts.sysdig.com repository: file://../cluster-shield - version: ~1.1.2 + version: ~1.2.0 alias: clusterShield condition: clusterShield.enabled