From b18854be70cb1eb794fd1da7577410ef1baff947 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Thu, 21 Apr 2016 13:52:42 +0000 Subject: [PATCH] Plumb disabling caches through the policy store --- logical/system_view.go | 9 +++++ vault/core.go | 4 ++ vault/dynamic_system_view.go | 5 +++ vault/policy_store.go | 50 ++++++++++++++++-------- vault/policy_store_test.go | 17 +++++++- website/source/docs/config/index.html.md | 6 +-- 6 files changed, 70 insertions(+), 21 deletions(-) diff --git a/logical/system_view.go b/logical/system_view.go index 33dd01a414..4e26300cb0 100644 --- a/logical/system_view.go +++ b/logical/system_view.go @@ -26,6 +26,10 @@ type SystemView interface { // when the stored CRL will be removed during the unmounting process // anyways), we can ignore the errors to allow unmounting to complete. Tainted() bool + + // Returns true if caching is disabled. If true, no caches should be used, + // despite known slowdowns. + CacheDisabled() bool } type StaticSystemView struct { @@ -33,6 +37,7 @@ type StaticSystemView struct { MaxLeaseTTLVal time.Duration SudoPrivilegeVal bool TaintedVal bool + CacheDisabledVal bool } func (d StaticSystemView) DefaultLeaseTTL() time.Duration { @@ -50,3 +55,7 @@ func (d StaticSystemView) SudoPrivilege(path string, token string) bool { func (d StaticSystemView) Tainted() bool { return d.TaintedVal } + +func (d StaticSystemView) CacheDisabled() bool { + return d.CacheDisabledVal +} diff --git a/vault/core.go b/vault/core.go index 4c209e0665..12ceefb923 100644 --- a/vault/core.go +++ b/vault/core.go @@ -218,6 +218,9 @@ type Core struct { maxLeaseTTL time.Duration logger *log.Logger + + // cacheDisabled indicates whether caches are disabled + cacheDisabled bool } // CoreConfig is used to parameterize a core @@ -315,6 +318,7 @@ func NewCore(conf *CoreConfig) (*Core, error) { logger: conf.Logger, defaultLeaseTTL: conf.DefaultLeaseTTL, maxLeaseTTL: conf.MaxLeaseTTL, + cacheDisabled: conf.DisableCache, } // Setup the backends diff --git a/vault/dynamic_system_view.go b/vault/dynamic_system_view.go index 9c9340ac9a..b4ef6a77ae 100644 --- a/vault/dynamic_system_view.go +++ b/vault/dynamic_system_view.go @@ -69,3 +69,8 @@ func (d dynamicSystemView) fetchTTLs() (def, max time.Duration) { func (d dynamicSystemView) Tainted() bool { return d.mountEntry.Tainted } + +// CacheDisabled indicates whether to use caching behavior +func (d dynamicSystemView) CacheDisabled() bool { + return d.core.cacheDisabled +} diff --git a/vault/policy_store.go b/vault/policy_store.go index 8bbb79a8de..d4729f740b 100644 --- a/vault/policy_store.go +++ b/vault/policy_store.go @@ -22,8 +22,9 @@ const ( // PolicyStore is used to provide durable storage of policy, and to // manage ACLs associated with them. type PolicyStore struct { - view *BarrierView - lru *lru.TwoQueueCache + view *BarrierView + lru *lru.TwoQueueCache + system logical.SystemView } // PolicyEntry is used to store a policy by name @@ -34,12 +35,16 @@ type PolicyEntry struct { // NewPolicyStore creates a new PolicyStore that is backed // using a given view. It used used to durable store and manage named policy. -func NewPolicyStore(view *BarrierView) *PolicyStore { - cache, _ := lru.New2Q(policyCacheSize) +func NewPolicyStore(view *BarrierView, system logical.SystemView) *PolicyStore { p := &PolicyStore{ - view: view, - lru: cache, + view: view, + system: system, } + if !system.CacheDisabled() { + cache, _ := lru.New2Q(policyCacheSize) + p.lru = cache + } + return p } @@ -50,7 +55,7 @@ func (c *Core) setupPolicyStore() error { view := c.systemBarrierView.SubView(policySubPath) // Create the policy store - c.policyStore = NewPolicyStore(view) + c.policyStore = NewPolicyStore(view, &dynamicSystemView{core: c}) // Ensure that the default policy exists, and if not, create it policy, err := c.policyStore.GetPolicy("default") @@ -95,23 +100,29 @@ func (ps *PolicyStore) SetPolicy(p *Policy) error { return fmt.Errorf("failed to persist policy: %v", err) } - // Update the LRU cache - ps.lru.Add(p.Name, p) + if !ps.system.CacheDisabled() { + // Update the LRU cache + ps.lru.Add(p.Name, p) + } return nil } // GetPolicy is used to fetch the named policy func (ps *PolicyStore) GetPolicy(name string) (*Policy, error) { defer metrics.MeasureSince([]string{"policy", "get_policy"}, time.Now()) - // Check for cached policy - if raw, ok := ps.lru.Get(name); ok { - return raw.(*Policy), nil + if !ps.system.CacheDisabled() { + // Check for cached policy + if raw, ok := ps.lru.Get(name); ok { + return raw.(*Policy), nil + } } // Special case the root policy if name == "root" { p := &Policy{Name: "root"} - ps.lru.Add(p.Name, p) + if !ps.system.CacheDisabled() { + ps.lru.Add(p.Name, p) + } return p, nil } @@ -152,8 +163,11 @@ func (ps *PolicyStore) GetPolicy(name string) (*Policy, error) { policy = p } - // Update the LRU cache - ps.lru.Add(name, policy) + if !ps.system.CacheDisabled() { + // Update the LRU cache + ps.lru.Add(name, policy) + } + return policy, nil } @@ -178,8 +192,10 @@ func (ps *PolicyStore) DeletePolicy(name string) error { return fmt.Errorf("failed to delete policy: %v", err) } - // Clear the cache - ps.lru.Remove(name) + if !ps.system.CacheDisabled() { + // Clear the cache + ps.lru.Remove(name) + } return nil } diff --git a/vault/policy_store_test.go b/vault/policy_store_test.go index 4e4b8fe0f9..456bc8375b 100644 --- a/vault/policy_store_test.go +++ b/vault/policy_store_test.go @@ -10,7 +10,16 @@ import ( func mockPolicyStore(t *testing.T) *PolicyStore { _, barrier, _ := mockBarrier(t) view := NewBarrierView(barrier, "foo/") - p := NewPolicyStore(view) + p := NewPolicyStore(view, logical.TestSystemView()) + return p +} + +func mockPolicyStoreNoCache(t *testing.T) *PolicyStore { + sysView := logical.TestSystemView() + sysView.CacheDisabledVal = true + _, barrier, _ := mockBarrier(t) + view := NewBarrierView(barrier, "foo/") + p := NewPolicyStore(view, sysView) return p } @@ -44,7 +53,13 @@ func TestPolicyStore_Root(t *testing.T) { func TestPolicyStore_CRUD(t *testing.T) { ps := mockPolicyStore(t) + testPolicyStore_CRUD(t, ps) + ps = mockPolicyStoreNoCache(t) + testPolicyStore_CRUD(t, ps) +} + +func testPolicyStore_CRUD(t *testing.T, ps *PolicyStore) { // Get should return nothing p, err := ps.GetPolicy("dev") if err != nil { diff --git a/website/source/docs/config/index.html.md b/website/source/docs/config/index.html.md index 7b7f0b2cfb..c428605558 100644 --- a/website/source/docs/config/index.html.md +++ b/website/source/docs/config/index.html.md @@ -50,9 +50,9 @@ sending a SIGHUP to the server process. These are denoted below. "tcp" is currently the only option available. A full reference for the inner syntax is below. -* `disable_cache` (optional) - A boolean. If true, this will disable the - read cache used by the physical storage subsystem. This will very - significantly impact performance. +* `disable_cache` (optional) - A boolean. If true, this will disable all caches + within Vault, including the read cache used by the physical storage + subsystem. This will very significantly impact performance. * `disable_mlock` (optional) - A boolean. If true, this will disable the server from executing the `mlock` syscall to prevent memory from being