Merge pull request #1649 from hashicorp/internal-policy-block

Closes hashicorp/vault#1618
This commit is contained in:
Laura Bennett 2016-07-25 17:41:48 -04:00 committed by GitHub
commit 06b1835469
6 changed files with 70 additions and 15 deletions

View file

@ -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)

View file

@ -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)

View file

@ -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

View file

@ -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)
}

View file

@ -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,

View file

@ -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)