diff --git a/charts/k8s-reporter/Chart.yaml b/charts/k8s-reporter/Chart.yaml index 8b1d76c7a..4fece5f6f 100644 --- a/charts/k8s-reporter/Chart.yaml +++ b/charts/k8s-reporter/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 2.1.0 +version: 2.2.0 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/charts/k8s-reporter/README.md b/charts/k8s-reporter/README.md index 3d2a12b63..5161b8713 100644 --- a/charts/k8s-reporter/README.md +++ b/charts/k8s-reporter/README.md @@ -4,7 +4,7 @@ title: Kubernetes Reporter Helm Chart # k8s-reporter -![Version: 2.1.0](https://img.shields.io/badge/Version-2.1.0-informational?style=flat-square) +![Version: 2.2.0](https://img.shields.io/badge/Version-2.2.0-informational?style=flat-square) A Helm chart for installing the Kosli K8S reporter as a cronjob. The chart allows you to create a Kubernetes cronjob and all its necessary RBAC to report running images to Kosli at a given cron schedule. @@ -96,11 +96,72 @@ helm upgrade kosli-reporter kosli/k8s-reporter -f values.yaml helm uninstall kosli-reporter ``` +## Running behind a TLS-inspecting proxy (corporate / custom CA bundle) + +If your network sits behind a TLS-inspecting appliance (Zscaler, Netskope, Palo Alto, etc.) that re-signs HTTPS traffic with a corporate CA certificate, the reporter will fail with `x509: certificate signed by unknown authority`. To fix this, make the appliance's CA bundle available to the reporter. + +The chart offers two ways to do this. Use whichever fits your deployment flow. + +### Option 1 — `customCA` convenience wrapper (recommended for the common case) + +1. Create a Secret containing the corporate CA certificate (PEM format, single cert or bundle): + +```shell {.command} +kubectl create secret generic corporate-ca-bundle --from-file=ca.crt=/path/to/corporate-ca.crt +``` + +2. Enable the wrapper in `values.yaml`: + +```yaml +customCA: + enabled: true + secretName: corporate-ca-bundle + key: ca.crt +``` + +The chart mounts the certificate as a single file at `/etc/ssl/certs/kosli-custom-ca.crt` using `subPath`. Go's standard library on Linux loads CA roots in two independent passes — it reads the system bundle file (e.g. `/etc/ssl/certs/ca-certificates.crt`) and **also** scans `/etc/ssl/certs/` for additional certificate files. The mounted file is picked up by the directory scan and added to the trust store alongside the system roots, so no `SSL_CERT_FILE` env var is needed. + +The wrapper deliberately does **not** set `SSL_CERT_FILE`. Setting it would replace the system bundle entirely with the customer's file, breaking trust for any public CAs the bundle does not include. + +### Option 2 — generic `extraVolumes` / `extraVolumeMounts` / `extraEnvVars` + +Use these when you need a non-default mount path, a ConfigMap instead of a Secret, multiple volumes, or any other shape the wrapper does not cover: + +```yaml +extraVolumes: + - name: corporate-ca + secret: + secretName: corporate-ca-bundle + +extraVolumeMounts: + - name: corporate-ca + mountPath: /etc/ssl/certs/corporate + readOnly: true +``` + +Note: if you mount the CA outside `/etc/ssl/certs/` and set `SSL_CERT_FILE` via `extraEnvVars`, your bundle must include the public CAs you also need to trust — Go uses only that file when `SSL_CERT_FILE` is set. + +### Pod Security Standards + +Both options use `secret`-backed volumes, which are permitted under the Pod Security Standards `restricted` profile. `hostPath` mounts are not permitted under that profile and should not be used here. + +### Cluster-wide alternative + +If you already run [cert-manager's trust-manager](https://cert-manager.io/docs/trust/trust-manager/) to distribute a corporate CA bundle into a well-known ConfigMap in every namespace, point `extraVolumes` / `extraVolumeMounts` at that ConfigMap instead of creating a per-namespace Secret. + ## Configurations | Key | Type | Default | Description | |-----|------|---------|-------------| | concurrencyPolicy | string | `"Replace"` | specifies how to treat concurrent executions of a Job that is created by this CronJob | | cronSchedule | string | `"*/5 * * * *"` | the cron schedule at which the reporter is triggered to report to Kosli | +| customCA | object | `{"enabled":false,"key":"ca.crt","secretName":""}` | convenience wrapper for mounting a corporate / custom CA bundle. See the "Running behind a TLS-inspecting proxy" section of the README for usage. | +| customCA.enabled | bool | `false` | enable mounting a corporate/custom CA bundle into the trust store | +| customCA.key | string | `"ca.crt"` | key within the Secret that holds the PEM-formatted CA certificate (single cert or multi-cert PEM bundle) | +| customCA.secretName | string | `""` | name of an existing Secret in the same namespace containing the CA bundle | +| env | object | `{}` | map of plain environment variables to inject into the reporter container. For a single-tenant Kosli instance, set KOSLI_HOST to https://.kosli.com. | +| extraEnvVars | list | `[]` | additional environment variables to inject into the reporter container. List of {name, value} or {name, valueFrom} entries, rendered verbatim into the container env. Supports plain values and valueFrom (secretKeyRef / configMapKeyRef). Note: entries here are appended after the chart's own env entries; on duplicate names the later entry wins. | +| extraVolumeMounts | list | `[]` | additional container-level volumeMounts for the reporter container. Rendered verbatim into the container spec alongside the chart's own mounts. | +| extraVolumes | list | `[]` | additional Pod-level volumes to attach to the reporter pod. Rendered verbatim into the Pod spec alongside the chart's own volumes. Use together with `extraVolumeMounts` to mount Secrets, ConfigMaps, or other volumes into the container. | | failedJobsHistoryLimit | int | `1` | specifies the number of failed finished jobs to keep | | fullnameOverride | string | `""` | overrides the fullname used for the created k8s resources. It has higher precedence than `nameOverride` | | image.pullPolicy | string | `"IfNotPresent"` | the kosli reporter image pull policy | diff --git a/charts/k8s-reporter/README.md.gotmpl b/charts/k8s-reporter/README.md.gotmpl index 71035bdec..c6c82ee37 100644 --- a/charts/k8s-reporter/README.md.gotmpl +++ b/charts/k8s-reporter/README.md.gotmpl @@ -17,6 +17,8 @@ title: Kubernetes Reporter Helm Chart {{ template "extra.uninstall" . }} +{{ template "extra.customCA" . }} + {{ template "extra.valuesHeader" . }} {{ template "chart.valuesTable" . }} diff --git a/charts/k8s-reporter/_templates.gotmpl b/charts/k8s-reporter/_templates.gotmpl index a8cd8fa04..5ce980faf 100644 --- a/charts/k8s-reporter/_templates.gotmpl +++ b/charts/k8s-reporter/_templates.gotmpl @@ -98,6 +98,61 @@ helm uninstall kosli-reporter ``` {{- end }} +{{ define "extra.customCA" -}} +## Running behind a TLS-inspecting proxy (corporate / custom CA bundle) + +If your network sits behind a TLS-inspecting appliance (Zscaler, Netskope, Palo Alto, etc.) that re-signs HTTPS traffic with a corporate CA certificate, the reporter will fail with `x509: certificate signed by unknown authority`. To fix this, make the appliance's CA bundle available to the reporter. + +The chart offers two ways to do this. Use whichever fits your deployment flow. + +### Option 1 — `customCA` convenience wrapper (recommended for the common case) + +1. Create a Secret containing the corporate CA certificate (PEM format, single cert or bundle): + +```shell {.command} +kubectl create secret generic corporate-ca-bundle --from-file=ca.crt=/path/to/corporate-ca.crt +``` + +2. Enable the wrapper in `values.yaml`: + +```yaml +customCA: + enabled: true + secretName: corporate-ca-bundle + key: ca.crt +``` + +The chart mounts the certificate as a single file at `/etc/ssl/certs/kosli-custom-ca.crt` using `subPath`. Go's standard library on Linux loads CA roots in two independent passes — it reads the system bundle file (e.g. `/etc/ssl/certs/ca-certificates.crt`) and **also** scans `/etc/ssl/certs/` for additional certificate files. The mounted file is picked up by the directory scan and added to the trust store alongside the system roots, so no `SSL_CERT_FILE` env var is needed. + +The wrapper deliberately does **not** set `SSL_CERT_FILE`. Setting it would replace the system bundle entirely with the customer's file, breaking trust for any public CAs the bundle does not include. + +### Option 2 — generic `extraVolumes` / `extraVolumeMounts` / `extraEnvVars` + +Use these when you need a non-default mount path, a ConfigMap instead of a Secret, multiple volumes, or any other shape the wrapper does not cover: + +```yaml +extraVolumes: + - name: corporate-ca + secret: + secretName: corporate-ca-bundle + +extraVolumeMounts: + - name: corporate-ca + mountPath: /etc/ssl/certs/corporate + readOnly: true +``` + +Note: if you mount the CA outside `/etc/ssl/certs/` and set `SSL_CERT_FILE` via `extraEnvVars`, your bundle must include the public CAs you also need to trust — Go uses only that file when `SSL_CERT_FILE` is set. + +### Pod Security Standards + +Both options use `secret`-backed volumes, which are permitted under the Pod Security Standards `restricted` profile. `hostPath` mounts are not permitted under that profile and should not be used here. + +### Cluster-wide alternative + +If you already run [cert-manager's trust-manager](https://cert-manager.io/docs/trust/trust-manager/) to distribute a corporate CA bundle into a well-known ConfigMap in every namespace, point `extraVolumes` / `extraVolumeMounts` at that ConfigMap instead of creating a per-namespace Secret. +{{- end }} + {{ define "extra.valuesHeader" -}} ## Configurations {{- end }} diff --git a/charts/k8s-reporter/templates/cronjob.yaml b/charts/k8s-reporter/templates/cronjob.yaml index a3fc7bb9f..b54f6e7be 100644 --- a/charts/k8s-reporter/templates/cronjob.yaml +++ b/charts/k8s-reporter/templates/cronjob.yaml @@ -18,15 +18,24 @@ spec: template: metadata: labels: - {{- range $key, $value := .Values.podLabels }} - {{ $key }}: {{ $value }} - {{ end }} + {{- range $key, $value := .Values.podLabels }} + {{ $key }}: {{ $value | quote }} + {{- end }} spec: serviceAccountName: {{ include "reporter.serviceAccountName" . }} volumes: - name: environments-config configMap: name: {{ include "reporter.fullname" . }}-environments-config + {{- if .Values.customCA.enabled }} + - name: custom-ca + secret: + secretName: {{ required "customCA.secretName is required when customCA.enabled is true" .Values.customCA.secretName | quote }} + defaultMode: 0644 + {{- end }} + {{- with .Values.extraVolumes }} + {{- toYaml . | nindent 10 }} + {{- end }} containers: - name: reporter image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" @@ -35,6 +44,15 @@ spec: - name: environments-config mountPath: /config readOnly: true + {{- if .Values.customCA.enabled }} + - name: custom-ca + mountPath: /etc/ssl/certs/kosli-custom-ca.crt + subPath: {{ required "customCA.key is required when customCA.enabled is true" .Values.customCA.key | quote }} + readOnly: true + {{- end }} + {{- with .Values.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} {{- if .Values.reporterConfig.securityContext }} securityContext: {{- if hasKey .Values.reporterConfig.securityContext "allowPrivilegeEscalation" }} @@ -61,10 +79,13 @@ spec: secretKeyRef: name: {{ required ".Values.kosliApiToken.secretName is required." .Values.kosliApiToken.secretName }} key: {{ .Values.kosliApiToken.secretKey | default "token" }} - {{- range $key, $value := .Values.env }} + {{- range $key, $value := .Values.env }} - name: {{ $key }} - value: {{ $value }} - {{ end }} + value: {{ $value | quote }} + {{- end }} + {{- with .Values.extraEnvVars }} + {{- toYaml . | nindent 14 }} + {{- end }} args: - snapshot - k8s diff --git a/charts/k8s-reporter/values.yaml b/charts/k8s-reporter/values.yaml index ca1742e82..a13f74495 100644 --- a/charts/k8s-reporter/values.yaml +++ b/charts/k8s-reporter/values.yaml @@ -82,9 +82,47 @@ reporterConfig: # Omit this field for OpenShift environments to allow automatic UID assignment runAsUser: 1000 -# Uncomment the env variable below and replace , if you are on a single tenant Kosli instance -# env: -# KOSLI_HOST: https://.kosli.com +# -- map of plain environment variables to inject into the reporter container. +# For a single-tenant Kosli instance, set KOSLI_HOST to https://.kosli.com. +env: {} + +# -- additional environment variables to inject into the reporter container. +# List of {name, value} or {name, valueFrom} entries, rendered verbatim into the container env. +# Supports plain values and valueFrom (secretKeyRef / configMapKeyRef). +# Note: entries here are appended after the chart's own env entries; on duplicate names the later entry wins. +extraEnvVars: [] + # - name: HTTPS_PROXY + # value: http://proxy.corp:8080 + # - name: MY_SECRET + # valueFrom: + # secretKeyRef: + # name: my-secret + # key: token + +# -- additional Pod-level volumes to attach to the reporter pod. +# Rendered verbatim into the Pod spec alongside the chart's own volumes. +# Use together with `extraVolumeMounts` to mount Secrets, ConfigMaps, or other volumes into the container. +extraVolumes: [] + # - name: corporate-ca + # secret: + # secretName: corporate-ca-bundle + +# -- additional container-level volumeMounts for the reporter container. +# Rendered verbatim into the container spec alongside the chart's own mounts. +extraVolumeMounts: [] + # - name: corporate-ca + # mountPath: /etc/ssl/certs/corporate + # readOnly: true + +# -- convenience wrapper for mounting a corporate / custom CA bundle. See the +# "Running behind a TLS-inspecting proxy" section of the README for usage. +customCA: + # -- enable mounting a corporate/custom CA bundle into the trust store + enabled: false + # -- name of an existing Secret in the same namespace containing the CA bundle + secretName: "" + # -- key within the Secret that holds the PEM-formatted CA certificate (single cert or multi-cert PEM bundle) + key: "ca.crt" # -- any custom annotations to be added to the cronjob podAnnotations: {} diff --git a/docs.kosli.com/content/helm/_index.md b/docs.kosli.com/content/helm/_index.md index 3d2a12b63..5161b8713 100644 --- a/docs.kosli.com/content/helm/_index.md +++ b/docs.kosli.com/content/helm/_index.md @@ -4,7 +4,7 @@ title: Kubernetes Reporter Helm Chart # k8s-reporter -![Version: 2.1.0](https://img.shields.io/badge/Version-2.1.0-informational?style=flat-square) +![Version: 2.2.0](https://img.shields.io/badge/Version-2.2.0-informational?style=flat-square) A Helm chart for installing the Kosli K8S reporter as a cronjob. The chart allows you to create a Kubernetes cronjob and all its necessary RBAC to report running images to Kosli at a given cron schedule. @@ -96,11 +96,72 @@ helm upgrade kosli-reporter kosli/k8s-reporter -f values.yaml helm uninstall kosli-reporter ``` +## Running behind a TLS-inspecting proxy (corporate / custom CA bundle) + +If your network sits behind a TLS-inspecting appliance (Zscaler, Netskope, Palo Alto, etc.) that re-signs HTTPS traffic with a corporate CA certificate, the reporter will fail with `x509: certificate signed by unknown authority`. To fix this, make the appliance's CA bundle available to the reporter. + +The chart offers two ways to do this. Use whichever fits your deployment flow. + +### Option 1 — `customCA` convenience wrapper (recommended for the common case) + +1. Create a Secret containing the corporate CA certificate (PEM format, single cert or bundle): + +```shell {.command} +kubectl create secret generic corporate-ca-bundle --from-file=ca.crt=/path/to/corporate-ca.crt +``` + +2. Enable the wrapper in `values.yaml`: + +```yaml +customCA: + enabled: true + secretName: corporate-ca-bundle + key: ca.crt +``` + +The chart mounts the certificate as a single file at `/etc/ssl/certs/kosli-custom-ca.crt` using `subPath`. Go's standard library on Linux loads CA roots in two independent passes — it reads the system bundle file (e.g. `/etc/ssl/certs/ca-certificates.crt`) and **also** scans `/etc/ssl/certs/` for additional certificate files. The mounted file is picked up by the directory scan and added to the trust store alongside the system roots, so no `SSL_CERT_FILE` env var is needed. + +The wrapper deliberately does **not** set `SSL_CERT_FILE`. Setting it would replace the system bundle entirely with the customer's file, breaking trust for any public CAs the bundle does not include. + +### Option 2 — generic `extraVolumes` / `extraVolumeMounts` / `extraEnvVars` + +Use these when you need a non-default mount path, a ConfigMap instead of a Secret, multiple volumes, or any other shape the wrapper does not cover: + +```yaml +extraVolumes: + - name: corporate-ca + secret: + secretName: corporate-ca-bundle + +extraVolumeMounts: + - name: corporate-ca + mountPath: /etc/ssl/certs/corporate + readOnly: true +``` + +Note: if you mount the CA outside `/etc/ssl/certs/` and set `SSL_CERT_FILE` via `extraEnvVars`, your bundle must include the public CAs you also need to trust — Go uses only that file when `SSL_CERT_FILE` is set. + +### Pod Security Standards + +Both options use `secret`-backed volumes, which are permitted under the Pod Security Standards `restricted` profile. `hostPath` mounts are not permitted under that profile and should not be used here. + +### Cluster-wide alternative + +If you already run [cert-manager's trust-manager](https://cert-manager.io/docs/trust/trust-manager/) to distribute a corporate CA bundle into a well-known ConfigMap in every namespace, point `extraVolumes` / `extraVolumeMounts` at that ConfigMap instead of creating a per-namespace Secret. + ## Configurations | Key | Type | Default | Description | |-----|------|---------|-------------| | concurrencyPolicy | string | `"Replace"` | specifies how to treat concurrent executions of a Job that is created by this CronJob | | cronSchedule | string | `"*/5 * * * *"` | the cron schedule at which the reporter is triggered to report to Kosli | +| customCA | object | `{"enabled":false,"key":"ca.crt","secretName":""}` | convenience wrapper for mounting a corporate / custom CA bundle. See the "Running behind a TLS-inspecting proxy" section of the README for usage. | +| customCA.enabled | bool | `false` | enable mounting a corporate/custom CA bundle into the trust store | +| customCA.key | string | `"ca.crt"` | key within the Secret that holds the PEM-formatted CA certificate (single cert or multi-cert PEM bundle) | +| customCA.secretName | string | `""` | name of an existing Secret in the same namespace containing the CA bundle | +| env | object | `{}` | map of plain environment variables to inject into the reporter container. For a single-tenant Kosli instance, set KOSLI_HOST to https://.kosli.com. | +| extraEnvVars | list | `[]` | additional environment variables to inject into the reporter container. List of {name, value} or {name, valueFrom} entries, rendered verbatim into the container env. Supports plain values and valueFrom (secretKeyRef / configMapKeyRef). Note: entries here are appended after the chart's own env entries; on duplicate names the later entry wins. | +| extraVolumeMounts | list | `[]` | additional container-level volumeMounts for the reporter container. Rendered verbatim into the container spec alongside the chart's own mounts. | +| extraVolumes | list | `[]` | additional Pod-level volumes to attach to the reporter pod. Rendered verbatim into the Pod spec alongside the chart's own volumes. Use together with `extraVolumeMounts` to mount Secrets, ConfigMaps, or other volumes into the container. | | failedJobsHistoryLimit | int | `1` | specifies the number of failed finished jobs to keep | | fullnameOverride | string | `""` | overrides the fullname used for the created k8s resources. It has higher precedence than `nameOverride` | | image.pullPolicy | string | `"IfNotPresent"` | the kosli reporter image pull policy |