From 7f832f22aafe4d18407b2dee79991edcd4e32e60 Mon Sep 17 00:00:00 2001 From: vishalnayak Date: Fri, 4 Mar 2016 13:21:07 -0500 Subject: [PATCH] refactoring changes due to acl.Capabilities --- api/sys_capabilities.go | 8 ++--- command/capabilities.go | 24 +++++++-------- http/sys_capabilities.go | 20 +++--------- vault/acl.go | 12 ++++---- vault/capabilities.go | 66 +++------------------------------------- vault/policy.go | 1 + 6 files changed, 30 insertions(+), 101 deletions(-) diff --git a/api/sys_capabilities.go b/api/sys_capabilities.go index 5001986749bf..1640a2fc9b1c 100644 --- a/api/sys_capabilities.go +++ b/api/sys_capabilities.go @@ -1,6 +1,6 @@ package api -func (c *Sys) CapabilitiesSelf(path string) (*CapabilitiesResponse, error) { +func (c *Sys) CapabilitiesSelf(path string) ([]string, error) { body := map[string]string{ "path": path, } @@ -18,10 +18,10 @@ func (c *Sys) CapabilitiesSelf(path string) (*CapabilitiesResponse, error) { var result CapabilitiesResponse err = resp.DecodeJSON(&result) - return &result, err + return result.Capabilities, err } -func (c *Sys) Capabilities(token, path string) (*CapabilitiesResponse, error) { +func (c *Sys) Capabilities(token, path string) ([]string, error) { body := map[string]string{ "token": token, "path": path, @@ -40,7 +40,7 @@ func (c *Sys) Capabilities(token, path string) (*CapabilitiesResponse, error) { var result CapabilitiesResponse err = resp.DecodeJSON(&result) - return &result, err + return result.Capabilities, err } type CapabilitiesResponse struct { diff --git a/command/capabilities.go b/command/capabilities.go index 9f60d6854ffa..0c637c37b689 100644 --- a/command/capabilities.go +++ b/command/capabilities.go @@ -3,8 +3,6 @@ package command import ( "fmt" "strings" - - "github.com/hashicorp/vault/api" ) // CapabilitiesCommand is a Command that enables a new endpoint. @@ -29,15 +27,12 @@ func (c *CapabilitiesCommand) Run(args []string) int { var token string var path string - switch len(args) { - case 1: - // only path is provided + switch { + case len(args) == 1: path = args[0] - case 2: - // both token and path are provided + case len(args) == 2: token = args[0] path = args[1] - default: } client, err := c.Client() @@ -47,11 +42,11 @@ func (c *CapabilitiesCommand) Run(args []string) int { return 2 } - var resp *api.CapabilitiesResponse + var capabilities []string if token == "" { - resp, err = client.Sys().CapabilitiesSelf(path) + capabilities, err = client.Sys().CapabilitiesSelf(path) } else { - resp, err = client.Sys().Capabilities(token, path) + capabilities, err = client.Sys().Capabilities(token, path) } if err != nil { c.Ui.Error(fmt.Sprintf( @@ -59,12 +54,12 @@ func (c *CapabilitiesCommand) Run(args []string) int { return 1 } - c.Ui.Output(fmt.Sprintf("Capabilities: %s", resp.Capabilities)) + c.Ui.Output(fmt.Sprintf("Capabilities: %s", capabilities)) return 0 } func (c *CapabilitiesCommand) Synopsis() string { - return "Fetch the capabilities of a given token on a given path" + return "Fetch the capabilities of a token on a given path" } func (c *CapabilitiesCommand) Help() string { @@ -76,6 +71,9 @@ Usage: vault capabilities [options] [token] path with the given token; otherwise API '/sys/capabilities-self' will be invoked with the client token. + Note that this command will respond with a ["deny"] capability if the given path + is invalid. + General Options: ` + generalOptionsUsage() diff --git a/http/sys_capabilities.go b/http/sys_capabilities.go index d6d638b90f68..22f85ea7f786 100644 --- a/http/sys_capabilities.go +++ b/http/sys_capabilities.go @@ -32,27 +32,15 @@ func handleSysCapabilities(core *vault.Core) http.Handler { data.Token = req.ClientToken } - resp, err := core.Capabilities(data.Token, data.Path) + capabilities, err := core.Capabilities(data.Token, data.Path) if err != nil { respondError(w, http.StatusInternalServerError, err) return } - if resp == nil { - respondOk(w, &capabilitiesResponse{ - Capabilities: nil, - }) - return - } - - var result capabilitiesResponse - switch resp.Root { - case true: - result.Capabilities = nil - case false: - result.Capabilities = resp.Capabilities - } - respondOk(w, result) + respondOk(w, &capabilitiesResponse{ + Capabilities: capabilities, + }) }) } diff --git a/vault/acl.go b/vault/acl.go index 6dc4e9bc67ef..ead38089d4ac 100644 --- a/vault/acl.go +++ b/vault/acl.go @@ -74,7 +74,7 @@ func NewACL(policies []*Policy) (*ACL, error) { func (a *ACL) Capabilities(path string) (pathCapabilities []string) { // Fast-path root if a.root { - return []string{"root"} + return []string{RootCapability} } // Find an exact matching rule, look for glob if no match @@ -88,13 +88,12 @@ func (a *ACL) Capabilities(path string) (pathCapabilities []string) { // Find a glob rule, default deny if no match _, raw, ok = a.globRules.LongestPrefix(path) if !ok { - return nil + return []string{DenyCapability} } else { capabilities = raw.(uint32) } CHECK: - if capabilities&SudoCapabilityInt > 0 { pathCapabilities = append(pathCapabilities, SudoCapability) } @@ -113,11 +112,12 @@ CHECK: if capabilities&CreateCapabilityInt > 0 { pathCapabilities = append(pathCapabilities, CreateCapability) } - // If "deny" capability is explicitly set, then ignore all other capabilities - if capabilities&DenyCapabilityInt > 0 { + + // If "deny" is explicitly set or if the path has no capabilities at all, + // set the path capabilities to "deny" + if capabilities&DenyCapabilityInt > 0 || len(pathCapabilities) == 0 { pathCapabilities = []string{DenyCapability} } - return } diff --git a/vault/capabilities.go b/vault/capabilities.go index c450684d4611..fcbdcd88f5a0 100644 --- a/vault/capabilities.go +++ b/vault/capabilities.go @@ -2,14 +2,8 @@ package vault import "fmt" -// CapabilitiesResponse holds the result of fetching the capabilities of token on a path -type CapabilitiesResponse struct { - Root bool - Capabilities []string -} - // Capabilities is used to fetch the capabilities of the given token on the given path -func (c *Core) Capabilities(token, path string) (*CapabilitiesResponse, error) { +func (c *Core) Capabilities(token, path string) ([]string, error) { if path == "" { return nil, fmt.Errorf("missing path") } @@ -27,7 +21,7 @@ func (c *Core) Capabilities(token, path string) (*CapabilitiesResponse, error) { } if te.Policies == nil { - return nil, nil + return []string{DenyCapability}, nil } var policies []*Policy @@ -40,7 +34,7 @@ func (c *Core) Capabilities(token, path string) (*CapabilitiesResponse, error) { } if len(policies) == 0 { - return nil, nil + return []string{DenyCapability}, nil } acl, err := NewACL(policies) @@ -48,57 +42,5 @@ func (c *Core) Capabilities(token, path string) (*CapabilitiesResponse, error) { return nil, err } - caps := acl.Capabilities(path) - /* - log.Printf("vishal: caps:%#v\n", caps) - - var result CapabilitiesResponse - capabilities := make(map[string]bool) - for _, tePolicy := range te.Policies { - if tePolicy == "root" { - capabilities = map[string]bool{ - "root": true, - } - break - } - policy, err := c.policyStore.GetPolicy(tePolicy) - if err != nil { - return nil, err - } - if policy == nil || policy.Paths == nil { - continue - } - for _, pathCapability := range policy.Paths { - switch { - case pathCapability.Glob: - if strings.HasPrefix(path, pathCapability.Prefix) { - for _, capability := range pathCapability.Capabilities { - if _, ok := capabilities[capability]; !ok { - capabilities[capability] = true - } - } - } - default: - if path == pathCapability.Prefix { - for _, capability := range pathCapability.Capabilities { - if _, ok := capabilities[capability]; !ok { - capabilities[capability] = true - } - } - } - } - } - } - - if len(capabilities) == 0 { - result.Capabilities = []string{"deny"} - return &result, nil - } - - for capability, _ := range capabilities { - result.Capabilities = append(result.Capabilities, capability) - } - sort.Strings(result.Capabilities) - */ - return &result, nil + return acl.Capabilities(path), nil } diff --git a/vault/policy.go b/vault/policy.go index 6f856e7b72b1..7e459f59a98b 100644 --- a/vault/policy.go +++ b/vault/policy.go @@ -15,6 +15,7 @@ const ( DeleteCapability = "delete" ListCapability = "list" SudoCapability = "sudo" + RootCapability = "root" // Backwards compatibility OldDenyPathPolicy = "deny"