@@ -10,6 +10,7 @@ import (
1010 "context"
1111 "encoding/json"
1212 "fmt"
13+ "io"
1314 "net/http"
1415 "net/url"
1516 "strings"
@@ -174,12 +175,12 @@ func (oa *OIDCAuthenticator) providerCallback() (OIDCCallback, error) {
174175 return nil , newAuthError (fmt .Sprintf ("%q must be specified for Azure OIDC" , resourceProp ), nil )
175176 }
176177 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.
179178 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
183184 }
184185
185186 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
228229 }
229230}
230231
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+
231263func (oa * OIDCAuthenticator ) getAccessToken (
232264 ctx context.Context ,
233265 conn driver.Connection ,
0 commit comments