From bbe87f531766995bd4da8d9bc3fd3343a94e3e14 Mon Sep 17 00:00:00 2001 From: Volodymyr Stoiko Date: Thu, 27 Aug 2026 12:33:32 +0300 Subject: [PATCH] chart: drop demoModeEnabled in favour of auth.defaultRole The demo is now a configuration of the knobs every deployment has rather than a mode of its own: tap.auth.enabled false so nobody logs in, and tap.auth.defaultRole kubeshark-viewer so an unidentified caller may only read. The Hub enforces that role on REST, MCP and Connect-RPC alike, so the keys this flag used to render are redundant with it. Scripting is the exception, because "may this caller run scripts" is not a capability anyone holds. It stays a deployment-wide switch and now follows scripting.enabled, the value that already decides whether scripting exists for an install. Until now a default install hid the scripting UI while the /scripts API kept answering. DISSECTION_CONTROL_ENABLED goes rather than losing its demo term: with the flag gone both branches of that expression render true. The suites in tests/ carry the reasoning, since nothing named demo survives in the templates for a reader to follow. --- config/configStruct.go | 1 - helm-chart/templates/06-front-deployment.yaml | 20 +---- helm-chart/templates/12-config-map.yaml | 13 +-- helm-chart/tests/auth_gating_test.yaml | 24 +----- helm-chart/tests/demo_posture_test.yaml | 80 +++++++++++++++++++ helm-chart/tests/worker_hub_token_test.yaml | 3 +- helm-chart/values.yaml | 1 - 7 files changed, 86 insertions(+), 56 deletions(-) create mode 100644 helm-chart/tests/demo_posture_test.yaml diff --git a/config/configStruct.go b/config/configStruct.go index 76a86957c..02fc51335 100644 --- a/config/configStruct.go +++ b/config/configStruct.go @@ -177,7 +177,6 @@ type ConfigStruct struct { License string `yaml:"license" json:"license" default:""` CloudApiUrl string `yaml:"cloudApiUrl" json:"cloudApiUrl" default:"https://api.kubeshark.com"` CloudLicenseEnabled bool `yaml:"cloudLicenseEnabled" json:"cloudLicenseEnabled" default:"true"` - DemoModeEnabled bool `yaml:"demoModeEnabled" json:"demoModeEnabled" default:"false"` SupportChatEnabled bool `yaml:"supportChatEnabled" json:"supportChatEnabled" default:"false"` BetaEnabled bool `yaml:"betaEnabled" json:"betaEnabled" default:"false"` InternetConnectivity bool `yaml:"internetConnectivity" json:"internetConnectivity" default:"true"` diff --git a/helm-chart/templates/06-front-deployment.yaml b/helm-chart/templates/06-front-deployment.yaml index a8d29a384..4b434b4b2 100644 --- a/helm-chart/templates/06-front-deployment.yaml +++ b/helm-chart/templates/06-front-deployment.yaml @@ -47,23 +47,11 @@ spec: false {{- end }}' - name: REACT_APP_SCRIPTING_DISABLED - value: '{{ default false .Values.demoModeEnabled }}' - - name: REACT_APP_TARGETED_PODS_UPDATE_DISABLED - value: '{{ default false .Values.demoModeEnabled }}' - - name: REACT_APP_PRESET_FILTERS_CHANGING_ENABLED - value: '{{ not (default false .Values.demoModeEnabled) }}' + value: '{{ not (default false ((.Values.scripting).enabled)) }}' - name: REACT_APP_BPF_OVERRIDE_DISABLED value: '{{ eq .Values.tap.packetCapture "af_packet" | ternary "false" "true" }}' - - name: REACT_APP_RECORDING_DISABLED - value: '{{ default false .Values.demoModeEnabled }}' - name: REACT_APP_DISSECTION_ENABLED value: '{{ .Values.tap.capture.dissection.enabled | ternary "true" "false" }}' - - name: REACT_APP_DISSECTION_CONTROL_ENABLED - value: '{{- if and (not .Values.demoModeEnabled) (not .Values.tap.capture.dissection.enabled) -}} - true - {{- else -}} - {{ (default false .Values.demoModeEnabled) | ternary false true }} - {{- end -}}' - name: 'REACT_APP_CLOUD_LICENSE_ENABLED' value: '{{- if or (and .Values.cloudLicenseEnabled (not (empty .Values.license))) (not .Values.internetConnectivity) -}} false @@ -74,12 +62,6 @@ spec: value: '{{ and .Values.supportChatEnabled .Values.internetConnectivity | ternary "true" "false" }}' - name: REACT_APP_BETA_ENABLED value: '{{ default false .Values.betaEnabled | ternary "true" "false" }}' - - name: REACT_APP_DISSECTORS_UPDATING_ENABLED - value: '{{ not (default false .Values.demoModeEnabled) }}' - - name: REACT_APP_SNAPSHOTS_UPDATING_ENABLED - value: '{{ not (default false .Values.demoModeEnabled) }}' - - name: REACT_APP_DEMO_MODE_ENABLED - value: '{{ default false .Values.demoModeEnabled }}' - name: REACT_APP_CLUSTER_WIDE_MAP_ENABLED value: '{{ default false (((.Values).tap).dashboard).clusterWideMapEnabled }}' - name: REACT_APP_RAW_CAPTURE_ENABLED diff --git a/helm-chart/templates/12-config-map.yaml b/helm-chart/templates/12-config-map.yaml index 21fe8039a..0ade315f6 100644 --- a/helm-chart/templates/12-config-map.yaml +++ b/helm-chart/templates/12-config-map.yaml @@ -40,15 +40,7 @@ data: false {{- end }}' TELEMETRY_DISABLED: '{{ not .Values.internetConnectivity | ternary "true" (not .Values.tap.telemetry.enabled | ternary "true" "false") }}' - SCRIPTING_DISABLED: '{{ default false .Values.demoModeEnabled }}' - TARGETED_PODS_UPDATE_DISABLED: '{{ default false .Values.demoModeEnabled }}' - PRESET_FILTERS_CHANGING_ENABLED: '{{ not (default false .Values.demoModeEnabled) }}' - RECORDING_DISABLED: '{{ (default false .Values.demoModeEnabled) | ternary true false }}' - DISSECTION_CONTROL_ENABLED: '{{- if and (not .Values.demoModeEnabled) (not .Values.tap.capture.dissection.enabled) -}} - true - {{- else -}} - {{ (default false .Values.demoModeEnabled) | ternary false true }} - {{- end }}' + SCRIPTING_DISABLED: '{{ not (default false ((.Values.scripting).enabled)) }}' GLOBAL_FILTER: {{ include "kubeshark.escapeDoubleQuotes" .Values.tap.globalFilter | quote }} DEFAULT_FILTER: {{ include "kubeshark.escapeDoubleQuotes" .Values.tap.defaultFilter | quote }} TRAFFIC_SAMPLE_RATE: '{{ .Values.tap.misc.trafficSampleRate }}' @@ -64,9 +56,6 @@ data: DUPLICATE_TIMEFRAME: '{{ .Values.tap.misc.duplicateTimeframe }}' ENABLED_DISSECTORS: '{{ gt (len .Values.tap.enabledDissectors) 0 | ternary (join "," .Values.tap.enabledDissectors) "" }}' CUSTOM_MACROS: '{{ toJson .Values.tap.customMacros }}' - DISSECTORS_UPDATING_ENABLED: '{{ not (default false .Values.demoModeEnabled) }}' - SNAPSHOTS_UPDATING_ENABLED: '{{ not (default false .Values.demoModeEnabled) }}' - DEMO_MODE_ENABLED: '{{ default false .Values.demoModeEnabled }}' DETECT_DUPLICATES: '{{ .Values.tap.misc.detectDuplicates | ternary "true" "false" }}' PCAP_DUMP_ENABLE: '{{ .Values.pcapdump.enabled }}' PCAP_TIME_INTERVAL: '{{ .Values.pcapdump.timeInterval }}' diff --git a/helm-chart/tests/auth_gating_test.yaml b/helm-chart/tests/auth_gating_test.yaml index 5b6588d62..aaaeccc3c 100644 --- a/helm-chart/tests/auth_gating_test.yaml +++ b/helm-chart/tests/auth_gating_test.yaml @@ -6,7 +6,7 @@ ## * Is the API gated? -> tap.auth.enabled ## * Does the dashboard need a login -> cloudLicenseEnabled + license + ## to fetch a licence key? internetConnectivity (front only) -## * Which features exist at all? -> demoModeEnabled +## * What may an unidentified caller do? -> tap.auth.defaultRole ## ## These tests pin each answer to its own input, so a future change that ## reconnects them fails here rather than in someone's cluster. @@ -71,19 +71,11 @@ tests: path: data.AUTH_TYPE value: saml - - it: is not turned on by demo mode - set: - demoModeEnabled: true - asserts: - - equal: - path: data.AUTH_ENABLED - value: "false" - ## AUTH_TYPE is the operator's choice, verbatim. ## ## It used to be rewritten to "default" whenever cloud licensing was on and - ## the type was not oidc/dex, and unconditionally under demo mode. An - ## operator's `saml` therefore became something else on a live cluster. + ## the type was not oidc/dex. An operator's `saml` therefore became + ## something else on a live cluster. - it: passes the configured auth type through unchanged set: @@ -106,16 +98,6 @@ tests: path: data.AUTH_TYPE value: oidc - - it: does not rewrite the auth type under demo mode - set: - demoModeEnabled: true - tap.auth.enabled: true - tap.auth.type: descope - asserts: - - equal: - path: data.AUTH_TYPE - value: descope - ## AUTH_DEFAULT_ROLE decides what a caller with no recognized group may do, ## including a caller on a deployment with no authentication at all. Its ## default is admin, so an ungated install behaves as it always has; a diff --git a/helm-chart/tests/demo_posture_test.yaml b/helm-chart/tests/demo_posture_test.yaml new file mode 100644 index 000000000..5bee23565 --- /dev/null +++ b/helm-chart/tests/demo_posture_test.yaml @@ -0,0 +1,80 @@ +suite: demo posture +templates: + - templates/12-config-map.yaml + +## The demo used to be a product mode: `demoModeEnabled: true` fanned out into +## eight ConfigMap keys, and the Hub read each one to decide whether a route +## answered or returned 409. Every one of those restrictions that is really a +## question of "what may this caller do" is now answered by the role instead, +## so the demo is a configuration of the same knobs every other deployment has: +## +## tap.auth.enabled: false -> no identity, nobody logs in +## tap.auth.defaultRole: viewer -> and an unidentified caller may only read +## +## These tests exist because that equivalence is invisible in the templates: +## nothing named "demo" remains to read, so only a test can state that the +## keys are gone and that no value brings them back. + +tests: + - it: renders none of the keys the demo flag used to fan out into + asserts: + - notExists: + path: data.DEMO_MODE_ENABLED + - notExists: + path: data.TARGETED_PODS_UPDATE_DISABLED + - notExists: + path: data.PRESET_FILTERS_CHANGING_ENABLED + - notExists: + path: data.RECORDING_DISABLED + - notExists: + path: data.DISSECTION_CONTROL_ENABLED + - notExists: + path: data.DISSECTORS_UPDATING_ENABLED + - notExists: + path: data.SNAPSHOTS_UPDATING_ENABLED + + ## demoModeEnabled is not a value any more. Helm accepts unknown --set keys + ## silently, so an operator carrying the old line in their values file gets + ## no error; what they must not get is the old behaviour reappearing. + - it: ignores a leftover demoModeEnabled in an operator's values + set: + demoModeEnabled: true + asserts: + - notExists: + path: data.DEMO_MODE_ENABLED + - equal: + path: data.AUTH_ENABLED + value: "false" + + ## The demo posture itself. Nothing here is demo-specific; it is the same + ## pair of values any read-only deployment would set. + - it: renders the demo as an ungated deployment pinned to viewer + set: + tap.auth.enabled: false + tap.auth.defaultRole: kubeshark-viewer + asserts: + - equal: + path: data.AUTH_ENABLED + value: "false" + - equal: + path: data.AUTH_DEFAULT_ROLE + value: kubeshark-viewer + + ## Scripting is the one restriction that is not a capability. It stays a + ## deployment-wide switch, but it now follows the value that already decides + ## whether scripting exists for this install rather than riding on the demo + ## flag. Before this, a default install hid the scripting UI while leaving + ## the /scripts API answering. + - it: disables the scripting API when scripting is not enabled + asserts: + - equal: + path: data.SCRIPTING_DISABLED + value: "true" + + - it: enables the scripting API when scripting is enabled + set: + scripting.enabled: true + asserts: + - equal: + path: data.SCRIPTING_DISABLED + value: "false" diff --git a/helm-chart/tests/worker_hub_token_test.yaml b/helm-chart/tests/worker_hub_token_test.yaml index 628c3b627..adf1a653d 100644 --- a/helm-chart/tests/worker_hub_token_test.yaml +++ b/helm-chart/tests/worker_hub_token_test.yaml @@ -73,10 +73,9 @@ tests: # The projection is independent of everything that used to feed the old # auth expression, not just of tap.auth.enabled. - - it: projects the token regardless of licensing or demo mode + - it: projects the token regardless of licensing set: license: ABC - demoModeEnabled: true cloudLicenseEnabled: false asserts: - contains: diff --git a/helm-chart/values.yaml b/helm-chart/values.yaml index 188e42953..774458245 100644 --- a/helm-chart/values.yaml +++ b/helm-chart/values.yaml @@ -301,7 +301,6 @@ headless: false license: "" cloudApiUrl: https://api.kubeshark.com cloudLicenseEnabled: true -demoModeEnabled: false supportChatEnabled: false betaEnabled: false internetConnectivity: true