From 4f73f440a60142255f7fb3ab97a74dc14b5f51fa Mon Sep 17 00:00:00 2001 From: Lars Kellogg-Stedman Date: Wed, 9 Apr 2014 11:20:16 -0400 Subject: [PATCH] support for managing ssh keys This change permits provisioning ssh public and private keys as part of creating the "nova" user. There are no changes to the default behavior of the module. This changes introduces three new parameters: - nova_public_key - nova_private_key - nova_shell These changes are intended to permit configuring live migration via qemu+ssh connections to remote hypervisors. Change-Id: Ib61f4574843a7e5ada9a08692f4488cb844c9eee Implements: blueprint provision-ssh-keys --- manifests/init.pp | 70 +++++++++++++++++- spec/classes/nova_init_spec.rb | 127 ++++++++++++++++++++++++++++++++- 2 files changed, 194 insertions(+), 3 deletions(-) diff --git a/manifests/init.pp b/manifests/init.pp index 52b5c672e..165145cd2 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -189,6 +189,22 @@ # the ownership of all files/dirs owned by nova. # Defaults to undef. # +# [*nova_public_key*] +# (optional) Install public key in .ssh/authorized_keys for the 'nova' user. +# Expects a hash of the form { type => 'key-type', key => 'key-data' } where +# 'key-type' is one of (ssh-rsa, ssh-dsa, ssh-ecdsa) and 'key-data' is the +# actual key data (e.g, 'AAAA...'). +# +# [*nova_private_key*] +# (optional) Install private key into .ssh/id_rsa (or appropriate equivalent +# for key type). Expects a hash of the form { type => 'key-type', key => +# 'key-data' }, where 'key-type' is one of (ssh-rsa, ssh-dsa, ssh-ecdsa) and +# 'key-data' is the contents of the private key file. +# +# [*nova_shell*] +# (optional) Set shell for 'nova' user to the specified value. +# Defaults to '/bin/false'. +# # [*mysql_module*] # (optional) Mysql module version to use. Tested versions # are 0.9 and 2.2 @@ -257,6 +273,9 @@ $rootwrap_config = '/etc/nova/rootwrap.conf', $nova_user_id = undef, $nova_group_id = undef, + $nova_public_key = undef, + $nova_private_key = undef, + $nova_shell = '/bin/false', # deprecated in folsom #$root_helper = $::nova::params::root_helper, $monitoring_notifications = false, @@ -293,11 +312,60 @@ groups => 'nova', home => '/var/lib/nova', managehome => false, - shell => '/bin/false', + shell => $nova_shell, uid => $nova_user_id, gid => $nova_group_id, } + if $nova_public_key or $nova_private_key { + file { '/var/lib/nova/.ssh': + ensure => directory, + mode => '0700', + owner => nova, + group => nova, + } + + if $nova_public_key { + if ! $nova_public_key[key] or ! $nova_public_key[type] { + fail('You must provide both a key type and key data.') + } + + ssh_authorized_key { 'nova-migration-public-key': + ensure => present, + key => $nova_public_key[key], + type => $nova_public_key[type], + user => 'nova', + require => File['/var/lib/nova/.ssh'], + } + } + + if $nova_private_key { + if ! $nova_private_key[key] or ! $nova_private_key[type] { + fail('You must provide both a key type and key data.') + } + + $nova_private_key_file = $nova_private_key[type] ? { + 'ssh-rsa' => '/var/lib/nova/.ssh/id_rsa', + 'ssh-dsa' => '/var/lib/nova/.ssh/id_dsa', + 'ssh-ecdsa' => '/var/lib/nova/.ssh/id_ecdsa', + default => undef + } + + if ! $nova_private_key_file { + fail("Unable to determine name of private key file. Type specified was '${nova_private_key[type]}' but should be one of: ssh-rsa, ssh-dsa, ssh-ecdsa.") + } + + file { $nova_private_key_file: + content => $nova_private_key[key], + mode => '0600', + owner => nova, + group => nova, + require => File['/var/lib/nova/.ssh'], + } + } + } + + # all nova_config resources should be applied # after the nova common package # before the file resource for nova.conf is managed diff --git a/spec/classes/nova_init_spec.rb b/spec/classes/nova_init_spec.rb index 47c7d001d..93d97f1bb 100644 --- a/spec/classes/nova_init_spec.rb +++ b/spec/classes/nova_init_spec.rb @@ -132,7 +132,8 @@ :notify_api_faults => true, :nova_user_id => '499', :nova_group_id => '499', - :report_interval => '60' } + :report_interval => '60', + :nova_shell => '/bin/bash' } end it 'creates user and group' do @@ -148,7 +149,7 @@ :groups => 'nova', :home => '/var/lib/nova', :managehome => false, - :shell => '/bin/false', + :shell => '/bin/bash', :uid => '499', :gid => '499' ) @@ -412,6 +413,128 @@ it { should contain_nova_config('DEFAULT/qpid_sasl_mechanisms').with_value('DIGEST-MD5 GSSAPI PLAIN') } end end + + context 'with ssh public key' do + let :params do + { + :nova_public_key => {'type' => 'ssh-rsa', + 'key' => 'keydata'} + } + end + + it 'should install ssh public key' do + should contain_ssh_authorized_key('nova-migration-public-key').with( + :ensure => 'present', + :key => 'keydata', + :type => 'ssh-rsa' + ) + end + end + + context 'with ssh public key missing key type' do + let :params do + { + :nova_public_key => {'type' => '', + 'key' => 'keydata'} + } + end + + it 'should raise an error' do + expect { + should contain_ssh_authorized_key('nova-migration-public-key').with( + :ensure => 'present', + :key => 'keydata', + :type => '' + ) + }.to raise_error Puppet::Error, /You must provide both a key type and key data./ + end + end + + context 'with ssh public key missing key data' do + let :params do + { + :nova_public_key => {'type' => 'ssh-rsa', + 'key' => ''} + } + end + + it 'should raise an error' do + expect { + should contain_ssh_authorized_key('nova-migration-public-key').with( + :ensure => 'present', + :key => 'keydata', + :type => '' + ) + }.to raise_error Puppet::Error, /You must provide both a key type and key data./ + end + end + + context 'with ssh private key' do + let :params do + { + :nova_private_key => {'type' => 'ssh-rsa', + 'key' => 'keydata'} + } + end + + it 'should install ssh private key' do + should contain_file('/var/lib/nova/.ssh/id_rsa').with( + :content => 'keydata' + ) + end + end + + context 'with ssh private key missing key type' do + let :params do + { + :nova_private_key => {'type' => '', + 'key' => 'keydata'} + } + end + + it 'should raise an error' do + expect { + should contain_file('/var/lib/nova/.ssh/id_rsa').with( + :content => 'keydata' + ) + }.to raise_error Puppet::Error, /You must provide both a key type and key data./ + end + end + + context 'with ssh private key having incorrect key type' do + let :params do + { + :nova_private_key => {'type' => 'invalid', + 'key' => 'keydata'} + } + end + + it 'should raise an error' do + expect { + should contain_file('/var/lib/nova/.ssh/id_rsa').with( + :content => 'keydata' + ) + }.to raise_error Puppet::Error, /Unable to determine name of private key file./ + end + end + + context 'with ssh private key missing key data' do + let :params do + { + :nova_private_key => {'type' => 'ssh-rsa', + 'key' => ''} + } + end + + it 'should raise an error' do + expect { + should contain_file('/var/lib/nova/.ssh/id_rsa').with( + :content => 'keydata' + ) + }.to raise_error Puppet::Error, /You must provide both a key type and key data./ + end + end + end context 'on Debian platforms' do