diff options
Diffstat (limited to 'site')
12 files changed, 318 insertions, 78 deletions
diff --git a/site/no_fail_file/lib/puppet/parser/functions/no_fail_file.rb b/site/no_fail_file/lib/puppet/parser/functions/no_fail_file.rb new file mode 100644 index 0000000..3819ebf --- /dev/null +++ b/site/no_fail_file/lib/puppet/parser/functions/no_fail_file.rb @@ -0,0 +1,36 @@ +require 'puppet/file_system' + +Puppet::Parser::Functions::newfunction( + :no_fail_file, :arity => -2, :type => :rvalue, + :doc => "Loads a file from a module and returns its contents as a string. + + This is a replacement to the file function that returns nothing + if the file specified cannot be found instead of erroring out. + + The argument to this function should be a `<MODULE NAME>/<FILE>` + reference, which will load `<FILE>` from a module's `files` + directory. (For example, the reference `mysql/mysqltuner.pl` will load the + file `<MODULES DIRECTORY>/mysql/files/mysqltuner.pl`.) + + This function can also accept: + + * An absolute path, which can load a file from anywhere on disk. + * Multiple arguments, which will return the contents of the **first** file + found, skipping any files that don't exist. + " +) do |vals| + path = nil + vals.each do |file| + found = Puppet::Parser::Files.find_file(file, compiler.environment) + if found && Puppet::FileSystem.exist?(found) + path = found + break + end + end + + if path + Puppet::FileSystem.read_preserve_line_endings(path) + else + nil + end +end diff --git a/site/profile/manifests/git_webhook.pp b/site/profile/manifests/git_webhook.pp new file mode 100644 index 0000000..12ef786 --- /dev/null +++ b/site/profile/manifests/git_webhook.pp @@ -0,0 +1,12 @@ +class profile::git_webhook ( + $force_zack_r10k_webhook = false +) { + + if versioncmp( $::pe_server_version, '2015.2.99' ) <= 0 or $force_zack_r10k_webhook { + include profile::git_webhook::zack_r10k_webhook + } else { + include profile::git_webhook::code_manager + include profile::git_webhook::zack_r10k_webhook_disable + } + +} diff --git a/site/profile/manifests/git_webhook/code_manager.pp b/site/profile/manifests/git_webhook/code_manager.pp new file mode 100644 index 0000000..7470e1c --- /dev/null +++ b/site/profile/manifests/git_webhook/code_manager.pp @@ -0,0 +1,150 @@ +class profile::git_webhook::code_manager { + + $authenticate_webhook = hiera('puppet_enterprise::master::code_manager::authenticate_webhook', true) + + $code_manager_service_user = 'code_manager_service_user' + $code_manager_service_user_password = fqdn_rand_string(40, '', "${code_manager_service_user}_password") + + #puppet_master_classifier_settings is a custom function + $classifier_settings = puppet_master_classifer_settings() + $classifier_hostname = $classifier_settings['server'] + $classifier_port = $classifier_settings['port'] + + $token_directory = '/etc/puppetlabs/puppetserver/.puppetlabs' + $token_filename = "${token_directory}/${code_manager_service_user}_token" + + $gms_api_token = hiera('gms_api_token', undef) + $git_management_system = hiera('git_management_system', undef) + + $code_manager_ssh_key_file = '/etc/puppetlabs/puppetserver/code_manager.key' + exec { 'create code manager ssh key' : + command => "/usr/bin/ssh-keygen -t rsa -b 2048 -C 'code_manager' -f ${code_manager_ssh_key_file} -q -N ''", + creates => $code_manager_ssh_key_file, + } + + file { $code_manager_ssh_key_file : + ensure => file, + owner => 'pe-puppet', + group => 'pe-puppet', + require => Exec['create code manager ssh key'], + } + + #If files exist in the codedir code manager can't manage them unless pe-puppet can read them + exec { 'chown all environments to pe-puppet' : + command => "/bin/chown -R pe-puppet:pe-puppet ${::settings::codedir}", + unless => "/usr/bin/test \$(stat -c %U ${::settings::codedir}/environments/production) = 'pe-puppet'", + } + + $code_manager_role_name = 'Deploy Environments' + $create_role_creates_file = '/etc/puppetlabs/puppetserver/.puppetlabs/deploy_environments_created' + $create_role_curl = @(EOT) + /opt/puppetlabs/puppet/bin/curl -k -X POST -H 'Content-Type: application/json' \ + https://<%= $::trusted['certname'] %>:4433/rbac-api/v1/roles \ + -d '{"permissions": [{"object_type": "environment", "action": "deploy_code", "instance": "*"}, + {"object_type": "tokens", "action": "override_lifetime", "instance": "*"}],"user_ids": [], "group_ids": [], "display_name": "<%= $code_manager_role_name %>", "description": ""}' \ + --cert <%= $::settings::certdir %>/<%= $::trusted['certname'] %>.pem \ + --key <%= $::settings::privatekeydir %>/<%= $::trusted['certname'] %>.pem \ + --cacert <%= $::settings::certdir %>/ca.pem; + touch <%= $create_role_creates_file %> + | EOT + + exec { 'create deploy environments role' : + command => inline_epp( $create_role_curl ), + creates => $create_role_creates_file, + logoutput => true, + path => $::path, + require => File[$token_directory], + } + + rbac_user { $code_manager_service_user : + ensure => 'present', + name => $code_manager_service_user, + email => "${code_manager_service_user}@example.com", + display_name => 'Code Manager Service Account', + password => $code_manager_service_user_password, + roles => [ $code_manager_role_name ], + require => Exec['create deploy environments role'], + } + + file { $token_directory : + ensure => directory, + owner => 'pe-puppet', + group => 'pe-puppet', + } + + exec { "Generate Token for ${code_manager_service_user}" : + command => epp('profile/git_webhook/code_manager/create_rbac_token.epp', + { 'code_manager_service_user' => $code_manager_service_user, + 'code_manager_service_user_password' => $code_manager_service_user_password, + 'classifier_hostname' => $classifier_hostname, + 'classifier_port' => $classifier_port, + 'token_filename' => $token_filename + }), + creates => $token_filename, + require => [ Rbac_user[$code_manager_service_user], File[$token_directory] ], + } + + #this file cannont be read until the next run after the above exec + #because the file function runs on the master not on the agent + #so the file doesn't exist at the time the function is run + $rbac_token_file_contents = no_fail_file($token_filename) + + #Only mv code if this is at least the 2nd run of puppet + #Code manager needs to be enabled and puppet server restarted + #before this exec can complete. Gating on the token file + #ensures at least one run has completed + if $::code_manager_mv_old_code and !empty($rbac_token_file_contents) { + + $timestamp = chomp(generate('/bin/date', '+%Y%d%m_%H:%M:%S')) + + exec { 'mv files out of $environmentpath' : + command => "mkdir /etc/puppetlabs/env_back_${timestamp}; + mv ${::settings::codedir}/environments/* /etc/puppetlabs/env_back_${timestamp}/; + rm /opt/puppetlabs/facter/facts.d/code_manager_mv_old_code.txt; + TOKEN=`/opt/puppetlabs/puppet/bin/ruby -e \"require 'json'; puts JSON.parse(File.read('${token_filename}'))['token']\"`; + /opt/puppetlabs/puppet/bin/curl -k -X POST -H 'Content-Type: application/json' \"https://${::trusted['certname']}:8170/code-manager/v1/deploys?token=\$TOKEN\" -d '{\"environments\": [\"${::environment}\"], \"wait\": true}'; + /opt/puppetlabs/puppet/bin/curl -k -X POST -H 'Content-Type: application/json' \"https://${::trusted['certname']}:8170/code-manager/v1/deploys?token=\$TOKEN\" -d '{\"deploy-all\": true, \"wait\": true}'; + sleep 15", + path => $::path, + logoutput => true, + require => Exec["Generate Token for ${code_manager_service_user}"], + } + } + + if !empty($gms_api_token) { + if $authenticate_webhook and !empty($rbac_token_file_contents) { + + $rbac_token = parsejson($rbac_token_file_contents)['token'] + + $token_info = "&token=${rbac_token}" + } + else { + $token_info = '' + } + + $code_manager_webhook_type = $git_management_system ? { + 'gitlab' => 'github', + default => $git_management_system, + } + + git_deploy_key { "add_deploy_key_to_puppet_control-${::fqdn}": + ensure => present, + name => $::fqdn, + path => "${code_manager_ssh_key_file}.pub", + token => $gms_api_token, + project_name => 'puppet/control-repo', + server_url => hiera('gms_server_url'), + provider => $git_management_system, + } + + git_webhook { "code_manager_post_receive_webhook-${::fqdn}" : + ensure => present, + webhook_url => "https://${::fqdn}:8170/code-manager/v1/webhook?type=${code_manager_webhook_type}${token_info}", + token => $gms_api_token, + project_name => 'puppet/control-repo', + server_url => hiera('gms_server_url'), + provider => $git_management_system, + disable_ssl_verify => true, + } + } +} diff --git a/site/profile/manifests/git_webhook/zack_r10k_webhook.pp b/site/profile/manifests/git_webhook/zack_r10k_webhook.pp new file mode 100644 index 0000000..ed05282 --- /dev/null +++ b/site/profile/manifests/git_webhook/zack_r10k_webhook.pp @@ -0,0 +1,58 @@ +class profile::git_webhook::zack_r10k_webhook ( + $use_mcollective = false, +) { + + $username = hiera('webhook_username', fqdn_rand_string(10, '', 'username')) + $password = hiera('webhook_password', fqdn_rand_string(20, '', 'password')) + + $gms_api_token = hiera('gms_api_token', undef) + $git_management_system = hiera('git_management_system', undef) + + if $use_mcollective { + class { 'r10k::mcollective': + notify => Service['mcollective'], + } + } + + class {'r10k::webhook::config': + enable_ssl => true, + protected => true, + user => $username, + pass => $password, + use_mcollective => $use_mcollective, + } + + class {'r10k::webhook': + user => 'root', + group => '0', + require => Class['r10k::webhook::config'], + } + + $r10k_ssh_key_file = '/root/.ssh/r10k_rsa' + exec { 'create r10k ssh key' : + command => "/usr/bin/ssh-keygen -t rsa -b 2048 -C 'r10k' -f ${r10k_ssh_key_file} -q -N ''", + creates => $r10k_ssh_key_file, + } + + if !empty($gms_api_token) { + git_deploy_key { "add_deploy_key_to_puppet_control-${::fqdn}": + ensure => present, + name => $::fqdn, + path => "${r10k_ssh_key_file}.pub", + token => $gms_api_token, + project_name => 'puppet/control-repo', + server_url => hiera('gms_server_url'), + provider => $git_management_system, + } + + git_webhook { "web_post_receive_webhook-${::fqdn}" : + ensure => present, + webhook_url => "https://${username}:${password}@${::fqdn}:8088/payload", + token => $gms_api_token, + project_name => 'puppet/control-repo', + server_url => hiera('gms_server_url'), + provider => $git_management_system, + disable_ssl_verify => true, + } + } +} diff --git a/site/profile/manifests/git_webhook/zack_r10k_webhook_disable.pp b/site/profile/manifests/git_webhook/zack_r10k_webhook_disable.pp new file mode 100644 index 0000000..ec54fc6 --- /dev/null +++ b/site/profile/manifests/git_webhook/zack_r10k_webhook_disable.pp @@ -0,0 +1,14 @@ +class profile::git_webhook::zack_r10k_webhook_disable { + + file { '/etc/webhook.yaml' : + ensure => absent, + notify => Exec['stop and disable webhook service'], + } + + exec { 'stop and disable webhook service' : + command => '/opt/puppetlabs/puppet/bin/puppet resource service webhook ensure=stopped enable=false', + logoutput => true, + refreshonly => true, + } + +} diff --git a/site/profile/manifests/puppetmaster.pp b/site/profile/manifests/puppetmaster.pp index 0954807..d73236f 100644 --- a/site/profile/manifests/puppetmaster.pp +++ b/site/profile/manifests/puppetmaster.pp @@ -1,7 +1,6 @@ -class profile::puppetmaster ( - $webhook_username, - $webhook_password -) { +class profile::puppetmaster { + + $hiera_yaml = "${::settings::confdir}/hiera.yaml" class { 'hiera': hierarchy => [ @@ -9,48 +8,28 @@ class profile::puppetmaster ( 'nodes/%{::trusted.certname}', 'common', ], - hiera_yaml => '/etc/puppetlabs/code/hiera.yaml', + hiera_yaml => $hiera_yaml, datadir => '/etc/puppetlabs/code/environments/%{environment}/hieradata', owner => 'pe-puppet', group => 'pe-puppet', notify => Service['pe-puppetserver'], } - #BEGIN - Generate an SSH key for r10k to connect to git - $r10k_ssh_key_file = '/root/.ssh/r10k_rsa' - exec { 'create r10k ssh key' : - command => "/usr/bin/ssh-keygen -t rsa -b 2048 -C 'r10k' -f ${r10k_ssh_key_file} -q -N ''", - creates => $r10k_ssh_key_file, + ini_setting { 'puppet.conf hiera_config' : + ensure => present, + path => "${::settings::confdir}/puppet.conf", + section => 'master', + setting => 'hiera_config', + value => $hiera_yaml, + notify => Service['pe-puppetserver'], } - #END - Generate an SSH key for r10k to connect to git - - #BEGIN - Add deploy key and webook to git management system - $git_management_system = hiera('git_management_system', '') - - if $git_management_system in ['gitlab', 'github'] { - - git_deploy_key { "add_deploy_key_to_puppet_control-${::fqdn}": - ensure => present, - name => $::fqdn, - path => "${r10k_ssh_key_file}.pub", - token => hiera('gms_api_token'), - project_name => 'puppet/control-repo', - server_url => hiera('gms_server_url'), - provider => $git_management_system, - } - - git_webhook { "web_post_receive_webhook-${::fqdn}" : - ensure => present, - webhook_url => "https://${webhook_username}:${webhook_password}@${::fqdn}:8088/payload", - token => hiera('gms_api_token'), - project_name => 'puppet/control-repo', - server_url => hiera('gms_server_url'), - provider => $git_management_system, - disable_ssl_verify => true, - } + #remove the default hiera.yaml from the code-staging directory + #after the next code manager deployment it should be removed + #from the live codedir + file { '/etc/puppetlabs/code-staging/hiera.yaml' : + ensure => absent, } - #END - Add deploy key and webhook to git management system #Lay down update-classes.sh for use in r10k postrun_command #This is configured via the pe_r10k::postrun key in hiera diff --git a/site/profile/manifests/zack_r10k_webhook.pp b/site/profile/manifests/zack_r10k_webhook.pp deleted file mode 100644 index 7e0bd40..0000000 --- a/site/profile/manifests/zack_r10k_webhook.pp +++ /dev/null @@ -1,29 +0,0 @@ -class profile::zack_r10k_webhook ( - $username, - $password, - $use_mcollective = false, -) { - - if $use_mcollective { - - class { 'r10k::mcollective': - notify => Service['mcollective'], - } - - } - - class {'r10k::webhook::config': - enable_ssl => true, - protected => true, - user => $username, - pass => $password, - use_mcollective => $use_mcollective, - } - - class {'r10k::webhook': - user => 'root', - group => '0', - require => Class['r10k::webhook::config'], - } - -} diff --git a/site/profile/templates/git_webhook/code_manager/create_rbac_token.epp b/site/profile/templates/git_webhook/code_manager/create_rbac_token.epp new file mode 100644 index 0000000..31bf00f --- /dev/null +++ b/site/profile/templates/git_webhook/code_manager/create_rbac_token.epp @@ -0,0 +1,7 @@ +<%- | String $code_manager_service_user, + String $code_manager_service_user_password, + String $classifier_hostname, + Integer $classifier_port, + String $token_filename +| -%> +/opt/puppetlabs/puppet/bin/curl -k -X POST -H 'Content-Type: application/json' -d '{"login": "<%= $code_manager_service_user %>", "password": "<%= $code_manager_service_user_password %>", "lifetime": "0"}' https://<%= $classifier_hostname %>:<%= $classifier_port %>/rbac-api/v1/auth/token >> <%= $token_filename %> diff --git a/site/puppet_master_classifer_settings_function/lib/puppet/parser/functions/puppet_master_classifer_settings.rb b/site/puppet_master_classifer_settings_function/lib/puppet/parser/functions/puppet_master_classifer_settings.rb new file mode 100644 index 0000000..5559849 --- /dev/null +++ b/site/puppet_master_classifer_settings_function/lib/puppet/parser/functions/puppet_master_classifer_settings.rb @@ -0,0 +1,5 @@ +module Puppet::Parser::Functions + newfunction(:puppet_master_classifer_settings, :type => :rvalue) do |args| + function_parseyaml([function_file([File.join(lookupvar('settings::confdir').to_s, 'classifier.yaml')])]) + end +end diff --git a/site/puppetdb_hostname_function/lib/puppet/parser/functions/puppetdb_hostname.rb b/site/puppetdb_hostname_function/lib/puppet/parser/functions/puppetdb_hostname.rb new file mode 100644 index 0000000..b43365f --- /dev/null +++ b/site/puppetdb_hostname_function/lib/puppet/parser/functions/puppetdb_hostname.rb @@ -0,0 +1,12 @@ +require 'puppet/util/puppetdb' + +module Puppet::Parser::Functions + newfunction(:puppetdb_hostnames, :type => :rvalue) do |args| + output = [] + Puppet::Util::Puppetdb.config.server_urls.each do | server_url | + output << server_url.hostname + end + + output + end +end diff --git a/site/role/manifests/all_in_one_pe.pp b/site/role/manifests/all_in_one_pe.pp index 6bc2eb3..9e93155 100644 --- a/site/role/manifests/all_in_one_pe.pp +++ b/site/role/manifests/all_in_one_pe.pp @@ -1,16 +1,6 @@ class role::all_in_one_pe { - $webhook_username = hiera('webhook_username', fqdn_rand_string(10, '', 'username')) - $webhook_password = hiera('webhook_password', fqdn_rand_string(20, '', 'password')) - - class { 'profile::puppetmaster' : - webhook_username => $webhook_username, - webhook_password => $webhook_password, - } - - class { 'profile::zack_r10k_webhook' : - username => $webhook_username, - password => $webhook_password, - } + include profile::puppetmaster + include profile::git_webhook } diff --git a/site/role/manifests/all_in_one_pe_2015_2.pp b/site/role/manifests/all_in_one_pe_2015_2.pp new file mode 100644 index 0000000..01bf717 --- /dev/null +++ b/site/role/manifests/all_in_one_pe_2015_2.pp @@ -0,0 +1,6 @@ +class role::all_in_one_pe_2015_2 { + + include profile::puppetmaster + include profile::zack_r10k_webhook + +} |