-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
) This moves the role-based alias configuration fields (`iam_alias`, `gce_alias` from an individual role to the GCP configuration. This will allow the user to specify the configuration for all roles rather than per-role.
- Loading branch information
Showing
10 changed files
with
338 additions
and
408 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,150 +1 @@ | ||
package gcpauth | ||
|
||
import ( | ||
"testing" | ||
|
||
"google.golang.org/api/compute/v1" | ||
"google.golang.org/api/iam/v1" | ||
) | ||
|
||
func TestGetIAMAlias(t *testing.T) { | ||
type testCase struct { | ||
role *gcpRole | ||
svcAccount *iam.ServiceAccount | ||
expectedAlias string | ||
expectErr bool | ||
} | ||
|
||
tests := map[string]testCase{ | ||
"invalid type": { | ||
role: &gcpRole{ | ||
IAMAliasType: "bogus", | ||
RoleID: "testRoleID", | ||
}, | ||
svcAccount: &iam.ServiceAccount{ | ||
UniqueId: "iamUniqueID", | ||
}, | ||
expectedAlias: "", | ||
expectErr: true, | ||
}, | ||
"empty type goes to default": { | ||
role: &gcpRole{ | ||
IAMAliasType: "", | ||
RoleID: "testRoleID", | ||
}, | ||
svcAccount: &iam.ServiceAccount{ | ||
UniqueId: "iamUniqueID", | ||
}, | ||
expectedAlias: "iamUniqueID", | ||
expectErr: false, | ||
}, | ||
"default type": { | ||
role: &gcpRole{ | ||
IAMAliasType: defaultIAMAlias, | ||
RoleID: "testRoleID", | ||
}, | ||
svcAccount: &iam.ServiceAccount{ | ||
UniqueId: "iamUniqueID", | ||
}, | ||
expectedAlias: "iamUniqueID", | ||
expectErr: false, | ||
}, | ||
"role_id": { | ||
role: &gcpRole{ | ||
IAMAliasType: "role_id", | ||
RoleID: "testRoleID", | ||
}, | ||
svcAccount: &iam.ServiceAccount{ | ||
UniqueId: "iamUniqueID", | ||
}, | ||
expectedAlias: "testRoleID", | ||
expectErr: false, | ||
}, | ||
} | ||
|
||
for name, test := range tests { | ||
t.Run(name, func(t *testing.T) { | ||
actualAlias, err := getIAMAlias(test.role, test.svcAccount) | ||
if test.expectErr && err == nil { | ||
t.Fatalf("err expected, got nil") | ||
} | ||
if !test.expectErr && err != nil { | ||
t.Fatalf("no error expected, got: %s", err) | ||
} | ||
if actualAlias != test.expectedAlias { | ||
t.Fatalf("Actual alias: %s Expected Alias: %s", actualAlias, test.expectedAlias) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestGetGCEAlias(t *testing.T) { | ||
type testCase struct { | ||
role *gcpRole | ||
instance *compute.Instance | ||
expectedAlias string | ||
expectErr bool | ||
} | ||
|
||
tests := map[string]testCase{ | ||
"invalid type": { | ||
role: &gcpRole{ | ||
GCEAliasType: "bogus", | ||
RoleID: "testRoleID", | ||
}, | ||
instance: &compute.Instance{ | ||
Id: 123, | ||
}, | ||
expectedAlias: "", | ||
expectErr: true, | ||
}, | ||
"empty type goes to default": { | ||
role: &gcpRole{ | ||
GCEAliasType: "", | ||
RoleID: "testRoleID", | ||
}, | ||
instance: &compute.Instance{ | ||
Id: 123, | ||
}, | ||
expectedAlias: "gce-123", | ||
expectErr: false, | ||
}, | ||
"default type": { | ||
role: &gcpRole{ | ||
GCEAliasType: defaultGCEAlias, | ||
RoleID: "testRoleID", | ||
}, | ||
instance: &compute.Instance{ | ||
Id: 123, | ||
}, | ||
expectedAlias: "gce-123", | ||
expectErr: false, | ||
}, | ||
"role_id": { | ||
role: &gcpRole{ | ||
GCEAliasType: "role_id", | ||
RoleID: "testRoleID", | ||
}, | ||
instance: &compute.Instance{ | ||
Id: 123, | ||
}, | ||
expectedAlias: "testRoleID", | ||
expectErr: false, | ||
}, | ||
} | ||
|
||
for name, test := range tests { | ||
t.Run(name, func(t *testing.T) { | ||
actualAlias, err := getGCEAlias(test.role, test.instance) | ||
if test.expectErr && err == nil { | ||
t.Fatalf("err expected, got nil") | ||
} | ||
if !test.expectErr && err != nil { | ||
t.Fatalf("no error expected, got: %s", err) | ||
} | ||
if actualAlias != test.expectedAlias { | ||
t.Fatalf("Actual alias: %s Expected Alias: %s", actualAlias, test.expectedAlias) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
package gcpauth | ||
|
||
import ( | ||
"encoding/json" | ||
"errors" | ||
"fmt" | ||
"strings" | ||
|
||
"github.com/hashicorp/errwrap" | ||
"github.com/hashicorp/go-gcp-common/gcputil" | ||
"github.com/hashicorp/vault/sdk/framework" | ||
"google.golang.org/api/compute/v1" | ||
"google.golang.org/api/iam/v1" | ||
) | ||
|
||
// gcpConfig contains all config required for the GCP backend. | ||
type gcpConfig struct { | ||
Credentials *gcputil.GcpCredentials `json:"credentials"` | ||
IAMAliasType string `json:"iam_alias"` | ||
GCEAliasType string `json:"gce_alias"` | ||
} | ||
|
||
// standardizedCreds wraps gcputil.GcpCredentials with a type to allow | ||
// parsing through Google libraries, since the google libraries struct is not | ||
// exposed. | ||
type standardizedCreds struct { | ||
*gcputil.GcpCredentials | ||
CredType string `json:"type"` | ||
} | ||
|
||
const serviceAccountCredsType = "service_account" | ||
|
||
// formatAsCredentialJSON converts and marshals the config credentials | ||
// into a parsable format by Google libraries. | ||
func (c *gcpConfig) formatAndMarshalCredentials() ([]byte, error) { | ||
if c == nil || c.Credentials == nil { | ||
return []byte{}, nil | ||
} | ||
|
||
return json.Marshal(standardizedCreds{ | ||
GcpCredentials: c.Credentials, | ||
CredType: serviceAccountCredsType, | ||
}) | ||
} | ||
|
||
// Update sets gcpConfig values parsed from the FieldData. | ||
func (c *gcpConfig) Update(d *framework.FieldData) (bool, error) { | ||
if d == nil { | ||
return false, nil | ||
} | ||
|
||
changed := false | ||
|
||
if v, ok := d.GetOk("credentials"); ok { | ||
creds, err := gcputil.Credentials(v.(string)) | ||
if err != nil { | ||
return false, errwrap.Wrapf("failed to read credentials: {{err}}", err) | ||
} | ||
|
||
if len(creds.PrivateKeyId) == 0 { | ||
return false, errors.New("missing private key in credentials") | ||
} | ||
|
||
c.Credentials = creds | ||
changed = true | ||
} | ||
|
||
rawIamAlias, exists := d.GetOk("iam_alias") | ||
if exists { | ||
iamAlias := rawIamAlias.(string) | ||
if iamAlias != c.IAMAliasType { | ||
c.IAMAliasType = iamAlias | ||
changed = true | ||
} | ||
} | ||
|
||
rawGceAlias, exists := d.GetOk("gce_alias") | ||
if exists { | ||
gceAlias := rawGceAlias.(string) | ||
if gceAlias != c.GCEAliasType { | ||
c.GCEAliasType = gceAlias | ||
changed = true | ||
} | ||
} | ||
|
||
return changed, nil | ||
} | ||
|
||
func (c *gcpConfig) getIAMAlias(role *gcpRole, svcAccount *iam.ServiceAccount) (alias string, err error) { | ||
aliasType := c.IAMAliasType | ||
if aliasType == "" { | ||
aliasType = defaultIAMAlias | ||
} | ||
|
||
aliaser, exists := allowedIAMAliases[aliasType] | ||
if !exists { | ||
return "", fmt.Errorf("invalid IAM alias type: must be one of: %s", strings.Join(allowedIAMAliasesSlice, ", ")) | ||
} | ||
return aliaser(role, svcAccount), nil | ||
} | ||
|
||
func (c *gcpConfig) getGCEAlias(role *gcpRole, instance *compute.Instance) (alias string, err error) { | ||
aliasType := c.GCEAliasType | ||
if aliasType == "" { | ||
aliasType = defaultGCEAlias | ||
} | ||
|
||
aliaser, exists := allowedGCEAliases[aliasType] | ||
if !exists { | ||
return "", fmt.Errorf("invalid GCE alias type: must be one of: %s", strings.Join(allowedGCEAliasesSlice, ", ")) | ||
} | ||
return aliaser(role, instance), nil | ||
} |
Oops, something went wrong.