JIT Credentials via TokenRequest
How iddio eliminates long-lived cluster credentials by minting short-lived tokens on every request. The proxy never stores a permanent key to your cluster.
The Static Credential Problem
Most Kubernetes configurations use long-lived credentials: a client certificate or service account token stored in a kubeconfig file. These credentials are valid forever (or until manually rotated). If compromised, an attacker has permanent cluster access.
Iddio’s JIT credential mode eliminates this. Instead of storing a permanent credential, the proxy mints a short-lived token on every request using the Kubernetes TokenRequest API.
How TokenRequest Works
The Kubernetes TokenRequest API (available since v1.12, stable since v1.20) mints bound service account tokens with configurable lifetimes and audiences:
tokenReq := &authv1.TokenRequest{
Spec: authv1.TokenRequestSpec{
Audiences: []string{"https://kubernetes.default.svc"},
ExpirationSeconds: ptr(int64(300)), // 5 minutes
},
}
token, err := clientset.CoreV1().
ServiceAccounts(namespace).
CreateToken(ctx, saName, tokenReq, metav1.CreateOptions{})
The resulting token is a JWT that expires after the configured duration. Kubernetes validates it normally — no special configuration needed on the cluster side.
Iddio’s JIT Flow
When JIT credentials are enabled, the proxy’s request lifecycle adds a token-minting step:
- Agent authenticates via mTLS or bearer token
- Request is classified by the tier engine
- Policy is evaluated — if denied, stop here
- Token is minted via TokenRequest with a 5-minute TTL
- Request is forwarded to the real cluster with the JIT token
- Token expires — no cleanup needed
func (p *Proxy) forwardWithJIT(r *http.Request) (*http.Response, error) {
token, err := p.mintToken(r.Context())
if err != nil {
return nil, fmt.Errorf("jit mint: %w", err)
}
// Replace the agent's auth with the JIT token
r.Header.Set("Authorization", "Bearer "+token.Status.Token)
return p.transport.RoundTrip(r)
}
What the Proxy Stores
Without JIT:
~/.kube/configwith a long-lived client cert or token
With JIT:
- A service account name and namespace (references, not secrets)
- The cluster CA certificate (for TLS verification)
- The ability to call
TokenRequest(requires a bootstrap credential, but only for the proxy — not stored per-agent)
The key difference: the proxy stores the ability to mint credentials, not the credentials themselves. The bootstrap credential has a single, narrow permission: create on serviceaccounts/token in the configured namespace.
Token Lifecycle
JIT tokens have a deliberately short lifetime:
| Property | Value |
|---|---|
| Default TTL | 300 seconds (5 minutes) |
| Minimum TTL | 60 seconds (Kubernetes minimum) |
| Maximum TTL | 3600 seconds (1 hour, configurable) |
| Audiences | ["https://kubernetes.default.svc"] |
| Bound to | Service account in configured namespace |
After 5 minutes, the token is invalid. There’s nothing to revoke, nothing to rotate, nothing to store. The next request mints a fresh token.
Configuration
JIT credentials are enabled with a flag:
iddio start \
--cluster-url https://cluster:6443 \
--credentials jit \
--jit-service-account iddio-proxy \
--jit-namespace iddio-system \
--jit-ttl 300s
Or in the config file:
credentials:
mode: jit
jit:
service_account: iddio-proxy
namespace: iddio-system
ttl: 300s
Security Properties
- No long-lived credentials — even if the proxy host is compromised, there are no permanent tokens to steal
- Time-bounded blast radius — a stolen JIT token expires in 5 minutes
- Per-request isolation — each request gets its own token; one request’s token can’t be used for another
- Audit trail — token minting events are recorded in the audit log with the requesting agent’s identity
- Fail-closed — if
TokenRequestfails, the request is denied (not forwarded without auth)
Compatibility
JIT credentials work with any Kubernetes cluster running v1.20+ (TokenRequest API GA). The cluster doesn’t need any iddio-specific configuration beyond:
- A service account in the iddio namespace
- A ClusterRoleBinding allowing that service account to create
serviceaccounts/token - The RBAC permissions you want the JIT tokens to have (bound to the service account’s roles)
Try It Yourself
Iddio is open source. Deploy a zero-trust command proxy for your AI agents in minutes.