Skip to content

rebac-authz-webhook

Purpose

rebac-authz-webhook connects kcp authorization requests to the relationship-based authorization data Platform Mesh keeps in OpenFGA. It is installed as a Kubernetes authorization webhook and answers SubjectAccessReview requests for kcp logical clusters.

It is the runtime bridge between the Kubernetes authorization path and the Platform Mesh permission model. Users and service accounts still authenticate through kcp and the identity stack; the webhook contributes authorization decisions based on the OpenFGA stores and tuples maintained by the Security operator.

WARNING

This component is in alpha. APIs, request handling, and deployment wiring may change on short notice, including breaking changes.

Runtime role

At runtime kcp calls this webhook from its authorization chain. The process runs the serve command, builds a kcp-aware multicluster manager, and serves an HTTPS endpoint at /authz.

The webhook:

  1. Receives Kubernetes SubjectAccessReview requests from kcp.
  2. Identifies the target logical cluster from the request attributes.
  3. Looks up workspace and organization context through kcp.
  4. Evaluates permissions against the relevant OpenFGA store.
  5. Returns an authorization response to kcp.

The webhook does not create workspaces, users, realms, OpenFGA stores, or authorization models. Those resources are prepared by other Platform Mesh components, especially the Account operator and Security operator.

rebac-authz-webhook does not own any CRDs. At runtime it reads LogicalCluster (core.kcp.io) and Store (core.platform-mesh.io) resources from kcp, and discovers virtual workspace URLs through APIExportEndpointSlice.

How it fits into Platform Mesh

Platform Mesh separates the responsibilities for identity, tenancy, policy storage, and request-time authorization:

ComponentRole
Account operatorCreates the account workspace structure in kcp.
Security operatorCreates OpenFGA stores, authorization models, tuples, and identity configuration.
OpenFGAStores and evaluates relationship-based authorization data.
kcpReceives Kubernetes API requests and calls the authorization webhook.
rebac-authz-webhookTranslates kcp authorization reviews into OpenFGA checks.

Upstream concepts and dependencies

rebac-authz-webhook depends on these Kubernetes and kcp concepts:

ConceptPlatform Mesh pageRole here
Kubernetes webhook authorizationNoneThe HTTPS webhook protocol used by kcp to call /authz.
SubjectAccessReviewNoneRequest and response object sent between kcp and the webhook.
Kubernetes RBACNoneUsed for the management-cluster ClusterRole listed under RBAC and permissions.
kcp workspaces and logical clusterskcp workspacesEach kcp workspace is a logical cluster; the webhook reads LogicalCluster to identify the request's workspace.
kcp APIExport / APIExportEndpointSliceAPI sharingUsed at startup to discover virtual-workspace URLs for per-shard access.
kcp virtual workspacesVirtual workspacesPer-export endpoints the webhook uses to read kcp resources.
multicluster-runtime + kcp-dev/multicluster-providermulti-cluster-runtimeProvide the multicluster manager used to watch kcp logical clusters.
kcp-operatorkcp-operatorReconciles RootShard and Shard CRs into running kcp shards, including the spec.authorization.webhook configuration that points kcp at this webhook.
OpenFGAOpenFGAThe relationship-based authorization engine the webhook delegates Check calls to.

Authorization model

The webhook accepts JSON authorization.k8s.io/v1 and v1beta1 SubjectAccessReview requests and returns the matching SubjectAccessReview response. Platform Mesh's kcp AuthorizationConfiguration requests subjectAccessReviewVersion: v1 (see kcp identity and authorization).

kcp authenticates the caller before invoking the webhook and sends the resulting user in spec.user. The webhook trusts that identity and only decides whether the requested verb and resource are allowed in OpenFGA.

The authorization path has three high-level cases:

CaseWhat happens
Non-resource requestsThis branch is only relevant for clusters that call the webhook without matchConditions. In Platform Mesh's default kcp config, matchConditions: has(request.resourceAttributes) prevents non-resource SARs from reaching the webhook, and kcp's AlwaysAllowPaths authorizer runs earlier in the chain. If a cluster does send non-resource SARs to the webhook, paths with a configured prefix (default /api, /openapi, /version) return allowed: true; other non-resource paths get no opinion.
The root:orgs workspaceRequests against the parent workspace that hosts all organizations are checked against the shared OpenFGA store named orgs.
Workspaces under root:orgsRequests against an organization workspace (for example root:orgs:default) or any account workspace beneath it (for example root:orgs:default:foo) are checked against that organization's own OpenFGA store.

The webhook returns allowed: true when OpenFGA authorizes the request. Otherwise it returns allowed: false without setting denied: true ("no opinion"). In Platform Mesh, the webhook is last in the kcp authorizer chain (after RBAC and Node, see kcp identity and authorization), so a no-opinion result is effectively a deny.

Workspace context

For account workspaces the webhook keeps a per-logical-cluster cache linking the logical cluster to its organization, account, REST mapping, and OpenFGA store ID. The cache is consulted on every request to evaluate Kubernetes verbs (get, create, list, watch, update, patch, delete) against the correct OpenFGA store.

Relationship-based checks

OpenFGA stores the relationship graph for organizations, accounts, namespaces, and resources. The webhook turns the Kubernetes request into an OpenFGA check using the requesting user, the requested verb, the resource type, and the workspace context. For account workspaces, the request can also include contextual parent relationships so OpenFGA can evaluate inherited permissions.

kcp and OpenFGA integration

The webhook needs access to the root kcp API server for discovery. It reads the APIExportEndpointSlice (default core.platform-mesh.io) from the root API server; the slice enumerates one virtual-workspace URL per kcp shard. The webhook connects to those URLs and uses the multicluster manager (multicluster-runtime + kcp-dev/multicluster-provider) to partition the resulting stream by logical cluster.

The default endpoint slice name is core.platform-mesh.io. This can be overridden with --kcp-api-export-endpoint-slice-name.

Startup dependencies

rebac-authz-webhook reads the following resources at startup. If a required resource is absent, the process exits.

ResourceKindPurpose
core.platform-mesh.io (or value of --kcp-api-export-endpoint-slice-name)APIExportEndpointSliceProvides the per-shard virtual-workspace URLs the webhook connects to.
cluster in root:orgsLogicalCluster (core.kcp.io/v1alpha1)Self-object for root:orgs; anchors the workspace context cache.
Store named orgsOpenFGA storeRequired shared OpenFGA store for root:orgs.
Per-organization storesStore (core.platform-mesh.io, in root:orgs)Read by the cluster cache; status.storeId routes account-workspace checks to the right OpenFGA store.

Configuration

CLI flags

FlagDefaultDescription
--metrics-bind-address:9090Bind address for controller-runtime metrics.
--health-probe-bind-address:8090Bind address for health and readiness probes.
--openfga-addropenfga.platform-mesh-system:8081OpenFGA gRPC address.
--webhook-cert-dirconfigDirectory containing webhook serving certificates. The chart mounts the cert secret at /config, matching this flag's working directory.
--webhook-cluster-keyauthorization.kubernetes.io/cluster-nameSubjectAccessReview.spec.extra key for the target logical-cluster ID. kcp sets this; the webhook uses it to route OpenFGA checks.
--webhook-allowed-nonresource-prefixes/api, /openapi, /versionNon-resource URL prefixes the webhook allows directly.
--kcp-api-export-endpoint-slice-namecore.platform-mesh.iokcp APIExportEndpointSlice used for logical-cluster discovery.

INFO

authorization.kubernetes.io/cluster-name is the legacy kcp extra key. It is deprecated as of kcp v0.28.3; the canonical key is authorization.kcp.io/cluster-name. Set --webhook-cluster-key=authorization.kcp.io/cluster-name when running against a kcp version that emits only the canonical key. See the kcp webhook authorizer documentation.

Environment variables

VariableDescription
KUBECONFIGKubeconfig used by controller-runtime. In the Helm chart this points to /api-kubeconfig/kubeconfig when kcp.kubeconfig.secret is set.

Helm

The deployment chart is rebac-authz-webhook in platform-mesh/helm-charts. The authoritative values table is generated in the chart README.

Important defaults:

ValueDefaultDescription
image.nameghcr.io/platform-mesh/rebac-authz-webhookContainer image.
openfga.urlopenfga:8081OpenFGA address passed to --openfga-addr.
kcp.kubeconfig.secretrebac-authz-webhook-kubeconfigSecret mounted at /api-kubeconfig; must contain key kubeconfig.
service.port9443HTTPS authorization webhook service port.
service.metricsPort8080Metrics port exposed by the Service.
healthProbeBindAddress:8081Health/readiness bind address used by the chart; passed to --health-probe-bind-address and overrides the binary default :8090.
certificates.createfalseWhen true, the chart renders cert-manager issuer and certificate resources.

The Deployment runs the binary with serve, mounts serving certificates from rebac-authz-webhook-cert at /config, and exposes container ports 9443 (webhook server) and 8080 (metrics, also exposed by the Service).

RBAC and permissions

The chart installs a ClusterRole bound to the webhook's ServiceAccount on the management cluster:

API groupResourcesVerbs
core.platform-mesh.ioaccounts, accounts/statusget, list, watch
(core)namespacesget, list, watch

All workspace-scoped reads (LogicalCluster, Store, APIExportEndpointSlice, dynamic REST mapping) go through the kcp kubeconfig mounted from rebac-authz-webhook-kubeconfig, not through the management-cluster ClusterRole.

Observability

The webhook exposes controller-runtime Prometheus metrics on --metrics-bind-address (binary default :9090). Standard controller-runtime metrics are exported, including reconcile counts, latencies, and workqueue depth.

OpenTelemetry instrumentation covers outgoing kcp HTTP calls and OpenFGA gRPC calls. Trace export is configured through standard OTEL_* environment variables, which can be supplied through the chart's extraEnvs.

Logging uses klog and the standard Kubernetes logging flags. The chart appends --v={{ .Values.v }} when v is set.

TLS and trust

kcp calls the webhook over HTTPS, so it must trust the certificate served by /authz. That certificate is signed by an in-cluster CA. The Platform Mesh operator copies the matching CA bundle into the kubeconfig kcp uses for the webhook call.

The webhook does not authenticate the caller itself. In the default setup, it relies on the in-cluster Service and serving certificate, and does not use client-certificate mTLS.

Deployment and Platform Mesh wiring

Platform Mesh installs the webhook through the platform-mesh-operator-components chart. The service entry is enabled by default:

ValueDefault
services.rebac-authz-webhook.enabledtrue
services.rebac-authz-webhook.values.openfga.urlopenfga:8081
services.rebac-authz-webhook.values.certManager.enabledtrue
services.rebac-authz-webhook.values.certManager.createCAtrue
services.rebac-authz-webhook.imageResources[].annotations.forrebac-authz-webhook

The infra chart configures kcp to call the webhook:

ValueDefault
kcp.webhook.enabledtrue
kcp.webhook.serverhttps://rebac-authz-webhook.platform-mesh-system.svc.cluster.local:9443/authz
kcp.webhook.authorizationWebhookSecretNamekcp-webhook-secret
kcp.webhook.port9443
kcp.webhook.versionv1

The infra chart templates these values into the RootShard and Shard custom resources (operator.kcp.io/v1alpha1) under spec.authorization.webhook.{configSecretName,version}. The kcp-operator reconciles those CRs into the running kcp shards.

At runtime, kcp loads kcp-webhook-secret and calls its /authz URL for authorization decisions. The CA bundle in that kubeconfig is filled in by the Platform Mesh operator, as described in TLS and trust. The chart's own certificates.create is left at false because the certificate is issued by the Platform Mesh operator.

Local setup

For local setup, see Set up Platform Mesh locally. The webhook ships with the standard local stack and depends on OpenFGA and the Security operator being healthy before it can return useful authorization decisions.

Repository

EU and German government funding logos

Funded by the European Union – NextGenerationEU.

The views and opinions expressed are solely those of the author(s) and do not necessarily reflect the views of the European Union or the European Commission. Neither the European Union nor the European Commission can be held responsible for them.