diff --git a/http/sys_policy_test.go b/http/sys_policy_test.go index ed8339e620..f0250a01e7 100644 --- a/http/sys_policy_test.go +++ b/http/sys_policy_test.go @@ -17,8 +17,8 @@ func TestSysPolicies(t *testing.T) { var actual map[string]interface{} expected := map[string]interface{}{ - "policies": []interface{}{"default", "response-wrapping", "root"}, - "keys": []interface{}{"default", "response-wrapping", "root"}, + "policies": []interface{}{"default", "root"}, + "keys": []interface{}{"default", "root"}, } testResponseStatus(t, resp, 200) testResponseBody(t, resp, &actual) @@ -62,8 +62,8 @@ func TestSysWritePolicy(t *testing.T) { var actual map[string]interface{} expected := map[string]interface{}{ - "policies": []interface{}{"default", "foo", "response-wrapping", "root"}, - "keys": []interface{}{"default", "foo", "response-wrapping", "root"}, + "policies": []interface{}{"default", "foo", "root"}, + "keys": []interface{}{"default", "foo", "root"}, } testResponseStatus(t, resp, 200) testResponseBody(t, resp, &actual) @@ -100,8 +100,8 @@ func TestSysDeletePolicy(t *testing.T) { var actual map[string]interface{} expected := map[string]interface{}{ - "policies": []interface{}{"default", "response-wrapping", "root"}, - "keys": []interface{}{"default", "response-wrapping", "root"}, + "policies": []interface{}{"default", "root"}, + "keys": []interface{}{"default", "root"}, } testResponseStatus(t, resp, 200) testResponseBody(t, resp, &actual) diff --git a/vault/logical_system_test.go b/vault/logical_system_test.go index f354c2d037..d5c9a6eb71 100644 --- a/vault/logical_system_test.go +++ b/vault/logical_system_test.go @@ -614,8 +614,8 @@ func TestSystemBackend_policyList(t *testing.T) { } exp := map[string]interface{}{ - "keys": []string{"default", "response-wrapping", "root"}, - "policies": []string{"default", "response-wrapping", "root"}, + "keys": []string{"default", "root"}, + "policies": []string{"default", "root"}, } if !reflect.DeepEqual(resp.Data, exp) { t.Fatalf("got: %#v expect: %#v", resp.Data, exp) @@ -667,8 +667,8 @@ func TestSystemBackend_policyCRUD(t *testing.T) { } exp = map[string]interface{}{ - "keys": []string{"default", "foo", "response-wrapping", "root"}, - "policies": []string{"default", "foo", "response-wrapping", "root"}, + "keys": []string{"default", "foo", "root"}, + "policies": []string{"default", "foo", "root"}, } if !reflect.DeepEqual(resp.Data, exp) { t.Fatalf("got: %#v expect: %#v", resp.Data, exp) @@ -702,8 +702,8 @@ func TestSystemBackend_policyCRUD(t *testing.T) { } exp = map[string]interface{}{ - "keys": []string{"default", "response-wrapping", "root"}, - "policies": []string{"default", "response-wrapping", "root"}, + "keys": []string{"default", "root"}, + "policies": []string{"default", "root"}, } if !reflect.DeepEqual(resp.Data, exp) { t.Fatalf("got: %#v expect: %#v", resp.Data, exp) diff --git a/vault/policy_store.go b/vault/policy_store.go index 45439ebd60..22750cf88f 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 response-wrapping policy from store: {{err}}", err) } if policy == nil || policy.Raw != cubbyholeResponseWrappingPolicy { err := c.policyStore.createCubbyholeResponseWrappingPolicy() @@ -210,7 +213,25 @@ 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 indices of non-assignable policies in keys + for index, key := range keys { + if key == nonAssignable { + // Delete collection outside the loop + deleteIndex = index + break + } + } + // Remove non-assignable policies when found + if deleteIndex != -1 { + keys = append(keys[:deleteIndex], keys[deleteIndex+1:]...) + } + } + + return keys, err } // DeletePolicy is used to delete the named policy diff --git a/vault/policy_store_test.go b/vault/policy_store_test.go index 3fcd381068..4a0656e23b 100644 --- a/vault/policy_store_test.go +++ b/vault/policy_store_test.go @@ -138,7 +138,8 @@ func TestPolicyStore_Predefined(t *testing.T) { if err != nil { t.Fatalf("err: %v", err) } - if len(out) != 2 || out[0] != "default" || out[1] != "response-wrapping" { + // This shouldn't contain response-wrapping since it's non-assignable + if len(out) != 1 || out[0] != "default" { t.Fatalf("bad: %v", out) } diff --git a/vault/token_store.go b/vault/token_store.go index c628bc279b..a62efa3906 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 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/vault/token_store_test.go b/vault/token_store_test.go index dfab0b0d1a..fcc7207bfd 100644 --- a/vault/token_store_test.go +++ b/vault/token_store_test.go @@ -503,6 +503,32 @@ func TestTokenStore_RevokeSelf(t *testing.T) { } } +func TestTokenStore_HandleRequest_NonAssignable(t *testing.T) { + _, ts, _, root := TestCoreWithTokenStore(t) + + req := logical.TestRequest(t, logical.UpdateOperation, "create") + req.ClientToken = root + req.Data["policies"] = []string{"default", "foo"} + + resp, err := ts.HandleRequest(req) + if err != nil { + t.Fatalf("err: %v %v", err, resp) + } + + req.Data["policies"] = []string{"default", "foo", cubbyholeResponseWrappingPolicyName} + + resp, err = ts.HandleRequest(req) + if err != nil { + t.Fatal(err) + } + if resp == nil { + t.Fatal("got a nil response") + } + if !resp.IsError() { + t.Fatalf("expected error; response is %#v", *resp) + } +} + func TestTokenStore_HandleRequest_CreateToken_DisplayName(t *testing.T) { _, ts, _, root := TestCoreWithTokenStore(t)