Skip to main content

Broker Policy

BrokerPolicy is the cluster-scoped Managed Config section that lists which brokers may use the Broker Endpoint, and how each of them may name a workload. Setting a socket path makes the Agent listen. BrokerPolicy is what makes any request succeed.

Every Agent in the cluster receives the same policy, and each Agent applies it to the brokers that connect to it.

broker-policy.yaml
section: BrokerPolicy
schema: v1
spec:
brokers:
# One entry per broker, matched on its exact SPIFFE ID.
- spiffeID: spiffe://example.org/ns/broker-system/sa/my-broker
# The reference types this broker may use. Anything else is denied.
referenceTypes:
- type.googleapis.com/spiffe.broker.KubernetesObjectReference

Fields

FieldRequiredDescription
brokersNoThe allowlist. An absent list and an empty list are equivalent: Both deny every broker.
brokers[].spiffeIDYesThe exact SPIFFE ID the broker presents in its client certificate. Must be well formed and in the cluster's own trust domain.
brokers[].referenceTypesYesThe reference types this broker may use, at least one.

Matching on spiffeID is exact. Prefixes, patterns, and wildcards in the SPIFFE ID are not supported, so each broker identity needs its own entry. Cross-trust-domain brokers are not supported either: A broker whose SPIFFE ID belongs to another trust domain is rejected at validation time.

Reference types

A reference type is how a broker is allowed to name a workload. The values are the reference type URLs themselves, which are the exact strings a broker puts on the wire:

ValueGrants
type.googleapis.com/spiffe.broker.KubernetesObjectReferenceNaming a pod on the Agent's own node, by namespace and name, by UID, or by both.
type.googleapis.com/spiffe.broker.WorkloadPIDReferenceNaming a process on the Agent's own node by its process ID.
*Every reference type. Must be the entry's only value.

The reference type is the only thing BrokerPolicy grants or withholds. Once a broker is entitled to a type, it chooses which specific pod, namespace, or PID to name within that type on each request. BrokerPolicy has no field for narrowing that choice, such as restricting a broker to a single namespace or a specific pod.

Entitlement is checked on every request and on every re-verification of an open subscription, so a broker that uses a type its entry does not list is denied that request even though it is allowlisted.

List the reference types a broker needs, rather than the wildcard. Reference-type entitlement is the only limit on how a broker may name a workload, so it is the narrowest control available over what a compromised broker can ask for. The two types differ in reach: A Kubernetes object reference resolves pods only, while a process-ID reference resolves any process on the node, including host processes that belong to no pod. A wildcard entry also silently grants every reference type added in a future release, widening the delegation without anyone editing the policy.

An absent policy denies every broker

The Broker Endpoint is fail-closed, and there is no accept-all setting:

  • No BrokerPolicy section at all denies every broker.
  • A BrokerPolicy section with an empty brokers list denies every broker.
  • A broker with no entry is rejected before its request reaches a handler.

A denied broker completes its TLS handshake and then receives PermissionDenied on every request, since the Agent's own serving certificate and trust bundles are unrelated to the allowlist.

Applying the policy

BrokerPolicy is applied per-cluster using Managed Config.

Using spirlctl

spirlctl config set cluster --id <cluster-id> broker-policy.yaml

The policy can also be edited from the cluster's settings in the Defakto web console.

Using Terraform

resource "spirl_cluster_config" "broker_policy" {
cluster_id = spirl_cluster.my_cluster.id
sections = {
BrokerPolicy = <<-YAML
section: BrokerPolicy
schema: v1
spec:
brokers:
- spiffeID: spiffe://example.org/ns/broker-system/sa/my-broker
referenceTypes:
- type.googleapis.com/spiffe.broker.KubernetesObjectReference
YAML
}
}

Validation

The control plane rejects the section, before storing anything, when an entry has a missing, malformed, duplicate, or cross-trust-domain spiffeID, or when its referenceTypes list is empty, unrecognized, or mixes * with a specific type.

Propagation

In most cases, policy changes apply almost instantly: A stored policy reaches every Agent, and governs every new request, within seconds. No Agent restart and no redeploy is required.

An already-open subscription is a partial exception. It re-checks the broker's entitlement only when it re-attests, on a fixed 5-minute interval, so a revoked entitlement can take up to 5 minutes to terminate an in-flight subscription with PermissionDenied. That same re-attestation is also what renews the subscription's SVID, so a renewal can never outrun a revocation: Entitlement is re-checked immediately before every renewal, not on a separate schedule, so a broker cannot receive a renewed credential after its entitlement is revoked.

Rollback

To revoke a broker, remove its entry and apply the section again. To revoke every broker, empty the brokers list or delete the section. Both take effect over the same sync path with the same bound: New requests are denied immediately, and open subscriptions end within 5 minutes.

Revoking a broker leaves the endpoint listening. To stop the Agent from serving the Broker API at all, unset the socket path. See Enabling the Broker API.

Verifying that a broker can fetch

Once a broker is allowlisted, confirm the whole path end to end with spirldbg, which can act as a broker. Run it from a pod on the node that mounts both the broker socket and the Workload API socket:

spirldbg broker-x509-svid \
--broker-socket /run/spirl/broker/broker.sock \
--spiffe-endpoint-socket /run/spirl/sockets/agent.sock \
--reference-type type.googleapis.com/spiffe.broker.KubernetesObjectReference \
--k8s-plural pods \
--k8s-group core \
--k8s-namespace default \
--k8s-name my-app

--spiffe-endpoint-socket is where spirldbg sources the identity it presents as the broker, so the SPIFFE ID under test is the identity of the pod spirldbg runs in. Allowlist that SPIFFE ID to test the path, or point --client-cert and --client-key at the broker's own credential.

On success the command prints the X.509 SVID issued for the referenced pod, whose SPIFFE ID is the one the cluster's identity template renders for that pod. On failure it prints the gRPC status the endpoint returned and exits non-zero, which is the same status a real broker would see. Use the --updates N flag to hold the subscription open past the first response, which makes rotation and revocation reaching an already-connected broker observable.