conduktor.io ↗

ApplicationGroup Cannot Span Tenants

ApplicationGroup must carry labels.tenant-id and every permission resource name must start with that tenant id. No wildcards.

“There's no noisy neighbors and all those types of things.”

Rationale

ApplicationGroups back the ACLs / permissions handed to a ServiceAccount. A group with permission on Topic:* or on a sibling tenant's prefix is an instant cross-tenant breach. This extends the starter's no-wildcard-acl-prod (which only blocks literal '*' resources) by also requiring every permission to be prefix-scoped to the group's owning tenant, closing the 'wildcard via prefix' loophole (e.g. PREFIXED 'prod.' would catch every tenant).

Pattern

labels.tenant-id REQUIRED AND every permission.name startsWith labels.tenant-id+'.' AND patternType != wildcard '*'

Examples

labels.tenant-id: t-ab12cd + permission: { name: t-ab12cd.prod.orders.*, patternType: PREFIXED, ... }
labels.tenant-id: t-ab12cd + permission: { name: prod., patternType: PREFIXED }
labels.tenant-id: t-ab12cd + permission: { name: t-zzzzzz.prod.payments, patternType: LITERAL }
no labels.tenant-id label

Parameters

NameDefaultDescription
tenant_id_label "tenant-id" Label key carrying the ApplicationGroup's owning tenant id.

Implementation

Drop this YAML into Conduktor Console as a ResourcePolicy, then link it from an ApplicationInstance, Application, or KafkaCluster.

Conduktor ResourcePolicy
# Conduktor self-service ResourcePolicy
# Schema: https://docs.conduktor.io/platform/reference/resource-reference/self-service/#resourcepolicy
# ApplicationGroup policies must be linked at Application or KafkaCluster level
# (NOT at ApplicationInstance — excluded by allowedApplicationInstancePolicies).
# Extends the starter no-wildcard-acl-prod by closing the cross-tenant-prefix loophole.
# NOTE: Conduktor Console 1.45.1 does not expose metadata.labels in CEL for the
# ApplicationGroup target kind, and its CEL flavor lacks substring/split/indexOf.
# We adopt the convention that the ApplicationGroup metadata.name IS the
# tenant id (t-<6 alphanum>). Every permission name must then be prefixed by
# the metadata.name + "." — this prevents wildcards and cross-tenant references.
---
apiVersion: self-serve/v1
kind: ResourcePolicy
metadata:
  name: tenant-application-group-no-cross-tenant
spec:
  targetKind: ApplicationGroup
  description: ApplicationGroup metadata.name must equal t-<6 alphanum> and every permission.name must be prefixed by metadata.name + "."
  rules:
    - condition: 'metadata.name.matches("^t-[a-z0-9]{6}$")'
      errorMessage: "ApplicationGroup metadata.name must be a tenant id of the form t-<6 alphanum> (e.g. t-ab12cd)"
    - condition: 'spec.permissions.all(p, p.name != "*" && p.name.startsWith(metadata.name + "."))'
      errorMessage: "Every permission.name must start with the owning tenant id (e.g. t-ab12cd.) — wildcard or cross-tenant prefixes are not allowed"

Related policies

Try Conduktor Console

Enforce policies like this across your team — central audit history, pre-commit guardrails, ApplicationInstance bindings. 5-min Docker install.

Get Started →