From 8ca75f6d074b83ee48d9ce713cdb3e28e57d2cf8 Mon Sep 17 00:00:00 2001 From: mh Date: Thu, 28 Jan 2016 00:55:26 +0100 Subject: update module to make it work with all the new features of trocla 0.2.2 --- .gitignore | 5 +- .travis.yml | 15 +++++ Gemfile | 23 ++++++++ README.md | 6 ++ Rakefile | 23 ++++++++ manifests/ca/params.pp | 11 ++++ manifests/config.pp | 63 +++++++++++++-------- manifests/master.pp | 13 +++-- manifests/master/hiera.pp | 6 ++ manifests/master/ree.pp | 13 ----- manifests/params.pp | 6 ++ manifests/yaml.pp | 22 +++----- metadata.json | 4 +- spec/classes/ca_params_spec.rb | 8 +++ spec/classes/config_spec.rb | 114 ++++++++++++++++++++++++++++++++++++++ spec/classes/master_hiera_spec.rb | 11 ++++ spec/classes/master_spec.rb | 52 +++++++++++++++++ spec/classes/params_spec.pp | 8 +++ spec/classes/yaml_spec.rb | 39 +++++++++++++ spec/spec_helper.rb | 13 +++++ templates/troclarc.yaml.erb | 62 ++++++++++++++------- 21 files changed, 442 insertions(+), 75 deletions(-) create mode 100644 .travis.yml create mode 100644 Gemfile create mode 100644 Rakefile create mode 100644 manifests/ca/params.pp create mode 100644 manifests/master/hiera.pp delete mode 100644 manifests/master/ree.pp create mode 100644 manifests/params.pp create mode 100644 spec/classes/ca_params_spec.rb create mode 100644 spec/classes/config_spec.rb create mode 100644 spec/classes/master_hiera_spec.rb create mode 100644 spec/classes/master_spec.rb create mode 100644 spec/classes/params_spec.pp create mode 100644 spec/classes/yaml_spec.rb create mode 100644 spec/spec_helper.rb diff --git a/.gitignore b/.gitignore index 01d0a08..493131d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ -pkg/ +spec/fixtures +.librarian +.tmp +*.lock diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..c85bde4 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,15 @@ +rvm: + - 1.8.7 + - 1.9.3 + - 2.0.0 +script: 'bundle exec rake spec' +env: + - PUPPET_VERSION=3.8.4 +matrix: + exclude: + # No support for Ruby 2.0 before Puppet 3.2 + - rvm: 2.0.0 + env: PUPPET_VERSION=3.0.0 + - rvm: 2.0.0 + env: PUPPET_VERSION=3.1.0 + diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..71032cf --- /dev/null +++ b/Gemfile @@ -0,0 +1,23 @@ +source 'https://rubygems.org' + +if ENV.key?('PUPPET_VERSION') + puppetversion = "~> #{ENV['PUPPET_VERSION']}" +else + puppetversion = ['>= 3.8.4'] +end + +if RUBY_VERSION == '1.8.7' + puppetversion = ['~> 3.8.4'] + gem 'i18n', '~> 0.6.11' + gem 'activesupport', '~> 3.2' + gem 'highline', '~> 1.6.21' + gem 'librarian-puppet', '~> 1.0.0' + gem 'rspec', '~> 3.1.0' +else + gem 'librarian-puppet' +end + +gem 'puppet', puppetversion +gem 'puppet-lint' +gem 'puppetlabs_spec_helper' +gem 'rake' diff --git a/README.md b/README.md index 551de54..8874f63 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,10 @@ clients if you do not want to use trocla on the clients itself. If you want to do your own very custom setup, you should look into the other classes. +## Compatibility + +* Version 0.2.2 of this module is for version 0.2.2 of trocla. + ## Functions ### trocla @@ -85,6 +89,8 @@ trocla, it will just install the necessary packages. Trocla can also be integrated into [Hiera](https://docs.puppetlabs.com/hiera/) by using ZeroPointEnergy's [hiera-backend](https://github.com/ZeroPointEnergy/hiera-backend-trocla). +Simply `include trocla::master::hiera` to make that backend available. + ## Moar RTFC and for more information about trocla visit: https://github.com/duritong/trocla diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..e5103dd --- /dev/null +++ b/Rakefile @@ -0,0 +1,23 @@ +require 'bundler' +Bundler.require(:rake) + +require 'puppetlabs_spec_helper/rake_tasks' +require 'puppet-lint/tasks/puppet-lint' + +PuppetLint.configuration.ignore_paths = ["spec/**/*.pp", "vendor/**/*.pp"] +PuppetLint.configuration.log_format = '%{path}:%{linenumber}:%{KIND}: %{message}' +PuppetLint.configuration.send("disable_class_inherits_from_params_class") + +# use librarian-puppet to manage fixtures instead of .fixtures.yml +# offers more possibilities like explicit version management, forge downloads,... +task :librarian_spec_prep do + sh "librarian-puppet install --path=spec/fixtures/modules/" + pwd = `pwd`.strip + unless File.directory?("#{pwd}/spec/fixtures/modules/trocla") + sh "ln -s #{pwd} #{pwd}/spec/fixtures/modules/trocla" + end +end +task :spec_prep => :librarian_spec_prep + + +task :default => [:spec, :lint] diff --git a/manifests/ca/params.pp b/manifests/ca/params.pp new file mode 100644 index 0000000..bb61248 --- /dev/null +++ b/manifests/ca/params.pp @@ -0,0 +1,11 @@ +# input for a ca from trocla, so that you need only +# +# trocla('some_ca','x509',$trocla::ca::params::ca_options) +class trocla::ca::params( + $trocla_options = { + 'profiles' => ['sysdomain_nc','x509long'], + 'CN' => "automated-ca ${name} for ${::domain}", + }, +) { + $ca_options = merge($trocla_options,{ become_ca => true, render => { certonly => true }}) +} diff --git a/manifests/config.pp b/manifests/config.pp index 7b23a3e..8c52db7 100644 --- a/manifests/config.pp +++ b/manifests/config.pp @@ -1,35 +1,55 @@ #Installs configuration files for the trocla agent/CLI # #Options -# [*adapter*] Defines the adapter type to use for trocla agent. -# By default it's YAML -# [*adapter_options*] This will contain a hash of the adapter options to pass the -# trocla configuration. -# [*encryption*] Defines the encryption method for password stored in the backend. -# By default no encryption is used. -# [*ssl_options*] This will contain a hash of the ssl options to pass the -# trocla configuration. -# [*password_length*] Define the length of default passwords to create. 16 by default -# [*random_passwords*] Should trocla generate random passwords -# if none can be found. *true* by default. -# [*manage_dependencies*] Whether to manage the dependencies or not. Default *true* +# [*options*] Options for trocla. Default: empty hash. +# [*profiles*] Profiles for trocla. Default: empty hash. +# [*x509_profile_domain_constraint*] +# A profile for x509 name constraint that matches +# the own domain by default. +# This will add a profile for x509 certs with the +# option 'name_constraints' set to this array of +# domains. +# [*store*] Defines the store to be used for trocla. By default +# it's not set, meaning trocla's default (moneta) will +# be used. +# [*store_options*] This will contain a hash of the options to pass the +# trocla store configuration. +# [*encryption*] Defines the encryption method for password stored in +# the backend. By default it's not set, meaning trocla's +# default (none) will be used. +# [*encryption_options*] This will contain a hash of the options for the +# encryption. Default: empty Hash +# [*manage_dependencies*] Whether to manage the dependencies or not. +# Default *true* class trocla::config ( - $adapter = 'YAML', - $password_length = 16, - $random_passwords = true, - $adapter_options = {}, - $encryption = undef, - $ssl_options = {}, - $manage_dependencies = true, + $options = {}, + $profiles = {}, + $x509_profile_domain_constraints = [$::domain], + $store = undef, + $store_options = {}, + $encryption = undef, + $encryption_options = {}, + $manage_dependencies = true, ) { + include ::trocla::params if $manage_dependencies { - require trocla::master + require ::trocla::master + } + + if empty($x509_profile_domain_constraints) { + $merged_profiles = $profiles + } else { + $default_profiles = { + "${trocla::params::sysdomain_profile_name}" => { + name_constraints => $x509_profile_domain_constraints + } + } + $merged_profiles = merge($default_profiles,$profiles) } # Deploy default config file and link it for trocla cli lookup file{ "${settings::confdir}/troclarc.yaml": - ensure => present, content => template('trocla/troclarc.yaml.erb'), owner => root, group => puppet, @@ -38,5 +58,4 @@ class trocla::config ( ensure => link, target => "${settings::confdir}/troclarc.yaml"; } - } diff --git a/manifests/master.pp b/manifests/master.pp index ad47914..43e203d 100644 --- a/manifests/master.pp +++ b/manifests/master.pp @@ -3,15 +3,18 @@ # This module manages the necessary things for trocla on a master. # class trocla::master ( - $provider = gem, + $provider = 'default', ) { - #Main trocla install package {'trocla': - ensure => present, - provider => $provider, + ensure => 'installed', } - if $provider != 'gem' { + if $provider != 'default' { + Package['trocla']{ + provider => $provider, + } + } + if $provider != 'gem' and $::osfamily == 'RedHat' { Package['trocla']{ name => 'rubygem-trocla' } diff --git a/manifests/master/hiera.pp b/manifests/master/hiera.pp new file mode 100644 index 0000000..75b8bb3 --- /dev/null +++ b/manifests/master/hiera.pp @@ -0,0 +1,6 @@ +# manage trocla/hiera integration +class trocla::master::hiera { + package{'rubygem-hiera-backend-trocla': + ensure => present, + } +} diff --git a/manifests/master/ree.pp b/manifests/master/ree.pp deleted file mode 100644 index bf2c400..0000000 --- a/manifests/master/ree.pp +++ /dev/null @@ -1,13 +0,0 @@ -# Class: trocla::master::ree -# -# This module manages the necessary things for trocla on a master for -# RubyEnterprise installation. -# -# [Remember: No empty lines between comments and class definition] -class trocla::master::ree { - - require ruby_enterprise::gems::moneta - require ruby_enterprise::gems::highline - - ruby_enterprise::gem{'trocla': } -} diff --git a/manifests/params.pp b/manifests/params.pp new file mode 100644 index 0000000..f99aa2a --- /dev/null +++ b/manifests/params.pp @@ -0,0 +1,6 @@ +# a set of default params for various trocla usages +class trocla::params( + $sysdomain_profile_name = 'sysdomain_nc' +){ + +} diff --git a/manifests/yaml.pp b/manifests/yaml.pp index dc20c2e..8ac0071 100644 --- a/manifests/yaml.pp +++ b/manifests/yaml.pp @@ -2,24 +2,20 @@ # This will install and configure trocla with the # default yaml storage. # -# [*password_length*] The default length of new passwords: 16 -# [*random_passwords*] Whether trocla should generate random -# passwords or not. Default: true # [*data_file*] Where to store the passwords. -# Default: {$settings::server_datadir}/trocla_data.yaml" -# This will likely be: /var/lib/puppet/server_data/trocla_data.yaml +# Default: /var/lib/trocla/trocla_data.yaml +# This should be managed using the package. class trocla::yaml( - $password_length = 16, - $random_passwords = true, - $data_file = "${settings::server_datadir}/trocla_data.yaml", + $data_file = '/var/lib/trocla/trocla_data.yaml', ) { class{'trocla::config': - password_length => $password_length, - random_passwords => $random_passwords, - adapter => 'YAML', - adapter_options => { - file => $data_file, + store => 'moneta', + store_options => { + adapter => 'YAML', + adapter_options => { + file => $data_file, + }, }, } diff --git a/metadata.json b/metadata.json index af2d50b..a5b7d9a 100644 --- a/metadata.json +++ b/metadata.json @@ -1,6 +1,6 @@ { "name": "duritong-trocla", - "version": "0.0.8", + "version": "0.2.2", "author": "duritong", "summary": "This modules allows you to use trocla (https://github.com/duritong/trocla) from puppet.", "license": "GPLv2", @@ -9,6 +9,6 @@ "issues_url": "https://github.com/duritong/puppet-trocla/issues", "description": "This modules allows you use trocla lookups as puppet functions.", "dependencies": [ - + {"name":"puppetlabs/stdlib","version_requirement":">= 3.2.0"} ] } diff --git a/spec/classes/ca_params_spec.rb b/spec/classes/ca_params_spec.rb new file mode 100644 index 0000000..5277972 --- /dev/null +++ b/spec/classes/ca_params_spec.rb @@ -0,0 +1,8 @@ +require File.expand_path(File.join(File.dirname(__FILE__),'../spec_helper')) + +describe 'trocla::ca::params', :type => 'class' do + context 'with default params' do + it { should compile.with_all_deps } + end +end + diff --git a/spec/classes/config_spec.rb b/spec/classes/config_spec.rb new file mode 100644 index 0000000..fc0a33a --- /dev/null +++ b/spec/classes/config_spec.rb @@ -0,0 +1,114 @@ +require File.expand_path(File.join(File.dirname(__FILE__),'../spec_helper')) + +describe 'trocla::config', :type => 'class' do + let(:facts){ + { + :domain => 'example.com', + } + } + context 'with default params' do + it { should contain_class('trocla::params') } + it { should contain_class('trocla::master') } + it { should contain_file('/etc/puppet/troclarc.yaml').with( + :owner => 'root', + :group => 'puppet', + :mode => '0640' + )} + it { should contain_file('/etc/puppet/troclarc.yaml').with_content("--- +profiles: + sysdomain_nc: + name_constraints: + - example.com +") } + it { should contain_file('/etc/troclarc.yaml').with( + :ensure => 'link', + :target => '/etc/puppet/troclarc.yaml' + )} + + it { should compile.with_all_deps } + end + + context 'with other params' do + let(:params) { + { + :options => { + 'length' => 24, + 'profiles' => 'mydefaultprofile', + 'random' => false, + 'expires' => 60*60*24, #1day + }, + :profiles => { + 'mydefaultprofile' => { + 'length' => 20, + }, + 'anotherprofile' => { + 'random' => true, + 'expires' => false, + }, + }, + :x509_profile_domain_constraints => ['domain1.com','domain2.com'], + :store => 'moneta', + :store_options => { + 'adapter' => 'Sequel', + 'adapter_options' => { + 'db' => 'mysql://db.server.name', + 'user' => 'trocla', + 'password' => 'secret_password', + 'database' => 'trocladb', + 'table' => 'trocla', + }, + }, + :encryption => 'ssl', + :encryption_options => { + 'private_key' => '/var/lib/puppet/ssl/private_keys/trocla.pem', + 'public_key' => '/var/lib/puppet/ssl/public_keys/trocla.pem', + }, + :manage_dependencies => false, + } + } + it { should contain_class('trocla::params') } + it { should_not contain_class('trocla::master') } + it { should contain_file('/etc/puppet/troclarc.yaml').with( + :owner => 'root', + :group => 'puppet', + :mode => '0640' + )} + it { should contain_file('/etc/puppet/troclarc.yaml').with_content("--- +encryption: :ssl +encryption_options: + :private_key: /var/lib/puppet/ssl/private_keys/trocla.pem + :public_key: /var/lib/puppet/ssl/public_keys/trocla.pem +options: + expires: 86400 + length: 24 + profiles: mydefaultprofile + random: false +profiles: + anotherprofile: + expires: false + random: true + mydefaultprofile: + length: 20 + sysdomain_nc: + name_constraints: + - domain1.com + - domain2.com +store: :moneta +store_options: + adapter: :Sequel + adapter_options: + :database: trocladb + :db: mysql://db.server.name + :password: secret_password + :table: trocla + :user: trocla +") } + it { should contain_file('/etc/troclarc.yaml').with( + :ensure => 'link', + :target => '/etc/puppet/troclarc.yaml' + )} + + it { should compile.with_all_deps } + end +end + diff --git a/spec/classes/master_hiera_spec.rb b/spec/classes/master_hiera_spec.rb new file mode 100644 index 0000000..62112fb --- /dev/null +++ b/spec/classes/master_hiera_spec.rb @@ -0,0 +1,11 @@ +require File.expand_path(File.join(File.dirname(__FILE__),'../spec_helper')) + +describe 'trocla::master::hiera', :type => 'class' do + context 'with default params' do + it { should compile.with_all_deps } + it { should contain_package('rubygem-hiera-backend-trocla').with( + :ensure => 'present', + )} + end +end + diff --git a/spec/classes/master_spec.rb b/spec/classes/master_spec.rb new file mode 100644 index 0000000..ad99c86 --- /dev/null +++ b/spec/classes/master_spec.rb @@ -0,0 +1,52 @@ +require File.expand_path(File.join(File.dirname(__FILE__),'../spec_helper')) + +describe 'trocla::master', :type => 'class' do + context 'with default params' do + context 'on RedHat' do + let(:facts) { + { + :osfamily => 'RedHat', + } + } + it { should contain_package('trocla').with( + :name => 'rubygem-trocla', + :ensure => 'installed' + )} + it { should compile.with_all_deps } + end + context 'on Debian' do + let(:facts) { + { + :osfamily => 'Debian', + } + } + it { should contain_package('trocla').with( + :ensure => 'installed' + )} + it { should compile.with_all_deps } + end + end + context 'with gem provider' do + let(:params){ + { + :provider => 'gem' + } + } + it { should contain_package('trocla').with( + :ensure => 'installed', + :provider => 'gem' + )} + + it { should compile.with_all_deps } + context 'on RedHat' do + it { should contain_package('trocla').with( + :name => 'trocla', + :ensure => 'installed', + :provider => 'gem' + )} + + it { should compile.with_all_deps } + end + end +end + diff --git a/spec/classes/params_spec.pp b/spec/classes/params_spec.pp new file mode 100644 index 0000000..4d05e1f --- /dev/null +++ b/spec/classes/params_spec.pp @@ -0,0 +1,8 @@ +require File.expand_path(File.join(File.dirname(__FILE__),'../spec_helper')) + +describe 'trocla::params', :type => 'class' do + context 'with default params' do + it { should compile.with_all_deps } + end +end + diff --git a/spec/classes/yaml_spec.rb b/spec/classes/yaml_spec.rb new file mode 100644 index 0000000..c5912f2 --- /dev/null +++ b/spec/classes/yaml_spec.rb @@ -0,0 +1,39 @@ +require File.expand_path(File.join(File.dirname(__FILE__),'../spec_helper')) + +describe 'trocla::yaml', :type => 'class' do + let(:facts){ + { + :domain => 'example.com', + } + } + context 'with default params' do + it { should contain_class('trocla::config').with( + 'store' => 'moneta', + 'store_options' => { + 'adapter' => 'YAML', + 'adapter_options' => { + 'file' => '/var/lib/trocla/trocla_data.yaml', + } + } + )} + it { should contain_file('/etc/puppet/troclarc.yaml').with_content("--- +profiles: + sysdomain_nc: + name_constraints: + - example.com +store: :moneta +store_options: + adapter: :YAML + adapter_options: + :file: /var/lib/trocla/trocla_data.yaml +") } + it { should contain_file('/var/lib/trocla/trocla_data.yaml').with( + :ensure => 'file', + :owner => 'puppet', + :group => 0, + :mode => '0600' + )} + it { should compile.with_all_deps } + end +end + diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..381f972 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,13 @@ +require 'puppetlabs_spec_helper/module_spec_helper' +require 'rake' + +fixture_path = File.expand_path(File.join(__FILE__, '..', 'fixtures')) + +RSpec.configure do |c| + c.module_path = File.join(fixture_path, 'modules') + c.manifest_dir = File.join(fixture_path, 'manifests') + c.pattern = FileList[c.pattern].exclude(/^spec\/fixtures/) +end + +Puppet::Util::Log.level = :warning +Puppet::Util::Log.newdestination(:console) diff --git a/templates/troclarc.yaml.erb b/templates/troclarc.yaml.erb index cd4da3d..5584fd8 100644 --- a/templates/troclarc.yaml.erb +++ b/templates/troclarc.yaml.erb @@ -1,20 +1,44 @@ ---- -options: - random: <%= @random_passwords %> - length: <%= @password_length %> -adapter: :<%= @adapter %> -<% unless @adapter_options.empty? %> -adapter_options: -<% @adapter_options.keys.sort.each do |key| -%> - :<%= key %>: '<%= @adapter_options[key] %>' -<% end -%> -<% end -%> -<% if @encryption %> -encryption: :<%= @encryption %> -<% end -%> -<% unless @ssl_options.empty? %> -ssl_options: -<% @ssl_options.keys.sort.each do |key| -%> - :<%= key %>: '<%= @ssl_options[key] %>' -<% end -%> +<% + # stupid but effective sorting of yaml + # forgive me for that, but puppet monkeypatches yaml heavily and breaks it constantly + # for our use case it should be sufficient, otherwise we need to + # extent it to address the new problems + def sort_pseudo_yaml(obj, indent='') + arr = obj.sort {|a,b| (a[0].is_a?(Symbol) ? a[0].to_s : a[0]) <=> (b[0].is_a?(Symbol) ? b[0].to_s : b[0]) } + out = [] + arr.each do |e| + if e[1].is_a?(Hash) + out << "#{indent}#{e[0]}:" + out << sort_pseudo_yaml(e[1],indent+' ') + elsif e[1].is_a?(Array) + out << (["#{indent}#{e[0]}:"]+e[1].collect{|e| "- #{e}" }).join("\n#{indent}") + else + out << "#{indent}#{e[0].is_a?(Symbol) ? ":#{e[0].to_s}" : e[0]}: #{e[1].is_a?(Symbol) ? ":#{e[1].to_s}" : e[1]}" + end + end + out.join("\n") + end + def sym_keys(h) + h.keys.inject({}) do |r,k| + r[k.to_sym] = h[k] + r + end + end + # transform special options so they are understood by the other libraries + so = @store_options.dup + so['adapter'] = so['adapter'].to_sym if so['adapter'] + so['adapter_options'] = sym_keys(so['adapter_options']) if so['adapter_options'] + eo = @encryption_options ? sym_keys(@encryption_options) : {} + options_hash = { + 'store' => @store.nil? ? @store : @store.to_sym, + 'store_options' => so, + 'encryption' => @encryption.nil? ? @encryption : @encryption.to_sym, + 'encryption_options' => eo, + 'options' => @options, + 'profiles' => @merged_profiles, + }.delete_if{|k,v| v.nil? || (v.is_a?(Symbol) ? v.to_s : v).empty? } + output = sort_pseudo_yaml(options_hash) +-%>--- +<% unless output.empty? -%> +<%= output %> <% end -%> -- cgit v1.2.3