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