{"id":12651,"date":"2026-08-24T20:56:41","date_gmt":"2026-08-25T01:56:41","guid":{"rendered":"https:\/\/www.rushworth.us\/lisa\/?p=12651"},"modified":"2026-11-02T10:04:40","modified_gmt":"2026-11-02T15:04:40","slug":"spire-rotation-without-outages-credential-and-trust-material-lifecycle","status":"publish","type":"post","link":"https:\/\/www.rushworth.us\/lisa\/?p=12651","title":{"rendered":"SPIFFE: Rotation Without Outages: Credential and Trust-Material Lifecycle"},"content":{"rendered":"<p>Automatic rotation removes manual renewal work, not lifecycle complexity. Your acceptance tests must cover planned rotation, unknown signing keys, transient outages, and the interaction between credentials issued at different layers.<\/p>\n<h2>Separate the trust-material paths<\/h2>\n<p>X.509-SVID verification uses certificate trust material. JWT-SVID verification uses the corresponding JWT signing public keys. An OIDC discovery\/JWKS integration can expose JWT verification metadata for consumers, but an X.509 bundle is not interchangeable with a JWKS document. Document exactly which discovery component is deployed and how PingFederate trusts it.<\/p>\n<p>Review discovery issuer association, TLS trust, permitted metadata endpoints, cache limits, and key rollover behavior. A kid identifies a candidate key; it does not make a key trustworthy. Do not follow arbitrary jku or x5u values from untrusted token input. Bind verification material to configured issuers.<\/p>\n<h2>Plan overlap and bounded refresh<\/h2>\n<p>Recommended sequence: publish the new verification key, allow intended verifiers to acquire it, begin signing with it, and retain old verification material for the remaining lifetime of valid old tokens plus permitted skew and bounded propagation delays. Confirm the actual signing-key publisher behavior rather than assuming it follows this sequence. Emergency compromise rollover requires a different plan because retaining the old key preserves trust in forged tokens.<\/p>\n<p>On unknown kid, perform a bounded, issuer-specific refresh if supported. If the key remains unknown, deny the token. Rate-limit and coalesce refreshes to prevent attacker-controlled kid values from turning verification into a discovery-service denial of service. Valid cached material may remain usable within a documented policy; this is not permission to extend token expiration or trust unknown keys.<\/p>\n<h2>Failure and recovery matrix<\/h2>\n<table>\n<tbody>\n<tr>\n<td width=\"221\"><strong>Condition<\/strong><\/td>\n<td width=\"221\"><strong>Recommended behavior<\/strong><\/td>\n<td width=\"221\"><strong>Evidence to collect<\/strong><\/td>\n<\/tr>\n<tr>\n<td width=\"221\"><strong>SPIRE unavailable<\/strong><\/td>\n<td width=\"221\">No fabricated credentials; use only still-valid material under policy<\/td>\n<td width=\"221\">Issuance failures and remaining lifetime<\/td>\n<\/tr>\n<tr>\n<td width=\"221\"><strong>STS unavailable<\/strong><\/td>\n<td width=\"221\">Do not bypass exchange or broaden authority<\/td>\n<td width=\"221\">Exchange failures and job\/backoff behavior<\/td>\n<\/tr>\n<tr>\n<td width=\"221\"><strong>Discovery unavailable<\/strong><\/td>\n<td width=\"221\">Bounded cache use; reject unknown keys<\/td>\n<td width=\"221\">Cache age and refresh outcomes<\/td>\n<\/tr>\n<tr>\n<td width=\"221\"><strong>Clock skew<\/strong><\/td>\n<td width=\"221\">Enforce reviewed bounded leeway<\/td>\n<td width=\"221\">Clock offset and time-validation failures<\/td>\n<\/tr>\n<tr>\n<td width=\"221\"><strong>Old signing key removed<\/strong><\/td>\n<td width=\"221\">Observe rejected old credentials; follow planned policy<\/td>\n<td width=\"221\">Affected kid and issuer<\/td>\n<\/tr>\n<tr>\n<td width=\"221\"><strong>Policy distribution unavailable<\/strong><\/td>\n<td width=\"221\">Explicit fail behavior, never implicit permit<\/td>\n<td width=\"221\">Policy version and stale-state duration<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<h2>Sender binding complicates credential rotation<\/h2>\n<p>RFC 8705 certificate-bound access tokens use the thumbprint of a specific client certificate. Binding to an X.509-SVID certificate therefore binds that token to that particular certificate, not merely to its stable SPIFFE ID. Coordinate token renewal and certificate rotation, and avoid a gap where only a replacement certificate remains but the access token expects the old one.<\/p>\n<p>DPoP is an alternative sender-constraint mechanism only where the issuer and resource server support the agreed profile. Its key lifecycle is separate from SPIRE certificate rotation. Do not imply that configuring SPIRE automatically enables DPoP in PingFederate or a downstream API.<\/p>\n<h2>Connections and authorization lifetime<\/h2>\n<p>Established TLS connections and application sessions need their own lifecycle review. A certificate rollover is not guaranteed to trigger a new authentication handshake on every existing connection. Decide whether token authorization is evaluated per request, once per connection, or when a session is created; verify the implementation. Connection draining and maximum session duration may be needed for predictable containment.<\/p>\n<ul>\n<li>Exercise a planned rotation under normal load.<\/li>\n<li>Test new-key visibility before switching signers.<\/li>\n<li>Measure clock offsets and verification-cache behavior.<\/li>\n<li>Simulate dependency outages without allowing permissive fallbacks.<\/li>\n<li>Prove emergency issuer compromise response separately from routine rollover.<\/li>\n<\/ul>\n<p>Takeaway: rotation must be tested as a distributed protocol, including consumers and their caches.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Automatic rotation removes manual renewal work, not lifecycle complexity. Your acceptance tests must cover planned rotation, unknown signing keys, transient outages, and the interaction between credentials issued at different layers. Separate the trust-material paths X.509-SVID verification uses certificate trust material. JWT-SVID verification uses the corresponding JWT signing public keys. An OIDC discovery\/JWKS integration can expose &hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2243],"tags":[2246,2244,2216,2245],"class_list":["post-12651","post","type-post","status-publish","format-standard","hentry","category-spiffe","tag-agent-identity","tag-spiffe","tag-spire","tag-workload-identity"],"_links":{"self":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts\/12651","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=12651"}],"version-history":[{"count":2,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts\/12651\/revisions"}],"predecessor-version":[{"id":12660,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts\/12651\/revisions\/12660"}],"wp:attachment":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=12651"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=12651"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=12651"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}