diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f079a06ac..95c7d70b5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -56,6 +56,9 @@ jobs: - name: Helm lint (cloud refs values) run: helm lint ./helm-chart -f ./helm-chart/tests/fixtures/values-cloud-refs.yaml + - name: Helm lint (extra objects values) + run: helm lint ./helm-chart -f ./helm-chart/tests/fixtures/values-extra-objects.yaml + - name: Install helm-unittest plugin run: helm plugin install https://github.com/helm-unittest/helm-unittest --verify=false @@ -78,3 +81,6 @@ jobs: - name: Validate GCS template run: helm template kubeshark ./helm-chart -f ./helm-chart/tests/fixtures/values-gcs.yaml | kubeconform -strict -kubernetes-version 1.35.0 -summary + + - name: Validate extra objects template + run: helm template kubeshark ./helm-chart -f ./helm-chart/tests/fixtures/values-extra-objects.yaml | kubeconform -strict -kubernetes-version 1.35.0 -summary diff --git a/Makefile b/Makefile index 1b0df6c28..41fe09e40 100644 --- a/Makefile +++ b/Makefile @@ -146,6 +146,7 @@ helm-test-full: helm-test ## Run Helm tests with kubeconform schema validation. helm template kubeshark ./helm-chart -f ./helm-chart/tests/fixtures/values-s3.yaml | kubeconform -strict -kubernetes-version 1.35.0 -summary helm template kubeshark ./helm-chart -f ./helm-chart/tests/fixtures/values-azblob.yaml | kubeconform -strict -kubernetes-version 1.35.0 -summary helm template kubeshark ./helm-chart -f ./helm-chart/tests/fixtures/values-gcs.yaml | kubeconform -strict -kubernetes-version 1.35.0 -summary + helm template kubeshark ./helm-chart -f ./helm-chart/tests/fixtures/values-extra-objects.yaml | kubeconform -strict -kubernetes-version 1.35.0 -summary lint: ## Lint the source code. golangci-lint run diff --git a/config/configStructs/tapConfig.go b/config/configStructs/tapConfig.go index db48085fd..86d22b8ec 100644 --- a/config/configStructs/tapConfig.go +++ b/config/configStructs/tapConfig.go @@ -481,6 +481,7 @@ type TapConfig struct { SecurityContext SecurityContextConfig `yaml:"securityContext" json:"securityContext"` MountBpf bool `yaml:"mountBpf" json:"mountBpf" default:"true"` HostNetwork bool `yaml:"hostNetwork" json:"hostNetwork" default:"true"` + ExtraObjects []interface{} `yaml:"extraObjects" json:"extraObjects" default:"[]"` } func (config *TapConfig) PodRegex() *regexp.Regexp { diff --git a/helm-chart/README.md b/helm-chart/README.md index 4283ce15f..2ecd6f3b3 100644 --- a/helm-chart/README.md +++ b/helm-chart/README.md @@ -91,6 +91,51 @@ tap: alb.ingress.kubernetes.io/scheme: internet-facing ``` +## Adding your own resources + +`tap.extraObjects` renders arbitrary manifests alongside the chart's own resources, so you can add +what your cluster needs without forking the chart. Entries are rendered through the template +engine, so `.Release`, `.Values` and the chart helpers are all available. + +On OpenShift, for example, you would disable the ingress and add a `Route` instead: + +```yaml +tap: + ingress: + enabled: false + extraObjects: + # A mapping entry, templated field by field. + - apiVersion: route.openshift.io/v1 + kind: Route + metadata: + name: kubeshark-front + namespace: '{{ .Release.Namespace }}' + labels: + app.kubeshark.com/app: front + spec: + host: kubeshark.apps.example.com + to: + kind: Service + name: kubeshark-front + port: + targetPort: kubeshark-front + tls: + termination: edge + insecureEdgeTerminationPolicy: Redirect + # A raw YAML string entry, templated as a whole. + - | + apiVersion: v1 + kind: ConfigMap + metadata: + name: {{ .Release.Name }}-extra + namespace: {{ .Release.Namespace }} + data: + note: rendered by tap.extraObjects +``` + +The chart never parses these manifests, it only renders them, so anything the cluster accepts works +here, including CRDs the chart knows nothing about. + ## Disabling IPV6 Not all have IPV6 enabled, hence this has to be disabled as follows: @@ -242,6 +287,7 @@ Example for overriding image names: | `tap.enabledDissectors` | This is an array of strings representing the list of supported protocols. Remove or comment out redundant protocols (e.g., dns).| The default list excludes: `udp` and `tcp` | | `tap.mountBpf` | BPF filesystem needs to be mounted for eBPF to work properly. This helm value determines whether Kubeshark will attempt to mount the filesystem. This option is not required if filesystem is already mounts. │ `true`| | `tap.hostNetwork` | Enable host network mode for worker DaemonSet pods. When enabled, worker pods use the host's network namespace for direct network access. | `true` | +| `tap.extraObjects` | Additional manifests to render alongside the chart's own resources. Each entry is either a mapping or a raw YAML string, and both are passed through the template engine. Use it for resources the chart does not ship, such as an OpenShift `Route`. See [Adding your own resources](#adding-your-own-resources). | `[]` | | `tap.packetCapture` | Packet capture backend: `best`, `af_packet`, or `pf_ring` | `best` | | `tap.misc.trafficSampleRate` | Percentage of traffic to process (0-100) | `100` | | `tap.misc.tcpStreamChannelTimeoutMs` | Timeout in milliseconds for TCP stream channel | `10000` | diff --git a/helm-chart/templates/23-extra-objects.yaml b/helm-chart/templates/23-extra-objects.yaml new file mode 100644 index 000000000..856ca8b8b --- /dev/null +++ b/helm-chart/templates/23-extra-objects.yaml @@ -0,0 +1,8 @@ +{{- range .Values.tap.extraObjects }} +--- +{{- if kindIs "string" . }} +{{ tpl . $ }} +{{- else }} +{{ tpl (toYaml .) $ }} +{{- end }} +{{- end }} diff --git a/helm-chart/tests/extra_objects_test.yaml b/helm-chart/tests/extra_objects_test.yaml new file mode 100644 index 000000000..8b0a3ea24 --- /dev/null +++ b/helm-chart/tests/extra_objects_test.yaml @@ -0,0 +1,142 @@ +suite: extra objects template +templates: + - templates/23-extra-objects.yaml +tests: + - it: should render nothing with default values + asserts: + - hasDocuments: + count: 0 + + - it: should render a mapping entry as-is + set: + tap.extraObjects: + - apiVersion: route.openshift.io/v1 + kind: Route + metadata: + name: kubeshark-front + spec: + to: + kind: Service + name: kubeshark-front + port: + targetPort: 80 + tls: + termination: edge + asserts: + - hasDocuments: + count: 1 + - isKind: + of: Route + - equal: + path: apiVersion + value: route.openshift.io/v1 + - equal: + path: metadata.name + value: kubeshark-front + - equal: + path: spec.to.name + value: kubeshark-front + - equal: + path: spec.tls.termination + value: edge + + - it: should render a raw YAML string entry + set: + tap.extraObjects: + - | + apiVersion: v1 + kind: ConfigMap + metadata: + name: extra-config + data: + foo: bar + asserts: + - hasDocuments: + count: 1 + - isKind: + of: ConfigMap + - equal: + path: metadata.name + value: extra-config + - equal: + path: data.foo + value: bar + + - it: should render multiple entries as separate documents + set: + tap.extraObjects: + - apiVersion: v1 + kind: ConfigMap + metadata: + name: first + - | + apiVersion: v1 + kind: Secret + metadata: + name: second + asserts: + - hasDocuments: + count: 2 + - isKind: + of: ConfigMap + documentIndex: 0 + - equal: + path: metadata.name + value: first + documentIndex: 0 + - isKind: + of: Secret + documentIndex: 1 + - equal: + path: metadata.name + value: second + documentIndex: 1 + + - it: should evaluate templates inside a mapping entry + release: + name: my-release + namespace: my-namespace + set: + tap.extraObjects: + - apiVersion: v1 + kind: ConfigMap + metadata: + name: '{{ .Release.Name }}-extra' + namespace: '{{ .Release.Namespace }}' + data: + host: '{{ .Values.tap.ingress.host }}' + asserts: + - equal: + path: metadata.name + value: my-release-extra + - equal: + path: metadata.namespace + value: my-namespace + - equal: + path: data.host + value: ks.svc.cluster.local + + - it: should evaluate templates inside a raw YAML string entry + release: + name: my-release + set: + tap.extraObjects: + - | + apiVersion: v1 + kind: ConfigMap + metadata: + name: {{ .Release.Name }}-from-string + labels: + {{- include "kubeshark.labels" . | nindent 4 }} + data: + chart: {{ .Chart.Name }} + asserts: + - equal: + path: metadata.name + value: my-release-from-string + - equal: + path: metadata.labels["app.kubernetes.io/managed-by"] + value: Helm + - equal: + path: data.chart + value: kubeshark diff --git a/helm-chart/tests/fixtures/values-extra-objects.yaml b/helm-chart/tests/fixtures/values-extra-objects.yaml new file mode 100644 index 000000000..a096fa1e4 --- /dev/null +++ b/helm-chart/tests/fixtures/values-extra-objects.yaml @@ -0,0 +1,23 @@ +tap: + ingress: + enabled: false + extraObjects: + - apiVersion: v1 + kind: ConfigMap + metadata: + name: '{{ .Release.Name }}-extra-mapping' + namespace: '{{ .Release.Namespace }}' + data: + source: mapping + - | + apiVersion: v1 + kind: Service + metadata: + name: {{ .Release.Name }}-extra-string + namespace: {{ .Release.Namespace }} + spec: + selector: + app.kubeshark.com/app: front + ports: + - port: 80 + targetPort: 80 diff --git a/helm-chart/values.yaml b/helm-chart/values.yaml index ef2c03dba..da91d09dc 100644 --- a/helm-chart/values.yaml +++ b/helm-chart/values.yaml @@ -282,6 +282,7 @@ tap: - IPC_LOCK mountBpf: true hostNetwork: true + extraObjects: [] logs: file: "" grep: ""