Skip to main content

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.

On a cluster that has an SVIDIssuancePolicy, the cluster's default path template is not consulted. Every policy section declares its own pathTemplate, in the base policy and in every override. A workload that resolves to no policy section receives no SVID. 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}}
warning

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.