From fe922d6990c4e935f17312a6fbab6724cfa08fbb Mon Sep 17 00:00:00 2001 From: Paul Donohue Date: Thu, 21 Dec 2017 16:40:45 -0500 Subject: [PATCH] Add support for generating and configuring repo metadata gpg keys --- README.md | 6 ++- manifests/init.pp | 42 +++++++++++++++-- manifests/katello.pp | 6 ++- manifests/params.pp | 11 +++++ manifests/repomd_gpg.pp | 64 ++++++++++++++++++++++++++ manifests/rhsm_reconfigure_script.pp | 34 +++++++++++++- spec/classes/certs_repomd_gpg_spec.rb | 11 +++++ templates/rhsm-katello-reconfigure.erb | 20 +++++++- 8 files changed, 184 insertions(+), 10 deletions(-) create mode 100644 manifests/repomd_gpg.pp create mode 100644 spec/classes/certs_repomd_gpg_spec.rb diff --git a/README.md b/README.md index 6356d237..cef53ef0 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,10 @@ This module is responsible for generating a CA and certificate used for communication between services inside the Katello deployment. +It is also responsible for generating a GPG key used by Pulp for +repository metadata signing and used by Yum for metadata signature +verification. + ### What certs affects * Installs and deploys a CA @@ -78,7 +82,7 @@ cert-specific resources: For now, the only implemented provider of the type is `katello_ssl_tool`. It works as follow: -1. **generation** - the artefact of this phase is an RPM with the keys +1. **generation** - the artifact of this phase is an RPM with the keys for the certificate; the RPMs, as well as other files generated in the process, are located in `/root/ssl-build` directory diff --git a/manifests/init.pp b/manifests/init.pp index ad422b29..8d4b6c0b 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -1,7 +1,7 @@ # == Class: certs # # Base for installing and configuring certs. It holds the basic configuration -# aournd certificates generation and deployment. The per-subsystem configuratoin +# around certificates generation and deployment. The per-subsystem configuration # of certificates should go into `subsystem_module/manifests/certs.pp`. # # === Parameters: @@ -24,6 +24,15 @@ # $server_cert_req:: Path to the ssl certificate request for https # if not specified, the default CA will generate one # +# $enable_repomd_gpg:: Should a GPG key for repository metadata signing be +# generated/used +# +# $repomd_gpg_name:: Name attribute for generated GPG key +# +# $repomd_gpg_comment:: Comment attribute for generated GPG key +# +# $repomd_gpg_email:: Email attribute for generated GPG key +# # === Advanced parameters: # # $log_dir:: Where the log files should go @@ -37,7 +46,7 @@ # $regenerate_ca:: Force regeneration of the ca certificate # # $deploy:: Deploy the certs on the configured system. False means -# we want apply it on a different system +# we want to apply it on a different system # # $ca_common_name:: Common name for the generated CA certificate # @@ -67,6 +76,21 @@ # # $server_ca_name:: The name of the server CA (used for https) # +# $regenerate_repomd_gpg:: Force regeneration of the GPG key for repository +# metadata signing +# +# $repomd_gpg_dir:: The directory where the GPG key for repository metadata +# signing will be generated +# +# $repomd_gpg_user:: The user who should own the GPG key for repository +# metadata signing +# +# $repomd_gpg_group:: The group who should own the GPG key for repository +# metadata signing +# +# $repomd_gpg_prefix:: Filename prefix for the public GPG key used to sign +# repository metadata +# class certs ( Stdlib::Absolutepath $log_dir = $::certs::params::log_dir, String $node_fqdn = $::certs::params::node_fqdn, @@ -93,6 +117,15 @@ String $group = $::certs::params::group, String $default_ca_name = $::certs::params::default_ca_name, String $server_ca_name = $::certs::params::server_ca_name, + Boolean $enable_repomd_gpg = $::certs::params::enable_repomd_gpg, + Boolean $regenerate_repomd_gpg = $::certs::params::regenerate_repomd_gpg, + Stdlib::Absolutepath $repomd_gpg_dir = $::certs::params::repomd_gpg_dir, + String $repomd_gpg_user = $::certs::params::repomd_gpg_user, + String $repomd_gpg_group = $::certs::params::repomd_gpg_group, + Optional[String] $repomd_gpg_name = $::certs::params::repomd_gpg_name, + Optional[String] $repomd_gpg_comment = $::certs::params::repomd_gpg_comment, + Optional[String] $repomd_gpg_email = $::certs::params::repomd_gpg_email, + String $repomd_gpg_prefix = $::certs::params::repomd_gpg_prefix, ) inherits certs::params { if $server_cert { @@ -113,11 +146,14 @@ contain ::certs::install contain ::certs::config contain ::certs::ca + contain ::certs::repomd_gpg Class['::certs::install'] -> Class['::certs::config'] -> - Class['::certs::ca'] + Class['::certs::ca'] -> + Class['::certs::repomd_gpg'] $default_ca = $::certs::ca::default_ca $server_ca = $::certs::ca::server_ca + $repomd_gpg_file = $::certs::repomd_gpg::pub_file } diff --git a/manifests/katello.pp b/manifests/katello.pp index 12732ad2..0f26c82e 100644 --- a/manifests/katello.pp +++ b/manifests/katello.pp @@ -14,6 +14,7 @@ $server_ca_name = $::certs::server_ca_name, $ca_cert = $::certs::ca_cert, $server_ca = $::certs::server_ca, + $repomd_gpg_file = $::certs::repomd_gpg_file, ) inherits certs { $katello_rhsm_setup_script = 'katello-rhsm-consumer' $katello_rhsm_setup_script_location = "/usr/bin/${katello_rhsm_setup_script}" @@ -44,8 +45,9 @@ require => File[$katello_server_ca_cert], } ~> certs::rhsm_reconfigure_script { "${katello_www_pub_dir}/${katello_rhsm_setup_script}": - ca_cert => $ca_cert, - server_ca_cert => $katello_server_ca_cert, + ca_cert => $ca_cert, + server_ca_cert => $katello_server_ca_cert, + repomd_gpg_file => $repomd_gpg_file, } ~> certs_bootstrap_rpm { $candlepin_consumer_name: dir => $katello_www_pub_dir, diff --git a/manifests/params.pp b/manifests/params.pp index 3c182ce3..cd0e9c56 100644 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -38,6 +38,17 @@ $server_cert_req = undef $server_ca_cert = undef + $enable_repomd_gpg = false + $regenerate_repomd_gpg = false + $repomd_gpg_dir = '/usr/share/httpd/.gnupg' + $repomd_gpg_user = 'apache' + $repomd_gpg_group = 'apache' + $repomd_gpg_name = 'Repository Metadata Signing Key' + $repomd_gpg_comment = undef + $repomd_gpg_email = undef + + $repomd_gpg_prefix = 'repomd' + $foreman_client_cert = '/etc/foreman/client_cert.pem' $foreman_client_key = '/etc/foreman/client_key.pem' # for verifying the foreman proxy https diff --git a/manifests/repomd_gpg.pp b/manifests/repomd_gpg.pp new file mode 100644 index 00000000..afdad9e8 --- /dev/null +++ b/manifests/repomd_gpg.pp @@ -0,0 +1,64 @@ +# == Class: certs +# Sets up the GPG key for Pulp repository metadata signing +class certs::repomd_gpg ( + $enable = $::certs::enable_repomd_gpg, + $regenerate = $::certs::regenerate_repomd_gpg, + $dir = $::certs::repomd_gpg_dir, + $user = $::certs::repomd_gpg_user, + $group = $::certs::repomd_gpg_group, + $gpg_name = $::certs::repomd_gpg_name, + $comment = $::certs::repomd_gpg_comment, + $email = $::certs::repomd_gpg_email, +) { + if $enable { + + $gpg_key_params = "Key-Type: RSA\nKey-Length:4096\nExpire-Date: 0\n" + $gpg_name_param = $gpg_name ? { undef => '', default => "Name-Real: ${gpg_name}\n", } + $gpg_comment_param = $comment ? { undef => '', default => "Name-Comment: ${comment}\n", } + $gpg_email_param = $email ? { undef => '', default => "Name-Email: ${email}\n", } + $gpg_name_params = "${gpg_name_param}${gpg_comment_param}${gpg_email_param}" + $gpg_params = "${gpg_key_params}${gpg_name_params}%no-protection\n%commit\n" + if $regenerate { + file { $dir: + ensure => absent, + force => true, + } + } + file { $dir: + ensure => directory, + owner => $user, + group => $group, + mode => '0700', + } -> + exec { 'generate repomd gpg': + unless => "/usr/bin/test -e '${dir}/secring.gpg' -o -e '${dir}/private-keys-v1.d'", + user => $user, + group => $group, + provider => shell, + command => "echo '${gpg_params}' | /usr/bin/gpg --homedir '${dir}' --gen-key --batch", + } + + $pub_file = "${dir}/pub.gpg" + $fp_cmd_print = "/usr/bin/gpg --homedir '${dir}' --list-secret-keys --with-colons" + $fp_cmd_parse = "/usr/bin/awk -F: '\$1 == \"fpr\" {print \$10; exit;}'" + $fp_cmd = "`${fp_cmd_print} | ${fp_cmd_parse}`" + exec { 'extract public repomd gpg key': + onlyif => "/usr/bin/test -e '${dir}'", + unless => "/usr/bin/test -e '${pub_file}'", + user => $user, + group => $group, + command => "/usr/bin/gpg --homedir '${dir}' --armor --export ${fp_cmd} --output '${pub_file}'", + } + + file { '/etc/pulp/server/plugins.conf.d/yum_distributor.json': + replace => false, + owner => 'root', + group => 'root', + mode => '0644', + content => "{ \"gpg_sign_metadata\": true}\n", + } + + } else { + $pub_file = undef + } +} diff --git a/manifests/rhsm_reconfigure_script.pp b/manifests/rhsm_reconfigure_script.pp index 4e564cb5..d0779794 100644 --- a/manifests/rhsm_reconfigure_script.pp +++ b/manifests/rhsm_reconfigure_script.pp @@ -1,4 +1,4 @@ -define certs::rhsm_reconfigure_script($ca_cert, $server_ca_cert) { +define certs::rhsm_reconfigure_script($ca_cert, $server_ca_cert, $repomd_gpg_file) { concat { $title: owner => 'root', @@ -48,10 +48,40 @@ order => '07', } + if $repomd_gpg_file { + + concat::fragment { "${title}+repomd_gpg_data": + target => $title, + content => "read -r -d '' REPOMD_GPG_DATA << EOM\n", + order => '08', + } + + concat::fragment { "${title}+repomd_gpg": + target => $title, + source => $repomd_gpg_file, + order => '09', + } + + concat::fragment { "${title}+end_repomd_gpg": + target => $title, + content => "EOM\n\n", + order => '10', + } + + } else { + + concat::fragment { "${title}+repomd_gpg": + target => $title, + content => "REPOMD_GPG_DATA=\n\n", + order => '08', + } + + } + concat::fragment { "${title}+reconfigure": target => $title, content => template('certs/rhsm-katello-reconfigure.erb'), - order => '10', + order => '50', } } diff --git a/spec/classes/certs_repomd_gpg_spec.rb b/spec/classes/certs_repomd_gpg_spec.rb new file mode 100644 index 00000000..32093c55 --- /dev/null +++ b/spec/classes/certs_repomd_gpg_spec.rb @@ -0,0 +1,11 @@ +require 'spec_helper' + +describe 'certs::repomd_gpg' do + let :facts do + on_supported_os['redhat-7-x86_64'] + end + + describe 'with default parameters' do + it { should compile.with_all_deps } + end +end diff --git a/templates/rhsm-katello-reconfigure.erb b/templates/rhsm-katello-reconfigure.erb index b1dbaac0..0382dafc 100755 --- a/templates/rhsm-katello-reconfigure.erb +++ b/templates/rhsm-katello-reconfigure.erb @@ -3,6 +3,7 @@ KATELLO_SERVER_CA_CERT=<%= scope['certs::server_ca_name'] %>.pem KATELLO_DEFAULT_CA_CERT=<%= scope['certs::default_ca_name'] %>.pem KATELLO_CERT_DIR=<%= scope['certs::katello::rhsm_ca_dir'] %> PORT=<%= scope['certs::katello::rhsm_port'] %> +REPOMD_GPG_FILE=<%= scope['certs::repomd_gpg_prefix'] %>.gpg PREFIX=<%= scope['certs::katello::deployment_url'] %> CFG=/etc/rhsm/rhsm.conf @@ -23,6 +24,19 @@ chmod 644 $KATELLO_CERT_DIR/$KATELLO_SERVER_CA_CERT echo "$KATELLO_DEFAULT_CA_DATA" > $KATELLO_CERT_DIR/$KATELLO_DEFAULT_CA_CERT chmod 644 $KATELLO_CERT_DIR/$KATELLO_DEFAULT_CA_CERT +REPOMD_GPG_PARAM= +if [ -n "$REPOMD_GPG_DATA" ] +then + echo "$REPOMD_GPG_DATA" > "$KATELLO_CERT_DIR/$REPOMD_GPG_FILE" + chmod 644 "$KATELLO_CERT_DIR/$REPOMD_GPG_FILE" + # the repomd_gpg_url parameter was introduced in rhsm 1.20.9 + # skip setting this parameter in older versions + if subscription-manager config --remove=rhsm.repomd_gpg_url >/dev/null 2>&1 + then + REPOMD_GPG_PARAM="--rhsm.repomd_gpg_url='file://%{ca_cert_dir}s$REPOMD_GPG_FILE'" + fi +fi + # if atomic machine handle it the atomic way, else handle the regular rhel way if [ -n "${IS_ATOMIC+1}" ] || [ -e "/run/ostree-booted" ] then @@ -36,7 +50,8 @@ then --server.prefix="$PREFIX" \ --server.port="$PORT" \ --rhsm.repo_ca_cert="%(ca_cert_dir)s$KATELLO_SERVER_CA_CERT" \ - --rhsm.baseurl="$BASEURL" + --rhsm.baseurl="$BASEURL" \ + $REPOMD_GPG_PARAM else # rhel setup BASEURL=https://$KATELLO_SERVER/pulp/repos @@ -57,7 +72,8 @@ else --server.prefix="$PREFIX" \ --server.port="$PORT" \ --rhsm.repo_ca_cert="%(ca_cert_dir)s$KATELLO_SERVER_CA_CERT" \ - --rhsm.baseurl="$BASEURL" + --rhsm.baseurl="$BASEURL" \ + $REPOMD_GPG_PARAM else sed -i "s/^hostname\s*=.*/hostname = $KATELLO_SERVER/g" $CFG sed -i "s/^port\s*=.*/port = $PORT/g" $CFG