Add ability to use option SSL chain certificate

Some organizations use an SSL certificate which requires an intermediate chain
cert. This provides support for that via a new attribute and is optional.

Change-Id: I1b31ca64378ff8c6f5367b75b4b7b210a650d676
This commit is contained in:
Lance Albertson 2016-07-19 15:37:40 -07:00
parent 3d1d8039cf
commit 648da86777
5 changed files with 79 additions and 3 deletions

View File

@ -58,6 +58,8 @@ default['openstack']['dashboard']['use_ssl'] = true
# they need to be manually set below, if not the conventional horizon.* names will be used.
default['openstack']['dashboard']['ssl']['cert'] = 'horizon.pem'
default['openstack']['dashboard']['ssl']['key'] = 'horizon.key'
# Optional Chain cert
default['openstack']['dashboard']['ssl']['chain'] = nil
# Which versions of the SSL/TLS protocol will be accepted in new connections.
default['openstack']['dashboard']['ssl']['protocol'] = 'All -SSLv2 -SSLv3'
# Which ciphers to use with the SSL/TLS protocol.

View File

@ -78,6 +78,12 @@ ssl_cert = secret('certs', node['openstack']['dashboard']['ssl']['cert'])
ssl_key = secret('certs', node['openstack']['dashboard']['ssl']['key'])
ssl_cert_file = File.join(node['openstack']['dashboard']['ssl']['cert_dir'], node['openstack']['dashboard']['ssl']['cert'])
ssl_key_file = File.join(node['openstack']['dashboard']['ssl']['key_dir'], node['openstack']['dashboard']['ssl']['key'])
if node['openstack']['dashboard']['ssl']['chain']
ssl_chain = secret('certs', node['openstack']['dashboard']['ssl']['chain'])
ssl_chain_file = File.join(node['openstack']['dashboard']['ssl']['cert_dir'], node['openstack']['dashboard']['ssl']['chain'])
else
ssl_chain_file = nil
end
if node['openstack']['dashboard']['use_ssl']
unless ssl_cert_file == ssl_key_file
@ -94,6 +100,20 @@ if node['openstack']['dashboard']['use_ssl']
end
end
if ssl_chain_file
cert_mode = 00644
cert_owner = 'root'
cert_group = 'root'
file ssl_chain_file do
content ssl_chain
mode cert_mode
owner cert_owner
group cert_group
notifies :run, 'execute[restore-selinux-context]', :immediately
end
end
key_mode = 00640
key_owner = 'root'
key_group = node['openstack']['dashboard']['key_group']
@ -138,6 +158,7 @@ template node['openstack']['dashboard']['apache']['sites-path'] do
variables(
ssl_cert_file: ssl_cert_file.to_s,
ssl_key_file: ssl_key_file.to_s,
ssl_chain_file: ssl_chain_file.to_s,
http_bind_address: http_bind_address,
http_bind_port: http_bind.port.to_i,
https_bind_address: https_bind_address,

View File

@ -99,7 +99,22 @@ describe 'openstack-dashboard::apache2-server' do
expect(key).to notify('execute[restore-selinux-context]').to(:run)
end
end
context 'set ssl chain' do
before do
node.set['openstack']['dashboard']['ssl']['chain'] = 'horizon-chain.pem'
end
let(:chain) { chef_run.file('/etc/ssl/certs/horizon-chain.pem') }
it 'create files and restarts apache' do
expect(chef_run).to create_file('/etc/ssl/certs/horizon-chain.pem').with(
content: 'horizon_chain_pem_value',
user: 'root',
group: 'root',
mode: 0644
)
expect(chain).to notify('execute[restore-selinux-context]').to(:run)
end
end
describe 'get secret with only one pem' do
let(:key) { chef_run.file('/etc/ssl/private/horizon.pem') }
@ -132,8 +147,10 @@ describe 'openstack-dashboard::apache2-server' do
it 'does not mess with certs if ssl not enabled' do
node.set['openstack']['dashboard']['use_ssl'] = false
node.set['openstack']['dashboard']['ssl']['chain'] = 'horizon-chain.pem'
expect(chef_run).not_to create_file('/etc/ssl/certs/horizon.pem')
expect(chef_run).not_to create_file('/etc/ssl/certs/horizon.key')
expect(chef_run).not_to create_file('/etc/ssl/certs/horizon-chain.pem')
end
end
@ -170,11 +187,29 @@ describe 'openstack-dashboard::apache2-server' do
expect(key).to notify('execute[restore-selinux-context]').to(:run)
expect(pem).to notify('execute[restore-selinux-context]').to(:run)
end
context 'set ssl chain' do
let(:chain) { chef_run.file('/etc/anypath/any-chain.pem') }
before do
node.set['openstack']['dashboard']['ssl']['chain'] = 'any-chain.pem'
allow_any_instance_of(Chef::Recipe).to receive(:secret)
.with('certs', 'any-chain.pem')
.and_return('any_chain_pem_value')
end
it 'create files and restarts apache' do
expect(chef_run).to create_file('/etc/anypath/any-chain.pem').with(
content: 'any_chain_pem_value',
user: 'root',
group: 'root',
mode: 0644
)
expect(chain).to notify('execute[restore-selinux-context]').to(:run)
end
end
it 'does not mess with certs if ssl not enabled' do
node.set['openstack']['dashboard']['use_ssl'] = false
expect(chef_run).not_to create_file('/etc/anypath/any.key')
expect(chef_run).not_to create_file('/etc/anypath/any.pem')
expect(chef_run).not_to create_file('/etc/anypath/any-chain.pem')
end
end
end
@ -262,8 +297,16 @@ describe 'openstack-dashboard::apache2-server' do
/^\s*SSLProtocol All -SSLv2 -SSLv3$/].each do |ssl_certificate_directive|
expect(chef_run).to render_file(file.name).with_content(ssl_certificate_directive)
end
expect(chef_run).to_not render_file(file.name)
.with_content(/SSLCertificateChainFile/)
end
context 'set ssl chain' do
it 'shows chain directive' do
node.set['openstack']['dashboard']['ssl']['chain'] = 'horizon-chain.pem'
expect(chef_run).to render_file(file.name)
.with_content(%r{^\s*SSLCertificateChainFile /etc/ssl/certs/horizon-chain.pem$})
end
end
it 'has no ssl ciphers configured by default' do
expect(chef_run).not_to render_file(file.name).with_content(/^\s*SSLCipherSuite.*$/)
end
@ -291,6 +334,8 @@ describe 'openstack-dashboard::apache2-server' do
/^\s*SSLCipherSuite ssl_ciphers_value$/].each do |ssl_directive|
expect(chef_run).to render_file(file.name).with_content(ssl_directive)
end
expect(chef_run).to_not render_file(file.name)
.with_content(/SSLCertificateChainFile/)
end
end
end
@ -315,6 +360,8 @@ describe 'openstack-dashboard::apache2-server' do
/^\s*SSLCertificateKeyFile/].each do |ssl_certificate_directive|
expect(chef_run).not_to render_file(file.name).with_content(ssl_certificate_directive)
end
expect(chef_run).to_not render_file(file.name)
.with_content(/SSLCertificateChainFile/)
end
end

View File

@ -32,6 +32,9 @@ shared_context 'dashboard_stubs' do
allow_any_instance_of(Chef::Recipe).to receive(:secret)
.with('certs', 'horizon.pem')
.and_return('horizon_pem_value')
allow_any_instance_of(Chef::Recipe).to receive(:secret)
.with('certs', 'horizon-chain.pem')
.and_return('horizon_chain_pem_value')
allow_any_instance_of(Chef::Recipe).to receive(:secret)
.with('certs', 'horizon.key')
.and_return('horizon_key_value')

View File

@ -67,6 +67,9 @@ NameVirtualHost <%= @https_bind_address %>:<%= @https_bind_port %>
SSLEngine on
SSLCertificateFile <%= @ssl_cert_file %>
SSLCertificateKeyFile <%= @ssl_key_file %>
<% if node['openstack']['dashboard']['ssl']['chain'] -%>
SSLCertificateChainFile <%= @ssl_chain_file %>
<% end -%>
SSLProtocol <%= node["openstack"]["dashboard"]["ssl"]["protocol"] %>
<% if node["openstack"]["dashboard"]["ssl"]["ciphers"] -%>
SSLCipherSuite <%= node["openstack"]["dashboard"]["ssl"]["ciphers"] %>
@ -93,4 +96,4 @@ NameVirtualHost <%= @https_bind_address %>:<%= @https_bind_port %>
<% unless node["openstack"]["dashboard"]["wsgi_socket_prefix"].nil? %>
WSGISocketPrefix <%= node["openstack"]["dashboard"]["wsgi_socket_prefix"] %>
<% end %>
<% end %>