Skip to content
2 changes: 1 addition & 1 deletion charts/k8s-reporter/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
63 changes: 62 additions & 1 deletion charts/k8s-reporter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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://<instance_name>.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 |
Expand Down
2 changes: 2 additions & 0 deletions charts/k8s-reporter/README.md.gotmpl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ title: Kubernetes Reporter Helm Chart

{{ template "extra.uninstall" . }}

{{ template "extra.customCA" . }}

{{ template "extra.valuesHeader" . }}
{{ template "chart.valuesTable" . }}

Expand Down
55 changes: 55 additions & 0 deletions charts/k8s-reporter/_templates.gotmpl
Original file line number Diff line number Diff line change
Expand Up @@ -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 }}
33 changes: 27 additions & 6 deletions charts/k8s-reporter/templates/cronjob.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Comment thread
AlexKantor87 marked this conversation as resolved.
{{- end }}
{{- with .Values.extraVolumes }}
{{- toYaml . | nindent 10 }}
{{- end }}
containers:
- name: reporter
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
Expand All @@ -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" }}
Expand All @@ -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 }}
Comment thread
AlexKantor87 marked this conversation as resolved.
{{- with .Values.extraEnvVars }}
{{- toYaml . | nindent 14 }}
{{- end }}
args:
- snapshot
- k8s
Expand Down
44 changes: 41 additions & 3 deletions charts/k8s-reporter/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,47 @@ reporterConfig:
# Omit this field for OpenShift environments to allow automatic UID assignment
runAsUser: 1000

Comment thread
AlexKantor87 marked this conversation as resolved.
# Uncomment the env variable below and replace <instance_name>, if you are on a single tenant Kosli instance
# env:
# KOSLI_HOST: https://<instance_name>.kosli.com
# -- map of plain environment variables to inject into the reporter container.
# For a single-tenant Kosli instance, set KOSLI_HOST to https://<instance_name>.kosli.com.
env: {}
Comment thread
AlexKantor87 marked this conversation as resolved.

# -- 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: {}
Expand Down
63 changes: 62 additions & 1 deletion docs.kosli.com/content/helm/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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://<instance_name>.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 |
Expand Down
Loading