Skip to content

Commit

Permalink
Properly lowercase policy names. (#3210)
Browse files Browse the repository at this point in the history
Previously we lowercased names on ingress but not on lookup or delete
which could cause unexpected results. Now, just unilaterally lowercase
policy names on write and delete. On get, to avoid the performance hit
of always lowercasing when not necessary since it's in the critical
path, we have a minor optimization -- we check the LRU first before
normalizing. For tokens, because they're already normalized when adding
policies during creation, this should always work; it might just be
slower for API calls.

Fixes #3187
  • Loading branch information
jefferai authored Aug 18, 2017
1 parent 60fec10 commit 88e9d19
Show file tree
Hide file tree
Showing 6 changed files with 28 additions and 13 deletions.
3 changes: 2 additions & 1 deletion command/policy_write.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ func (c *PolicyWriteCommand) Run(args []string) int {
return 2
}

name := args[0]
// Policies are normalized to lowercase
name := strings.ToLower(args[0])
path := args[1]

// Read the policy
Expand Down
4 changes: 2 additions & 2 deletions vault/acl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ path "auth/token/create*" {
`

var aclPolicy = `
name = "dev"
name = "DeV"
path "dev/*" {
policy = "sudo"
}
Expand Down Expand Up @@ -482,7 +482,7 @@ path "foo/bar" {
`

var aclPolicy2 = `
name = "ops"
name = "OpS"
path "dev/hide/*" {
policy = "deny"
}
Expand Down
7 changes: 4 additions & 3 deletions vault/logical_system.go
Original file line number Diff line number Diff line change
Expand Up @@ -1846,7 +1846,7 @@ func (b *SystemBackend) handlePolicyRead(

return &logical.Response{
Data: map[string]interface{}{
"name": name,
"name": policy.Name,
"rules": policy.Raw,
},
}, nil
Expand All @@ -1873,8 +1873,9 @@ func (b *SystemBackend) handlePolicySet(
return handleError(err)
}

// Override the name
parse.Name = strings.ToLower(name)
if name != "" {
parse.Name = name
}

// Update the policy
if err := b.Core.policyStore.SetPolicy(parse); err != nil {
Expand Down
8 changes: 6 additions & 2 deletions vault/logical_system_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1239,8 +1239,12 @@ func TestSystemBackend_policyCRUD(t *testing.T) {
t.Fatalf("err: %v", err)
}

if resp != nil {
t.Fatalf("err: expected nil response, got %#v", *resp)
exp = map[string]interface{}{
"name": "foo",
"rules": rules,
}
if !reflect.DeepEqual(resp.Data, exp) {
t.Fatalf("got: %#v expect: %#v", resp.Data, exp)
}

// List the policies
Expand Down
9 changes: 9 additions & 0 deletions vault/policy_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ func (ps *PolicyStore) SetPolicy(p *Policy) error {
if p.Name == "" {
return fmt.Errorf("policy name missing")
}
// Policies are normalized to lower-case
p.Name = strings.ToLower(strings.TrimSpace(p.Name))
if strutil.StrListContains(immutablePolicies, p.Name) {
return fmt.Errorf("cannot update %s policy", p.Name)
}
Expand Down Expand Up @@ -230,13 +232,17 @@ func (ps *PolicyStore) setPolicyInternal(p *Policy) error {
// GetPolicy is used to fetch the named policy
func (ps *PolicyStore) GetPolicy(name string) (*Policy, error) {
defer metrics.MeasureSince([]string{"policy", "get_policy"}, time.Now())

if ps.lru != nil {
// Check for cached policy
if raw, ok := ps.lru.Get(name); ok {
return raw.(*Policy), nil
}
}

// Policies are normalized to lower-case
name = strings.ToLower(strings.TrimSpace(name))

// Special case the root policy
if name == "root" {
p := &Policy{Name: "root"}
Expand Down Expand Up @@ -320,6 +326,9 @@ func (ps *PolicyStore) ListPolicies() ([]string, error) {
// DeletePolicy is used to delete the named policy
func (ps *PolicyStore) DeletePolicy(name string) error {
defer metrics.MeasureSince([]string{"policy", "delete_policy"}, time.Now())

// Policies are normalized to lower-case
name = strings.ToLower(strings.TrimSpace(name))
if strutil.StrListContains(immutablePolicies, name) {
return fmt.Errorf("cannot delete %s policy", name)
}
Expand Down
10 changes: 5 additions & 5 deletions vault/policy_store_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func TestPolicyStore_CRUD(t *testing.T) {

func testPolicyStore_CRUD(t *testing.T, ps *PolicyStore) {
// Get should return nothing
p, err := ps.GetPolicy("dev")
p, err := ps.GetPolicy("Dev")
if err != nil {
t.Fatalf("err: %v", err)
}
Expand All @@ -70,7 +70,7 @@ func testPolicyStore_CRUD(t *testing.T, ps *PolicyStore) {
}

// Delete should be no-op
err = ps.DeletePolicy("dev")
err = ps.DeletePolicy("deV")
if err != nil {
t.Fatalf("err: %v", err)
}
Expand All @@ -92,7 +92,7 @@ func testPolicyStore_CRUD(t *testing.T, ps *PolicyStore) {
}

// Get should work
p, err = ps.GetPolicy("dev")
p, err = ps.GetPolicy("dEv")
if err != nil {
t.Fatalf("err: %v", err)
}
Expand All @@ -110,13 +110,13 @@ func testPolicyStore_CRUD(t *testing.T, ps *PolicyStore) {
}

// Delete should be clear the entry
err = ps.DeletePolicy("dev")
err = ps.DeletePolicy("Dev")
if err != nil {
t.Fatalf("err: %v", err)
}

// Get should fail
p, err = ps.GetPolicy("dev")
p, err = ps.GetPolicy("deV")
if err != nil {
t.Fatalf("err: %v", err)
}
Expand Down

0 comments on commit 88e9d19

Please sign in to comment.