SPIFFE ID templates
Defakto generates SPIFFE IDs for new SPIFFE Verifiable Identity Documents (SVIDs) in a platform-dependent way. For example, the default path template for Kubernetes is:
/{{cluster.name}}/ns/{{kubernetes.pod.namespace}}/sa/{{kubernetes.pod.service_account}}
Assuming a trust domain of spirl.example.com, a cluster name of
edge-global, a namespace of prod and a service account named
nginx, this expands to the following SPIFFE ID:
spiffe://spirl.example.com/edge-global/ns/prod/sa/nginx
By default, the following path templates are used, depending on the platform:
# Default Kubernetes path template
/{{cluster.name}}/ns/{{kubernetes.pod.namespace}}/sa/{{kubernetes.pod.service_account}}
# Default Istio path template
/ns/{{kubernetes.pod.namespace}}/sa/{{kubernetes.pod.service_account}}
# Default Linux path template
/{{node_group.name}}/{{linux.user.name}}
# Default developer identity path template
/users/{{email.domain}}/{{email.username}}
Customizing the path template
Set a custom path template for a cluster using the SVIDIssuancePolicy managed configuration:
section: SVIDIssuancePolicy
schema: v1
spec:
policy:
pathTemplate: "/{{cluster.name}}/ns/{{kubernetes.pod.namespace}}/n/{{kubernetes.pod.name}}"
Apply it with spirlctl:
spirlctl config set cluster --id <cluster-id> svid-issuance-policy.yaml
Or with Terraform:
resource "spirl_cluster_config" "example" {
cluster_id = spirl_cluster.my_cluster.id
sections = {
SVIDIssuancePolicy = <<-YAML
section: SVIDIssuancePolicy
schema: v1
spec:
policy:
pathTemplate: "/{{cluster.name}}/ns/{{kubernetes.pod.namespace}}/n/{{kubernetes.pod.name}}"
YAML
}
}
The new path template replaces the default and is used to generate SPIFFE IDs for all workloads in the cluster.
From 0.39.0, once a cluster has an SVIDIssuancePolicy the cluster's default path template is never consulted for that cluster. Every policy section must declare a non-empty pathTemplate of its own, in the base policy and in every override. A workload that resolves to no policy section, or to a section with no pathTemplate, receives no SVID at all.
Earlier server versions fall back to the cluster's default path template, which masks a missing pathTemplate today. Admission now rejects a policy that omits one, so the shape cannot be written any more, but a policy stored before that requirement still loads and starts denying on upgrade. See Implicit deny.
To apply different path templates to specific workloads within the same cluster, use per-workload overrides.
Path segment characters
Separators come from the template, not from attribute values, so each variable fills exactly one path segment. A substituted value may contain only letters, numbers, dots, dashes, and underscores.
A value containing anything else, most often /, makes the segment invalid and the SVID request is rejected:
code = InvalidArgument desc = payments/checkout-api (attribute custom.path) is not a valid
segment value: path segment characters are limited to letters, numbers, dots, dashes, and
underscores
Allowing a value to span segments
Prefixing a variable with ! lifts that restriction, letting the value contain / and expand into more than one segment:
/{{!custom.path}}
With custom.path set to payments/checkout-api, this produces:
spiffe://spirl.example.com/payments/checkout-api
Reach for the marker in two situations.
The first is a path produced outside Defakto rather than assembled from individual attributes, which is how registration-list behavior is built on top of templates. A Workload Attestation Extension returns the complete path and the template consumes it whole. See Registration Entries for a worked example.
The second is an attribute whose values routinely contain /. A CI repository claim holds values such as my-org/my-service, and a Git ref claim holds values such as refs/heads/main, so a template referencing either needs the marker:
/ci/{{!jwt.claim.repository}}
A ! variable lets its attribute source choose several segments of the SPIFFE ID, rather than one value inside a structure you defined. Only use it with an attribute whose values you can predict, and never with one a workload can set. The rendered result must still be a valid SPIFFE ID, as defined by the SPIFFE ID specification.
Available Template Variables
Attributes from both agent attestation and workload attestation are available in path templates. Each attestation method produces its own set of attributes — see the individual method pages for the attributes available:
Realm Template Variable
When a cluster is registered within a realm, the {{realm.name}} template variable is automatically prepended to the SPIFFE ID path when the default path templates are used. For example the default path template for kubernetes becomes:
/{{realm.name}}/{{cluster.name}}/ns/{{kubernetes.pod.namespace}}/sa/{{kubernetes.pod.service_account}}
For a cluster assigned to a realm, every pathTemplate you write yourself must begin with the {{realm.name}} template variable, in the base policy and in every override. The control plane rejects a policy for a realm-assigned cluster whose template does not lead with it. Such as:
/{{realm.name}}/{{cluster.name}}/{{kubernetes.pod.name}}
The variable is only available for clusters assigned to a realm. On a cluster with no realm, {{realm.name}} is not a valid template variable, which is why the custom path templates earlier on this page omit it.
See the Realm Operations guide for more information on realm management.
Legacy configuration
You can also set a custom path template using the spirlctl CLI when adding a cluster:
spirlctl cluster add production --trust-domain spirl.example.com \
--platform k8s \
--path-template /{{cluster.name}}/ns/{{kubernetes.pod.namespace}}/n/{{kubernetes.pod.name}}
This method is supported, but it applies only to clusters with no SVIDIssuancePolicy. On a cluster that has a policy, the --path-template value is ignored entirely.