Adding default policies while creating tokens
This commit is contained in:
parent
65298bd9a9
commit
49b4c83580
|
@ -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 == "" {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue