TokenStore: Provide access based on sudo permissions and not policy name

This commit is contained in:
vishalnayak 2015-09-18 19:59:06 -04:00
parent e27b824dcb
commit fb77ec3623
3 changed files with 63 additions and 15 deletions

View File

@ -12,6 +12,10 @@ type SystemView interface {
// authors should take care not to issue credentials that last longer than
// this value, as Vault will revoke them
MaxLeaseTTL() time.Duration
// SudoPrivilege returns true if given policy name contains sudo policy
// for the given path
SudoPrivilege(path, policy string) bool
}
type StaticSystemView struct {
@ -26,3 +30,7 @@ func (d StaticSystemView) DefaultLeaseTTL() time.Duration {
func (d StaticSystemView) MaxLeaseTTL() time.Duration {
return d.MaxLeaseTTLVal
}
func (d StaticSystemView) SudoPrivilege(path, policy string) bool {
return false
}

View File

@ -1,6 +1,9 @@
package vault
import "time"
import (
"log"
"time"
)
type dynamicSystemView struct {
core *Core
@ -17,6 +20,31 @@ func (d dynamicSystemView) MaxLeaseTTL() time.Duration {
return max
}
func (d dynamicSystemView) SudoPrivilege(path, policy string) bool {
// Special "root" policy name can never be overwritten and it always will
// have all the privileges
if policy == "root" {
return true
}
// Get the associated policy from core's PolicyStore
p, err := d.core.policy.GetPolicy(policy)
if err != nil {
log.Printf("[WARN] Failed to retrieve policy '%s': %s", policy, err)
return false
}
// Look all the paths in the policy object to find an entry for given path
// and check its respective policy.
for _, item := range p.Paths {
if item.Prefix == path && item.Policy == PathPolicySudo {
return true
}
}
return false
}
// TTLsByPath returns the default and max TTLs corresponding to a particular
// mount point, or the system default
func (d dynamicSystemView) fetchTTLs() (def, max time.Duration) {

View File

@ -484,8 +484,14 @@ func (ts *TokenStore) handleCreate(
logical.ErrInvalidRequest
}
// Check if the parent policy is root
isRoot := strListContains(parent.Policies, "root")
// Check if the parent policy has sudo/root privileges for the requested path
var isSudo bool
for _, item := range parent.Policies {
isSudo = ts.System().SudoPrivilege(req.MountPoint, item)
if isSudo {
break
}
}
// Read and parse the fields
var data struct {
@ -525,28 +531,28 @@ func (ts *TokenStore) handleCreate(
te.DisplayName = full
}
// Allow specifying the ID of the token if the client is root
// Allow specifying the ID of the token if the client has root or sudo privileges
if data.ID != "" {
if !isRoot {
return logical.ErrorResponse("root required to specify token id"),
if !isSudo {
return logical.ErrorResponse("root or sudo privileges required to specify token id"),
logical.ErrInvalidRequest
}
te.ID = data.ID
}
// Only permit policies to be a subset unless the client is root
// Only permit policies to be a subset unless the client has root or sudo privileges
if len(data.Policies) == 0 {
data.Policies = parent.Policies
}
if !isRoot && !strListSubset(parent.Policies, data.Policies) {
if !isSudo && !strListSubset(parent.Policies, data.Policies) {
return logical.ErrorResponse("child policies must be subset of parent"), logical.ErrInvalidRequest
}
te.Policies = data.Policies
// Only allow an orphan token if the client is root
// Only allow an orphan token if the client has sudo policy
if data.NoParent {
if !isRoot {
return logical.ErrorResponse("root required to create orphan token"),
if !isSudo {
return logical.ErrorResponse("root or sudo privileges required to create orphan token"),
logical.ErrInvalidRequest
}
@ -638,11 +644,17 @@ func (ts *TokenStore) handleRevokeOrphan(
return logical.ErrorResponse("parent token lookup failed"), logical.ErrInvalidRequest
}
// Check if the parent policy is root
isRoot := strListContains(parent.Policies, "root")
// Check if the parent policy has sudo privileges for the requested path
var isSudo bool
for _, item := range parent.Policies {
isSudo = ts.System().SudoPrivilege(req.MountPoint, item)
if isSudo {
break
}
}
if !isRoot {
return logical.ErrorResponse("root required to revoke and orphan"),
if !isSudo {
return logical.ErrorResponse("root or sudo privileges required to revoke and orphan"),
logical.ErrInvalidRequest
}