Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add custom hiera backend for trocla #15

Merged
merged 1 commit into from
Oct 18, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions lib/hiera/backend/trocla_backend.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Custom hiera backend for trocla
#
# Only reacts to key namespace trocla::password::<trocla_key>. Looks up
# additional parameters via hiera itself as
# trocla::options::<trocla_key>::format (string) and
# trocla::options::<trocla_key>::options (hash). Looks for <trocla_key> in
# trocla as hiera/<source>/<trocla> with <source> iterating over the configured
# hiera hierarchy. If not found, creates and returns a new password with trocla
# key <trocla_key>.
#
# example entry in hiera.yaml:
# backends:
# - ...
# - trocla
# trocla:
# - configfile: /etc/puppet/troclarc.yaml
# - format: plain
# - options:
# length: 16
#
# example usage in hiera yaml file:
# kerberos::kdc_database_password: "%{hiera('trocla::password::kdc_database_password')}"
# trocla::options::kdc_database_password::format: 'plain'
# trocla::options::kdc_database_password::options:
# length: 71
class Hiera
module Backend
class Trocla_backend

def initialize
@trocla = nil

Hiera.debug("Hiera Trocla backend starting")
require 'trocla'

default_configfile = "/etc/puppet/troclarc.yaml"
default_default_format = "plain"
default_default_options = {}

begin
configfile = Config[:trocla][:configfile] || default_configfile
rescue
configfile = default_configfile
end

if not File.exist?(configfile)
Hiera.warn("Trocla config file #{configfile} is not readable")
return
end

begin
@default_format = Config[:trocla][:format] || default_default_format
rescue
@default_format = default_default_format
end

begin
@default_options = Config[:trocla][:options] || default_default_options
rescue
@default_options = default_default_options
end

@trocla = Trocla.new(configfile)
end

def lookup(key, scope, order_override, resolution_type)
return nil unless @trocla

Hiera.debug("Looking up #{key} in trocla backend")

password_namespace = 'trocla::password::'
options_namespace = 'trocla::options::'

# we only accept trocla::password:: lookups because we do hiera lookups
# ourselves and could otherwise cause loops
return nil unless key.start_with?(password_namespace)

# cut off trocla hiera namespace: trocla::password::root -> root
trocla_key = key[password_namespace.length,
key.length - password_namespace.length]
Hiera.debug("Looking for key #{trocla_key} in trocla")

# HERE BE DRAGONS: hiera lookups from backend to determine additional
# trocla options for this password
format = Backend.lookup(options_namespace + trocla_key + '::format',
@default_format, scope, nil, :priority)

answer = nil
# Go looking for existing password as hiera/<source>/<trocla_key>.
# Would need to be initialised externally, e.g by calling
# trocla('hiera/osfamily/Debian/jessie/root' in site.pp. Alternatively
# we could use hiera's concept of datafiles to look into different
# trocla password stores. But this would need somehow providing
# different troclarcs as well.
sources = Backend.datasources(scope, order_override) do |source|
Hiera.debug("Looking for data source #{source}")
break if answer = @trocla.send(:get_password,
'hiera/' + source + '/' + trocla_key,
format)
end

if not answer
# create a new password
options = Backend.lookup(options_namespace + trocla_key + '::options',
@default_options, scope, nil, :hash)
answer = @trocla.send(:password, trocla_key, format, options)
end

return answer
end

end
end
end