Created
November 16, 2017 18:14
-
-
Save alzabo/aa48f36bf624e88143d7da4ffed83c5b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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