From dbdeda036e360ca11d3d8d3de219e895d91cffae Mon Sep 17 00:00:00 2001 From: srinandan <13950006+srinandan@users.noreply.github.com> Date: Tue, 17 Oct 2023 14:47:21 -0700 Subject: [PATCH] feat: adds support for GDAC #144 --- README.md | 21 +++++++++++++++++++-- cmd/root.go | 29 ++++++++++++++++++++++------- internal/apiclient/token.go | 17 +++++++++++++++++ 3 files changed, 58 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 54aad43f..28a8721a 100644 --- a/README.md +++ b/README.md @@ -22,10 +22,10 @@ Run this script to download & install the latest version (on Linux or Darwin) curl -L https://raw.githubusercontent.com/GoogleCloudPlatform/application-integration-management-toolkit/main/downloadLatest.sh | sh - ``` - ## Getting Started ### User Tokens + The simplest way to get started with integrationcli is ```sh @@ -44,7 +44,24 @@ If you are using `integrationcli` on Cloud Shell, GCE instances, Cloud Build, th integrationcli integrations list -p $project -r $region --metadata-token ``` +### Google Default Application Credentials + +You can configure gcloud to setup/create default application credentials. These credentials can be used by `apigeecli`. + +```sh +gcloud auth application-default login +integrationcli integrations list -p $project -r $region --default-token +``` + +or through impersonation + +```sh +gcloud auth application-default login --impersonate-service-account +integrationcli integrations list -p $project -r $region --default-token +``` + ### Set Preferences + If you are using the same GCP project for Integration, then consider setting up preferences so they don't have to be included in every command ```sh @@ -97,7 +114,6 @@ or integrationcli token cache --metadata-token ``` - ## Available Commands Here is a [list](./docs/integrationcli.md) of available commands @@ -118,6 +134,7 @@ The following environment variables may be set to control the behavior of `integ Please see [here](./cicd/README.md) for details on how to automate deployments via Cloud Build. The container images for integrationcli are: * Container image for the CLI + ``` docker pull us-docker.pkg.dev/appintegration-toolkit/images/integrationcli:latest ``` diff --git a/cmd/root.go b/cmd/root.go index da2e7511..37f30042 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -50,17 +50,20 @@ var RootCmd = &cobra.Command{ cmdServiceAccount := cmd.Flag("account").Value.String() cmdToken := cmd.Flag("token").Value.String() + if metadataToken && defaultToken { + return fmt.Errorf("metadata-token and default-token cannot be used together") + } + if metadataToken && (cmdServiceAccount != "" || cmdToken != "") { return fmt.Errorf("metadata-token cannot be used with token or account flags") } - if cmdServiceAccount != "" && cmdToken != "" { - return fmt.Errorf("token and account flags cannot be used together") + if defaultToken && (cmdServiceAccount != "" || cmdToken != "") { + return fmt.Errorf("default-token cannot be used with token or account flags") } - if !metadataToken { - apiclient.SetServiceAccount(cmdServiceAccount) - apiclient.SetIntegrationToken(cmdToken) + if cmdServiceAccount != "" && cmdToken != "" { + return fmt.Errorf("token and account flags cannot be used together") } if !disableCheck { @@ -77,10 +80,19 @@ var RootCmd = &cobra.Command{ apiclient.SetAPI(api) + if !metadataToken { + apiclient.SetServiceAccount(cmdServiceAccount) + apiclient.SetIntegrationToken(cmdToken) + } + if metadataToken { return apiclient.GetDefaultAccessToken() } + if defaultToken { + return apiclient.GetDefaultAccessToken() + } + _ = apiclient.SetAccessToken() return nil @@ -96,8 +108,8 @@ func Execute() { } var ( - disableCheck, printOutput, noOutput, suppressWarnings, verbose, metadataToken bool - api apiclient.API + disableCheck, printOutput, noOutput, suppressWarnings, verbose, metadataToken, defaultToken bool + api apiclient.API ) const ENABLED = "true" @@ -131,6 +143,9 @@ func init() { RootCmd.PersistentFlags().BoolVarP(&metadataToken, "metadata-token", "", false, "Metadata OAuth2 access token") + RootCmd.PersistentFlags().BoolVarP(&defaultToken, "default-token", "", + false, "Use Google default application credentials access token") + RootCmd.PersistentFlags().Var(&api, "api", "Sets the control plane API. Must be one of prod, "+ "staging or autopush; default is prod") diff --git a/internal/apiclient/token.go b/internal/apiclient/token.go index daafe556..387a6ad9 100644 --- a/internal/apiclient/token.go +++ b/internal/apiclient/token.go @@ -15,6 +15,7 @@ package apiclient import ( + "context" "crypto/x509" "encoding/json" "encoding/pem" @@ -33,6 +34,7 @@ import ( "github.com/lestrrat-go/jwx/v2/jwa" "github.com/lestrrat-go/jwx/v2/jwt" + "golang.org/x/oauth2/google" ) type serviceAccount struct { @@ -262,6 +264,21 @@ func SetAccessToken() error { // GetDefaultAccessToken func GetDefaultAccessToken() (err error) { + ctx := context.Background() + tokenSource, err := google.DefaultTokenSource(ctx, "https://www.googleapis.com/auth/cloud-platform") + if err != nil { + return err + } + token, err := tokenSource.Token() + if err != nil { + return err + } + SetIntegrationToken(token.AccessToken) + return nil +} + +// GetMetadataAccessToken +func GetMetadataAccessToken() (err error) { var req *http.Request var tokenResponse map[string]interface{}