Enabling the Broker API
The Broker API requires spirl-system 0.44.0 or later.
The Broker API is off by default. Turning it on takes two independent steps: Set a socket path in the Agent's Helm values to enable the Broker Endpoint, and allowlist your broker in the cluster's BrokerPolicy section in Managed Config. This page covers the first step, which is what makes the Agent listen at all. Until a broker is allowlisted, the endpoint denies every request, so both steps are needed before a broker can fetch anything. See Broker Policy for the second step.
Prerequisites
An identity template that covers brokered workloads
A brokered workload receives whatever SPIFFE ID the cluster's identity template renders from the attributes the Agent attested for it, exactly as it would through the Workload API. The template must therefore render from the attributes a brokered reference produces. Resolving a Kubernetes object reference contributes pod-scoped attributes only, such as the pod's namespace, name, UID, service account, and node, so a template that requires container-level or process-level attributes cannot render for that reference type.
The failure mode is an error, not a wrong identity. When the template cannot be rendered from the attested attributes, the issuance request fails with an InvalidArgument template error that reaches the broker. The Agent forces a fresh attestation and retries with backoff rather than issuing a credential under an unexpected SPIFFE ID.
What the broker needs
A broker connects as an ordinary mutually authenticated gRPC client, and must:
- Dial the socket path configured below, on the node it runs on.
- Present a client certificate that chains to a trust bundle the Agent currently holds. In practice a broker is itself an ordinary attested workload of the same Agent: It fetches its own SVID from the Workload API, then presents that SVID on the Broker Endpoint.
- Send the gRPC metadata header
broker.spiffe.io: trueon every request. The header defends against confused-deputy requests from browsers and other clients that cannot set custom gRPC headers, and a request without it is rejected withInvalidArgument. - Have filesystem access to the socket, which usually means sharing a group with the Agent. See Filesystem permissions.
- Be allowlisted in the cluster's
BrokerPolicysection, for each reference type it uses.
Enabling via Helm
Set the socket path in the Agent's Helm values:
agent:
brokerEndpoint:
socketPath: /run/spirl/broker/broker.sock
Apply the values:
helm upgrade --install spirl-system \
oci://ghcr.io/spirl/charts/spirl-system \
--values agent-values.yaml
The endpoint is served only when agent.brokerEndpoint.socketPath is set. There is no separate enable flag, and removing the value disables the endpoint on the next rollout.
The chart mounts the socket's parent directory as a dedicated hostPath volume of type DirectoryOrCreate, so kubelet creates the directory on each node. No init container or mkdir step is required.
Socket path constraints
The broker socket must not live in, under, or above the Workload API socket directory, configured by node.spirlAgentSocketDirectory. A broker that dialed the wrong socket in a shared directory would silently talk to the peer-tracked, non-mTLS Workload API, so both the chart and the Agent fail closed instead.
The examples below assume a Workload API socket directory of /run/spirl/sockets, the chart's default for node.spirlAgentSocketDirectory:
| Socket path | Result |
|---|---|
/run/spirl/broker/broker.sock (sibling directory) | Allowed |
/run/spirl/sockets-broker/broker.sock (shared name prefix) | Allowed |
/run/spirl/sockets/broker.sock (same directory) | Rejected |
/run/spirl/sockets/broker/broker.sock (inside the Workload API directory) | Rejected |
/run/spirl/broker.sock (its directory contains the Workload API directory) | Rejected |
run/spirl/broker/broker.sock (relative path) | Rejected |
A path whose directory resolves to / | Rejected |
Filesystem permissions
You need to coordinate group ownership between the Agent and the broker. The Agent creates the socket at mode 0770, owned by its own uid and gid, and there is no chown setting or broker-group Helm value. A broker that runs as a different user, as it normally does, cannot connect to that socket, or even traverse its parent directory, unless it shares that group.
Pick a group ID for broker access and give it to both sides:
- On the Agent, set the group the Agent process runs as through
agent.containerSecurityContext. The socket's group ownership follows the Agent process's group. - On the broker's pod, add the same group ID to its
securityContext.supplementalGroups, or run the broker as that group.
A broker whose group does not match reports a connection error on the socket rather than a gRPC status, because it never completes a connection. See Connection refused, or permission denied on the socket for the diagnosis.
Verifying the endpoint is up
Three signals confirm the Agent is listening. Check them in order.
The endpoint metric reads 1. spirl_agent_broker_endpoint_enabled only exists when agent.brokerEndpoint.socketPath is set. Once it is, the Agent sets it to 0 at startup and flips it to 1 once the socket is listening, so an absent series with the socket path configured means Agent metrics are not enabled:
kubectl port-forward -n spirl-system <agent-pod-name> 9090:9090
curl -s http://localhost:9090/metrics | grep broker_endpoint_enabled
# HELP spirl_agent_broker_endpoint_enabled 1 if the Broker Endpoint is configured and running, 0 otherwise
# TYPE spirl_agent_broker_endpoint_enabled gauge
spirl_agent_broker_endpoint_enabled 1
The Agent logged that it started the endpoint. The log line carries the socket path it is serving, which is worth checking against the path the broker dials:
{
"logger": "agent.brokerEndpoint",
"msg": "Starting Broker Endpoint",
"socket": "/run/spirl/broker/broker.sock"
}
The socket file exists with mode 0770. The Agent does not create the socket until it holds its own serving credential, so a missing socket on an otherwise healthy Agent usually means the Agent has not finished starting:
kubectl exec -n spirl-system <agent-pod-name> -- ls -l /run/spirl/broker/broker.sock
srwxrwx--- 1 root root 0 Aug 18 14:02 /run/spirl/broker/broker.sock
A listening endpoint does not mean any broker can use it. Every broker is denied until the cluster's BrokerPolicy allowlists it, which is the next step.