Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into sys-hostinfo
Browse files Browse the repository at this point in the history
  • Loading branch information
calvn committed Oct 3, 2019
2 parents ad7788b + e54c2e9 commit b0f7c36
Show file tree
Hide file tree
Showing 69 changed files with 1,716 additions and 222 deletions.
22 changes: 21 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@

FEATURES:

* **Stackdriver Metrics Sync**: Vault can now send metrics to
* **Stackdriver Metrics Sink**: Vault can now send metrics to
[Stackdriver](https://cloud.google.com/stackdriver/). See the [configuration
documentation](https://www.vaultproject.io/docs/config/index.html) for
details. [GH-6957]

CHANGES:
* sys/seal-status now has a `storage_type` field denoting what type of storage
the cluster is configured to use

IMPROVEMENTS:

* auth/jwt: The redirect callback host may now be specified for CLI logins
Expand All @@ -15,6 +19,22 @@ IMPROVEMENTS:
* secrets/aws: The root config can now be read [GH-7245]
* storage/cassandra: Improve storage efficiency by eliminating unnecessary
copies of value data [GH-7199]
* replication (enterprise): Write-Ahead-Log entries will not duplicate the
data belonging to the encompassing physical entries of the transaction,
thereby improving the performance and storage capacity.

BUG FIXES:
* agent: Fix handling of gzipped responses [GH-7470]
* auth/gcp: Fix a bug where region information in instance groups names could
cause an authorization attempt to fail [GCP-74]
* cli: Fix a bug where a token of an unknown format (e.g. in ~/.vault-token)
could cause confusing error messages during `vault login` [GH-7508]
* identity: Add required field `response_types_supported` to identity token
`.well-known/openid-configuration` response [GH-7533]
* identity (enterprise): Fixed identity case sensitive loading in secondary
cluster [GH-7327]
* ui: using the `wrapped_token` query param will work with `redirect_to` and
will automatically log in as intended [GH-7398]

## 1.2.3 (September 12, 2019)

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ Developing Vault
--------------------

If you wish to work on Vault itself or any of its built-in systems, you'll
first need [Go](https://www.golang.org) installed on your machine (version
1.12.1+ is *required*).
first need [Go](https://www.golang.org) installed on your machine. Go version
1.12.7+ is *required*. Note: version 1.13.x is not yet supported.

For local dev first make sure Go is properly installed, including setting up a
[GOPATH](https://golang.org/doc/code.html#GOPATH). Ensure that `$GOPATH/bin` is in
Expand Down
2 changes: 1 addition & 1 deletion api/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ require (
github.com/hashicorp/go-retryablehttp v0.6.2
github.com/hashicorp/go-rootcerts v1.0.1
github.com/hashicorp/hcl v1.0.0
github.com/hashicorp/vault/sdk v0.1.14-0.20190904164450-29f2490f986b
github.com/hashicorp/vault/sdk v0.1.14-0.20190919081434-645ac174deeb
github.com/mitchellh/mapstructure v1.1.2
github.com/shirou/gopsutil v0.0.0-20190731134726-d80c43f9c984 // indirect
golang.org/x/net v0.0.0-20190620200207-3b0461eec859
Expand Down
1 change: 1 addition & 0 deletions api/sys_seal.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ type SealStatusResponse struct {
ClusterName string `json:"cluster_name,omitempty"`
ClusterID string `json:"cluster_id,omitempty"`
RecoverySeal bool `json:"recovery_seal"`
StorageType string `json:"storage_type,omitempty"`
}

type UnsealOpts struct {
Expand Down
1 change: 0 additions & 1 deletion builtin/credential/aws/backend_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ func TestBackend_E2E_Initialize(t *testing.T) {
// Make sure that the upgrade happened, by fishing the 'config/version'
// entry out of storage. We can't use core.Client.Logical().Read() to do
// this, because 'config/version' hasn't been exposed as a path.
// TODO: should we expose 'config/version' as a path?
version, err := core.UnderlyingStorage.Get(ctx, awsPath+"config/version")
if err != nil {
t.Fatal(err)
Expand Down
65 changes: 44 additions & 21 deletions builtin/logical/aws/backend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,25 @@ func TestBackend_basic(t *testing.T) {
})
}

func TestBackend_IamUserWithPermissionsBoundary(t *testing.T) {
t.Parallel()
roleData := map[string]interface{}{
"credential_type": iamUserCred,
"policy_arns": adminAccessPolicyArn,
"permissions_boundary_arn": iamPolicyArn,
}
logicaltest.Test(t, logicaltest.TestCase{
AcceptanceTest: true,
PreCheck: func() { testAccPreCheck(t) },
LogicalBackend: getBackend(t),
Steps: []logicaltest.TestStep{
testAccStepConfig(t),
testAccStepWriteRole(t, "test", roleData),
testAccStepRead(t, "creds", "test", []credentialTestFunc{listIamUsersTest, describeAzsTestUnauthorized}),
},
})
}

func TestBackend_basicSTS(t *testing.T) {
t.Parallel()
awsAccountID, err := getAccountID()
Expand Down Expand Up @@ -681,13 +700,14 @@ func testAccStepReadPolicy(t *testing.T, name string, value string) logicaltest.
}

expected := map[string]interface{}{
"policy_arns": []string(nil),
"role_arns": []string(nil),
"policy_document": value,
"credential_type": strings.Join([]string{iamUserCred, federationTokenCred}, ","),
"default_sts_ttl": int64(0),
"max_sts_ttl": int64(0),
"user_path": "",
"policy_arns": []string(nil),
"role_arns": []string(nil),
"policy_document": value,
"credential_type": strings.Join([]string{iamUserCred, federationTokenCred}, ","),
"default_sts_ttl": int64(0),
"max_sts_ttl": int64(0),
"user_path": "",
"permissions_boundary_arn": "",
}
if !reflect.DeepEqual(resp.Data, expected) {
return fmt.Errorf("bad: got: %#v\nexpected: %#v", resp.Data, expected)
Expand All @@ -714,6 +734,7 @@ const testDynamoPolicy = `{
}
`

const adminAccessPolicyArn = "arn:aws:iam::aws:policy/AdministratorAccess"
const ec2PolicyArn = "arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess"
const iamPolicyArn = "arn:aws:iam::aws:policy/IAMReadOnlyAccess"
const dynamoPolicyArn = "arn:aws:iam::aws:policy/AmazonDynamoDBReadOnlyAccess"
Expand Down Expand Up @@ -782,13 +803,14 @@ func TestBackend_iamUserManagedInlinePolicies(t *testing.T) {
"user_path": "/path/",
}
expectedRoleData := map[string]interface{}{
"policy_document": compacted,
"policy_arns": []string{ec2PolicyArn, iamPolicyArn},
"credential_type": iamUserCred,
"role_arns": []string(nil),
"default_sts_ttl": int64(0),
"max_sts_ttl": int64(0),
"user_path": "/path/",
"policy_document": compacted,
"policy_arns": []string{ec2PolicyArn, iamPolicyArn},
"credential_type": iamUserCred,
"role_arns": []string(nil),
"default_sts_ttl": int64(0),
"max_sts_ttl": int64(0),
"user_path": "/path/",
"permissions_boundary_arn": "",
}

logicaltest.Test(t, logicaltest.TestCase{
Expand Down Expand Up @@ -986,13 +1008,14 @@ func testAccStepReadArnPolicy(t *testing.T, name string, value string) logicalte
}

expected := map[string]interface{}{
"policy_arns": []string{value},
"role_arns": []string(nil),
"policy_document": "",
"credential_type": iamUserCred,
"default_sts_ttl": int64(0),
"max_sts_ttl": int64(0),
"user_path": "",
"policy_arns": []string{value},
"role_arns": []string(nil),
"policy_document": "",
"credential_type": iamUserCred,
"default_sts_ttl": int64(0),
"max_sts_ttl": int64(0),
"user_path": "",
"permissions_boundary_arn": "",
}
if !reflect.DeepEqual(resp.Data, expected) {
return fmt.Errorf("bad: got: %#v\nexpected: %#v", resp.Data, expected)
Expand Down
54 changes: 47 additions & 7 deletions builtin/logical/aws/path_roles.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,14 @@ GetFederationToken API call, acting as a filter on permissions available.`,
},
},

"permissions_boundary_arn": &framework.FieldSchema{
Type: framework.TypeString,
Description: "ARN of an IAM policy to attach as a permissions boundary on IAM user credentials; only valid when credential_type is" + iamUserCred,
DisplayAttrs: &framework.DisplayAttributes{
Name: "Permissions Boundary ARN",
},
},

"arn": &framework.FieldSchema{
Type: framework.TypeString,
Description: `Use role_arns or policy_arns instead.`,
Expand Down Expand Up @@ -269,6 +277,13 @@ func (b *backend) pathRolesWrite(ctx context.Context, req *logical.Request, d *f
roleEntry.UserPath = userPathRaw.(string)
}

if permissionsBoundaryARNRaw, ok := d.GetOk("permissions_boundary_arn"); ok {
if legacyRole != "" {
return logical.ErrorResponse("cannot supply deprecated role or policy parameters with permissions_boundary_arn"), nil
}
roleEntry.PermissionsBoundaryARN = permissionsBoundaryARNRaw.(string)
}

if legacyRole != "" {
roleEntry = upgradeLegacyPolicyEntry(legacyRole)
if roleEntry.InvalidData != "" {
Expand Down Expand Up @@ -414,6 +429,20 @@ func upgradeLegacyPolicyEntry(entry string) *awsRoleEntry {
return newRoleEntry
}

func validateAWSManagedPolicy(policyARN string) error {
parsedARN, err := arn.Parse(policyARN)
if err != nil {
return err
}
if parsedARN.Service != "iam" {
return fmt.Errorf("expected a service of iam but got %s", parsedARN.Service)
}
if !strings.HasPrefix(parsedARN.Resource, "policy/") {
return fmt.Errorf("expected a resource type of policy but got %s", parsedARN.Resource)
}
return nil
}

func setAwsRole(ctx context.Context, s logical.Storage, roleName string, roleEntry *awsRoleEntry) error {
if roleName == "" {
return fmt.Errorf("empty role name")
Expand Down Expand Up @@ -445,17 +474,19 @@ type awsRoleEntry struct {
DefaultSTSTTL time.Duration `json:"default_sts_ttl"` // Default TTL for STS credentials
MaxSTSTTL time.Duration `json:"max_sts_ttl"` // Max allowed TTL for STS credentials
UserPath string `json:"user_path"` // The path for the IAM user when using "iam_user" credential type
PermissionsBoundaryARN string `json:"permissions_boundary_arn"` // ARN of an IAM policy to attach as a permissions boundary
}

func (r *awsRoleEntry) toResponseData() map[string]interface{} {
respData := map[string]interface{}{
"credential_type": strings.Join(r.CredentialTypes, ","),
"policy_arns": r.PolicyArns,
"role_arns": r.RoleArns,
"policy_document": r.PolicyDocument,
"default_sts_ttl": int64(r.DefaultSTSTTL.Seconds()),
"max_sts_ttl": int64(r.MaxSTSTTL.Seconds()),
"user_path": r.UserPath,
"credential_type": strings.Join(r.CredentialTypes, ","),
"policy_arns": r.PolicyArns,
"role_arns": r.RoleArns,
"policy_document": r.PolicyDocument,
"default_sts_ttl": int64(r.DefaultSTSTTL.Seconds()),
"max_sts_ttl": int64(r.MaxSTSTTL.Seconds()),
"user_path": r.UserPath,
"permissions_boundary_arn": r.PermissionsBoundaryARN,
}

if r.InvalidData != "" {
Expand Down Expand Up @@ -501,6 +532,15 @@ func (r *awsRoleEntry) validate() error {
}
}

if r.PermissionsBoundaryARN != "" {
if !strutil.StrListContains(r.CredentialTypes, iamUserCred) {
errors = multierror.Append(errors, fmt.Errorf("cannot supply permissions_boundary_arn when credential_type isn't %s", iamUserCred))
}
if err := validateAWSManagedPolicy(r.PermissionsBoundaryARN); err != nil {
errors = multierror.Append(fmt.Errorf("invalid permissions_boundary_arn parameter: %v", err))
}
}

if len(r.RoleArns) > 0 && !strutil.StrListContains(r.CredentialTypes, assumedRoleCred) {
errors = multierror.Append(errors, fmt.Errorf("cannot supply role_arns when credential_type isn't %s", assumedRoleCred))
}
Expand Down
Loading

0 comments on commit b0f7c36

Please sign in to comment.