diff --git a/manifests/init.pp b/manifests/init.pp index dbce9d4..986252e 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -516,7 +516,10 @@ class ssh ( } validate_absolute_path($ssh_config_global_known_hosts_file) - + validate_string($ssh_config_global_known_hosts_owner) + validate_string($ssh_config_global_known_hosts_group) + validate_re($ssh_config_global_known_hosts_mode, '^[0-7]{4}$', + "ssh::ssh_config_global_known_hosts_mode must be a valid 4 digit mode in octal notation. Detected value is <${ssh_config_global_known_hosts_mode}>.") case $purge_keys { 'true','false': { @@ -533,7 +536,6 @@ class ssh ( #sshd_config template validate_string($sshd_config_template) - #loglevel $supported_loglevel_vals=['QUIET', 'FATAL', 'ERROR', 'INFO', 'VERBOSE'] validate_re($sshd_config_loglevel, $supported_loglevel_vals) @@ -662,16 +664,16 @@ class ssh ( key => $key, } - if $ssh_key_import_real == true { - file { 'ssh_known_hosts': - ensure => file, - path => $ssh_config_global_known_hosts_file, - owner => $ssh_config_global_known_hosts_owner, - group => $ssh_config_global_known_hosts_group, - mode => $ssh_config_global_known_hosts_mode, - } + file { 'ssh_known_hosts': + ensure => file, + path => $ssh_config_global_known_hosts_file, + owner => $ssh_config_global_known_hosts_owner, + group => $ssh_config_global_known_hosts_group, + mode => $ssh_config_global_known_hosts_mode, + } - # import all nodes' ssh keys + # import all nodes' ssh keys + if $ssh_key_import_real == true { Sshkey <<||>> { target => $ssh_config_global_known_hosts_file, } diff --git a/spec/classes/init_spec.rb b/spec/classes/init_spec.rb index a2072d5..4a263a1 100644 --- a/spec/classes/init_spec.rb +++ b/spec/classes/init_spec.rb @@ -26,6 +26,16 @@ describe 'ssh' do } end + it { + should contain_file('ssh_known_hosts').with({ + 'ensure' => 'file', + 'path' => '/etc/ssh/ssh_known_hosts', + 'owner' => 'root', + 'group' => 'root', + 'mode' => '0644', + }) + } + it { should contain_file('ssh_config').with({ 'ensure' => 'file', @@ -157,6 +167,16 @@ describe 'ssh' do } end + it { + should contain_file('ssh_known_hosts').with({ + 'ensure' => 'file', + 'path' => '/etc/ssh/ssh_known_hosts', + 'owner' => 'root', + 'group' => 'root', + 'mode' => '0644', + }) + } + it { should contain_file('ssh_config').with({ 'ensure' => 'file', @@ -261,6 +281,16 @@ describe 'ssh' do } end + it { + should contain_file('ssh_known_hosts').with({ + 'ensure' => 'file', + 'path' => '/etc/ssh/ssh_known_hosts', + 'owner' => 'root', + 'group' => 'root', + 'mode' => '0644', + }) + } + it { should contain_file('ssh_config').with({ 'ensure' => 'file', @@ -364,6 +394,16 @@ describe 'ssh' do } end + it { + should contain_file('ssh_known_hosts').with({ + 'ensure' => 'file', + 'path' => '/etc/ssh/ssh_known_hosts', + 'owner' => 'root', + 'group' => 'root', + 'mode' => '0644', + }) + } + it { should contain_file('ssh_config').with({ 'ensure' => 'file', @@ -466,6 +506,16 @@ describe 'ssh' do } end + it { + should contain_file('ssh_known_hosts').with({ + 'ensure' => 'file', + 'path' => '/etc/ssh/ssh_known_hosts', + 'owner' => 'root', + 'group' => 'root', + 'mode' => '0644', + }) + } + it { should contain_file('ssh_config').with({ 'ensure' => 'file', @@ -576,6 +626,16 @@ describe 'ssh' do }) } + it { + should contain_file('ssh_known_hosts').with({ + 'ensure' => 'file', + 'path' => '/etc/ssh/ssh_known_hosts', + 'owner' => 'root', + 'group' => 'root', + 'mode' => '0644', + }) + } + it { should contain_file('ssh_config').with({ 'ensure' => 'file', @@ -686,6 +746,16 @@ describe 'ssh' do }) } + it { + should contain_file('ssh_known_hosts').with({ + 'ensure' => 'file', + 'path' => '/etc/ssh/ssh_known_hosts', + 'owner' => 'root', + 'group' => 'root', + 'mode' => '0644', + }) + } + it { should contain_file('ssh_config').with({ 'ensure' => 'file', @@ -2422,6 +2492,194 @@ describe 'ssh' do end end + describe 'with parameter ssh_config_global_known_hosts_file' do + context 'specified as a valid path' do + let(:params) { { :ssh_config_global_known_hosts_file => '/valid/path' } } + let(:facts) do + { :fqdn => 'monkey.example.com', + :osfamily => 'RedHat', + :sshrsakey => 'AAAAB3NzaC1yc2EAAAABIwAAAQEArGElx46pD6NNnlxVaTbp0ZJMgBKCmbTCT3RaeCk0ZUJtQ8wkcwTtqIXmmiuFsynUT0DFSd8UIodnBOPqitimmooAVAiAi30TtJVzADfPScMiUnBJKZajIBkEMkwUcqsfh630jyBvLPE/kyQcxbEeGtbu1DG3monkeymanOBW1AKc5o+cJLXcInLnbowMG7NXzujT3BRYn/9s5vtT1V9cuZJs4XLRXQ50NluxJI7sVfRPVvQI9EMbTS4AFBXUej3yfgaLSV+nPZC/lmJ2gR4t/tKvMFF9m16f8IcZKK7o0rK7v81G/tREbOT5YhcKLK+0wBfR6RsmHzwy4EddZloyLQ==' + } + end + + it { + should contain_file('ssh_known_hosts').with({ + 'ensure' => 'file', + 'path' => '/valid/path', + 'owner' => 'root', + 'group' => 'root', + 'mode' => '0644', + }) + } + + it { should contain_file('ssh_config').with_content(/^\s*GlobalKnownHostsFile \/valid\/path$/) } + end + + context 'specified as an invalid path' do + let(:params) { { :ssh_config_global_known_hosts_file => 'invalid/path' } } + let(:facts) do + { :fqdn => 'monkey.example.com', + :osfamily => 'RedHat', + :sshrsakey => 'AAAAB3NzaC1yc2EAAAABIwAAAQEArGElx46pD6NNnlxVaTbp0ZJMgBKCmbTCT3RaeCk0ZUJtQ8wkcwTtqIXmmiuFsynUT0DFSd8UIodnBOPqitimmooAVAiAi30TtJVzADfPScMiUnBJKZajIBkEMkwUcqsfh630jyBvLPE/kyQcxbEeGtbu1DG3monkeymanOBW1AKc5o+cJLXcInLnbowMG7NXzujT3BRYn/9s5vtT1V9cuZJs4XLRXQ50NluxJI7sVfRPVvQI9EMbTS4AFBXUej3yfgaLSV+nPZC/lmJ2gR4t/tKvMFF9m16f8IcZKK7o0rK7v81G/tREbOT5YhcKLK+0wBfR6RsmHzwy4EddZloyLQ==' + } + end + + it do + expect { + should contain_class('ssh') + }.to raise_error(Puppet::Error,/^\"invalid\/path\" is not an absolute path./) + end + end + + context 'specified as an invalid type' do + let(:params) { { :ssh_config_global_known_hosts_file => ['invalid','type'] } } + let(:facts) do + { :fqdn => 'monkey.example.com', + :osfamily => 'RedHat', + :sshrsakey => 'AAAAB3NzaC1yc2EAAAABIwAAAQEArGElx46pD6NNnlxVaTbp0ZJMgBKCmbTCT3RaeCk0ZUJtQ8wkcwTtqIXmmiuFsynUT0DFSd8UIodnBOPqitimmooAVAiAi30TtJVzADfPScMiUnBJKZajIBkEMkwUcqsfh630jyBvLPE/kyQcxbEeGtbu1DG3monkeymanOBW1AKc5o+cJLXcInLnbowMG7NXzujT3BRYn/9s5vtT1V9cuZJs4XLRXQ50NluxJI7sVfRPVvQI9EMbTS4AFBXUej3yfgaLSV+nPZC/lmJ2gR4t/tKvMFF9m16f8IcZKK7o0rK7v81G/tREbOT5YhcKLK+0wBfR6RsmHzwy4EddZloyLQ==' + } + end + + it do + expect { + should contain_class('ssh') + }.to raise_error(Puppet::Error,/^\[\"invalid\", \"type\"\] is not an absolute path./) + end + end + end + + describe 'with parameter ssh_config_global_known_hosts_owner' do + context 'specified as a valid string' do + let(:params) { { :ssh_config_global_known_hosts_owner => 'gh' } } + let(:facts) do + { :fqdn => 'monkey.example.com', + :osfamily => 'RedHat', + :sshrsakey => 'AAAAB3NzaC1yc2EAAAABIwAAAQEArGElx46pD6NNnlxVaTbp0ZJMgBKCmbTCT3RaeCk0ZUJtQ8wkcwTtqIXmmiuFsynUT0DFSd8UIodnBOPqitimmooAVAiAi30TtJVzADfPScMiUnBJKZajIBkEMkwUcqsfh630jyBvLPE/kyQcxbEeGtbu1DG3monkeymanOBW1AKc5o+cJLXcInLnbowMG7NXzujT3BRYn/9s5vtT1V9cuZJs4XLRXQ50NluxJI7sVfRPVvQI9EMbTS4AFBXUej3yfgaLSV+nPZC/lmJ2gR4t/tKvMFF9m16f8IcZKK7o0rK7v81G/tREbOT5YhcKLK+0wBfR6RsmHzwy4EddZloyLQ==' + } + end + + it { + should contain_file('ssh_known_hosts').with({ + 'ensure' => 'file', + 'path' => '/etc/ssh/ssh_known_hosts', + 'owner' => 'gh', + 'group' => 'root', + 'mode' => '0644', + }) + } + end + + context 'specified as an invalid type [non-string]' do + let(:params) { { :ssh_config_global_known_hosts_owner => ['invalid','type'] } } + let(:facts) do + { :fqdn => 'monkey.example.com', + :osfamily => 'RedHat', + :sshrsakey => 'AAAAB3NzaC1yc2EAAAABIwAAAQEArGElx46pD6NNnlxVaTbp0ZJMgBKCmbTCT3RaeCk0ZUJtQ8wkcwTtqIXmmiuFsynUT0DFSd8UIodnBOPqitimmooAVAiAi30TtJVzADfPScMiUnBJKZajIBkEMkwUcqsfh630jyBvLPE/kyQcxbEeGtbu1DG3monkeymanOBW1AKc5o+cJLXcInLnbowMG7NXzujT3BRYn/9s5vtT1V9cuZJs4XLRXQ50NluxJI7sVfRPVvQI9EMbTS4AFBXUej3yfgaLSV+nPZC/lmJ2gR4t/tKvMFF9m16f8IcZKK7o0rK7v81G/tREbOT5YhcKLK+0wBfR6RsmHzwy4EddZloyLQ==' + } + end + + it do + expect { + should contain_class('ssh') + }.to raise_error(Puppet::Error,/^\[\"invalid\", \"type\"\] is not a string. It looks to be a Array/) + end + end + end + + describe 'with parameter ssh_config_global_known_hosts_group' do + context 'specified as a valid string' do + let(:params) { { :ssh_config_global_known_hosts_group => 'gh' } } + let(:facts) do + { :fqdn => 'monkey.example.com', + :osfamily => 'RedHat', + :sshrsakey => 'AAAAB3NzaC1yc2EAAAABIwAAAQEArGElx46pD6NNnlxVaTbp0ZJMgBKCmbTCT3RaeCk0ZUJtQ8wkcwTtqIXmmiuFsynUT0DFSd8UIodnBOPqitimmooAVAiAi30TtJVzADfPScMiUnBJKZajIBkEMkwUcqsfh630jyBvLPE/kyQcxbEeGtbu1DG3monkeymanOBW1AKc5o+cJLXcInLnbowMG7NXzujT3BRYn/9s5vtT1V9cuZJs4XLRXQ50NluxJI7sVfRPVvQI9EMbTS4AFBXUej3yfgaLSV+nPZC/lmJ2gR4t/tKvMFF9m16f8IcZKK7o0rK7v81G/tREbOT5YhcKLK+0wBfR6RsmHzwy4EddZloyLQ==' + } + end + + it { + should contain_file('ssh_known_hosts').with({ + 'ensure' => 'file', + 'path' => '/etc/ssh/ssh_known_hosts', + 'owner' => 'root', + 'group' => 'gh', + 'mode' => '0644', + }) + } + end + + context 'specified as an invalid type [non-string]' do + let(:params) { { :ssh_config_global_known_hosts_group => ['invalid','type'] } } + let(:facts) do + { :fqdn => 'monkey.example.com', + :osfamily => 'RedHat', + :sshrsakey => 'AAAAB3NzaC1yc2EAAAABIwAAAQEArGElx46pD6NNnlxVaTbp0ZJMgBKCmbTCT3RaeCk0ZUJtQ8wkcwTtqIXmmiuFsynUT0DFSd8UIodnBOPqitimmooAVAiAi30TtJVzADfPScMiUnBJKZajIBkEMkwUcqsfh630jyBvLPE/kyQcxbEeGtbu1DG3monkeymanOBW1AKc5o+cJLXcInLnbowMG7NXzujT3BRYn/9s5vtT1V9cuZJs4XLRXQ50NluxJI7sVfRPVvQI9EMbTS4AFBXUej3yfgaLSV+nPZC/lmJ2gR4t/tKvMFF9m16f8IcZKK7o0rK7v81G/tREbOT5YhcKLK+0wBfR6RsmHzwy4EddZloyLQ==' + } + end + + it do + expect { + should contain_class('ssh') + }.to raise_error(Puppet::Error,/^\[\"invalid\", \"type\"\] is not a string. It looks to be a Array/) + end + end + end + + describe 'with parameter ssh_config_global_known_hosts_mode' do + context 'specified as a valid mode' do + let(:params) { { :ssh_config_global_known_hosts_mode => '0666' } } + let(:facts) do + { :fqdn => 'monkey.example.com', + :osfamily => 'RedHat', + :sshrsakey => 'AAAAB3NzaC1yc2EAAAABIwAAAQEArGElx46pD6NNnlxVaTbp0ZJMgBKCmbTCT3RaeCk0ZUJtQ8wkcwTtqIXmmiuFsynUT0DFSd8UIodnBOPqitimmooAVAiAi30TtJVzADfPScMiUnBJKZajIBkEMkwUcqsfh630jyBvLPE/kyQcxbEeGtbu1DG3monkeymanOBW1AKc5o+cJLXcInLnbowMG7NXzujT3BRYn/9s5vtT1V9cuZJs4XLRXQ50NluxJI7sVfRPVvQI9EMbTS4AFBXUej3yfgaLSV+nPZC/lmJ2gR4t/tKvMFF9m16f8IcZKK7o0rK7v81G/tREbOT5YhcKLK+0wBfR6RsmHzwy4EddZloyLQ==' + } + end + + it { + should contain_file('ssh_known_hosts').with({ + 'ensure' => 'file', + 'path' => '/etc/ssh/ssh_known_hosts', + 'owner' => 'root', + 'group' => 'root', + 'mode' => '0666', + }) + } + end + + ['666','0842','06666'].each do |value| + context "specified as invalid mode - #{value}" do + let(:params) { { :ssh_config_global_known_hosts_mode => value } } + let(:facts) do + { :fqdn => 'monkey.example.com', + :osfamily => 'RedHat', + :sshrsakey => 'AAAAB3NzaC1yc2EAAAABIwAAAQEArGElx46pD6NNnlxVaTbp0ZJMgBKCmbTCT3RaeCk0ZUJtQ8wkcwTtqIXmmiuFsynUT0DFSd8UIodnBOPqitimmooAVAiAi30TtJVzADfPScMiUnBJKZajIBkEMkwUcqsfh630jyBvLPE/kyQcxbEeGtbu1DG3monkeymanOBW1AKc5o+cJLXcInLnbowMG7NXzujT3BRYn/9s5vtT1V9cuZJs4XLRXQ50NluxJI7sVfRPVvQI9EMbTS4AFBXUej3yfgaLSV+nPZC/lmJ2gR4t/tKvMFF9m16f8IcZKK7o0rK7v81G/tREbOT5YhcKLK+0wBfR6RsmHzwy4EddZloyLQ==' + } + end + + it do + expect { + should contain_class('ssh') + }.to raise_error(Puppet::Error,/^ssh::ssh_config_global_known_hosts_mode must be a valid 4 digit mode in octal notation. Detected value is <#{value}>./) + end + end + end + + context 'specified as an invalid type [non-string]' do + let(:params) { { :ssh_config_global_known_hosts_mode => ['invalid','type'] } } + let(:facts) do + { :fqdn => 'monkey.example.com', + :osfamily => 'RedHat', + :sshrsakey => 'AAAAB3NzaC1yc2EAAAABIwAAAQEArGElx46pD6NNnlxVaTbp0ZJMgBKCmbTCT3RaeCk0ZUJtQ8wkcwTtqIXmmiuFsynUT0DFSd8UIodnBOPqitimmooAVAiAi30TtJVzADfPScMiUnBJKZajIBkEMkwUcqsfh630jyBvLPE/kyQcxbEeGtbu1DG3monkeymanOBW1AKc5o+cJLXcInLnbowMG7NXzujT3BRYn/9s5vtT1V9cuZJs4XLRXQ50NluxJI7sVfRPVvQI9EMbTS4AFBXUej3yfgaLSV+nPZC/lmJ2gR4t/tKvMFF9m16f8IcZKK7o0rK7v81G/tREbOT5YhcKLK+0wBfR6RsmHzwy4EddZloyLQ==' + } + end + + it do + expect { + should contain_class('ssh') + }.to raise_error(Puppet::Error,/^ssh::ssh_config_global_known_hosts_mode must be a valid 4 digit mode in octal notation. Detected value is ./) + end + end + end + describe 'with ssh_key_import parameter specified' do context 'as a non-boolean or non-string' do let(:params) { { :ssh_key_import => ['not_a_boolean','or_a_string'] } }