SVID Issuance Policy
The SVIDIssuancePolicy managed configuration section centralizes per-cluster SVID issuance settings and adds an optional list of workload-specific overrides. It is the preferred way to configure:
- SPIFFE ID path templates — the path structure of issued SPIFFE IDs
- X.509-SVID customization — X.509 certificate TTL and Subject
- JWT-SVID customization — JWT-SVID TTL
See those pages for field-level documentation and examples.
Why use it?
- Single configuration source: Manage TTLs, subjects, and path templates per cluster from a single managed-config document instead of separate CLI flags.
- Per-workload variations: Issue shorter-lived certificates for specific namespaces, distinct path templates for sensitive workloads, or different subjects for one service account — without writing a separate cluster.
- Live updates: Configuration changes propagate to servers without restart.
Per-Workload Overrides
policyOverrides is an ordered list of conditional policy variations. When a workload's attested attributes match an override's when clause, that override's policy applies in place of the base policy. The first match wins; later overrides and the base policy are skipped for that workload.
section: SVIDIssuancePolicy
schema: v1
spec:
policy:
pathTemplate: "/{{cluster.name}}/default/ns/{{kubernetes.pod.namespace}}/sa/{{kubernetes.pod.service_account}}"
x509:
ttl: "24h"
policyOverrides:
- when:
kubernetes.pod.namespace: production
policy:
pathTemplate: "/{{cluster.name}}/prod/ns/{{kubernetes.pod.namespace}}/sa/{{kubernetes.pod.service_account}}"
x509:
ttl: "4h"
- when:
kubernetes.pod.service_account: critical-service
policy:
pathTemplate: "/{{cluster.name}}/critical/ns/{{kubernetes.pod.namespace}}/sa/{{kubernetes.pod.service_account}}"
x509:
ttl: "1h"
In this example:
- A pod in the
productionnamespace receives a SPIFFE ID under/prod/...with a 4h TTL. - A pod whose service account is
critical-service(in any namespace exceptproduction) receives a SPIFFE ID under/critical/...with a 1h TTL. - Every other pod receives the base policy:
/default/...with a 24h TTL.
When-Clause Match Semantics
Each entry in a when map is one condition. All conditions in a single when clause must match (logical AND).
| Entry | Match Type |
|---|---|
key: value | Exact match — the workload must carry that attribute with that exact string value. |
key: (no value) | Presence match — the workload must carry that attribute with any value. |
Allowed When Keys
when keys are restricted to attributes whose values represent a real authorization boundary — that is, attributes a pod author or process launcher cannot freely pick to claim a more privileged policy.
| Source | Attribute | Set by |
|---|---|---|
| Agent / cluster identity | agent.id | SPIRL agent provisioning |
cluster.name | Operator (cluster config) | |
realm.name | Operator (realm config) | |
node_group.name | Operator (node group config) | |
| Kubernetes admission | kubernetes.pod.namespace | Kubernetes RBAC |
kubernetes.pod.service_account | Kubernetes RBAC |
Attributes that look like identity but are pod-spec- or process-launcher-chosen — including kubernetes.pod.name, kubernetes.pod.node.name, kubernetes.container.name, kubernetes.container.image.name, linux.user.*, and linux.binary.path — are not on the allowlist. Anyone with create pod permission can pick those values, so matching on them adds no security restriction beyond what the underlying RBAC already provides.
Workload-supplied or content-addressed attributes (custom.*, pod annotations, pod labels, JWT claims, kubernetes.container.image.id, linux.binary.sha256) are also excluded: when-clause matching is scoped to platform-set identity, not workload content.
Override Semantics
When an override's when clause matches at issuance time, the override's policy fully replaces the base policy for that workload; there is no merging of fields. Each override must therefore be self-contained. It must declare its own pathTemplate, and any of x509 / jwt it wants to apply. This keeps the model easy to reason about.
| Base declares | Override declares | Effective for matching workload |
|---|---|---|
pathTemplate, x509, jwt | pathTemplate, x509, jwt | All from override |
pathTemplate, x509, jwt | pathTemplate, x509: {ttl: 4h} | Override's pathTemplate and x509. JWT not configured for matching workload. |
pathTemplate, x509, jwt | (no pathTemplate) | Rejected at admission — overrides must carry their own pathTemplate. |
Validation
The control plane rejects configurations that:
- Set neither
policynorpolicyOverrides. - Include an override with an empty
whenclause. - Include an override whose
policydeclares no fields. - Use a
whenkey not on the allow-list above, or awhenkey that isn't a valid attribute name. - Contain two overrides with identical
whenclauses. - Omit
pathTemplateon any override (overrides do not inherit from the base policy).
Path-template syntax and platform-specific allowed tags are validated the same way they are for SPIFFE ID templates, against both the base policy and each override.