diff --git a/pkg/clients/gke/gke.go b/pkg/clients/gke/gke.go index 722f2d5..470a8ef 100644 --- a/pkg/clients/gke/gke.go +++ b/pkg/clients/gke/gke.go @@ -19,6 +19,7 @@ package gke import ( "context" + "encoding/json" "net/http" "github.com/pkg/errors" @@ -36,15 +37,49 @@ var DefaultScopes = []string{ // WrapRESTConfig configures the supplied REST config to use OAuth2 bearer // tokens fetched using the supplied Google Application Credentials. func WrapRESTConfig(ctx context.Context, rc *rest.Config, credentials []byte, scopes ...string) error { - creds, err := google.CredentialsFromJSON(ctx, credentials, scopes...) + var ts oauth2.TokenSource + if credentials != nil { + if isJSON(credentials) { + // If credentials are in a JSON format, extract the credential from the JSON + // CredentialsFromJSON creates a TokenSource that handles token caching. + creds, err := google.CredentialsFromJSON(ctx, credentials, scopes...) + if err != nil { + return errors.Wrap(err, "cannot load Google Application Credentials from JSON") + } + ts = creds.TokenSource + rc.Wrap(func(rt http.RoundTripper) http.RoundTripper { + return &oauth2.Transport{Source: ts, Base: rt} + }) + return nil + } + // if the credential not in a JSON format, treat the credential as an access token + t := oauth2.Token{ + AccessToken: string(credentials), + } + if ok := t.Valid(); !ok { + return errors.New("Access token invalid") + } + ts = oauth2.StaticTokenSource(&t) + rc.Wrap(func(rt http.RoundTripper) http.RoundTripper { + return &oauth2.Transport{Source: ts, Base: rt} + }) + return nil + } + var t *oauth2.Token + // DefaultTokenSource retrieves a token source from an injected identity. + gsrc, err := google.DefaultTokenSource(ctx, scopes...) if err != nil { - return errors.Wrap(err, "cannot load Google Application Credentials from JSON") + return errors.Wrap(err, "failed to extract default credentials source") } - - // CredentialsFromJSON creates a TokenSource that handles token caching. + ts = oauth2.ReuseTokenSource(t, gsrc) rc.Wrap(func(rt http.RoundTripper) http.RoundTripper { - return &oauth2.Transport{Source: creds.TokenSource, Base: rt} + return &oauth2.Transport{Source: ts, Base: rt} }) return nil } + +func isJSON(b []byte) bool { + var js json.RawMessage + return json.Unmarshal(b, &js) == nil +} diff --git a/pkg/controller/release/release.go b/pkg/controller/release/release.go index 254f383..05a9f2f 100644 --- a/pkg/controller/release/release.go +++ b/pkg/controller/release/release.go @@ -136,7 +136,7 @@ func withRelease(cr *v1beta1.Release) helmClient.ArgsApplier { } } -func (c *connector) Connect(ctx context.Context, mg resource.Managed) (managed.ExternalClient, error) { +func (c *connector) Connect(ctx context.Context, mg resource.Managed) (managed.ExternalClient, error) { //nolint:gocyclo cr, ok := mg.(*v1beta1.Release) if !ok { return nil, errors.New(errNotRelease) @@ -184,14 +184,21 @@ func (c *connector) Connect(ctx context.Context, mg resource.Managed) (managed.E // NOTE(negz): We don't currently check the identity type because at the // time of writing there's only one valid value (Google App Creds), and // that value is required. - if id := p.Spec.Identity; id != nil { - creds, err := c.gcpExtractorFn(ctx, id.Source, c.client, id.CommonCredentialSelectors) - if err != nil { - return nil, errors.Wrap(err, errFailedToExtractGoogleCredentials) - } + if id := p.Spec.Identity; id != nil { //nolint:exhaustive + switch id.Source { //nolint:exhaustive + case xpv1.CredentialsSourceInjectedIdentity: + if err := c.gcpInjectorFn(ctx, rc, nil, gke.DefaultScopes...); err != nil { + return nil, errors.Wrap(err, errFailedToInjectGoogleCredentials) + } + default: + creds, err := c.gcpExtractorFn(ctx, id.Source, c.client, id.CommonCredentialSelectors) + if err != nil { + return nil, errors.Wrap(err, errFailedToExtractGoogleCredentials) + } - if err := c.gcpInjectorFn(ctx, rc, creds, gke.DefaultScopes...); err != nil { - return nil, errors.Wrap(err, errFailedToInjectGoogleCredentials) + if err := c.gcpInjectorFn(ctx, rc, creds, gke.DefaultScopes...); err != nil { + return nil, errors.Wrap(err, errFailedToInjectGoogleCredentials) + } } }