Created
October 11, 2018 13:33
-
-
Save antaflos/1208b0cfa87a9aeb6a7151bd96da1268 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
Puppet::Functions.create_function(:file_eyaml_lookup_key) do | |
unless Puppet.features.hiera_eyaml? | |
raise Puppet::DataBinding::LookupError, 'Lookup using function '\ | |
'file_eyaml_lookup_key is only supported when the hiera_eyaml '\ | |
'library is present' | |
end | |
dispatch :file_eyaml_lookup_key do | |
param 'String[1]', :key | |
param 'Hash[String[1],Any]', :options | |
param 'Puppet::LookupContext', :context | |
end | |
require 'hiera/backend/eyaml/options' | |
require 'hiera/backend/eyaml/encryptor' | |
def file_eyaml_lookup_key(key, options, context) | |
return context.cached_value(key) if context.cache_has_key(key) | |
# Set interpolate = true by default and override it with the value of | |
# options['interpolate'], if set. | |
interpolate = true | |
interpolate = options['interpolate'] unless options['interpolate'].nil? | |
# Set extension = enc by default and override it with the value of | |
# options['extension'], if set. Thus the file path and name from which we | |
# will look up the encrypted contents is constructed from | |
# path + key + '.' + enc | |
# If the value is the "special" string 'none' then no extension will be | |
# added when constructing the file path and name and we will effectively | |
# not distinguish between files with encrypted content and regular content. | |
extension = options['extension'] || 'enc' | |
if !options['extension'].nil? && options['extension'] == 'none' | |
extension = nil | |
end | |
context.explain { "Setting interpolate = #{interpolate}" } | |
context.explain { "Setting extension = #{extension}" } | |
options.each_pair do |k, v| | |
unless ['path', 'interpolate', 'extension'].include?(k) | |
Hiera::Backend::Eyaml::Options[k.to_sym] = v | |
context.explain { "Setting Eyaml option '#{k}' to '#{v}'" } | |
end | |
end | |
data = nil | |
encrypted_data_file_path = File.join(options['path'], key) | |
encrypted_data_file_path += '.' + extension unless extension.nil? | |
regular_data_file_path = File.join(options['path'], key) | |
if File.exist?(encrypted_data_file_path) | |
data = context.cached_file_data(encrypted_data_file_path) do |content| | |
decrypt(content, encrypted_data_file_path, context) | |
end | |
elsif File.exist?(regular_data_file_path) | |
data = context.cached_file_data(regular_data_file_path) | |
context.explain { "#{regular_data_file_path}: returning data as is "\ | |
"from regular, non-encrypted file" } | |
if encrypted?(data) | |
warnmsg = "#{regular_data_file_path}: file contents appear to be "\ | |
"Eyaml-encrypted but file does not have extension '#{extension}', "\ | |
"therefore no decryption was attempted" | |
context.explain { warnmsg } | |
end | |
else | |
context.not_found | |
end | |
if interpolate == true | |
context.cache(key, context.interpolate(data)) | |
else | |
context.cache(key, data) | |
end | |
end | |
def encrypted?(data) | |
/^ENC\[.*?\]$/ =~ data ? true : false | |
end | |
def decrypt(data, path, context) | |
unless encrypted?(data) | |
warnmsg = "#{path}: file contents do not seem to be Eyaml-encrypted, "\ | |
"even though file name suggests they should be; returning data as is" | |
context.explain { warnmsg } | |
return data | |
end | |
enc_method, enc_data = data.match(/^ENC\[((\w+),)?([a-zA-Z0-9\+\/=]+?)\]$/)[2,3] | |
begin | |
encryptor = Hiera::Backend::Eyaml::Encryptor.find(enc_method) | |
encryptor.decrypt(encryptor.decode(enc_data)) | |
rescue StandardError => e | |
context.explain { "failed to decrypt contents: #{e.message}" } | |
nil | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment