Convert map to bitmap
This commit is contained in:
parent
da87d490eb
commit
87fba5dad0
56
vault/acl.go
56
vault/acl.go
|
@ -5,24 +5,6 @@ import (
|
|||
"github.com/hashicorp/vault/logical"
|
||||
)
|
||||
|
||||
var (
|
||||
// permittedPolicyLevel is used to map each logical operation
|
||||
// into the set of capabilities that allow the operation.
|
||||
permittedPolicyLevels = map[logical.Operation][]string{
|
||||
logical.CreateOperation: []string{CreateCapability},
|
||||
logical.ReadOperation: []string{ReadCapability},
|
||||
logical.UpdateOperation: []string{UpdateCapability},
|
||||
logical.DeleteOperation: []string{DeleteCapability},
|
||||
logical.ListOperation: []string{ListCapability},
|
||||
logical.RevokeOperation: []string{UpdateCapability},
|
||||
logical.RenewOperation: []string{UpdateCapability},
|
||||
logical.RollbackOperation: []string{UpdateCapability},
|
||||
|
||||
// Help is special-cased to always be allowed, so we don't need anything in this list
|
||||
logical.HelpOperation: []string{},
|
||||
}
|
||||
)
|
||||
|
||||
// ACL is used to wrap a set of policies to provide
|
||||
// an efficient interface for access control.
|
||||
type ACL struct {
|
||||
|
@ -71,11 +53,11 @@ func NewACL(policies []*Policy) (*ACL, error) {
|
|||
existing := raw.(*PathCapabilities)
|
||||
|
||||
switch {
|
||||
case existing.CapabilitiesMap[DenyCapability]:
|
||||
case existing.CapabilitiesBitmap&DenyCapabilityInt > 0:
|
||||
// If we are explicitly denied in the existing capability set,
|
||||
// don't save anything else
|
||||
|
||||
case pc.CapabilitiesMap[DenyCapability]:
|
||||
case pc.CapabilitiesBitmap&DenyCapabilityInt > 0:
|
||||
// If this new policy explicitly denies, only save the deny value
|
||||
tree.Insert(pc.Prefix, pc)
|
||||
|
||||
|
@ -83,18 +65,17 @@ func NewACL(policies []*Policy) (*ACL, error) {
|
|||
// Insert the capabilities in this new policy into the existing
|
||||
// value; since it's a pointer we can just modify the
|
||||
// underlying data
|
||||
|
||||
for k, _ := range pc.CapabilitiesMap {
|
||||
existing.CapabilitiesMap[k] = true
|
||||
}
|
||||
existing.CapabilitiesBitmap |= pc.CapabilitiesBitmap
|
||||
}
|
||||
}
|
||||
}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
// AllowOperation is used to check if the given operation is permitted
|
||||
func (a *ACL) AllowOperation(op logical.Operation, path string) (opAllowed bool, sudoPriv bool) {
|
||||
// AllowOperation is used to check if the given operation is permitted. The
|
||||
// first bool indicates if an op is allowed, the second whether sudo priviliges
|
||||
// exist for that op and path.
|
||||
func (a *ACL) AllowOperation(op logical.Operation, path string) (allowed bool, sudo bool) {
|
||||
// Fast-path root
|
||||
if a.root {
|
||||
return true, true
|
||||
|
@ -125,5 +106,26 @@ CHECK:
|
|||
// Check if the minimum permissions are met
|
||||
// If "deny" has been explicitly set, only deny will be in the map, so we
|
||||
// only need to check for the existence of other values
|
||||
return policy.CapabilitiesMap[op.String()], policy.CapabilitiesMap[SudoCapability]
|
||||
sudo = policy.CapabilitiesBitmap&SudoCapabilityInt > 0
|
||||
switch op.String() {
|
||||
case "read":
|
||||
allowed = policy.CapabilitiesBitmap&ReadCapabilityInt > 0
|
||||
case "list":
|
||||
allowed = policy.CapabilitiesBitmap&ListCapabilityInt > 0
|
||||
case "update":
|
||||
allowed = policy.CapabilitiesBitmap&UpdateCapabilityInt > 0
|
||||
case "delete":
|
||||
allowed = policy.CapabilitiesBitmap&DeleteCapabilityInt > 0
|
||||
case "create":
|
||||
allowed = policy.CapabilitiesBitmap&CreateCapabilityInt > 0
|
||||
case "revoke":
|
||||
allowed = policy.CapabilitiesBitmap&UpdateCapabilityInt > 0
|
||||
case "renew":
|
||||
allowed = policy.CapabilitiesBitmap&UpdateCapabilityInt > 0
|
||||
case "rollback":
|
||||
allowed = policy.CapabilitiesBitmap&UpdateCapabilityInt > 0
|
||||
default:
|
||||
return false, false
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
@ -8,12 +8,12 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
DenyCapability = "deny"
|
||||
CreateCapability = "create"
|
||||
ReadCapability = "read"
|
||||
UpdateCapability = "update"
|
||||
DeleteCapability = "delete"
|
||||
ListCapability = "list"
|
||||
DenyCapability = "deny"
|
||||
SudoCapability = "sudo"
|
||||
|
||||
// Backwards compatibility
|
||||
|
@ -23,6 +23,28 @@ const (
|
|||
OldSudoPathPolicy = "sudo"
|
||||
)
|
||||
|
||||
const (
|
||||
DenyCapabilityInt uint32 = 1 << iota
|
||||
CreateCapabilityInt
|
||||
ReadCapabilityInt
|
||||
UpdateCapabilityInt
|
||||
DeleteCapabilityInt
|
||||
ListCapabilityInt
|
||||
SudoCapabilityInt
|
||||
)
|
||||
|
||||
var (
|
||||
cap2Int = map[string]uint32{
|
||||
DenyCapability: DenyCapabilityInt,
|
||||
CreateCapability: CreateCapabilityInt,
|
||||
ReadCapability: ReadCapabilityInt,
|
||||
UpdateCapability: UpdateCapabilityInt,
|
||||
DeleteCapability: DeleteCapabilityInt,
|
||||
ListCapability: ListCapabilityInt,
|
||||
SudoCapability: SudoCapabilityInt,
|
||||
}
|
||||
)
|
||||
|
||||
// Policy is used to represent the policy specified by
|
||||
// an ACL configuration.
|
||||
type Policy struct {
|
||||
|
@ -33,11 +55,11 @@ type Policy struct {
|
|||
|
||||
// Capability represents a policy for a path in the namespace
|
||||
type PathCapabilities struct {
|
||||
Prefix string `hcl:",key"`
|
||||
Policy string
|
||||
Capabilities []string
|
||||
CapabilitiesMap map[string]bool `hcl:"-"`
|
||||
Glob bool
|
||||
Prefix string `hcl:",key"`
|
||||
Policy string
|
||||
Capabilities []string
|
||||
CapabilitiesBitmap uint32 `hcl:"-"`
|
||||
Glob bool
|
||||
}
|
||||
|
||||
// Parse is used to parse the specified ACL rules into an
|
||||
|
@ -61,7 +83,7 @@ func Parse(rules string) (*Policy, error) {
|
|||
// Map old-style policies into capabilities
|
||||
switch pc.Policy {
|
||||
case OldDenyPathPolicy:
|
||||
pc.Capabilities = append(pc.Capabilities, DenyCapability)
|
||||
pc.Capabilities = []string{DenyCapability}
|
||||
case OldReadPathPolicy:
|
||||
pc.Capabilities = append(pc.Capabilities, []string{ReadCapability, ListCapability}...)
|
||||
case OldWritePathPolicy:
|
||||
|
@ -71,18 +93,16 @@ func Parse(rules string) (*Policy, error) {
|
|||
}
|
||||
|
||||
// Initialize the map
|
||||
pc.CapabilitiesMap = make(map[string]bool, len(pc.Capabilities))
|
||||
pc.CapabilitiesBitmap = 0
|
||||
for _, cap := range pc.Capabilities {
|
||||
switch cap {
|
||||
// If it's deny, don't include any other capability
|
||||
case DenyCapability:
|
||||
pc.Capabilities = []string{DenyCapability}
|
||||
pc.CapabilitiesMap = map[string]bool{
|
||||
DenyCapability: true,
|
||||
}
|
||||
pc.CapabilitiesBitmap = DenyCapabilityInt
|
||||
goto PathFinished
|
||||
case CreateCapability, ReadCapability, UpdateCapability, DeleteCapability, ListCapability, SudoCapability:
|
||||
pc.CapabilitiesMap[cap] = true
|
||||
pc.CapabilitiesBitmap |= cap2Int[cap]
|
||||
default:
|
||||
return nil, fmt.Errorf("Invalid capability: %#v", pc)
|
||||
}
|
||||
|
|
|
@ -20,9 +20,7 @@ func TestPolicy_Parse(t *testing.T) {
|
|||
&PathCapabilities{"", "deny",
|
||||
[]string{
|
||||
"deny",
|
||||
}, map[string]bool{
|
||||
"deny": true,
|
||||
}, true},
|
||||
}, DenyCapabilityInt, true},
|
||||
&PathCapabilities{"stage/", "sudo",
|
||||
[]string{
|
||||
"create",
|
||||
|
@ -31,38 +29,23 @@ func TestPolicy_Parse(t *testing.T) {
|
|||
"delete",
|
||||
"list",
|
||||
"sudo",
|
||||
}, map[string]bool{
|
||||
"create": true,
|
||||
"read": true,
|
||||
"update": true,
|
||||
"delete": true,
|
||||
"list": true,
|
||||
"sudo": true,
|
||||
}, true},
|
||||
}, CreateCapabilityInt | ReadCapabilityInt | UpdateCapabilityInt |
|
||||
DeleteCapabilityInt | ListCapabilityInt | SudoCapabilityInt, true},
|
||||
&PathCapabilities{"prod/version", "read",
|
||||
[]string{
|
||||
"read",
|
||||
"list",
|
||||
}, map[string]bool{
|
||||
"read": true,
|
||||
"list": true,
|
||||
}, false},
|
||||
}, ReadCapabilityInt | ListCapabilityInt, false},
|
||||
&PathCapabilities{"foo/bar", "read",
|
||||
[]string{
|
||||
"read",
|
||||
"list",
|
||||
}, map[string]bool{
|
||||
"read": true,
|
||||
"list": true,
|
||||
}, false},
|
||||
}, ReadCapabilityInt | ListCapabilityInt, false},
|
||||
&PathCapabilities{"foo/bar", "",
|
||||
[]string{
|
||||
"create",
|
||||
"sudo",
|
||||
}, map[string]bool{
|
||||
"create": true,
|
||||
"sudo": true,
|
||||
}, false},
|
||||
}, CreateCapabilityInt | SudoCapabilityInt, false},
|
||||
}
|
||||
if !reflect.DeepEqual(p.Paths, expect) {
|
||||
ret := fmt.Sprintf("bad:\nexpected:\n")
|
||||
|
|
Loading…
Reference in New Issue