diff --git a/manifests/install/puppetdb.pp b/manifests/install/puppetdb.pp new file mode 100644 index 00000000..94a0184e --- /dev/null +++ b/manifests/install/puppetdb.pp @@ -0,0 +1,30 @@ +# +# Copyright (C) 2014 eNovance SAS +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# == Class: cloud::install::puppetdb +# +# Configure the puppetdb server +# +class cloud::install::puppetdb { + + exec { 'puppetdb ssl-setup' : + unless => 'stat /etc/puppetdb/ssl', + path => ['/bin', '/sbin', '/usr/bin', '/usr/sbin'], + before => Class['puppetdb::server'], + } + + include ::puppetdb + +} diff --git a/manifests/install/puppetmaster.pp b/manifests/install/puppetmaster.pp new file mode 100644 index 00000000..7be4b321 --- /dev/null +++ b/manifests/install/puppetmaster.pp @@ -0,0 +1,143 @@ +# +# Copyright (C) 2014 eNovance SAS +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# == Class: cloud::install::puppetmaster +# +# Configure the puppet master on the install-server +# +# == Parameters: +# +# [*puppetmaster_package_name*] +# (optional) Name of the puppetmaster package name +# Default: cloud::params::puppetmaster_package_name +# +# [*puppetmaster_service_name*] +# (optional) Name of the puppetmaster service name +# Default: cloud::params::puppetmaster_service_name +# +# [*main_configuration*] +# (optional) Hash of ini settings to set in the main section of the configuration +# Default: {} +# +# [*agent_configuration*] +# (optional) Hash of ini settings to set in the agent section of the configuration +# Default: {} +# +# [*master_configuration*] +# (optional) Hash of ini settings to set in the master section of the configuration +# Default: {} +# +# [*puppetmaster_vhost_configuration*] +# (optional) Hash of vhost configuration for the puppetmaster vhost +# Default: {} +# +# [*puppetconf_path*] +# (optional) Path to the puppet master configuration file +# Default: /etc/puppet/puppet.conf +# +# [*puppetdb_enable*] +# (optional) Whether the configuration for puppetdb should be enabled +# Default: true +# +# [*autosign_domains*] +# (optional) Array of domain origin to be auto signed +# Default: empty +# +class cloud::install::puppetmaster ( + $puppetmaster_package_name = $cloud::params::puppetmaster_package_name, + $puppetmaster_service_name = $cloud::params::puppetmaster_service_name, + $main_configuration = {}, + $agent_configuration = {}, + $master_configuration = {}, + $puppetmaster_vhost_configuration = {}, + $puppetconf_path = '/etc/puppet/puppet.conf', + $puppetdb_enable = true, + $autosign_domains = [], +) inherits cloud::params { + + package { $puppetmaster_package_name : + ensure => present, + before => File['/usr/share/puppet/rack'], + } -> + service { $puppetmaster_service_name : + ensure => stopped, + hasstatus => true, + hasrestart => true, + } -> + exec { "puppet cert generate ${::fqdn}": + unless => "stat /var/lib/puppet/ssl/certs/${::fqdn}.pem", + path => ['/usr/bin', '/bin'] + } + + # TODO (spredzy): Dirty hack + # to have the package in the catalog + # so puppetlabs/apache won't try to install it + # and fail since it's not present on rhel7 + if $::osfamily == 'RedHat' and $::operatingsystemmajrelease == 7 { + package { 'mod_passenger' : + ensure => absent, + before => Class['apache'], + } + } + + # Create the proper passenger configuration + # Per https://docs.puppetlabs.com/guides/passenger.html + file { + '/usr/share/puppet/rack' : + ensure => directory; + '/usr/share/puppet/rack/puppetmasterd' : + ensure => directory; + '/usr/share/puppet/rack/puppetmasterd/public' : + ensure => directory; + '/usr/share/puppet/rack/puppetmasterd/tmp' : + ensure => directory; + '/usr/share/puppet/rack/puppetmasterd/config.ru' : + ensure => link, + owner => 'puppet', + group => 'puppet', + target => '/usr/share/puppet/ext/rack/config.ru'; + } + + class { 'hiera' : + datadir => '/etc/puppet/data', + hierarchy => [ + '%{::type}/%{::fqdn}', + '%{::type}/common', + 'common', + ] + } + + if $puppetdb_enable { + Class['::puppetdb::master::config'] ~> Service['httpd'] + include ::puppetdb::master::config + } + + include ::apache + create_resources('apache::vhost', $puppetmaster_vhost_configuration, { 'require' => "Exec[puppet cert generate ${::fqdn}]" }) + + create_resources('ini_setting', $main_configuration, { 'section' => 'main', 'path' => $puppetconf_path, 'require' => "Package[${puppetmaster_package_name}]", 'notify' => 'Service[httpd]' }) + create_resources('ini_setting', $agent_configuration, { 'section' => 'agent', 'path' => $puppetconf_path, 'require' => "Package[${puppetmaster_package_name}]", 'notify' => 'Service[httpd]' }) + create_resources('ini_setting', $master_configuration, { 'section' => 'master', 'path' => $puppetconf_path, 'require' => "Package[${puppetmaster_package_name}]", 'notify' => 'Service[httpd]' }) + + file { '/etc/puppet/autosign.conf' : + ensure => present, + owner => 'puppet', + group => 'puppet', + content => template('cloud/installserver/autosign.conf.erb'), + require => Package[$puppetmaster_package_name], + notify => Service['httpd'], + } + +} diff --git a/manifests/params.pp b/manifests/params.pp index c1de5d2b..a482b074 100644 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -36,6 +36,8 @@ class cloud::params { } } + $puppetmaster_service_name = 'puppetmaster' + case $::osfamily { 'RedHat': { # Specific to Red Hat @@ -45,6 +47,7 @@ class cloud::params { $libvirt_service_name = 'libvirtd' $keepalived_name_is_process = false $keepalived_vrrp_script = 'systemctl status haproxy.service' + $puppetmaster_package_name = 'puppet-server' } # RedHat 'Debian': { # Specific to Debian / Ubuntu @@ -53,6 +56,7 @@ class cloud::params { $horizon_auth_url = 'horizon' $keepalived_name_is_process = true $keepalived_vrrp_script = undef + $puppetmaster_package_name = 'puppetmaster' case $::operatingsystem { 'Ubuntu': { $libvirt_service_name = 'libvirt-bin' @@ -66,4 +70,5 @@ class cloud::params { fail("Unsupported osfamily (${::osfamily})") } } + } diff --git a/scripts/bootstrap.pp b/scripts/bootstrap.pp new file mode 100644 index 00000000..ba3db242 --- /dev/null +++ b/scripts/bootstrap.pp @@ -0,0 +1,78 @@ +case $::osfamily { + 'RedHat': { + augeas {'httpd-lang' : + context => '/files/etc/sysconfig/httpd/', + changes => 'set LANG en_US.UTF-8', + notify => Service['httpd'], + require => Package['httpd'], + } + } + 'Debian': { + # Bug Puppet: https://tickets.puppetlabs.com/browse/PUP-1386 + exec { 'echo \'. /etc/default/locale\' >> /etc/apache2/envvars' : + path => ['/bin', '/usr/bin'], + unless => 'grep \'^. /etc/default/locale$\' /etc/apache2/envvars', + notify => Service['httpd'], + require => Package['httpd'], + } + # Bug Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=736849 + exec { 'echo \'umask 022\' >> /etc/apache2/envvars' : + path => ['/bin', '/usr/bin'], + unless => 'grep \'umask 022\' /etc/apache2/envvars', + notify => Service['httpd'], + require => Package['httpd'], + } + } + default: { + fail("Unsupported osfamily (${::osfamily})") + } +} + +class { 'cloud::install::puppetmaster' : + puppetdb_enable => false, + autosign_domains => ['*'], + agent_configuration => { + 'agent-ssl_client_header' => { + 'setting' => 'ssl_client_header', + 'value' => 'SSL_CLIENT_S_DN' + }, + 'agent-ssl_client_verify_header' => { + 'setting' => 'ssl_client_verify_header', + 'value' => 'SSL_CLIENT_VERIFY' + }, + 'agent-certname' => { + 'setting' => 'certname', + 'value' => $::fqdn + }, + 'agent-server' => { + 'setting' => 'server', + 'value' => $::fqdn + }, + }, + main_configuration => { + 'main-configtimeout' => { + 'setting' => 'configtimeout', + 'value' => '10m' + }, + }, + puppetmaster_vhost_configuration => { + 'puppetmasterd' => { + 'docroot' => '/usr/share/puppet/rack/puppetmasterd/public', + 'port' => 8140, + 'ssl' => true, + 'ssl_protocol' => 'ALL -SSLv2 -SSLv3', + 'ssl_cipher' => 'ALL:!aNULL:!eNULL:!DES:!3DES:!IDEA:!SEED:!DSS:!PSK:!RC4:!MD5:+HIGH:+MEDIUM:!LOW:!SSLv2:!EXP', + 'ssl_honorcipherorder' => 'On', + 'ssl_cert' => "/var/lib/puppet/ssl/certs/${::fqdn}.pem", + 'ssl_key' => "/var/lib/puppet/ssl/private_keys/${::fqdn}.pem", + 'ssl_chain' => '/var/lib/puppet/ssl/certs/ca.pem', + 'ssl_ca' => '/var/lib/puppet/ssl/certs/ca.pem', + 'ssl_verify_client' => 'optional', + 'ssl_verify_depth' => 1, + 'ssl_options' => ['+StdEnvVars', '+ExportCertData'], + 'request_headers' => ['unset X-Forwarded-For', 'set X-SSL-Subject %{SSL_CLIENT_S_DN}e', 'set X-Client-DN %{SSL_CLIENT_S_DN}e', 'set X-Client-Verify %{SSL_CLIENT_VERIFY}e'], + 'rack_base_uris' => '/', + 'add_default_charset' => 'UTF-8', + } + } +} diff --git a/scripts/bootstrap_post_puppetdb.pp b/scripts/bootstrap_post_puppetdb.pp new file mode 100644 index 00000000..141c11ed --- /dev/null +++ b/scripts/bootstrap_post_puppetdb.pp @@ -0,0 +1,48 @@ +class { 'cloud::install::puppetmaster' : + puppetdb_enable => true, + autosign_domains => ['*'], + agent_configuration => { + 'agent-ssl_client_header' => { + 'setting' => 'ssl_client_header', + 'value' => 'SSL_CLIENT_S_DN' + }, + 'agent-ssl_client_verify_header' => { + 'setting' => 'ssl_client_verify_header', + 'value' => 'SSL_CLIENT_VERIFY' + }, + 'agent-certname' => { + 'setting' => 'certname', + 'value' => $::fqdn + }, + 'agent-server' => { + 'setting' => 'server', + 'value' => $::fqdn + }, + }, + main_configuration => { + 'main-configtimeout' => { + 'setting' => 'configtimeout', + 'value' => '10m' + }, + }, + puppetmaster_vhost_configuration => { + 'puppetmasterd' => { + 'docroot' => '/usr/share/puppet/rack/puppetmasterd/public', + 'port' => 8140, + 'ssl' => true, + 'ssl_protocol' => 'ALL -SSLv2 -SSLv3', + 'ssl_cipher' => 'ALL:!aNULL:!eNULL:!DES:!3DES:!IDEA:!SEED:!DSS:!PSK:!RC4:!MD5:+HIGH:+MEDIUM:!LOW:!SSLv2:!EXP', + 'ssl_honorcipherorder' => 'On', + 'ssl_cert' => "/var/lib/puppet/ssl/certs/${::fqdn}.pem", + 'ssl_key' => "/var/lib/puppet/ssl/private_keys/${::fqdn}.pem", + 'ssl_chain' => '/var/lib/puppet/ssl/certs/ca.pem', + 'ssl_ca' => '/var/lib/puppet/ssl/certs/ca.pem', + 'ssl_verify_client' => 'optional', + 'ssl_verify_depth' => 1, + 'ssl_options' => ['+StdEnvVars', '+ExportCertData'], + 'request_headers' => ['unset X-Forwarded-For', 'set X-SSL-Subject %{SSL_CLIENT_S_DN}e', 'set X-Client-DN %{SSL_CLIENT_S_DN}e', 'set X-Client-Verify %{SSL_CLIENT_VERIFY}e'], + 'rack_base_uris' => '/', + 'add_default_charset' => 'UTF-8', + } + } +} diff --git a/spec/classes/cloud_install_puppetdb_server.rb b/spec/classes/cloud_install_puppetdb_server.rb new file mode 100644 index 00000000..a3cdd849 --- /dev/null +++ b/spec/classes/cloud_install_puppetdb_server.rb @@ -0,0 +1,28 @@ +require 'spec_helper' + +describe 'cloud::install::puppetdb_server' do + + shared_examples_for 'puppetdb' do + + it 'install puppetdb' do + is_exptected.to contain_class('puppetdb::server') + end + + end + + + context 'on Debian platforms' do + let :facts do + { :osfamily => 'Debian' } + end + + it_configures 'puppetdb' + end + + context 'on RedHat platforms' do + let :facts do + { :osfamily => 'RedHat' } + end + it_configures 'puppetdb' + end +end diff --git a/spec/classes/cloud_install_puppetmaster.rb b/spec/classes/cloud_install_puppetmaster.rb new file mode 100644 index 00000000..9ce612fd --- /dev/null +++ b/spec/classes/cloud_install_puppetmaster.rb @@ -0,0 +1,112 @@ +require 'spec_helper' + +describe 'cloud::install::puppetmaster' do + + shared_examples_for 'puppetmaster' do + + let :params do + { :puppetconf_path => '/etc/puppet/puppet.conf', + :main_configuration => {}, + :agent_configuration => { + 'certname' => { 'setting' => 'certname', 'value' => 'foo.bar' } + }, + :master_configuration => { + 'timeout' => { 'setting' => 'timeout', 'value' => '0' } + }} + end + + it 'install puppetmaster package' do + is_expected.to contain_package(platform_params[:puppetmaster_package_name]).with({ + :ensure => 'present', + }) + end + + it 'ensure puppetmaster is stopped' do + is_exptected.to contain_server(platform_params[:puppetmaster_service_name]).with({ + :ensure => 'stopped', + :hasstatus => true, + :hasrestart => true, + }) + end + + it 'generate certificate if necessary' do + is_expected.to contain_exec('puppet cert generate node.example.com') + end + + it 'install hiera' do + is_expected.to contain_class('hiera') + end + + it 'configure the puppetdb settings of puppetmaster' do + is_exptected.to contain_class('puppetdb::master::config') + end + + it 'configure the puppet master configuration file' do + is_expected.to contain_init_setting('certname').with( + :setting => 'certname', + :value => 'foo.bar', + :section => 'agent', + :path => '/etc/puppet/puppet.conf', + ) + is_expected.to contain_init_setting('timeout').with( + :setting => 'timeout', + :value => '0', + :section => 'master', + :path => '/etc/puppet/puppet.conf', + ) + end + + it 'configure the autosign.conf' do + is_expected.to contain_file('/etc/puppet/autosign/conf').with({ + :ensure => 'present', + :owner => 'puppet', + :group => 'puppet', + :conent => 'template(\'cloud/installserver/autosign.conf.erb\')', + }) + end + + end + + + context 'on Debian platforms' do + let :facts do + { :osfamily => 'Debian', + :fqdn => 'node.example.com' + } + end + + let :platform_params do + { :puppetmaster_package_name => 'puppet-server', + :puppetmaster_service_name => 'puppetmaster', + } + end + + it_configures 'puppetmaster' + end + + context 'on RedHat platforms' do + let :facts do + { :osfamily => 'RedHat', + :fqdn => 'node.example.com' + } + end + + let :platform_params do + { :puppetmaster_package_name => 'puppetmaster', + :puppetmaster_service_name => 'puppetmaster', + } + end + + it_configures 'puppetmaster' + + context 'on Maj Release 7' do + facts.merge!(:operatingsystemmajrelease => '7') + + it 'ensure package mod_passenger is not installed' do + is_expected.to contain_package('mod_passenger').with({ + :ensure => 'absent', + }) + end + end + end +end diff --git a/templates/installserver/autosign.conf.erb b/templates/installserver/autosign.conf.erb new file mode 100644 index 00000000..d7ae0e10 --- /dev/null +++ b/templates/installserver/autosign.conf.erb @@ -0,0 +1,5 @@ +<% if @autosign_domains -%> +<% @autosign_domains.each do | domain | -%> +<%= domain %> +<% end -%> +<% end -%>