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

Added support for access tokens in gcpkms #1358

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 18 additions & 6 deletions gcpkms/keysource.go
Expand Up @@ -3,7 +3,9 @@ package gcpkms // import "github.com/getsops/sops/v3/gcpkms"
import (
"context"
"encoding/base64"
"encoding/json"
"fmt"
"golang.org/x/oauth2"
"os"
"regexp"
"strings"
Expand Down Expand Up @@ -208,16 +210,26 @@ func (key *MasterKey) newKMSClient() (*kms.KeyManagementClient, error) {
}

var opts []option.ClientOption
switch {
case key.credentialJSON != nil:
opts = append(opts, option.WithCredentialsJSON(key.credentialJSON))
default:
credentialJSON := key.credentialJSON

if credentialJSON == nil {
credentials, err := getGoogleCredentials()
if err != nil {
return nil, err
}
if credentials != nil {
opts = append(opts, option.WithCredentialsJSON(credentials))

credentialJSON = credentials
}

if credentialJSON != nil {
token := oauth2.Token{}

if err := json.Unmarshal(credentialJSON, &token); err != nil {
return nil, err
} else if token.AccessToken != "" {
opts = append(opts, option.WithTokenSource(oauth2.StaticTokenSource(&token)))
} else {
opts = append(opts, option.WithCredentialsJSON(credentialJSON))
}
}
if key.grpcConn != nil {
Expand Down
87 changes: 74 additions & 13 deletions gcpkms/keysource_test.go
Expand Up @@ -3,7 +3,9 @@ package gcpkms
import (
"encoding/base64"
"fmt"
"io"
"net"
"os"
"testing"
"time"

Expand Down Expand Up @@ -118,34 +120,93 @@ func TestMasterKey_ToMap(t *testing.T) {

func TestMasterKey_createCloudKMSService(t *testing.T) {
tests := []struct {
key MasterKey
errString string
key MasterKey
credentials string
errString string
description string
}{
{
key: MasterKey{
ResourceID: "/projects",
credentialJSON: []byte("some secret"),
ResourceID: "/projects",
},
errString: "no valid resource ID",
credentials: "some secret",
errString: "no valid resource ID",
description: "invalid resource ID",
},
{
key: MasterKey{
ResourceID: testResourceID,
credentialJSON: []byte(`{ "client_id": "<client-id>.apps.googleusercontent.com",
},
credentials: `{ "client_id": "<client-id>.apps.googleusercontent.com",
"client_secret": "<secret>",
"type": "authorized_user"}`),
"type": "authorized_user"}`,
description: "valid user credentials",
},
{
key: MasterKey{
ResourceID: testResourceID,
},
credentials: `{ "access_token": "access_token"}`,
description: "valid access token credentials",
},
{
key: MasterKey{
ResourceID: testResourceID,
},
credentials: `{ invalid_json }`,
errString: "invalid character 'i' looking for beginning of object key string",
description: "invalid json",
},
{
key: MasterKey{
ResourceID: testResourceID,
},
credentials: `{}`,
errString: "missing 'type' field in credentials",
description: "invalid credentials",
},
}

for _, tt := range tests {
_, err := tt.key.newKMSClient()
if tt.errString != "" {
assert.Error(t, err)
assert.ErrorContains(t, err, tt.errString)
return
r := func(t *testing.T) {
_, err := tt.key.newKMSClient()
if tt.errString != "" {
assert.Error(t, err)
assert.ErrorContains(t, err, tt.errString)
return
}
assert.NoError(t, err)
}
assert.NoError(t, err)

t.Run(tt.description+" credentials from var", func(t *testing.T) {
tt.key.credentialJSON = []byte(tt.credentials)
r(t)
})

t.Run(tt.description+" credentials from env json", func(t *testing.T) {
t.Setenv("GOOGLE_CREDENTIALS", tt.credentials)
tt.key.credentialJSON = nil
r(t)
})

t.Run(tt.description+" credentials from env file", func(t *testing.T) {
file, err := os.CreateTemp(t.TempDir(), "gcp_creds.*.json")
assert.NoError(t, err)

_, err = io.WriteString(file, tt.credentials)
assert.NoError(t, err)

t.Setenv("GOOGLE_CREDENTIALS", file.Name())
tt.key.credentialJSON = nil
r(t)

// Test file permissions
err = os.Chmod(file.Name(), 200)
assert.NoError(t, err)

_, err = tt.key.newKMSClient()
assert.Error(t, err)
})
}
}

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Expand Up @@ -35,6 +35,7 @@ require (
github.com/stretchr/testify v1.8.4
github.com/urfave/cli v1.22.14
golang.org/x/net v0.19.0
golang.org/x/oauth2 v0.14.0
golang.org/x/sys v0.15.0
golang.org/x/term v0.15.0
google.golang.org/api v0.153.0
Expand Down Expand Up @@ -117,7 +118,6 @@ require (
go.opencensus.io v0.24.0 // indirect
golang.org/x/crypto v0.16.0 // indirect
golang.org/x/mod v0.9.0 // indirect
golang.org/x/oauth2 v0.14.0 // indirect
golang.org/x/sync v0.5.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.5.0 // indirect
Expand Down