From e8cc6a0fc87b27cac85659e5254b4a0835474aaf Mon Sep 17 00:00:00 2001 From: mwoolsey Date: Fri, 14 Oct 2016 10:17:25 -0700 Subject: [PATCH] created structure for permissions and modified parsePaths in policy.go and newAcl/AllowOperation in acl.go --- vault/acl.go | 55 +++++++++++++++++++++++++++++++++++++------------ vault/policy.go | 39 +++++++++++++++++++++++++++-------- 2 files changed, 72 insertions(+), 22 deletions(-) diff --git a/vault/acl.go b/vault/acl.go index badf3f4bc607c..3afcd820dd55a 100644 --- a/vault/acl.go +++ b/vault/acl.go @@ -47,24 +47,27 @@ func NewACL(policies []*Policy) (*ACL, error) { // Check for an existing policy raw, ok := tree.Get(pc.Prefix) if !ok { - tree.Insert(pc.Prefix, pc.CapabilitiesBitmap) + tree.Insert(pc.Prefix, pc.Permissions) continue } - existing := raw.(uint32) + perm := raw.(Permissions) + existing := perm.CapabilitiesBitmap switch { case existing&DenyCapabilityInt > 0: // If we are explicitly denied in the existing capability set, // don't save anything else - case pc.CapabilitiesBitmap&DenyCapabilityInt > 0: + case pc.Permissions.CapabilitiesBitmap&DenyCapabilityInt > 0: // If this new policy explicitly denies, only save the deny value - tree.Insert(pc.Prefix, DenyCapabilityInt) + pc.Permissions.CapabilitesBitmap = DenyCapabilityInt + tree.Insert(pc.Prefix, pc.Permissions) default: // Insert the capabilities in this new policy into the existing // value - tree.Insert(pc.Prefix, existing|pc.CapabilitiesBitmap) + pc.Permissions.CapabilitesBitmap = existing | pc.Permissions.CapabilitesBitmap + tree.Insert(pc.Prefix, pc.Permissions) } } } @@ -80,8 +83,10 @@ func (a *ACL) Capabilities(path string) (pathCapabilities []string) { // Find an exact matching rule, look for glob if no match var capabilities uint32 raw, ok := a.exactRules.Get(path) + if ok { - capabilities = raw.(uint32) + perm := raw.(Permissions) + capbilities := perm.CapabilitiesBitmap goto CHECK } @@ -90,7 +95,8 @@ func (a *ACL) Capabilities(path string) (pathCapabilities []string) { if !ok { return []string{DenyCapability} } else { - capabilities = raw.(uint32) + perm := raw.(Permissions) + capbilities := perm.CapabilitiesBitmap } CHECK: @@ -124,12 +130,22 @@ CHECK: // 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. + +// change arguments to hold a full request that holds the operation, path, and parameter +// that is to be modified. +//func (a *ACL) AllowOperation(req Request) (allowed bool, sudo bool) { func (a *ACL) AllowOperation(op logical.Operation, path string) (allowed bool, sudo bool) { // Fast-path root if a.root { return true, true } + /////////////////////////////////////////////////////////////////////////////////// + // Parse Request and set variables to check on + /////////////////////////////////////////////////////////////////////////////////// + op := req.Operation + path := req.Path + // Help is always allowed if op == logical.HelpOperation { return true, false @@ -156,24 +172,37 @@ CHECK: // 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 sudo = capabilities&SudoCapabilityInt > 0 + operationAllowed := false switch op { case logical.ReadOperation: - allowed = capabilities&ReadCapabilityInt > 0 + operationAllowed = capabilities&ReadCapabilityInt > 0 case logical.ListOperation: - allowed = capabilities&ListCapabilityInt > 0 + operationAllowed = capabilities&ListCapabilityInt > 0 case logical.UpdateOperation: - allowed = capabilities&UpdateCapabilityInt > 0 + operationAllowed = capabilities&UpdateCapabilityInt > 0 case logical.DeleteOperation: - allowed = capabilities&DeleteCapabilityInt > 0 + operationAllowed = capabilities&DeleteCapabilityInt > 0 case logical.CreateOperation: - allowed = capabilities&CreateCapabilityInt > 0 + operationAllowed = capabilities&CreateCapabilityInt > 0 // These three re-use UpdateCapabilityInt since that's the most appropriate capability/operation mapping case logical.RevokeOperation, logical.RenewOperation, logical.RollbackOperation: - allowed = capabilities&UpdateCapabilityInt > 0 + operationAllowed = capabilities&UpdateCapabilityInt > 0 default: return false, false } + + if !operationAllowed { + return false, sudo + } + /////////////////////////////////////////////////////////////////////////////////////////////////////// + // need to know how to access parameter/parameters. If only one it is trivial to look it up, + // if there are many, have to loop through and check each one. + /////////////////////////////////////////////////////////////////////////////////////////////////////// + //check whether parameter change is allowed + + //if raw.AllowOperation[param_trying_to_be_set] + return } diff --git a/vault/policy.go b/vault/policy.go index b37ced139fce7..8b38dcbea1341 100644 --- a/vault/policy.go +++ b/vault/policy.go @@ -56,13 +56,22 @@ type Policy struct { Raw string } +type Permissions struct { + CapabilitiesBitmap uint32 `hcl:"-"` + AllowedParams map[string]bool + DisallowedParams map[string]bool +} + +/* + */ // PathCapabilities represents a policy for a path in the namespace. type PathCapabilities struct { - Prefix string - Policy string - Capabilities []string - CapabilitiesBitmap uint32 `hcl:"-"` - Glob bool + Prefix string + Policy string + Capabilities []string + //CapabilitiesBitmap uint32 `hcl:"-"` + AclCapabilites *Permissions + Glob bool } // Parse is used to parse the specified ACL rules into an @@ -107,16 +116,19 @@ func Parse(rules string) (*Policy, error) { } func parsePaths(result *Policy, list *ast.ObjectList) error { + // specifically how can we access the key value pairs for + // permissions paths := make([]*PathCapabilities, 0, len(list.Items)) for _, item := range list.Items { key := "path" if len(item.Keys) > 0 { - key = item.Keys[0].Token.Value().(string) + key = item.Keys[0].Token.Value().(string) // "secret/foo" } valid := []string{ "policy", "capabilities", + "permissions", // added here to validate } if err := checkHCLKeys(item.Val, valid); err != nil { return multierror.Prefix(err, fmt.Sprintf("path %q:", key)) @@ -156,21 +168,30 @@ func parsePaths(result *Policy, list *ast.ObjectList) error { } // Initialize the map - pc.CapabilitiesBitmap = 0 + pc.Permissions.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.CapabilitiesBitmap = DenyCapabilityInt + pc.Permissions.CapabilitiesBitmap = DenyCapabilityInt goto PathFinished case CreateCapability, ReadCapability, UpdateCapability, DeleteCapability, ListCapability, SudoCapability: - pc.CapabilitiesBitmap |= cap2Int[cap] + pc.Permissions.CapabilitiesBitmap |= cap2Int[cap] default: return fmt.Errorf("path %q: invalid capability '%s'", key, cap) } } + ////////////////////////////////////////////////////////////////////////////// + + // filter out permissions from list object + // if p := item.Filter("permissions"); len(p.Whatever) > 0 { + // } + + // go through p and initialize pc.Permissions.Allowed/Disallowed + + ////////////////////////////////////////////////////////////////////////////// PathFinished: paths = append(paths, &pc)