open-vault/vault/capabilities.go
Austin Gebauer e09657e1f3
Adds ability to define an inline policy and internal metadata on tokens (#12682)
* Adds ability to define an inline policy and internal metadata to tokens

* Update comment on fetchEntityAndDerivedPolicies

* Simplify handling of inline policy

* Update comment on InternalMeta

Co-authored-by: Brian Kassouf <briankassouf@users.noreply.github.com>

* Improve argument name

Co-authored-by: Brian Kassouf <briankassouf@users.noreply.github.com>

* Use explicit SkipIdentityInheritance token field instead of implicit InlinePolicy behavior

* Add SkipIdentityInheritance to pb struct in token store create method

* Rename SkipIdentityInheritance to NoIdentityPolicies

* Merge latest from main and make proto

Co-authored-by: Brian Kassouf <briankassouf@users.noreply.github.com>
2021-10-07 10:36:22 -07:00

88 lines
2.2 KiB
Go

package vault
import (
"context"
"sort"
"github.com/hashicorp/vault/helper/namespace"
"github.com/hashicorp/vault/sdk/logical"
)
// Capabilities is used to fetch the capabilities of the given token on the
// given path
func (c *Core) Capabilities(ctx context.Context, token, path string) ([]string, error) {
if path == "" {
return nil, &logical.StatusBadRequest{Err: "missing path"}
}
if token == "" {
return nil, &logical.StatusBadRequest{Err: "missing token"}
}
te, err := c.tokenStore.Lookup(ctx, token)
if err != nil {
return nil, err
}
if te == nil {
return nil, &logical.StatusBadRequest{Err: "invalid token"}
}
tokenNS, err := NamespaceByID(ctx, te.NamespaceID, c)
if err != nil {
return nil, err
}
if tokenNS == nil {
return nil, namespace.ErrNoNamespace
}
var policyCount int
policyNames := make(map[string][]string)
policyNames[tokenNS.ID] = te.Policies
policyCount += len(te.Policies)
entity, identityPolicies, err := c.fetchEntityAndDerivedPolicies(ctx, tokenNS, te.EntityID, te.NoIdentityPolicies)
if err != nil {
return nil, err
}
if entity != nil && entity.Disabled {
c.logger.Warn("permission denied as the entity on the token is disabled")
return nil, logical.ErrPermissionDenied
}
if te.EntityID != "" && entity == nil {
c.logger.Warn("permission denied as the entity on the token is invalid")
return nil, logical.ErrPermissionDenied
}
for nsID, nsPolicies := range identityPolicies {
policyNames[nsID] = append(policyNames[nsID], nsPolicies...)
policyCount += len(nsPolicies)
}
// Add capabilities of the inline policy if it's set
policies := make([]*Policy, 0)
if te.InlinePolicy != "" {
inlinePolicy, err := ParseACLPolicy(tokenNS, te.InlinePolicy)
if err != nil {
return nil, err
}
policies = append(policies, inlinePolicy)
policyCount++
}
if policyCount == 0 {
return []string{DenyCapability}, nil
}
// Construct the corresponding ACL object. ACL construction should be
// performed on the token's namespace.
tokenCtx := namespace.ContextWithNamespace(ctx, tokenNS)
acl, err := c.policyStore.ACL(tokenCtx, entity, policyNames, policies...)
if err != nil {
return nil, err
}
capabilities := acl.Capabilities(ctx, path)
sort.Strings(capabilities)
return capabilities, nil
}