TokenStore: Provide access based on sudo permissions and not policy name
This commit is contained in:
parent
e27b824dcb
commit
fb77ec3623
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue