Class: Cache

Inherits:
Object
  • Object
show all
Defined in:
lib/puppet/functions/hiera_vault.rb

Overview

Cache will keep track of all the results gotten from the Vault server. To avoid leaking secrets both the key looked for and the options are used as the key for the cache so that using the same key with different options will not risk leaking a secret. To keep things fast and not have the pruning method take longer as the number of entries grow we create a Hash for each value of cache_for and keep entries in this hash ordered from the oldest one to the most recent. When looking for entries to evict we iterate over each Hash in order and stop when we find the first entry that we must keep: because all the subsequent entries will be younger there is no need to continue as we will need to keep them all. Doing this make time spent pruning the cache proportional to number of entries that actually need to be evicted, and not to the total number of entries in the cache. We avoid keeping secrets in memory for longer than necessary by calling prune before each operation of the cache, we always evict secret from memory as soon as we can. Note that we don’t need synchronization primitives in Cache because we always hold hiera_vault_mutex when accessing the cache.

Defined Under Namespace

Classes: CacheKey, CacheValue

Instance Method Summary collapse

Constructor Details

#initializeCache

Returns a new instance of Cache.



23
24
25
# File 'lib/puppet/functions/hiera_vault.rb', line 23

def initialize
  @caches = Hash.new { |hash, key| hash[key] = {} }
end

Instance Method Details

#get(key, options) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/puppet/functions/hiera_vault.rb', line 45

def get(key, options)
  prune

  cache_for = options['cache_for']

  # Early exit if the cache is deactivated
  return nil if cache_for.nil?

  k = CacheKey.new(key, options)
  cache = @caches[cache_for]

  # We don't need to check whether the value has expired because it would
  # have been removed during prune
  cache[k]
end

#pruneObject

Removes all the expired entries from the cache



62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/puppet/functions/hiera_vault.rb', line 62

def prune
  @caches.each_value do |cache|
    cache.each do |key, value|
      # Because the entries in each cache are ordered we can stop as soon as
      # we find one that we need to keep, all the following ones will be
      # younger and need to be kept too
      break if value.until >= Time.now

      cache.delete(key)
    end
  end
end

#set(key, value, options) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/puppet/functions/hiera_vault.rb', line 27

def set(key, value, options)
  prune

  cache_for = options['cache_for']

  # Early exit if the cache is deactivated
  return nil if cache_for.nil?

  k = CacheKey.new(key, options)
  cache = @caches[cache_for]

  # We first delete the key from the cache so it will always be ordered from
  # oldest entries to most recent
  cache.delete(k)

  cache[k] = CacheValue.new(value, Time.now + cache_for)
end