Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GKE Default Credentials and Temporary Access Tokens #63

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 35 additions & 4 deletions internal/clients/gke/gke.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package gke

import (
"context"
"encoding/json"
"net/http"

"github.com/pkg/errors"
Expand All @@ -33,15 +34,45 @@ var DefaultScopes []string = []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...)
if err != nil {
return errors.Wrap(err, "cannot load Google Application Credentials from JSON")
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
} else {
// 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)
}
} else {
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, "failed to extract default credentials source")
}
ts = oauth2.ReuseTokenSource(t, gsrc)
}

// CredentialsFromJSON creates a TokenSource that handles token caching.
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
}
19 changes: 13 additions & 6 deletions internal/controller/object/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,13 +161,20 @@ func (c *connector) Connect(ctx context.Context, mg resource.Managed) (managed.E
// time of writing there's only one valid value (Google App Creds), and
// that value is required.
if id := pc.Spec.Identity; id != nil {
creds, err := c.gcpExtractorFn(ctx, id.Source, c.kube, id.CommonCredentialSelectors)
if err != nil {
return nil, errors.Wrap(err, errFailedToExtractGoogleCredentials)
}
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.kube, 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)
}
}
}

Expand Down