diff --git a/vault/policy_store.go b/vault/policy_store.go index 45439ebd60..d5800aad33 100644 --- a/vault/policy_store.go +++ b/vault/policy_store.go @@ -36,6 +36,9 @@ var ( "root", cubbyholeResponseWrappingPolicyName, } + nonAssignablePolicies = []string{ + cubbyholeResponseWrappingPolicyName, + } ) // PolicyStore is used to provide durable storage of policy, and to @@ -89,7 +92,7 @@ func (c *Core) setupPolicyStore() error { // Ensure that the cubbyhole response wrapping policy exists policy, err = c.policyStore.GetPolicy(cubbyholeResponseWrappingPolicyName) if err != nil { - return errwrap.Wrapf("error fetching default policy from store: {{err}}", err) + return errwrap.Wrapf("error fetching cubbyhole response wrapping policy from store: {{err}}", err) } if policy == nil || policy.Raw != cubbyholeResponseWrappingPolicy { err := c.policyStore.createCubbyholeResponseWrappingPolicy() @@ -114,7 +117,7 @@ func (ps *PolicyStore) SetPolicy(p *Policy) error { if p.Name == "" { return fmt.Errorf("policy name missing") } - if strutil.StrListContains(immutablePolicies, p.Name) { + if strutil.StrListContains(immutablePolicies, p.Name) || strutil.StrListContains(nonAssignablePolicies, p.Name) { return fmt.Errorf("cannot update %s policy", p.Name) } @@ -210,13 +213,30 @@ func (ps *PolicyStore) ListPolicies() ([]string, error) { defer metrics.MeasureSince([]string{"policy", "list_policies"}, time.Now()) // Scan the view, since the policy names are the same as the // key names. - return CollectKeys(ps.view) + keys, err := CollectKeys(ps.view) + + for _, nonAssignable := range nonAssignablePolicies { + deleteIndex := -1 + // Find the index of the non-assignable policies in keys + for index, key := range keys { + if key == nonAssignable { + // Don't delete a collection item while iterating + deleteIndex = index + break + } + } + // Remove any non-assignable policies found in keys + if deleteIndex != -1 { + keys = append(keys[:deleteIndex], keys[deleteIndex+1:]...) + } + } + return keys, err } // DeletePolicy is used to delete the named policy func (ps *PolicyStore) DeletePolicy(name string) error { defer metrics.MeasureSince([]string{"policy", "delete_policy"}, time.Now()) - if strutil.StrListContains(immutablePolicies, name) { + if strutil.StrListContains(immutablePolicies, name) || strutil.StrListContains(nonAssignablePolicies, name) { return fmt.Errorf("cannot delete %s policy", name) } if name == "default" { diff --git a/vault/token_store.go b/vault/token_store.go index c628bc279b..1da42b997a 100644 --- a/vault/token_store.go +++ b/vault/token_store.go @@ -1193,6 +1193,13 @@ func (ts *TokenStore) handleCreateCommon( return logical.ErrorResponse(err.Error()), logical.ErrInvalidRequest } + // Prevent internal policies from being assigned to any tokens + for _, policy := range te.Policies { + if strutil.StrListContains(nonAssignablePolicies, policy) { + return logical.ErrorResponse(fmt.Sprintf("cannot assign %s policy", policy)), nil + } + } + // Generate the response resp.Auth = &logical.Auth{ DisplayName: te.DisplayName, diff --git a/website/source/docs/audit/index.html.md b/website/source/docs/audit/index.html.md index 7646184078..74f8699c48 100644 --- a/website/source/docs/audit/index.html.md +++ b/website/source/docs/audit/index.html.md @@ -21,9 +21,10 @@ but also a second copy in case the first is tampered with. ## Sensitive Information The audit logs contain the full request and response objects for every -interaction with Vault. The data in the request and the data in the -response (including secrets and authentication tokens) will be hashed -with a salt using HMAC-SHA256. +interaction with Vault. The request and response can be matched utilizing a +unique identifier assigned to each request. The data in the request and the +data in the response (including secrets and authentication tokens) will be +hashed with a salt using HMAC-SHA256. The purpose of the hash is so that secrets aren't in plaintext within your audit logs. However, you're still able to check the value of secrets by