diff --git a/README.md b/README.md index d86ae35..0edb4e9 100644 --- a/README.md +++ b/README.md @@ -160,6 +160,12 @@ sshd_config's mode. The default is '0600' on Linux and '0644' on Solaris. - *Default*: 'USE_DEFAULTS' +sshd_listen_address +------------------- +String or Array to specify address(es) for which sshd will bind. Corresponds to ListenAddress in sshd_config. + +- *Default*: undef + sshd_config_port --------------------------- String to specify listen port for sshd. Port option in sshd_config. diff --git a/manifests/init.pp b/manifests/init.pp index adc783d..da08605 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -65,6 +65,7 @@ class ssh ( $sshd_gssapicleanupcredentials = 'USE_DEFAULTS', $sshd_acceptenv = 'USE_DEFAULTS', $sshd_config_hostkey = 'USE_DEFAULTS', + $sshd_listen_address = undef, $service_ensure = 'running', $service_name = 'USE_DEFAULTS', $service_enable = 'true', @@ -348,6 +349,10 @@ class ssh ( $sshd_config_hostkey_real = $sshd_config_hostkey } + if $sshd_listen_address { + validate_array($sshd_listen_address) + } + if $service_hasstatus == 'USE_DEFAULTS' { $service_hasstatus_real = $default_service_hasstatus } else { diff --git a/spec/classes/init_spec.rb b/spec/classes/init_spec.rb index f5a8efa..eebd65d 100644 --- a/spec/classes/init_spec.rb +++ b/spec/classes/init_spec.rb @@ -81,6 +81,7 @@ describe 'ssh' do it { should contain_file('sshd_config').with_content(/^GSSAPIAuthentication yes$/) } it { should contain_file('sshd_config').with_content(/^GSSAPICleanupCredentials yes$/) } it { should contain_file('sshd_config').with_content(/^HostKey \/etc\/ssh\/ssh_host_rsa_key$/) } + it { should contain_file('sshd_config').without_content(/^\s*ListenAddress/) } it { should_not contain_file('sshd_config').with_content(/^\s*PAMAuthenticationViaKBDInt yes$/) } it { should_not contain_file('sshd_config').with_content(/^\s*GSSAPIKeyExchange no$/) } it { should_not contain_file('sshd_config').with_content(/^AuthorizedKeysFile/) } @@ -211,6 +212,7 @@ describe 'ssh' do it { should contain_file('sshd_config').without_content(/^\s*DenyGroups/) } it { should contain_file('sshd_config').without_content(/^\s*AllowUsers/) } it { should contain_file('sshd_config').without_content(/^\s*AllowGroups/) } + it { should contain_file('sshd_config').without_content(/^\s*ListenAddress/) } it { should contain_service('sshd_service').with({ @@ -312,6 +314,7 @@ describe 'ssh' do it { should contain_file('sshd_config').without_content(/^\s*DenyGroups/) } it { should contain_file('sshd_config').without_content(/^\s*AllowUsers/) } it { should contain_file('sshd_config').without_content(/^\s*AllowGroups/) } + it { should contain_file('sshd_config').without_content(/^\s*ListenAddress/) } it { should contain_service('sshd_service').with({ @@ -412,6 +415,7 @@ describe 'ssh' do it { should contain_file('sshd_config').without_content(/^\s*DenyGroups/) } it { should contain_file('sshd_config').without_content(/^\s*AllowUsers/) } it { should contain_file('sshd_config').without_content(/^\s*AllowGroups/) } + it { should contain_file('sshd_config').without_content(/^\s*ListenAddress/) } it { should contain_service('sshd_service').with({ @@ -519,6 +523,7 @@ describe 'ssh' do it { should contain_file('sshd_config').without_content(/^\s*DenyGroups/) } it { should contain_file('sshd_config').without_content(/^\s*AllowUsers/) } it { should contain_file('sshd_config').without_content(/^\s*AllowGroups/) } + it { should contain_file('sshd_config').without_content(/^\s*ListenAddress/) } it { should contain_service('sshd_service').with({ @@ -626,6 +631,7 @@ describe 'ssh' do it { should contain_file('sshd_config').without_content(/^\s*DenyGroups/) } it { should contain_file('sshd_config').without_content(/^\s*AllowUsers/) } it { should contain_file('sshd_config').without_content(/^\s*AllowGroups/) } + it { should contain_file('sshd_config').without_content(/^\s*ListenAddress/) } it { should contain_service('sshd_service').with({ @@ -733,6 +739,7 @@ describe 'ssh' do it { should contain_file('sshd_config').without_content(/^\s*DenyGroups/) } it { should contain_file('sshd_config').without_content(/^\s*AllowUsers/) } it { should contain_file('sshd_config').without_content(/^\s*AllowGroups/) } + it { should contain_file('sshd_config').without_content(/^\s*ListenAddress/) } it { should contain_service('sshd_service').with({ @@ -882,6 +889,9 @@ describe 'ssh' do :sshd_config_allowgroups => [ 'ssh', 'security', ], + :sshd_listen_address => [ '192.168.1.1', + '2001:db8::dead:f00d', + ], } end @@ -931,6 +941,7 @@ describe 'ssh' do it { should contain_file('sshd_config').with_content(/^\s*DenyGroups nossh wheel$/) } it { should contain_file('sshd_config').with_content(/^\s*AllowUsers foo bar$/) } it { should contain_file('sshd_config').with_content(/^\s*AllowGroups ssh security$/) } + it { should contain_file('sshd_config').with_content(/^ListenAddress 192.168.1.1\nListenAddress 2001:db8::dead:f00d$/) } it { should contain_file('sshd_banner').with({ @@ -945,6 +956,66 @@ describe 'ssh' do } end + describe 'sshd_listen_address param' do + context 'when set to an array' do + let :facts do + { + :fqdn => 'monkey.example.com', + :osfamily => 'RedHat', + :root_home => '/root', + :sshrsakey => 'AAAAB3NzaC1yc2EAAAABIwAAAQEArGElx46pD6NNnlxVaTbp0ZJMgBKCmbTCT3RaeCk0ZUJtQ8wkcwTtqIXmmiuFsynUT0DFSd8UIodnBOPqitimmooAVAiAi30TtJVzADfPScMiUnBJKZajIBkEMkwUcqsfh630jyBvLPE/kyQcxbEeGtbu1DG3monkeymanOBW1AKc5o+cJLXcInLnbowMG7NXzujT3BRYn/9s5vtT1V9cuZJs4XLRXQ50NluxJI7sVfRPVvQI9EMbTS4AFBXUej3yfgaLSV+nPZC/lmJ2gR4t/tKvMFF9m16f8IcZKK7o0rK7v81G/tREbOT5YhcKLK+0wBfR6RsmHzwy4EddZloyLQ==' + } + end + let (:params) {{'sshd_listen_address' => ['192.168.1.1','2001:db8::dead:f00d'] }} + + it { should contain_file('sshd_config').with_content(/^ListenAddress 192.168.1.1\nListenAddress 2001:db8::dead:f00d$/) } + end + + context 'when set to a string' do + let :facts do + { + :fqdn => 'monkey.example.com', + :osfamily => 'RedHat', + :root_home => '/root', + :sshrsakey => 'AAAAB3NzaC1yc2EAAAABIwAAAQEArGElx46pD6NNnlxVaTbp0ZJMgBKCmbTCT3RaeCk0ZUJtQ8wkcwTtqIXmmiuFsynUT0DFSd8UIodnBOPqitimmooAVAiAi30TtJVzADfPScMiUnBJKZajIBkEMkwUcqsfh630jyBvLPE/kyQcxbEeGtbu1DG3monkeymanOBW1AKc5o+cJLXcInLnbowMG7NXzujT3BRYn/9s5vtT1V9cuZJs4XLRXQ50NluxJI7sVfRPVvQI9EMbTS4AFBXUej3yfgaLSV+nPZC/lmJ2gR4t/tKvMFF9m16f8IcZKK7o0rK7v81G/tREbOT5YhcKLK+0wBfR6RsmHzwy4EddZloyLQ==' + } + end + let (:params) {{'sshd_listen_address' => ['192.168.1.1'] }} + + it { should contain_file('sshd_config').with_content(/^ListenAddress 192.168.1.1$/) } + end + + context 'when not set' do + let :facts do + { + :fqdn => 'monkey.example.com', + :osfamily => 'RedHat', + :root_home => '/root', + :sshrsakey => 'AAAAB3NzaC1yc2EAAAABIwAAAQEArGElx46pD6NNnlxVaTbp0ZJMgBKCmbTCT3RaeCk0ZUJtQ8wkcwTtqIXmmiuFsynUT0DFSd8UIodnBOPqitimmooAVAiAi30TtJVzADfPScMiUnBJKZajIBkEMkwUcqsfh630jyBvLPE/kyQcxbEeGtbu1DG3monkeymanOBW1AKc5o+cJLXcInLnbowMG7NXzujT3BRYn/9s5vtT1V9cuZJs4XLRXQ50NluxJI7sVfRPVvQI9EMbTS4AFBXUej3yfgaLSV+nPZC/lmJ2gR4t/tKvMFF9m16f8IcZKK7o0rK7v81G/tREbOT5YhcKLK+0wBfR6RsmHzwy4EddZloyLQ==' + } + end + + it { should_not contain_file('sshd_config').with_content(/^\s*ListenAddress/) } + end + + + context 'when set to an invalid type (not string or array)' do + let :facts do + { + :fqdn => 'monkey.example.com', + :osfamily => 'RedHat', + :root_home => '/root', + :sshrsakey => 'AAAAB3NzaC1yc2EAAAABIwAAAQEArGElx46pD6NNnlxVaTbp0ZJMgBKCmbTCT3RaeCk0ZUJtQ8wkcwTtqIXmmiuFsynUT0DFSd8UIodnBOPqitimmooAVAiAi30TtJVzADfPScMiUnBJKZajIBkEMkwUcqsfh630jyBvLPE/kyQcxbEeGtbu1DG3monkeymanOBW1AKc5o+cJLXcInLnbowMG7NXzujT3BRYn/9s5vtT1V9cuZJs4XLRXQ50NluxJI7sVfRPVvQI9EMbTS4AFBXUej3yfgaLSV+nPZC/lmJ2gR4t/tKvMFF9m16f8IcZKK7o0rK7v81G/tREbOT5YhcKLK+0wBfR6RsmHzwy4EddZloyLQ==' + } + end + let (:params) {{'sshd_listen_address' => true }} + + it 'should fail' do + expect { subject }.to raise_error(Puppet::Error) + end + end + end + describe 'sshd_loglevel param' do context 'when set to an invalid value' do let :facts do diff --git a/templates/sshd_config.erb b/templates/sshd_config.erb index 0acebdd..7e04039 100644 --- a/templates/sshd_config.erb +++ b/templates/sshd_config.erb @@ -18,8 +18,13 @@ Port <%= @sshd_config_port %> #Protocol 2,1 Protocol 2 #AddressFamily any -#ListenAddress 0.0.0.0 -#ListenAddress :: +<% if @sshd_listen_address.class == Array -%> +<% @sshd_listen_address.each do |val| -%> +ListenAddress <%= val %> +<% end -%> +<% elsif @sshd_listen_address.class == String -%> +ListenAddress <%= @sshd_listen_address %> +<% end -%> # HostKey for protocol version 1 #HostKey /etc/ssh/ssh_host_key