@@ -10,6 +10,7 @@ import (
10
10
"context"
11
11
"encoding/json"
12
12
"fmt"
13
+ "io"
13
14
"net/http"
14
15
"net/url"
15
16
"strings"
@@ -174,12 +175,12 @@ func (oa *OIDCAuthenticator) providerCallback() (OIDCCallback, error) {
174
175
return nil , newAuthError (fmt .Sprintf ("%q must be specified for Azure OIDC" , resourceProp ), nil )
175
176
}
176
177
return getAzureOIDCCallback (oa .userName , resource , oa .httpClient ), nil
177
- // TODO GODRIVER-2806: Automatic token acquisition for GCP Identity Provider
178
- // This is here just to pass the linter, it will be fixed in one of the above tickets.
179
178
case gcpEnvironmentValue :
180
- return func (ctx context.Context , args * OIDCArgs ) (* OIDCCredential , error ) {
181
- return nil , fmt .Errorf ("automatic token acquisition for %q not implemented yet" , env )
182
- }, fmt .Errorf ("automatic token acquisition for %q not implemented yet" , env )
179
+ resource , ok := oa .AuthMechanismProperties [resourceProp ]
180
+ if ! ok {
181
+ return nil , newAuthError (fmt .Sprintf ("%q must be specified for GCP OIDC" , resourceProp ), nil )
182
+ }
183
+ return getGCPOIDCCallback (resource , oa .httpClient ), nil
183
184
}
184
185
185
186
return nil , fmt .Errorf ("%q %q not supported for MONGODB-OIDC" , environmentProp , env )
@@ -228,6 +229,37 @@ func getAzureOIDCCallback(clientID string, resource string, httpClient *http.Cli
228
229
}
229
230
}
230
231
232
+ // getGCPOIDCCallback returns the callback for the GCP Identity Provider.
233
+ func getGCPOIDCCallback (resource string , httpClient * http.Client ) OIDCCallback {
234
+ // return the callback parameterized by the clientID and resource, also passing in the user
235
+ // configured httpClient.
236
+ return func (ctx context.Context , args * OIDCArgs ) (* OIDCCredential , error ) {
237
+ resource = url .QueryEscape (resource )
238
+ uri := fmt .Sprintf ("http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience=%s" , resource )
239
+ req , err := http .NewRequestWithContext (ctx , http .MethodGet , uri , nil )
240
+ if err != nil {
241
+ return nil , newAuthError ("error creating http request to GCP Identity Provider" , err )
242
+ }
243
+ req .Header .Add ("Metadata-Flavor" , "Google" )
244
+ resp , err := httpClient .Do (req )
245
+ if err != nil {
246
+ return nil , newAuthError ("error getting access token from GCP Identity Provider" , err )
247
+ }
248
+ defer resp .Body .Close ()
249
+ if resp .StatusCode != http .StatusOK {
250
+ return nil , newAuthError (fmt .Sprintf ("failed to get a valid response from GCP Identity Provider, http code: %d" , resp .StatusCode ), nil )
251
+ }
252
+ accessToken , err := io .ReadAll (resp .Body )
253
+ if err != nil {
254
+ return nil , newAuthError ("failed parsing reading response from GCP Identity Provider" , err )
255
+ }
256
+ return & OIDCCredential {
257
+ AccessToken : string (accessToken ),
258
+ ExpiresAt : nil ,
259
+ }, nil
260
+ }
261
+ }
262
+
231
263
func (oa * OIDCAuthenticator ) getAccessToken (
232
264
ctx context.Context ,
233
265
conn driver.Connection ,
0 commit comments