From 944580600239b1b6c4ca0b694ca0c643f96c14ce Mon Sep 17 00:00:00 2001 From: Volodymyr Stoiko Date: Mon, 18 May 2026 21:35:13 +0000 Subject: [PATCH] auth: add tap.auth.roles operator-defined role catalogue Chart-side companion to hub commit 67162b2e (Phase C of the permissions refactor). Operators can now declare named roles with their own capability set + namespace scope under tap.auth.roles; the 12-config-map renders these as AUTH_ROLES JSON for the hub to consume. - config/configStructs: AuthConfig.Roles map[string]RoleConfig with Capabilities + Namespaces; doc comments updated for groupMapping + defaultRole to reflect that user-defined names are now accepted. - config/configStruct.go: zero-value initializer for Roles so `kubeshark config` renders `roles: {}` consistently. - helm-chart/templates/12-config-map.yaml: AUTH_ROLES emits the full roles map as JSON; hub-side syncAuthRoles validates names (kubeshark-* prefix reserved) and capabilities (unknown caps warn-dropped). - helm-chart/values.yaml: regenerated. Diff is the single `roles: {}` line under tap.auth. Spot-checked the rendered ConfigMap: AUTH_ROLES: '{"payments-viewer":{"capabilities":["snapshot:read", "dissection:live"], "namespaces":"payments"}}' which is exactly the shape the hub parser expects. --- config/configStruct.go | 1 + config/configStructs/tapConfig.go | 35 +++++++++++++++++++------ helm-chart/templates/12-config-map.yaml | 1 + helm-chart/values.yaml | 1 + 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/config/configStruct.go b/config/configStruct.go index 4b07f313e..d0cfe1b00 100644 --- a/config/configStruct.go +++ b/config/configStruct.go @@ -105,6 +105,7 @@ func CreateDefaultConfig() ConfigStruct { RolesClaim: "groups", DefaultRole: "kubeshark-viewer", GroupMapping: map[string]string{}, + Roles: map[string]configStructs.RoleConfig{}, }, EnabledDissectors: []string{ "amqp", diff --git a/config/configStructs/tapConfig.go b/config/configStructs/tapConfig.go index c181ee827..d30c2af58 100644 --- a/config/configStructs/tapConfig.go +++ b/config/configStructs/tapConfig.go @@ -178,16 +178,35 @@ type AuthConfig struct { // DefaultRole is applied when the authenticated user's SSO claim has no // recognized group. Must be one of the four built-in roles // (kubeshark-admin / kubeshark-realtime / kubeshark-snapshot / - // kubeshark-viewer) or empty for strict-deny. See hub plans/ - // permissions-refactoring.md for the capability matrix per role. + // kubeshark-viewer), the name of an operator-defined role under + // `tap.auth.roles`, or empty for strict-deny. DefaultRole string `yaml:"defaultRole" json:"defaultRole"` - // GroupMapping translates SSO group names into built-in role names. - // Optional — groups whose name already matches a built-in role are - // identity-matched and don't need an entry here. Use this map when SSO - // groups are named differently from the built-in roles (e.g. an existing - // AD group "engineering-leads" that should resolve to kubeshark-admin). + // GroupMapping translates SSO group names into role names (built-in or + // operator-defined). Optional — groups whose name already matches a + // built-in role are identity-matched and don't need an entry here. + // Operator-defined role names MUST appear here to participate in + // resolution (identity-match is built-in-only). GroupMapping map[string]string `yaml:"groupMapping" json:"groupMapping"` - Saml SamlConfig `yaml:"saml" json:"saml"` + // Roles is the operator-defined role catalogue, keyed by role name. + // Each role has its own capability set + namespace scope. Names with + // the `kubeshark-` prefix are reserved for built-ins and will be + // rejected at hub startup. Unknown capability strings are dropped + // with a warning; empty / "*" namespace specs mean deny-all-data and + // allow-all respectively (see hub plans/permissions-decisions.md). + Roles map[string]RoleConfig `yaml:"roles" json:"roles"` + Saml SamlConfig `yaml:"saml" json:"saml"` +} + +// RoleConfig is an operator-defined role declared under tap.auth.roles. +// Capabilities is the closed vocabulary documented in the hub project +// (snapshot:read / snapshot:write / snapshot:dissection / dissection:live / +// dissection:control / pods:target:write / settings:write); unknown +// capability strings are warn-dropped at hub startup. Namespaces is a +// comma-separated list with `*` (allow-all) and glob (`foo-*`, `*-bar`, +// `*mid*`) support; empty string means deny-all-data. +type RoleConfig struct { + Capabilities []string `yaml:"capabilities" json:"capabilities"` + Namespaces string `yaml:"namespaces" json:"namespaces"` } type IngressConfig struct { diff --git a/helm-chart/templates/12-config-map.yaml b/helm-chart/templates/12-config-map.yaml index 79a558a48..1849af543 100644 --- a/helm-chart/templates/12-config-map.yaml +++ b/helm-chart/templates/12-config-map.yaml @@ -32,6 +32,7 @@ data: AUTH_ROLES_CLAIM: '{{ .Values.tap.auth.rolesClaim }}' AUTH_DEFAULT_ROLE: '{{ default "" .Values.tap.auth.defaultRole }}' AUTH_GROUP_MAPPING: '{{ default (dict) .Values.tap.auth.groupMapping | toJson }}' + AUTH_ROLES: '{{ default (dict) .Values.tap.auth.roles | toJson }}' AUTH_OIDC_ISSUER: '{{ default "not set" (((.Values.tap).auth).oidc).issuer }}' AUTH_OIDC_REFRESH_TOKEN_LIFETIME: '{{ default "3960h" (((.Values.tap).auth).oidc).refreshTokenLifetime }}' AUTH_OIDC_STATE_PARAM_EXPIRY: '{{ default "10m" (((.Values.tap).auth).oidc).oauth2StateParamExpiry }}' diff --git a/helm-chart/values.yaml b/helm-chart/values.yaml index 586424ab4..e0df98612 100644 --- a/helm-chart/values.yaml +++ b/helm-chart/values.yaml @@ -156,6 +156,7 @@ tap: rolesClaim: groups defaultRole: kubeshark-viewer groupMapping: {} + roles: {} saml: idpMetadataUrl: "" x509crt: ""