Adding default policies while creating tokens

This commit is contained in:
vishalnayak 2016-05-13 11:50:00 -04:00
parent 65298bd9a9
commit 49b4c83580
8 changed files with 54 additions and 43 deletions

View File

@ -138,7 +138,7 @@ func (b *backend) pathCertWrite(
name := strings.ToLower(d.Get("name").(string))
certificate := d.Get("certificate").(string)
displayName := d.Get("display_name").(string)
policies := policyutil.ParsePolicies(d.Get("policies").(string))
policies := policyutil.ParsePolicies(d.Get("policies").(string), true)
// Default the display name to the certificate name if not given
if displayName == "" {

View File

@ -95,7 +95,7 @@ func (b *backend) pathGroupWrite(
req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
// Store it
entry, err := logical.StorageEntryJSON("group/"+d.Get("name").(string), &GroupEntry{
Policies: policyutil.ParsePolicies(d.Get("policies").(string)),
Policies: policyutil.ParsePolicies(d.Get("policies").(string), true),
})
if err != nil {
return nil, err

View File

@ -44,7 +44,7 @@ func (b *backend) pathUserPoliciesUpdate(
return nil, fmt.Errorf("username does not exist")
}
userEntry.Policies = policyutil.ParsePolicies(d.Get("policies").(string))
userEntry.Policies = policyutil.ParsePolicies(d.Get("policies").(string), true)
return nil, b.setUser(req.Storage, username, userEntry)
}

View File

@ -163,7 +163,7 @@ func (b *backend) userCreateUpdate(req *logical.Request, d *framework.FieldData)
}
if policiesRaw, ok := d.GetOk("policies"); ok {
userEntry.Policies = policyutil.ParsePolicies(policiesRaw.(string))
userEntry.Policies = policyutil.ParsePolicies(policiesRaw.(string), true)
}
ttlStr := userEntry.TTL.String()

View File

@ -7,17 +7,32 @@ import (
"github.com/hashicorp/vault/helper/strutil"
)
func ParsePolicies(policiesRaw string) []string {
// ParsePolicies parses a comma-delimited list of policies.
// The resulting collection will have no duplicate elements.
// If 'root' policy was present in the list of policies, then
// all other policies will be ignored, the result will contain
// just the 'root'. In cases where 'root' is not present, if
// 'default' policy is not already present, it will be added
// if addDefault is set to true.
func ParsePolicies(policiesRaw string, addDefault bool) []string {
if policiesRaw == "" {
return []string{"default"}
}
policies := strings.Split(policiesRaw, ",")
return SanitizePolicies(policies)
return SanitizePolicies(policies, addDefault)
}
func SanitizePolicies(policies []string) []string {
// SanitizePolicies performs the common input validation tasks
// which are performed on the list of policies across Vault.
// The resulting collection will have no duplicate elements.
// If 'root' policy was present in the list of policies, then
// all other policies will be ignored, the result will contain
// just the 'root'. In cases where 'root' is not present, if
// 'default' policy is not already present, it will be added
// if addDefault is set to true.
func SanitizePolicies(policies []string, addDefault bool) []string {
defaultFound := false
for i, p := range policies {
policies[i] = strings.ToLower(strings.TrimSpace(p))
@ -38,7 +53,7 @@ func SanitizePolicies(policies []string) []string {
}
// Always add 'default' except only if the policies contain 'root'.
if len(policies) == 0 || !defaultFound {
if addDefault && (len(policies) == 0 || !defaultFound) {
policies = append(policies, "default")
}

View File

@ -3,35 +3,47 @@ package policyutil
import "testing"
func TestParsePolicies(t *testing.T) {
expected := []string{"foo", "bar", "default"}
actual := ParsePolicies("foo,bar")
expected := []string{"foo", "bar"}
actual := ParsePolicies("foo,bar", false)
if !EquivalentPolicies(expected, actual) {
t.Fatal("bad: expected:%s\ngot:%s\n", expected, actual)
}
expected = []string{"foo", "bar", "default"}
actual = ParsePolicies("foo,bar", true)
// add default if not present.
if !EquivalentPolicies(expected, actual) {
t.Fatal("bad: expected:%s\ngot:%s\n", expected, actual)
}
// do not add default more than once.
actual = ParsePolicies("foo,bar,default")
actual = ParsePolicies("foo,bar,default", true)
if !EquivalentPolicies(expected, actual) {
t.Fatal("bad: expected:%s\ngot:%s\n", expected, actual)
}
// If 'default' is already added, do not remove it.
actual = ParsePolicies("foo,bar,default", false)
if !EquivalentPolicies(expected, actual) {
t.Fatal("bad: expected:%s\ngot:%s\n", expected, actual)
}
// handle spaces and tabs.
actual = ParsePolicies(" foo , bar , default")
actual = ParsePolicies(" foo , bar , default", true)
if !EquivalentPolicies(expected, actual) {
t.Fatal("bad: expected:%s\ngot:%s\n", expected, actual)
}
// ignore all others if root is present.
expected = []string{"root"}
actual = ParsePolicies("foo,bar,root")
actual = ParsePolicies("foo,bar,root", true)
if !EquivalentPolicies(expected, actual) {
t.Fatal("bad: expected:%s\ngot:%s\n", expected, actual)
}
// with spaces and tabs.
expected = []string{"root"}
actual = ParsePolicies("foo ,bar, root ")
actual = ParsePolicies("foo ,bar, root ", true)
if !EquivalentPolicies(expected, actual) {
t.Fatal("bad: expected:%s\ngot:%s\n", expected, actual)
}

View File

@ -4,7 +4,6 @@ import (
"encoding/json"
"fmt"
"regexp"
"sort"
"strconv"
"strings"
"sync"
@ -510,6 +509,8 @@ func (ts *TokenStore) create(entry *TokenEntry) error {
entry.ID = entryUUID
}
entry.Policies = policyutil.SanitizePolicies(entry.Policies, false)
err := ts.createAccessor(entry)
if err != nil {
return err
@ -1001,8 +1002,8 @@ func (ts *TokenStore) handleCreateCommon(
data.Policies = role.AllowedPolicies
} else {
// Sanitize passed-in and role policies before comparison
sanitizedInputPolicies := policyutil.SanitizePolicies(data.Policies)
sanitizedRolePolicies := policyutil.SanitizePolicies(role.AllowedPolicies)
sanitizedInputPolicies := policyutil.SanitizePolicies(data.Policies, true)
sanitizedRolePolicies := policyutil.SanitizePolicies(role.AllowedPolicies, true)
if !strutil.StrListSubset(sanitizedRolePolicies, sanitizedInputPolicies) {
return logical.ErrorResponse(fmt.Sprintf("token policies (%v) must be subset of the role's allowed policies (%v)", sanitizedInputPolicies, sanitizedRolePolicies)), logical.ErrInvalidRequest
@ -1016,33 +1017,16 @@ func (ts *TokenStore) handleCreateCommon(
// the client has root or sudo privileges
case !isSudo:
// Sanitize passed-in and parent policies before comparison
sanitizedInputPolicies := policyutil.SanitizePolicies(data.Policies)
sanitizedParentPolicies := policyutil.SanitizePolicies(parent.Policies)
sanitizedInputPolicies := policyutil.SanitizePolicies(data.Policies, true)
sanitizedParentPolicies := policyutil.SanitizePolicies(parent.Policies, true)
if !strutil.StrListSubset(sanitizedParentPolicies, sanitizedInputPolicies) {
return logical.ErrorResponse("child policies must be subset of parent"), logical.ErrInvalidRequest
}
}
// Use a map to filter out/prevent duplicates
policyMap := map[string]bool{}
for _, policy := range data.Policies {
if policy == "" {
// Don't allow a policy with no name, even though it is a valid
// slice member
continue
}
policyMap[policy] = true
}
if !policyMap["root"] &&
!data.NoDefaultPolicy {
policyMap["default"] = true
}
for k, _ := range policyMap {
te.Policies = append(te.Policies, k)
}
sort.Strings(te.Policies)
// Do not add the 'default' policy if requested not to.
te.Policies = policyutil.SanitizePolicies(data.Policies, !data.NoDefaultPolicy)
switch {
case role != nil:
@ -1551,10 +1535,10 @@ func (ts *TokenStore) tokenStoreRoleCreateUpdate(
if ok {
allowedPolicies := allowedPoliciesInt.(string)
if allowedPolicies != "" {
entry.AllowedPolicies = strings.Split(allowedPolicies, ",")
entry.AllowedPolicies = policyutil.ParsePolicies(allowedPolicies, true)
}
} else if req.Operation == logical.CreateOperation {
entry.AllowedPolicies = strings.Split(data.Get("allowed_policies").(string), ",")
entry.AllowedPolicies = policyutil.ParsePolicies(data.Get("allowed_policies").(string), true)
}
// Explicit max TTLs and periods cannot be used at the same time since the

View File

@ -1270,7 +1270,7 @@ func TestTokenStore_RoleCRUD(t *testing.T) {
"name": "test",
"orphan": true,
"period": int64(259200),
"allowed_policies": []string{"test1", "test2"},
"allowed_policies": []string{"default", "test1", "test2"},
"path_suffix": "happenin",
"explicit_max_ttl": int64(0),
}
@ -1311,7 +1311,7 @@ func TestTokenStore_RoleCRUD(t *testing.T) {
"name": "test",
"orphan": true,
"period": int64(284400),
"allowed_policies": []string{"test3"},
"allowed_policies": []string{"default", "test3"},
"path_suffix": "happenin",
"explicit_max_ttl": int64(0),
}
@ -1358,7 +1358,7 @@ func TestTokenStore_RoleCRUD(t *testing.T) {
"name": "test",
"orphan": true,
"explicit_max_ttl": int64(5),
"allowed_policies": []string{"test3"},
"allowed_policies": []string{"default", "test3"},
"path_suffix": "happenin",
"period": int64(0),
}