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
}
}

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 not consulted, including when the policy omits additionalClaims. See Legacy configuration to move existing claims into a policy.

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. 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 ""