Skip to content

Commit

Permalink
gcp: add support for custom OAuth2 scopes
Browse files Browse the repository at this point in the history
This commit adds support for custom OAuth2 scopes.
On GCP / GKE an instance / application can have
custom OAuth2 scopes. The scopes define which APIs
the application / instance can access.

Before, KES always used the default scopes and
didn't provide a way to specify custom scopes.
This can lead to authentication failures to GCP
when custom scopes are used.

Now, custom scopes can be specified via the `scopes` option:
```
scopes:
- "scope-1"
- "scope-2"
- ...
```

Signed-off-by: Andreas Auernhammer <hi@aead.dev>
  • Loading branch information
aead committed May 13, 2022
1 parent fbe6fa7 commit 0189dea
Show file tree
Hide file tree
Showing 8 changed files with 43 additions and 12 deletions.
8 changes: 8 additions & 0 deletions cmd/kes/config.go
Expand Up @@ -138,9 +138,17 @@ func connect(config *yml.ServerConfig, quiet quiet, errorLog *log.Logger) (key.S
case config.KeyStore.GCP.SecretManager.ProjectID.Value() != "":
msg := fmt.Sprintf("Authenticating to GCP SecretManager Project: '%s' ... ", config.KeyStore.GCP.SecretManager.ProjectID.Value())
quiet.Print(msg)

scopes := make([]string, 0, len(config.KeyStore.GCP.SecretManager.Scopes))
for _, scope := range config.KeyStore.GCP.SecretManager.Scopes {
if scope.Value() != "" {
scopes = append(scopes, scope.Value())
}
}
gcpStore, err := gcp.Connect(context.Background(), &gcp.Config{
Endpoint: config.KeyStore.GCP.SecretManager.Endpoint.Value(),
ProjectID: config.KeyStore.GCP.SecretManager.ProjectID.Value(),
Scopes: scopes,
Credentials: gcp.Credentials{
ClientID: config.KeyStore.GCP.SecretManager.Credentials.ClientID.Value(),
Client: config.KeyStore.GCP.SecretManager.Credentials.Client.Value(),
Expand Down
20 changes: 16 additions & 4 deletions internal/gcp/config.go
Expand Up @@ -72,6 +72,12 @@ type Config struct {
// access the SecretManager.
Credentials Credentials

// Scopes are GCP OAuth2 scopes for accessing GCP APIs.
// If not set, defaults to the GCP default scopes.
//
// Ref: https://developers.google.com/identity/protocols/oauth2/scopes
Scopes []string

// ErrorLog is an optional logger for errors
// that may occur when interacting with GCP
// SecretManager.
Expand All @@ -90,11 +96,17 @@ func (c *Config) Clone() *Config {

c.lock.RLock()
defer c.lock.RUnlock()
return &Config{
Endpoint: c.Endpoint,
ProjectID: c.ProjectID,
ErrorLog: c.ErrorLog,
clone := &Config{
Endpoint: c.Endpoint,
ProjectID: c.ProjectID,
Credentials: c.Credentials,
ErrorLog: c.ErrorLog,
}
if len(c.Scopes) > 0 {
clone.Scopes = make([]string, 0, len(c.Scopes))
clone.Scopes = append(clone.Scopes, c.Scopes...)
}
return clone
}

func (c *Config) setDefaults() {
Expand Down
3 changes: 3 additions & 0 deletions internal/gcp/secret-manager.go
Expand Up @@ -77,6 +77,9 @@ func Connect(ctx context.Context, c *Config) (*SecretManager, error) {
}
options = append(options, option.WithCredentialsJSON(credentialsJSON))
}
if len(c.Scopes) != 0 {
options = append(options, option.WithScopes(c.Scopes...))
}

client, err := secretmanager.NewClient(ctx, options...)
if err != nil {
Expand Down
5 changes: 3 additions & 2 deletions internal/yml/server-config.go
Expand Up @@ -129,8 +129,9 @@ type ServerConfig struct {

GCP struct {
SecretManager struct {
ProjectID String `yaml:"project_id"`
Endpoint String `yaml:"endpoint"`
ProjectID String `yaml:"project_id"`
Endpoint String `yaml:"endpoint"`
Scopes []String `yaml:"scopes"`
Credentials struct {
Client String `yaml:"client_email"`
ClientID String `yaml:"client_id"`
Expand Down
5 changes: 3 additions & 2 deletions internal/yml/server-config_v0.13.5.go
Expand Up @@ -115,8 +115,9 @@ type serverConfigV0135 struct {

GCP struct {
SecretManager struct {
ProjectID String `yaml:"project_id"`
Endpoint String `yaml:"endpoint"`
ProjectID String `yaml:"project_id"`
Endpoint String `yaml:"endpoint"`
Scopes []String `yaml:"scopes"`
Credentials struct {
Client String `yaml:"client_email"`
ClientID String `yaml:"client_id"`
Expand Down
5 changes: 3 additions & 2 deletions internal/yml/server-config_v0.14.0.go
Expand Up @@ -119,8 +119,9 @@ type serverConfigV0140 struct {

GCP struct {
SecretManager struct {
ProjectID String `yaml:"project_id"`
Endpoint String `yaml:"endpoint"`
ProjectID String `yaml:"project_id"`
Endpoint String `yaml:"endpoint"`
Scopes []String `yaml:"scopes"`
Credentials struct {
Client String `yaml:"client_email"`
ClientID String `yaml:"client_id"`
Expand Down
5 changes: 3 additions & 2 deletions internal/yml/server-config_v0.17.0.go
Expand Up @@ -120,8 +120,9 @@ type serverConfigV0170 struct {

GCP struct {
SecretManager struct {
ProjectID String `yaml:"project_id"`
Endpoint String `yaml:"endpoint"`
ProjectID String `yaml:"project_id"`
Endpoint String `yaml:"endpoint"`
Scopes []String `yaml:"scopes"`
Credentials struct {
Client String `yaml:"client_email"`
ClientID String `yaml:"client_id"`
Expand Down
4 changes: 4 additions & 0 deletions server-config.yaml
Expand Up @@ -257,6 +257,10 @@ keystore:
project_id: ""
# An optional GCP SecretManager endpoint. If not set, defaults to: secretmanager.googleapis.com:443
endpoint: ""
# An optional list of GCP OAuth2 scopes. For a list of GCP scopes refer to: https://developers.google.com/identity/protocols/oauth2/scopes
# If not set, the GCP default scopes are used.
scopes:
- ""
# The credentials for your GCP service account. If running inside GCP (app engine) the credentials
# can be empty and will be fetched from the app engine environment automatically.
credentials:
Expand Down

0 comments on commit 0189dea

Please sign in to comment.