@@ -31,6 +31,7 @@ import (
3131 apiauth "chainguard.dev/sdk/auth"
3232 pboidc "chainguard.dev/sdk/proto/platform/oidc/v1"
3333 "github.com/chainguard-dev/clog"
34+ "github.com/octo-sts/app/pkg/jwks"
3435 "github.com/octo-sts/app/pkg/provider"
3536)
3637
@@ -57,10 +58,11 @@ var (
5758type sts struct {
5859 pboidc.UnimplementedSecurityTokenServiceServer
5960
60- atr * ghinstallation.AppsTransport
61- ceclient cloudevents.Client
62- domain string
63- metrics bool
61+ atr * ghinstallation.AppsTransport
62+ ceclient cloudevents.Client
63+ domain string
64+ metrics bool
65+ jwksConfigOpts []jwks.ConfigOption
6466}
6567
6668type cacheTrustPolicyKey struct {
@@ -107,22 +109,41 @@ func (s *sts) Exchange(ctx context.Context, request *pboidc.ExchangeRequest) (_
107109 }
108110 bearer := strings .TrimPrefix (auth [0 ], "Bearer " )
109111
110- // Validate the Bearer token.
111- issuer , err := apiauth .ExtractIssuer (bearer )
112+ e .InstallationID , e .TrustPolicy , err = s .lookupInstallAndTrustPolicy (ctx , request .Scope , request .Identity )
112113 if err != nil {
113- return nil , status . Errorf ( codes . InvalidArgument , "invalid bearer token: %v" , err )
114+ return nil , err
114115 }
116+ clog .FromContext (ctx ).Infof ("trust policy: %#v" , e .TrustPolicy )
115117
116- // Fetch the provider from the cache or create a new one and add to the cache
117- p , err := provider .Get (ctx , issuer )
118- if err != nil {
119- return nil , status .Errorf (codes .InvalidArgument , "unable to fetch or create the provider: %v" , err )
118+ var verifier * oidc.IDTokenVerifier
119+
120+ // If a JWKS is set on the trust policy, we need to use it to validate the
121+ // incoming token. This is for supporting OIDC discovery endpoints that are
122+ // not reachable from the Internet, such as air-gapped environments.
123+ if e .TrustPolicy .JWKS != "" {
124+ var err error
125+ verifier , err = jwks .NewVerifier (e .TrustPolicy .JWKS , s .jwksConfigOpts ... )
126+ if err != nil {
127+ return nil , status .Errorf (codes .InvalidArgument , "failed to parse JWKS: %v" , err )
128+ }
129+ } else {
130+ // Validate the Bearer token.
131+ issuer , err := apiauth .ExtractIssuer (bearer )
132+ if err != nil {
133+ return nil , status .Errorf (codes .InvalidArgument , "invalid bearer token: %v" , err )
134+ }
135+
136+ // Fetch the provider from the cache or create a new one and add to the cache
137+ p , err := provider .Get (ctx , issuer )
138+ if err != nil {
139+ return nil , status .Errorf (codes .InvalidArgument , "unable to fetch or create the provider: %v" , err )
140+ }
141+ verifier = p .Verifier (& oidc.Config {
142+ // The audience is verified later on by the trust policy.
143+ SkipClientIDCheck : true ,
144+ })
120145 }
121146
122- verifier := p .Verifier (& oidc.Config {
123- // The audience is verified later on by the trust policy.
124- SkipClientIDCheck : true ,
125- })
126147 tok , err := verifier .Verify (ctx , bearer )
127148 if err != nil {
128149 return nil , status .Errorf (codes .Unauthenticated , "unable to validate token: %v" , err )
@@ -134,12 +155,6 @@ func (s *sts) Exchange(ctx context.Context, request *pboidc.ExchangeRequest) (_
134155 Subject : tok .Subject ,
135156 }
136157
137- e .InstallationID , e .TrustPolicy , err = s .lookupInstallAndTrustPolicy (ctx , request .Scope , request .Identity )
138- if err != nil {
139- return nil , err
140- }
141- clog .FromContext (ctx ).Infof ("trust policy: %#v" , e .TrustPolicy )
142-
143158 // Check the token against the federation rules.
144159 e .Actor , err = e .TrustPolicy .CheckToken (tok , s .domain )
145160 if err != nil {
0 commit comments