From 2b83ae20f2c18e8ce2eebfa4cdfe301625ec4ff4 Mon Sep 17 00:00:00 2001 From: Tobias Urdin Date: Fri, 31 Aug 2018 17:51:41 +0200 Subject: [PATCH] Add octavia::certificates::client_ca and data This patch adds two new parameters client_ca and client_ca_data. When setting up a development or testing Octavia setup there is no real issue to using the same CA for both the client and server part (client_ca and ca_certificate, server_ca). However when you have a production environment you want to separate the client_ca and ca_certificate/server_ca into to separate CAs. This is because otherwise if one amphora is compromised it could use its certificate to access all other amphoras. This change is backward compatible since by setting the default value for client_ca to undef the pick() function will select the ca_certificate value by default. Change-Id: I41de310daab5bf1bc623819df40dea61b852ffc9 --- manifests/certificates.pp | 34 ++++++++++- .../notes/client-ca-b05d5a5e4a93bfe3.yaml | 6 ++ spec/classes/octavia_certificates_spec.rb | 57 +++++++++++++++++++ 3 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 releasenotes/notes/client-ca-b05d5a5e4a93bfe3.yaml diff --git a/manifests/certificates.pp b/manifests/certificates.pp index df84eb1d..cf42be85 100644 --- a/manifests/certificates.pp +++ b/manifests/certificates.pp @@ -32,6 +32,12 @@ # (Optional) CA password used to sign certificates # Defaults to $::os_service_default # +# [*client_ca*] +# (Optional) Path to the client CA certificate. +# This option is not needed unless you want to separate the +# ca_certificate/server_ca and the client_ca. +# Defaults to undef +# # [*client_cert*] # (Optional) Path for client certificate used to connect to amphorae. # Defaults to $::os_service_default @@ -44,6 +50,12 @@ # (Optional) CA private key for signing certificates # Defaults to undef # +# [*client_ca_data*] +# (Optional) Client CA certificate. +# You must specify the client_ca parameter where to place this CA +# if you give the data here. +# Defaults to undef +# # [*client_cert_data*] # (Optional) Client certificate used for connecting to amphorae # Defaults to undef @@ -64,9 +76,11 @@ class octavia::certificates ( $ca_certificate = $::os_service_default, $ca_private_key = $::os_service_default, $ca_private_key_passphrase = $::os_service_default, + $client_ca = undef, $client_cert = $::os_service_default, $ca_certificate_data = undef, $ca_private_key_data = undef, + $client_ca_data = undef, $client_cert_data = undef, $file_permission_owner = 'octavia', $file_permission_group = 'octavia' @@ -74,6 +88,8 @@ class octavia::certificates ( include ::octavia::deps + $client_ca_real = pick($client_ca, $ca_certificate) + octavia_config { 'certificates/cert_generator' : value => $cert_generator; 'certificates/cert_manager' : value => $cert_manager; @@ -82,7 +98,7 @@ class octavia::certificates ( 'certificates/ca_certificate' : value => $ca_certificate; 'certificates/ca_private_key' : value => $ca_private_key; 'certificates/ca_private_key_passphrase' : value => $ca_private_key_passphrase; - 'controller_worker/client_ca' : value => $ca_certificate; + 'controller_worker/client_ca' : value => $client_ca_real; 'haproxy_amphora/client_cert' : value => $client_cert; 'haproxy_amphora/server_ca' : value => $ca_certificate; } @@ -127,6 +143,22 @@ class octavia::certificates ( replace => true } } + if $client_ca and $client_ca_data { + ensure_resource('file', dirname($client_ca), { + ensure => directory, + owner => $file_permission_owner, + group => $file_permission_group, + mode => '0755' + }) + file { $client_ca: + ensure => file, + content => $client_ca_data, + group => $file_permission_owner, + owner => $file_permission_group, + mode => '0755', + replace => true + } + } if $client_cert_data { if is_service_default($client_cert) { fail('You must provide a path for storing the client certificate') diff --git a/releasenotes/notes/client-ca-b05d5a5e4a93bfe3.yaml b/releasenotes/notes/client-ca-b05d5a5e4a93bfe3.yaml new file mode 100644 index 00000000..e42029ba --- /dev/null +++ b/releasenotes/notes/client-ca-b05d5a5e4a93bfe3.yaml @@ -0,0 +1,6 @@ +features: + - | + Added new parameter client_ca and client_data_data to octavia::certificates. + These can be used to separate the ca_certificate/server_ca and client_ca used + which is something you want to do in production environment to avoid a compromised + Amphora being able to connect to the other running amphoras. diff --git a/spec/classes/octavia_certificates_spec.rb b/spec/classes/octavia_certificates_spec.rb index 66cc356b..8a2c63b2 100644 --- a/spec/classes/octavia_certificates_spec.rb +++ b/spec/classes/octavia_certificates_spec.rb @@ -206,6 +206,63 @@ describe 'octavia::certificates' do end end + context 'with ca_certificate and client_ca being different' do + let :params do + { + :ca_certificate => '/etc/octavia/ca.pem', + :client_ca => '/etc/octavia/client_ca.pem' + } + end + + it 'should configure certificates' do + is_expected.to contain_octavia_config('certificates/ca_certificate').with_value('/etc/octavia/ca.pem') + is_expected.to contain_octavia_config('controller_worker/client_ca').with_value('/etc/octavia/client_ca.pem') + end + + it 'should not populate certificate file' do + is_expected.not_to contain_file('/etc/octavia/client_ca.pem') + is_expected.not_to contain_file('/etc/octavia') + end + end + + context 'with ca_certificate and client_ca being different and populate files' do + let :params do + { + :ca_certificate => '/etc/octavia/ca.pem', + :client_ca => '/etc/octavia/client_ca.pem', + :ca_certificate_data => 'my_ca_certificate', + :client_ca_data => 'my_client_ca' + } + end + + it 'should configure certificates' do + is_expected.to contain_octavia_config('certificates/ca_certificate').with_value('/etc/octavia/ca.pem') + is_expected.to contain_octavia_config('controller_worker/client_ca').with_value('/etc/octavia/client_ca.pem') + end + + it 'populates certificate files' do + is_expected.to contain_file('/etc/octavia/ca.pem').with({ + 'ensure' => 'file', + 'owner' => 'octavia', + 'group' => 'octavia', + 'mode' => '0755', + }) + is_expected.to contain_file('/etc/octavia/ca.pem').with_content('my_ca_certificate') + is_expected.to contain_file('/etc/octavia/client_ca.pem').with({ + 'ensure' => 'file', + 'owner' => 'octavia', + 'group' => 'octavia', + 'mode' => '0755', + }) + is_expected.to contain_file('/etc/octavia/client_ca.pem').with_content('my_client_ca') + is_expected.to contain_file('/etc/octavia').with({ + 'ensure' => 'directory', + 'owner' => 'octavia', + 'group' => 'octavia', + 'mode' => '0755', + }) + end + end end on_supported_os({