Skip to content

Instantly share code, notes, and snippets.

@alzabo
Created November 16, 2017 18:14
Show Gist options
  • Save alzabo/aa48f36bf624e88143d7da4ffed83c5b to your computer and use it in GitHub Desktop.
Save alzabo/aa48f36bf624e88143d7da4ffed83c5b to your computer and use it in GitHub Desktop.
# HACK: This is a pretty crappy thing to do in a system that needs to be
# reliable, but older Rubies don't have this method and the vault gem calls
# it on strings.
# lol copy paste from stack overflow
module DisgustingHack
def b
self.dup.force_encoding("ASCII-8BIT")
end
end
Puppet::Functions.create_function(:vault_lookup_key) do
begin
require 'vault'
rescue LoadError
raise Puppet::DataBinding::LookupError,
'Lookup using vault lookup_key function is only supported when the '\
'vault RubyGem library is present'
end
local_types do
type 'SecretPath = Pattern[/\/secret\/?.*/]'
type 'SecretBase = Variant[SecretPath, Array[SecretPath]]'
end
dispatch :vault_lookup_key do
param 'String[1]', :key
param 'Struct[{secret_base => SecretBase,
Optional[vault_addr] => Pattern[/http(s)?:\/\/.*/],
Optional[vault_token] => String[1],
Optional[default_key] => String[1]}]', :options
param 'Puppet::LookupContext', :context
end
def vault_lookup_key(key, options, context)
return context.cached_value(key) if context.cache_has_key(key)
result_raw = do_lookup(key, options)
context.not_found if result_raw.empty?
result = if options["default_key"].nil? || result_raw[options["default_key"]].nil?
result_raw
else
result_raw[options["default_key"]]
end
context.cache(key, result)
end
# Returns the first secret data hash found in vault, or an empty hash
def do_lookup(key, options)
Vault.address = options["vault_addr"] if options["vault_addr"]
Vault.token = options["vault_token"] if options["vault_token"]
data = normalized_paths(options["secret_base"]).collect do |base|
Vault.with_retries(Vault::HTTPError) do
secret = Vault.logical.read(create_lookup_string(base, key))
break secret.data unless secret.nil?
end
end.compact.first
if data.is_a?(Hash)
Puppet::Pops::Lookup::HieraConfig.symkeys_to_string(data)
else
{}
end
end
def create_lookup_string(*args)
path = File.join(*args)
# HACK: Inject the `b` method into the string that will be sent to
# `Vault.logical.read`
path.extend(DisgustingHack) if RUBY_VERSION < "2.0"
end
# Munge String or Array of SecretPaths into an array of paths
# removing consecutive duplicates
def normalized_paths(paths)
Array[paths].flatten.collect do |path|
path.sub(%r{\/+$}, '')
end.uniq
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment