-
Notifications
You must be signed in to change notification settings - Fork 43
Support per Audience JWT SVIDs #141
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -46,12 +46,14 @@ const ( | |
| type SVIDResponse struct { | ||
| X509Certificates []*x509.Certificate | ||
| JWT *string | ||
| PerAudienceJWT map[string]string | ||
| } | ||
|
|
||
| // Identity contains both X.509 and JWT SVIDs for a workload. | ||
| type Identity struct { | ||
| X509SVID *x509svid.SVID | ||
| JWTSVID *jwtsvid.SVID | ||
| X509SVID *x509svid.SVID | ||
| JWTSVID *jwtsvid.SVID | ||
| PerAudienceJWTSVID map[string]*jwtsvid.SVID | ||
| } | ||
|
|
||
| type ( | ||
|
|
@@ -77,8 +79,11 @@ type Options struct { | |
| // Used to manage workload SVIDs, and share read-only interfaces to consumers. | ||
| type SPIFFE struct { | ||
| currentX509SVID *x509svid.SVID | ||
| currentJWTSVID *jwtsvid.SVID | ||
| requestSVIDFn RequestSVIDFn | ||
|
|
||
| currentBaseJWTSVID *jwtsvid.SVID | ||
| currentPerAudJWTSVID map[string]*jwtsvid.SVID | ||
|
|
||
| requestSVIDFn RequestSVIDFn | ||
|
|
||
| dir *dir.Dir | ||
| trustAnchors trustanchors.Interface | ||
|
|
@@ -124,7 +129,8 @@ func (s *SPIFFE) Run(ctx context.Context) error { | |
| } | ||
|
|
||
| s.currentX509SVID = initialIdentity.X509SVID | ||
| s.currentJWTSVID = initialIdentity.JWTSVID | ||
| s.currentBaseJWTSVID = initialIdentity.JWTSVID | ||
| s.currentPerAudJWTSVID = initialIdentity.PerAudienceJWTSVID | ||
| close(s.readyCh) | ||
| s.lock.Unlock() | ||
|
|
||
|
|
@@ -169,7 +175,7 @@ func (s *SPIFFE) runRotation(ctx context.Context) { | |
|
|
||
| s.lock.RLock() | ||
| cert := s.currentX509SVID.Certificates[0] | ||
| jwtSVID := s.currentJWTSVID | ||
| jwtSVID := s.currentBaseJWTSVID | ||
| s.lock.RUnlock() | ||
|
|
||
| renewTime := calculateRenewalTime(time.Now(), cert, jwtSVID) | ||
|
|
@@ -197,7 +203,8 @@ func (s *SPIFFE) runRotation(ctx context.Context) { | |
|
|
||
| s.lock.Lock() | ||
| s.currentX509SVID = identity.X509SVID | ||
| s.currentJWTSVID = identity.JWTSVID | ||
| s.currentBaseJWTSVID = identity.JWTSVID | ||
| s.currentPerAudJWTSVID = identity.PerAudienceJWTSVID | ||
| cert = identity.X509SVID.Certificates[0] | ||
| jwtSVID = identity.JWTSVID | ||
| s.lock.Unlock() | ||
|
|
@@ -265,6 +272,19 @@ func (s *SPIFFE) fetchIdentity(ctx context.Context) (*Identity, error) { | |
| s.log.Infof("Successfully received JWT SVID with expiry: %s", jwtSvid.Expiry.String()) | ||
| } | ||
|
|
||
| for aud, token := range svidResponse.PerAudienceJWT { | ||
| jwtSvid, err := jwtsvid.ParseInsecure(token, []string{aud}) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("failed to parse JWT SVID: %w", err) | ||
| } | ||
|
Comment on lines
+275
to
+279
|
||
|
|
||
| if identity.PerAudienceJWTSVID == nil { | ||
| identity.PerAudienceJWTSVID = make(map[string]*jwtsvid.SVID) | ||
| } | ||
| identity.PerAudienceJWTSVID[aud] = jwtSvid | ||
| s.log.Infof("Successfully received per-audience JWT SVID for audience %s with expiry: %s", aud, jwtSvid.Expiry.String()) | ||
| } | ||
|
Comment on lines
+275
to
+286
|
||
|
|
||
| if s.dir != nil { | ||
| pkPEM, err := pem.EncodePrivateKey(key) | ||
| if err != nil { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The rotation scheduler still computes renewal time using only the base JWT SVID. Per-audience JWT SVIDs may have earlier expiries, which could leave expired per-audience tokens being served until the next cert/base-JWT renewal. Consider incorporating the earliest expiry among all JWT SVIDs (base + per-audience) when calculating renewTime.