Skip to main content

JWT-SVID Customization

Defakto allows customization of JWT-SVIDs on a per-cluster basis, including TTL and additional claims beyond the standard SPIFFE claims (sub, aud, exp).

JWT-SVID TTL

Set a custom JWT-SVID TTL using the SVIDIssuancePolicy managed configuration:

section: SVIDIssuancePolicy
schema: v1
spec:
policy:
pathTemplate: "/{{cluster.name}}/ns/{{kubernetes.pod.namespace}}/sa/{{kubernetes.pod.service_account}}"
jwt:
ttl: "12h"

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}}/sa/{{kubernetes.pod.service_account}}"
jwt:
ttl: "12h"
YAML
}
}

The jwt.ttl field accepts a duration between 5m (5 minutes) and 168h. A policy that leaves jwt.ttl unset falls back to the Trust Domain Server's --jwt-svid-ttl flag, and then to the 24h default.

To apply different JWT TTLs to specific workloads within the same cluster, use per-workload overrides.

Custom Claims

tip

This feature is only available with spirl-server version 0.36.0 and beyond

Add additional claims to JWT-SVIDs using a customization template in the SVIDIssuancePolicy managed configuration. Custom claims appear alongside the standard JWT-SVID claims. Custom claims cannot override the registered JWT claims (iss, sub, aud, exp, nbf, iat, jti).

section: SVIDIssuancePolicy
schema: v1
spec:
policy:
pathTemplate: "/{{cluster.name}}/ns/{{kubernetes.pod.namespace}}/sa/{{kubernetes.pod.service_account}}"
jwt:
additionalClaims:
namespace: "{{kubernetes.pod.namespace}}"
pod_service_account: "{{kubernetes.pod.service_account}}"

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}}/sa/{{kubernetes.pod.service_account}}"
jwt:
additionalClaims:
namespace: {{kubernetes.pod.namespace}}
pod_service_account: {{kubernetes.pod.service_account}}
YAML
}
}
Behavior change in spirl-server 0.39.0

From 0.39.0, on a cluster that has an SVIDIssuancePolicy the policy's jwt.additionalClaims is the only source of additional claims. The legacy per-cluster template is never consulted, including when the policy omits additionalClaims. The gate is the presence of a policy on the cluster, not what any individual policy section sets.

Earlier versions fall back to the legacy template whenever the policy omits additionalClaims, so a cluster that relies on both keeps its claims today and silently loses them on upgrade. Copy the claims into jwt.additionalClaims before upgrading. See Legacy configuration for migration guidance.

To apply different claims to specific workloads within the same cluster, use per-workload overrides.

Template Format

The customization template is a list of templated strings that define additional custom claims to be added to JWT-SVIDs. Each claim follows the format claim_name: {{attribute}}:

additionalClaims:
claim_name: {{discovered.attribute}}
another_claim: {{another.attribute}}

Claim Names and Values

  • Claim names: Custom names that you choose.
  • Claim values: Must reference discovered attributes available in the cluster platform.

Example

Include claims based on attributes, similar to how they are used in path templates:

additionalClaims:
namespace: {{kubernetes.pod.namespace}}
pod_service_account: {{kubernetes.pod.service_account}}

Restrictions

  • Static values are not allowed: Claim values must reference dynamic attributes discovered from the cluster platform. This ensures claims remain current and reflect the actual workload context.
  • Attribute validation: All referenced attributes must exist and be discoverable in the target cluster.

Legacy configuration

Custom JWT claims can also be set using the spirlctl CLI. From spirl-server 0.39.0 the legacy template applies only to clusters with no SVIDIssuancePolicy. Before adding a policy to a cluster that relies on the legacy template, copy its claims into jwt.additionalClaims. For example, for a template like namespace={{kubernetes.pod.namespace}},service_account={{kubernetes.pod.service_account}}, the equivalent configuration would be:

additionalClaims:
namespace: {{kubernetes.pod.namespace}}
service_account: {{kubernetes.pod.service_account}}

Setting the Claims Template for a New Cluster

By default, clusters have an empty JWT customization template. You can set a template when adding a cluster to the trust domain:

spirlctl cluster add production --trust-domain spirl.example.com \
--platform k8s \
--jwt-customization-template "namespace={{kubernetes.pod.namespace}},pod_service_account={{kubernetes.pod.service_account}}"

Setting the Claims Template for an Existing Cluster

To set or update the JWT customization template for an existing cluster, use the change-jwt-template subcommand:

spirlctl cluster config --trust-domain spirl.example.com \
change-jwt-template ClusterName "namespace={{kubernetes.pod.namespace}},pod_service_account={{kubernetes.pod.service_account}}"

Removing the Claims Template

To remove the customization template from a cluster, set it to an empty string:

spirlctl cluster config --trust-domain spirl.example.com \
change-jwt-template ClusterName ""