Fix etcd's support for internal TLS

Fixes for etcd's certmonger cert and key generation:
- Do not chown the cert and key files generated on the host. In addition
  to the fact that "etcd" is not a valid user|grep name on the host, an
  ACL must be used to allow other services (such as cinder) to access
  the files. That ACL will be handled at the THT layer.
- New $dnsnames parameter supports adding a list of subject alternative
  name (SAN) to the cert.
- Remove obsolete default $postsave_cmd (see comment in the code), but
  make it a parameter so it can be overridden if necessary.

The cinder-volume service uses etcd when cinder is configured for
active/active mode. When internal TLS is enabled, the backend_url must
include references to etcd's cert and key files.

Partial-Bug: #1869955
Change-Id: Ifa7452ec15b81f48d7e5fb1252f20b5af1dff95c
(cherry picked from commit 63111546cd)
This commit is contained in:
Alan Bishop 2020-04-01 09:23:26 -07:00
parent 6006891aef
commit a1da18aed6
4 changed files with 68 additions and 24 deletions

View File

@ -31,6 +31,15 @@
# (Optional) The CA that certmonger will use to generate the certificates. # (Optional) The CA that certmonger will use to generate the certificates.
# Defaults to hiera('certmonger_ca', 'local'). # Defaults to hiera('certmonger_ca', 'local').
# #
# [*dnsnames*]
# (Optional) The DNS names that will be added for the SubjectAltNames entry
# in the certificate.
# Defaults to $hostname
#
# [*postsave_cmd*]
# (Optional) Specifies the command to execute after requesting a certificate.
# Defaults to undef
#
# [*principal*] # [*principal*]
# (Optional) The haproxy service principal that is set for etcd in kerberos. # (Optional) The haproxy service principal that is set for etcd in kerberos.
# Defaults to undef # Defaults to undef
@ -40,17 +49,21 @@ class tripleo::certmonger::etcd (
$service_certificate, $service_certificate,
$service_key, $service_key,
$certmonger_ca = hiera('certmonger_ca', 'local'), $certmonger_ca = hiera('certmonger_ca', 'local'),
$dnsnames = $hostname,
$postsave_cmd = undef,
$principal = undef, $principal = undef,
) { ) {
include ::certmonger include ::certmonger
$postsave_cmd = 'systemctl reload etcd' # Note: A $postsave_cmd should not be needed because etcd doesn't cache
# certificates. See https://github.com/etcd-io/etcd/pull/7784.
certmonger_certificate { 'etcd' : certmonger_certificate { 'etcd' :
ensure => 'present', ensure => 'present',
certfile => $service_certificate, certfile => $service_certificate,
keyfile => $service_key, keyfile => $service_key,
hostname => $hostname, hostname => $hostname,
dnsname => $hostname, dnsname => $dnsnames,
principal => $principal, principal => $principal,
postsave_cmd => $postsave_cmd, postsave_cmd => $postsave_cmd,
ca => $certmonger_ca, ca => $certmonger_ca,
@ -58,13 +71,9 @@ class tripleo::certmonger::etcd (
require => Class['::certmonger'], require => Class['::certmonger'],
} }
file { $service_certificate : file { $service_certificate :
owner => 'etcd',
group => 'etcd',
require => Certmonger_certificate['etcd'], require => Certmonger_certificate['etcd'],
} }
file { $service_key : file { $service_key :
owner => 'etcd',
group => 'etcd',
require => Certmonger_certificate['etcd'], require => Certmonger_certificate['etcd'],
} }

View File

@ -98,6 +98,10 @@
# (Optional) Whether TLS in the internal network is enabled or not # (Optional) Whether TLS in the internal network is enabled or not
# Defaults to hiera('enable_internal_tls', false) # Defaults to hiera('enable_internal_tls', false)
# #
# [*etcd_certificate_specs*]
# (optional) TLS certificate specs for the etcd service
# Defaults to hiera('tripleo::profile::base::etcd::certificate_specs', {})
#
# [*etcd_enabled*] # [*etcd_enabled*]
# (optional) Whether the etcd service is enabled or not # (optional) Whether the etcd service is enabled or not
# Defaults to hiera('etcd_enabled', false) # Defaults to hiera('etcd_enabled', false)
@ -136,6 +140,7 @@ class tripleo::profile::base::cinder::volume (
$cinder_rbd_client_name = hiera('tripleo::profile::base::cinder::volume::rbd::cinder_rbd_user_name','openstack'), $cinder_rbd_client_name = hiera('tripleo::profile::base::cinder::volume::rbd::cinder_rbd_user_name','openstack'),
$cinder_volume_cluster = hiera('tripleo::profile::base::cinder::volume::cinder_volume_cluster', ''), $cinder_volume_cluster = hiera('tripleo::profile::base::cinder::volume::cinder_volume_cluster', ''),
$enable_internal_tls = hiera('enable_internal_tls', false), $enable_internal_tls = hiera('enable_internal_tls', false),
$etcd_certificate_specs = hiera('tripleo::profile::base::etcd::certificate_specs', {}),
$etcd_enabled = hiera('etcd_enabled', false), $etcd_enabled = hiera('etcd_enabled', false),
$etcd_host = hiera('etcd_vip', undef), $etcd_host = hiera('etcd_vip', undef),
$etcd_port = hiera('tripleo::profile::base::etcd::client_port', '2379'), $etcd_port = hiera('tripleo::profile::base::etcd::client_port', '2379'),
@ -159,10 +164,14 @@ class tripleo::profile::base::cinder::volume (
} }
if $enable_internal_tls { if $enable_internal_tls {
$protocol = 'https' $protocol = 'https'
$tls_keyfile = $etcd_certificate_specs['service_key']
$tls_certfile = $etcd_certificate_specs['service_certificate']
$options = sprintf('?cert_key=%s&cert_cert=%s', $tls_keyfile, $tls_certfile)
} else { } else {
$protocol = 'http' $protocol = 'http'
$options = ''
} }
$backend_url = sprintf('etcd3+%s://%s:%s', $protocol, normalize_ip_for_uri($etcd_host), $etcd_port) $backend_url = sprintf('etcd3+%s://%s:%s%s', $protocol, normalize_ip_for_uri($etcd_host), $etcd_port, $options)
class { '::cinder::coordination' : class { '::cinder::coordination' :
backend_url => $backend_url, backend_url => $backend_url,
} }

View File

@ -29,6 +29,7 @@ describe 'tripleo::certmonger::etcd' do
} }
end end
context 'with defaults' do
it 'should include the base for using certmonger' do it 'should include the base for using certmonger' do
is_expected.to contain_class('certmonger') is_expected.to contain_class('certmonger')
end end
@ -40,6 +41,8 @@ describe 'tripleo::certmonger::etcd' do
:keyfile => '/etc/pki/key.pem', :keyfile => '/etc/pki/key.pem',
:hostname => 'localhost', :hostname => 'localhost',
:dnsname => 'localhost', :dnsname => 'localhost',
:principal => nil,
:postsave_cmd => nil,
:ca => 'local', :ca => 'local',
:wait => true, :wait => true,
) )
@ -47,6 +50,25 @@ describe 'tripleo::certmonger::etcd' do
is_expected.to contain_file('/etc/pki/key.pem') is_expected.to contain_file('/etc/pki/key.pem')
end end
end end
context 'with overrides' do
before :each do
params.merge!({
:certmonger_ca => 'IPA',
:dnsnames => 'host1,127.0.0.42',
:postsave_cmd => '/usr/bin/refresh_me.sh',
:principal => 'Principal_Lewis',
})
end
it 'should request a certificate with overrides' do
is_expected.to contain_certmonger_certificate('etcd').with(
:dnsname => 'host1,127.0.0.42',
:principal => 'Principal_Lewis',
:postsave_cmd => '/usr/bin/refresh_me.sh',
:ca => 'IPA',
)
end
end
end
on_supported_os.each do |os, facts| on_supported_os.each do |os, facts|
context "on #{os}" do context "on #{os}" do

View File

@ -327,11 +327,15 @@ describe 'tripleo::profile::base::cinder::volume' do
before :each do before :each do
params.merge!({ params.merge!({
:enable_internal_tls => true, :enable_internal_tls => true,
:etcd_certificate_specs => {
'service_certificate' => '/path/to/etcd.cert',
'service_key' => '/path/to/etcd.key',
},
}) })
end end
it 'should configure coordination backend_url with https' do it 'should configure coordination backend_url with https' do
is_expected.to contain_class('cinder::coordination').with( is_expected.to contain_class('cinder::coordination').with(
:backend_url => 'etcd3+https://127.0.0.1:2379', :backend_url => 'etcd3+https://127.0.0.1:2379?cert_key=/path/to/etcd.key&cert_cert=/path/to/etcd.cert',
) )
end end
end end