Skip to content

Commit

Permalink
feat(sgartifactregistry): determine if access token is expired on npm…
Browse files Browse the repository at this point in the history
… auth

When using `gcloud auth print-access-token`, gcloud will print the token
regardless on whether the token is expired or not.
We use gcloud to figure out if the token is expired for a better user
experience (instead of the user getting back a 403 which can be
confusing)
  • Loading branch information
alethenorio committed Nov 22, 2023
1 parent 4907ca6 commit 419fcdb
Showing 1 changed file with 40 additions and 1 deletion.
41 changes: 40 additions & 1 deletion tools/sgartifactregistry/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"os/exec"
"strconv"
"strings"

"go.einride.tech/sage/sg"
Expand All @@ -24,13 +25,22 @@ func NpmAuthenticate(ctx context.Context, packageJSONDir, registryURL string) er
if err := cmd.Run(); err != nil {
return err
}

registry := strings.TrimPrefix(registryURL, "https://")
// Trailing slashes at the end of the URL have been known to cause issues with some setups
registry = strings.TrimSuffix(registry, "/")

expired, err := isGoogleAuthExpired(ctx)
if err != nil {
return fmt.Errorf("unable to verify Google authentication token expiration: %v", err)
}
if expired {
return fmt.Errorf("google authentication token is expired. Please authenticate using 'gcloud auth login'")
}

// If we have yarn installed, find its version
yarnMajor := "1"
_, err := exec.LookPath("yarn")
_, err = exec.LookPath("yarn")
if err != nil {
if !errors.Is(err, exec.ErrNotFound) {
return err
Expand Down Expand Up @@ -81,3 +91,32 @@ func NpmAuthenticate(ctx context.Context, packageJSONDir, registryURL string) er

return nil
}

// isGoogleAuthExpired uses gcloud to determine whether the user has an expired token or not.
// false (along with a warning log) is returned if the gcloud auth describe command does not return data
// in the format we are expecting.
func isGoogleAuthExpired(ctx context.Context) (bool, error) {
var strExpiry string
account := sg.Output(sg.Command(ctx, "gcloud", "config", "get-value", "account"))
// gcloud auth describe is an undocumented gcloud API which allows us to get back
// information about the currently authenticated user including the token expiration time.
authInfo := sg.Output(sg.Command(ctx, "gcloud", "auth", "describe", account))
lines := strings.Split(authInfo, "\n")
for _, line := range lines {
if !strings.HasPrefix(line, "expired: ") {
continue
}
strExpiry = strings.TrimPrefix(line, "expired: ")
}
// Because the atuth describe command is not documented and could potentially changes,
// if we are unable to parse its output we will log a warning and return false.
if strExpiry == "" {
sg.Logger(ctx).Println("WARNING: unable to determine expiration time of Google authentication token")
return false, nil
}
authExpired, err := strconv.ParseBool(strExpiry)
if err != nil {
return false, fmt.Errorf("unable to parse expiration time of Google authentication token: %v", err)
}
return authExpired, nil
}

0 comments on commit 419fcdb

Please # to comment.