Refactored get SSL Certificate method

* removed old remote_file and file method to get certs
  now uses the "secret" method from common to use data_bags
* removed now unused / obsolete attributes
* now uses new bind_address method from common
* edited specs to work with the new method

Change-Id: I296ae2241f38da51a07e52b913b86932153120e6
Depends-On: I7a4279aa6b3cbcc60a334900cd8442fd76792896
This commit is contained in:
Christoph Albers 2016-03-01 14:48:32 +01:00
parent 14ce391e1b
commit f794a7ef0c
5 changed files with 147 additions and 157 deletions

View File

@ -52,8 +52,6 @@ default['openstack']['dashboard']['keystone_service_chef_role'] = 'keystone'
default['openstack']['dashboard']['server_hostname'] = nil
default['openstack']['dashboard']['use_ssl'] = true
default['openstack']['dashboard']['ssl']['cert_url'] = nil
default['openstack']['dashboard']['ssl']['key_url'] = nil
# When using a remote certificate and key, the names of the actual installed certificate
# and key in the file system are determined by the following two attributes.
# If you want the name of the installed files to match the name of the files from the URL,
@ -107,10 +105,12 @@ default['openstack']['dashboard']['hash_algorithm'] = 'md5'
case node['platform_family']
when 'rhel'
default['openstack']['dashboard']['key_group'] = 'root'
default['openstack']['dashboard']['horizon_user'] = 'apache'
default['openstack']['dashboard']['horizon_group'] = 'apache'
default['openstack']['dashboard']['secret_key_path'] = '/usr/share/openstack-dashboard/openstack_dashboard/local/.secret_key_store'
default['openstack']['dashboard']['ssl']['dir'] = '/etc/pki/tls'
default['openstack']['dashboard']['ssl']['cert_dir'] = '/etc/pki/tls/certs/'
default['openstack']['dashboard']['ssl']['key_dir'] = '/etc/pki/tls/private/'
default['openstack']['dashboard']['local_settings_path'] = '/etc/openstack-dashboard/local_settings'
default['openstack']['dashboard']['django_path'] = '/usr/share/openstack-dashboard'
default['openstack']['dashboard']['login_url'] = "#{node['openstack']['dashboard']['webroot']}auth/login/"
@ -122,27 +122,13 @@ when 'rhel'
'package_overrides' => ''
}
default['openstack']['dashboard']['apache']['sites-path'] = "#{node['apache']['dir']}/sites-available/openstack-dashboard.conf"
when 'suse'
default['openstack']['dashboard']['horizon_user'] = 'wwwrun'
default['openstack']['dashboard']['horizon_group'] = 'www'
default['openstack']['dashboard']['secret_key_path'] = '/srv/www/openstack-dashboard/openstack_dashboard/local/.secret_key_store'
default['openstack']['dashboard']['ssl']['dir'] = '/etc/ssl'
default['openstack']['dashboard']['local_settings_path'] = '/srv/www/openstack-dashboard/openstack_dashboard/local/local_settings.py'
default['openstack']['dashboard']['django_path'] = '/srv/www/openstack-dashboard'
default['openstack']['dashboard']['login_url'] = nil
default['openstack']['dashboard']['logout_url'] = nil
default['openstack']['dashboard']['login_redirect_url'] = nil
default['openstack']['dashboard']['platform'] = {
'horizon_packages' => ['openstack-dashboard'],
'memcache_python_packages' => ['python-python-memcached'],
'package_overrides' => ''
}
default['openstack']['dashboard']['apache']['sites-path'] = "#{node['apache']['dir']}/conf.d/openstack-dashboard.conf"
when 'debian'
default['openstack']['dashboard']['key_group'] = 'ssl-cert'
default['openstack']['dashboard']['horizon_user'] = 'horizon'
default['openstack']['dashboard']['horizon_group'] = 'horizon'
default['openstack']['dashboard']['secret_key_path'] = '/var/lib/openstack-dashboard/secret_key'
default['openstack']['dashboard']['ssl']['dir'] = '/etc/ssl'
default['openstack']['dashboard']['ssl']['cert_dir'] = '/etc/ssl/certs/'
default['openstack']['dashboard']['ssl']['key_dir'] = '/etc/ssl/private/'
default['openstack']['dashboard']['local_settings_path'] = '/etc/openstack-dashboard/local_settings.py'
default['openstack']['dashboard']['django_path'] = '/usr/share/openstack-dashboard'
default['openstack']['dashboard']['login_url'] = nil
@ -154,6 +140,8 @@ when 'debian'
}
default['openstack']['dashboard']['platform']['horizon_packages'] = ['node-less', 'openstack-dashboard']
default['openstack']['dashboard']['apache']['sites-path'] = "#{node['apache']['dir']}/sites-available/openstack-dashboard.conf"
else
default['openstack']['dashboard']['key_group'] = 'root'
end
default['openstack']['dashboard']['dash_path'] = "#{node['openstack']['dashboard']['django_path']}/openstack_dashboard"

View File

@ -42,7 +42,10 @@ execute 'set-selinux-permissive' do
end
http_bind = node['openstack']['bind_service']['dashboard_http']
http_bind_address = bind_address http_bind
https_bind = node['openstack']['bind_service']['dashboard_https']
https_bind_address = bind_address https_bind
# This allows the apache2/templates/default/ports.conf.erb to setup the correct listeners.
# Need to convert from Chef::Node::ImmutableArray in order to be able to modify
apache2_listen = Array(node['apache']['listen'])
@ -80,64 +83,37 @@ file "#{node['apache']['dir']}/conf.d/openstack-dashboard.conf" do
only_if { platform_family?('rhel') } # :pragma-foodcritic: ~FC024 - won't fix this
end
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']['use_ssl']
cert_file = "#{node['openstack']['dashboard']['ssl']['dir']}/certs/#{node['openstack']['dashboard']['ssl']['cert']}"
cert_mode = 00644
cert_owner = 'root'
cert_group = 'root'
if node['openstack']['dashboard']['ssl']['cert_url']
remote_file cert_file do
sensitive true
source node['openstack']['dashboard']['ssl']['cert_url']
mode cert_mode
owner cert_owner
group cert_group
file ssl_cert_file.to_s do
content ssl_cert
notifies :run, 'execute[restore-selinux-context]', :immediately
end
else
cookbook_file cert_file do
sensitive true
source 'horizon.pem'
mode cert_mode
owner cert_owner
group cert_group
mode cert_mode
owner cert_owner
group cert_group
notifies :run, 'execute[restore-selinux-context]', :immediately
end
notifies :run, 'execute[restore-selinux-context]', :immediately
end
key_file = "#{node['openstack']['dashboard']['ssl']['dir']}/private/#{node['openstack']['dashboard']['ssl']['key']}"
key_mode = 00640
key_owner = 'root'
case node['platform_family']
when 'debian'
key_group = 'ssl-cert'
else
key_group = 'root'
end
key_group = node['openstack']['dashboard']['key_group']
if node['openstack']['dashboard']['ssl']['key_url']
remote_file key_file do
sensitive true
source node['openstack']['dashboard']['ssl']['key_url']
mode key_mode
owner key_owner
group key_group
file ssl_key_file.to_s do
content ssl_key
notifies :restart, 'service[apache2]', :immediately
notifies :run, 'execute[restore-selinux-context]', :immediately
end
else
cookbook_file key_file do
sensitive true
source 'horizon.key'
mode key_mode
owner key_owner
group key_group
mode key_mode
owner key_owner
group key_group
notifies :run, 'execute[restore-selinux-context]', :immediately
end
notifies :run, 'execute[restore-selinux-context]', :immediately
end
end
@ -170,11 +146,11 @@ template node['openstack']['dashboard']['apache']['sites-path'] do
mode 00644
variables(
ssl_cert_file: "#{node['openstack']['dashboard']['ssl']['dir']}/certs/#{node['openstack']['dashboard']['ssl']['cert']}",
ssl_key_file: "#{node['openstack']['dashboard']['ssl']['dir']}/private/#{node['openstack']['dashboard']['ssl']['key']}",
http_bind_address: http_bind.host,
ssl_cert_file: ssl_cert_file.to_s,
ssl_key_file: ssl_key_file.to_s,
http_bind_address: http_bind_address,
http_bind_port: http_bind.port.to_i,
https_bind_address: https_bind.host,
https_bind_address: https_bind_address,
https_bind_port: https_bind.port.to_i
)

View File

@ -8,7 +8,6 @@ describe 'openstack-dashboard::apache2-server' do
let(:chef_run) do
runner.converge(described_recipe)
end
include_context 'dashboard_stubs'
include_context 'redhat_stubs'
@ -23,33 +22,33 @@ describe 'openstack-dashboard::apache2-server' do
expect(chef_run).to run_execute(cmd)
end
describe 'certs' do
let(:crt) { chef_run.cookbook_file('/etc/pki/tls/certs/horizon.pem') }
let(:key) { chef_run.cookbook_file('/etc/pki/tls/private/horizon.key') }
describe 'get seceret' do
let(:pem) { chef_run.file('/etc/pki/tls/certs/horizon.pem') }
let(:key) { chef_run.file('/etc/pki/tls/private/horizon.key') }
it 'creates horizon.pem' do
expect(chef_run).to create_cookbook_file(crt.name).with(
user: 'root',
group: 'root',
mode: 0644
)
end
it 'create files and restarts apache' do
expect(chef_run).to create_file('/etc/pki/tls/certs/horizon.pem').with(
user: 'root',
group: 'root',
mode: 0644
)
expect(chef_run).to create_file('/etc/pki/tls/private/horizon.key').with(
user: 'root',
group: 'root',
mode: 0640
)
expect(pem).to notify('execute[restore-selinux-context]').to(:run)
expect(key).to notify('execute[restore-selinux-context]').to(:run)
end
it 'creates horizon.key' do
expect(chef_run).to create_cookbook_file(key.name).with(
user: 'root',
group: 'root',
mode: 0640
)
end
it 'notifies restore-selinux-context' do
expect(crt).to notify('execute[restore-selinux-context]').to(:run)
expect(key).to notify('execute[restore-selinux-context]').to(:run)
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/ssl/certs/horizon.pem')
expect(chef_run).not_to create_file('/etc/pki/tls/private/horizon.key')
end
end
end
it 'deletes openstack-dashboard.conf' do
file = '/etc/httpd/conf.d/openstack-dashboard.conf'

View File

@ -45,7 +45,6 @@ describe 'openstack-dashboard::apache2-server' do
node.set['openstack']['dashboard']['session_backend'] = 'sql'
runner.converge(described_recipe)
end
include_context 'non_redhat_stubs'
include_context 'dashboard_stubs'
@ -79,59 +78,72 @@ describe 'openstack-dashboard::apache2-server' do
end
describe 'certs' do
let(:crt) { chef_run.cookbook_file('/etc/ssl/certs/horizon.pem') }
let(:key) { chef_run.cookbook_file('/etc/ssl/private/horizon.key') }
let(:remote_key) { chef_run.remote_file('/etc/ssl/private/horizon.key') }
describe 'get seceret' do
let(:pem) { chef_run.file('/etc/ssl/certs/horizon.pem') }
let(:key) { chef_run.file('/etc/ssl/private/horizon.key') }
it 'has proper owner and group' do
expect(crt.owner).to eq('root')
expect(crt.group).to eq('root')
expect(key.owner).to eq('root')
expect(key.group).to eq('ssl-cert')
it 'create files and restarts apache' do
expect(chef_run).to create_file('/etc/ssl/certs/horizon.pem').with(
content: 'horizon_pem_value',
user: 'root',
group: 'root',
mode: 0644
)
expect(chef_run).to create_file('/etc/ssl/private/horizon.key').with(
content: 'horizon_key_value',
user: 'root',
group: 'ssl-cert',
mode: 0640
)
expect(pem).to notify('execute[restore-selinux-context]').to(:run)
expect(key).to notify('execute[restore-selinux-context]').to(:run)
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/ssl/certs/horizon.pem')
expect(chef_run).not_to create_file('/etc/ssl/certs/horizon.key')
end
end
describe 'get different seceret' do
let(:pem) { chef_run.file('/etc/anypath/any.pem') }
let(:key) { chef_run.file('/etc/anypath/any.key') }
it 'has proper modes' do
expect(crt.mode).to eq(0644)
expect(key.mode).to eq(0640)
end
before do
node.set['openstack']['dashboard']['ssl']['cert_dir'] = '/etc/anypath'
node.set['openstack']['dashboard']['ssl']['key_dir'] = '/etc/anypath'
node.set['openstack']['dashboard']['ssl']['cert'] = 'any.pem'
node.set['openstack']['dashboard']['ssl']['key'] = 'any.key'
allow_any_instance_of(Chef::Recipe).to receive(:secret)
.with('certs', 'any.pem')
.and_return('any_pem_value')
allow_any_instance_of(Chef::Recipe).to receive(:secret)
.with('certs', 'any.key')
.and_return('any_key_value')
node.set['openstack']['dashboard']
end
it 'create files and restarts apache' do
expect(chef_run).to create_file('/etc/anypath/any.pem').with(
content: 'any_pem_value',
user: 'root',
group: 'root',
mode: 0644
)
expect(chef_run).to create_file('/etc/anypath/any.key').with(
content: 'any_key_value',
user: 'root',
group: 'ssl-cert',
mode: 0640
)
expect(key).to notify('execute[restore-selinux-context]').to(:run)
expect(pem).to notify('execute[restore-selinux-context]').to(:run)
end
it 'has proper sensitvity' do
expect(crt.sensitive).to eq(true)
expect(key.sensitive).to eq(true)
end
it 'notifies restore-selinux-context' do
expect(crt).to notify('execute[restore-selinux-context]').to(:run)
expect(key).to notify('execute[restore-selinux-context]').to(:run)
end
it 'does not download certs if not needed' do
expect(chef_run).not_to create_remote_file('/etc/ssl/certs/horizon.pem')
expect(chef_run).not_to create_remote_file('/etc/ssl/private/horizon.key')
end
it 'downloads certs if needed and restarts apache' do
node.set['openstack']['dashboard']['ssl']['cert_url'] = 'http://server/mycert.pem'
node.set['openstack']['dashboard']['ssl']['key_url'] = 'http://server/mykey.key'
expect(chef_run).to create_remote_file('/etc/ssl/certs/horizon.pem').with(
sensitive: true,
user: 'root',
group: 'root',
mode: 0644
)
expect(chef_run).to create_remote_file('/etc/ssl/private/horizon.key').with(
sensitive: true,
user: 'root',
group: 'ssl-cert',
mode: 0640
)
expect(remote_key).to notify('service[apache2]').to(:restart)
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_cookbook_file(crt)
expect(chef_run).not_to create_cookbook_file(key)
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')
end
end
end
@ -223,24 +235,33 @@ describe 'openstack-dashboard::apache2-server' do
it 'has no ssl ciphers configured by default' do
expect(chef_run).not_to render_file(file.name).with_content(/^\s*SSLCipherSuite.*$/)
end
it 'shows ssl related directives overrides' do
node.set['openstack']['dashboard']['ssl']['dir'] = 'ssl_dir_value'
node.set['openstack']['dashboard']['ssl']['cert'] = 'ssl_cert_value'
node.set['openstack']['dashboard']['ssl']['key'] = 'ssl_key_value'
node.set['openstack']['dashboard']['ssl']['protocol'] = 'ssl_protocol_value'
node.set['openstack']['dashboard']['ssl']['ciphers'] = 'ssl_ciphers_value'
[/^\s*SSLEngine on$/,
%r{^\s*SSLCertificateFile ssl_dir_value/certs/ssl_cert_value$},
%r{^\s*SSLCertificateKeyFile ssl_dir_value/private/ssl_key_value$},
/^\s*SSLProtocol ssl_protocol_value$/,
/^\s*SSLCipherSuite ssl_ciphers_value$/].each do |ssl_directive|
expect(chef_run).to render_file(file.name).with_content(ssl_directive)
# noinspection CookbookSourceRoot
context 'override attributes' do
before do
allow_any_instance_of(Chef::Recipe).to receive(:secret)
.with('certs', 'ssl.cert')
.and_return('ssl_cert_value')
allow_any_instance_of(Chef::Recipe).to receive(:secret)
.with('certs', 'ssl.key')
.and_return('ssl_key_value')
node.set['openstack']['dashboard']['ssl']['cert'] = 'ssl.cert'
node.set['openstack']['dashboard']['ssl']['key'] = 'ssl.key'
node.set['openstack']['dashboard']['ssl']['cert_dir'] = 'ssl_dir_value/certs'
node.set['openstack']['dashboard']['ssl']['key_dir'] = 'ssl_dir_value/private'
node.set['openstack']['dashboard']['ssl']['protocol'] = 'ssl_protocol_value'
node.set['openstack']['dashboard']['ssl']['ciphers'] = 'ssl_ciphers_value'
end
it 'shows ssl related directives overrides' do
[/^\s*SSLEngine on$/,
%r{^\s*SSLCertificateFile ssl_dir_value/certs/ssl.cert$},
%r{^\s*SSLCertificateKeyFile ssl_dir_value/private/ssl.key$},
/^\s*SSLProtocol ssl_protocol_value$/,
/^\s*SSLCipherSuite ssl_ciphers_value$/].each do |ssl_directive|
expect(chef_run).to render_file(file.name).with_content(ssl_directive)
end
end
end
end
context 'with use_ssl disabled' do
before do
node.set['openstack']['dashboard']['use_ssl'] = false

View File

@ -29,6 +29,12 @@ shared_context 'dashboard_stubs' do
allow_any_instance_of(Chef::Recipe).to receive(:get_password)
.with('db', 'horizon')
.and_return('test-passes')
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.key')
.and_return('horizon_key_value')
end
end