Cleanup; remove everything but double-salting from the router and give

the token store cubby backend information for direct calling.
This commit is contained in:
Jeff Mitchell 2015-09-15 11:28:07 -04:00
parent 538852d6d6
commit bdb8cf128d
3 changed files with 51 additions and 34 deletions

View File

@ -52,25 +52,11 @@ func (b *CubbyholeBackend) revoke(saltedToken string, storageView logical.Storag
if saltedToken == "" {
return fmt.Errorf("[ERR] cubbyhole: client token empty during revocation")
}
// Delete the entire tree in a stupid fashion for the moment
// to avoid changing the Storage interface
keys, err := storageView.List(saltedToken + "/")
if err != nil {
if err := ClearView(storageView.(*BarrierView).SubView(saltedToken + "/")); err != nil {
return err
}
errors := []string{}
for _, key := range keys {
err = storageView.Delete(saltedToken + "/" + key)
if err != nil {
errors = append(errors, err.Error())
}
}
if len(errors) != 0 {
return fmt.Errorf("[ERR] cubbyhole: errors were encountered when deleting the tree for token %s: %s", saltedToken, strings.Join(errors, "; "))
}
return nil
}

View File

@ -14,11 +14,9 @@ import (
// Router is used to do prefix based routing of a request to a logical backend
type Router struct {
l sync.RWMutex
root *radix.Tree
cubbyholeEntry *routeEntry
cubbyholeDestroyFunc func(string, logical.Storage) error
tokenStoreSalt *salt.Salt
l sync.RWMutex
root *radix.Tree
tokenStoreSalt *salt.Salt
}
// NewRouter returns a new router
@ -72,18 +70,26 @@ func (r *Router) Mount(backend logical.Backend, prefix string, mountEntry *Mount
}
r.root.Insert(prefix, re)
if mountEntry.Type == "cubbyhole" {
r.cubbyholeEntry = re
be := backend.(CubbyholeBackend)
r.cubbyholeDestroyFunc = be.revoke
switch mountEntry.Type {
case "token":
// this is loaded *after* the normal mounts, including cubbyhole
r.tokenStoreSalt = backend.(*TokenStore).salt
// We still hold the lock for the tree so we can't call MatchingBackend
_, raw, ok := r.root.LongestPrefix("cubbyhole/")
if !ok {
return fmt.Errorf("unable to find cubbyhole")
}
cubbyRouteEntry := raw.(*routeEntry)
cubbyBackend := cubbyRouteEntry.backend.(CubbyholeBackend)
re.backend.(*TokenStore).cubbyConfig = cubbyholeConfig{
revokeFunc: cubbyBackend.revoke,
storageView: cubbyRouteEntry.view,
saltUUID: cubbyRouteEntry.mountEntry.UUID,
}
}
return nil
}
func (r *Router) destroyCubbyhole(saltedID string) error {
return r.cubbyholeDestroyFunc(r.cubbyholeEntry.SaltID(saltedID), r.cubbyholeEntry.view)
}
// Unmount is used to remove a logical backend from a given prefix
func (r *Router) Unmount(prefix string) error {
r.l.Lock()
@ -171,6 +177,17 @@ func (r *Router) MatchingMountEntry(path string) *MountEntry {
return raw.(*routeEntry).mountEntry
}
// MatchingMountEntry returns the MountEntry used for a path
func (r *Router) MatchingBackend(path string) logical.Backend {
r.l.RLock()
_, raw, ok := r.root.LongestPrefix(path)
r.l.RUnlock()
if !ok {
return nil
}
return raw.(*routeEntry).backend
}
// MatchingSystemView returns the SystemView used for a path
func (r *Router) MatchingSystemView(path string) logical.SystemView {
r.l.RLock()

View File

@ -34,6 +34,14 @@ var (
displayNameSanitize = regexp.MustCompile("[^a-zA-Z0-9-]")
)
// cubbyholeConfig is used to store information necessary for telling the
// cubbyhole backend to remove the tree for the token
type cubbyholeConfig struct {
revokeFunc func(string, logical.Storage) error
storageView *BarrierView
saltUUID string
}
// TokenStore is used to manage client tokens. Tokens are used for
// clients to authenticate, and each token is mapped to an applicable
// set of policy which is used for authorization.
@ -45,7 +53,7 @@ type TokenStore struct {
expiration *ExpirationManager
router *Router
cubbyConfig cubbyholeConfig
}
// NewTokenStore is used to construct a token store that is
@ -56,8 +64,7 @@ func NewTokenStore(c *Core, config *logical.BackendConfig) (*TokenStore, error)
// Initialize the store
t := &TokenStore{
view: view,
router: c.router,
view: view,
}
// Setup the salt
@ -66,7 +73,6 @@ func NewTokenStore(c *Core, config *logical.BackendConfig) (*TokenStore, error)
return nil, err
}
t.salt = salt
t.router.tokenStoreSalt = salt
// Setup the framework endpoints
t.Backend = &framework.Backend{
@ -405,7 +411,7 @@ func (ts *TokenStore) revokeSalted(saltedId string) error {
}
// Destroy the cubby space
err = ts.router.destroyCubbyhole(saltedId)
err = ts.destroyCubbyhole(saltedId)
if err != nil {
return err
}
@ -707,6 +713,14 @@ func (ts *TokenStore) handleRenew(
return resp, nil
}
func (ts *TokenStore) destroyCubbyhole(saltedID string) error {
if ts.cubbyConfig.revokeFunc == nil {
// Should only ever happen in testing
return nil
}
return ts.cubbyConfig.revokeFunc(salt.SaltID(ts.cubbyConfig.saltUUID, saltedID, salt.SHA1Hash), ts.cubbyConfig.storageView)
}
const (
tokenBackendHelp = `The token credential backend is always enabled and builtin to Vault.
Client tokens are used to identify a client and to allow Vault to associate policies and ACLs