From bdb8cf128dc5b7e067cae78266481724bd50d933 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Tue, 15 Sep 2015 11:28:07 -0400 Subject: [PATCH] Cleanup; remove everything but double-salting from the router and give the token store cubby backend information for direct calling. --- vault/logical_cubbyhole.go | 18 ++-------------- vault/router.go | 43 ++++++++++++++++++++++++++------------ vault/token_store.go | 24 ++++++++++++++++----- 3 files changed, 51 insertions(+), 34 deletions(-) diff --git a/vault/logical_cubbyhole.go b/vault/logical_cubbyhole.go index d6948dced..b365c1b5a 100644 --- a/vault/logical_cubbyhole.go +++ b/vault/logical_cubbyhole.go @@ -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 } diff --git a/vault/router.go b/vault/router.go index 8be6ed3fd..697d3581c 100644 --- a/vault/router.go +++ b/vault/router.go @@ -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() diff --git a/vault/token_store.go b/vault/token_store.go index 5c1393ea1..8c2bda440 100644 --- a/vault/token_store.go +++ b/vault/token_store.go @@ -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