Skip to content

Commit

Permalink
Use oauth/google library to check for ADC validity
Browse files Browse the repository at this point in the history
This change actually does:
  1. ADC login will not be triggered interactively, only an error
     message with the gcloud command will be shown.
  2. automatic_auth is now supported anywhere that has an ADC token
     available such as GCE
  3. Bootstrap will now verify that it can get a token in the critical
     path of startup for ADC, manually specified or automatic auth ADC.
     This may add 200-300ms of latency to startup but will ensure that
     all builds with ADC have valid credentials.

Branched from original change: []

Test: Added integration and unit tests
Bug: b/300945159
Change-Id: I95eb26acb2a7fa0a1e4c2d9823521b3e9695f23b
GitOrigin-RevId: f4832cfb64ec25d5ab2afed3017eae568e307eb3
  • Loading branch information
gkousik authored and copybara-github committed Oct 20, 2023
1 parent 74710a8 commit 565f0f5
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 9 deletions.
2 changes: 2 additions & 0 deletions internal/pkg/auth/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ go_library(
"@org_golang_google_protobuf//encoding/prototext",
"@org_golang_google_protobuf//types/known/timestamppb",
"@org_golang_x_oauth2//:oauth2",
"@org_golang_x_oauth2//google",
],
)

Expand All @@ -26,6 +27,7 @@ go_test(
],
embed = [":auth"],
deps = [
"//internal/pkg/auth/fakes",
"@com_github_google_go_cmp//cmp",
"@com_github_google_go_cmp//cmp/cmpopts",
"@org_golang_x_oauth2//:oauth2",
Expand Down
48 changes: 39 additions & 9 deletions internal/pkg/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package auth

import (
"context"
"encoding/json"
"errors"
"flag"
Expand All @@ -31,6 +32,7 @@ import (

log "github.com/golang/glog"
"golang.org/x/oauth2"
googleOauth "golang.org/x/oauth2/google"
grpcOauth "google.golang.org/grpc/credentials/oauth"
)

Expand Down Expand Up @@ -312,11 +314,6 @@ func (c *Credentials) TokenSource() *grpcOauth.TokenSource {
func runAuthCommand(m Mechanism) error {
var cmd *exec.Cmd
switch m {
case ADC:
cmd = exec.Command("gcloud", "auth", "application-default", "login")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
default:
return nil
}
Expand All @@ -325,10 +322,43 @@ func runAuthCommand(m Mechanism) error {
}

func checkADCStatus() error {
cmd := exec.Command("gcloud", "auth", "application-default", "print-access-token")
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
return cmd.Run()
ts, err := googleOauth.FindDefaultCredentialsWithParams(context.Background(), googleOauth.CredentialsParams{
EarlyTokenRefresh: 5 * time.Minute,
})
if err != nil {
return fmt.Errorf("could not find Application Default Credentials: %w", err)
}
token, err := ts.TokenSource.Token()

if err != nil {
aerr, ok := err.(*googleOauth.AuthenticationError)
if !ok {
return fmt.Errorf("could not get valid Application Default Credentials token: %w", err)
}
if aerr.Temporary() {
log.Errorf("Ignoring temporary ADC error: %v", err)
return nil
}
rerr, ok := aerr.Unwrap().(*oauth2.RetrieveError)
if !ok {
return fmt.Errorf("could not get valid Application Default Credentials token: %w", err)
}
var resp struct {
Error string `json:"error"`
ErrorSubtype string `json:"error_subtype"`
}
if err := json.Unmarshal(rerr.Body, &resp); err == nil &&
resp.Error == "invalid_grant" &&
resp.ErrorSubtype == "invalid_rapt" {
return fmt.Errorf("reauth required, run `gcloud auth application-default login` and try again")
}
return fmt.Errorf("could not get valid Application Default Credentials token: %w", err)
}
if !token.Valid() {
log.Errorf("Could not get valid Application Default Credentials token: %v", err)
return fmt.Errorf("could not get valid Application Default Credentials token: %w", err)
}
return nil
}

type gcpTokenProvider interface {
Expand Down

0 comments on commit 565f0f5

Please sign in to comment.