From ec5141de8459bcb46e6f038f8b85facdc40aad81 Mon Sep 17 00:00:00 2001 From: David Hollinger Date: Fri, 21 Jul 2017 10:00:03 -0500 Subject: [PATCH 1/6] Update HostCertificate to take an array of certs --- manifests/init.pp | 1 + spec/classes/init_spec.rb | 26 ++++++++++++++++---------- templates/sshd_config.erb | 4 +++- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/manifests/init.pp b/manifests/init.pp index eee805e..83c38a2 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -839,6 +839,7 @@ class ssh ( } if $sshd_config_hostcertificate_real != undef { + validate_array($sshd_config_hostcertificate_real) validate_absolute_path($sshd_config_hostcertificate_real) } diff --git a/spec/classes/init_spec.rb b/spec/classes/init_spec.rb index aa2270d..76868b2 100644 --- a/spec/classes/init_spec.rb +++ b/spec/classes/init_spec.rb @@ -1068,16 +1068,22 @@ describe 'sshd_config_print_last_log param' do end describe 'sshd_config_hostcertificate param' do - ['unset', '/etc/ssh/ssh_host_key-cert.pub'].each do |value| - context "set to #{value}" do - let (:params) { { :sshd_config_hostcertificate => value } } + context 'unset value' do + let(:params) { { :sshd_config_hostcertificate => 'unset' } } - if value == 'unset' - it { should contain_file('sshd_config').without_content(/^\s*HostCertificate/) } - else - it { should contain_file('sshd_config').with_content(/^HostCertificate #{value}/) } - end - end + it { should contain_file('sshd_config').without_content(/^\s*HostCertificate/) } + end + + context 'with a certificate' do + let(:params) { { :sshd_config_hostcertificate => ['/etc/ssh/ssh_host_key-cert.pub'] } } + + it { should contain_file('sshd_config').with_content(/^HostCertificate \/etc\/ssh\/ssh_host_key-cert\.pub/) } + end + + context 'with multiple certs' do + let(:params) { { :sshd_config_hostcertificate => [ '/etc/ssh/ssh_host_key-cert.pub', '/etc/ssh/ssh_host_key-cert2.pub'] } } + + it { should contain_file('sshd_config').with_content(/^HostCertificate \/etc\/ssh\/ssh_host_key-cert\.pub\nHostCertificate \/etc\/ssh\/ssh_host_key-cert2\.pub/)} end end @@ -1087,7 +1093,7 @@ describe 'sshd_config_print_last_log param' do it 'should fail' do expect { should contain_class('ssh') - }.to raise_error(Puppet::Error,/"invalid" is not an absolute path/) + }.to raise_error(Puppet::PreformattedError,/"invalid" is not an Array/) end end diff --git a/templates/sshd_config.erb b/templates/sshd_config.erb index 4e06f40..e88b27b 100644 --- a/templates/sshd_config.erb +++ b/templates/sshd_config.erb @@ -264,7 +264,9 @@ Match <%= key %> <% end -%> <% end -%> <% if @sshd_config_hostcertificate_real -%> -HostCertificate <%= @sshd_config_hostcertificate_real %> +<% @sshd_config_hostcertificate_real.each do |cert| -%> +HostCertificate <%= cert %> +<% end -%> <% end -%> <% if @sshd_config_trustedusercakeys_real -%> TrustedUserCAKeys <%= @sshd_config_trustedusercakeys_real %> From 717a237cc0b0e11e901b488df5d087dfeb1f2326 Mon Sep 17 00:00:00 2001 From: David Hollinger Date: Fri, 21 Jul 2017 16:47:19 -0500 Subject: [PATCH 2/6] Add parameter to set AuthorizedPrincipalsFile setting --- manifests/init.pp | 238 ++++++++++++++++++++------------------ spec/classes/init_spec.rb | 14 +++ templates/sshd_config.erb | 3 + 3 files changed, 141 insertions(+), 114 deletions(-) diff --git a/manifests/init.pp b/manifests/init.pp index 83c38a2..e15e608 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -3,120 +3,121 @@ # Manage ssh client and server # class ssh ( - $hiera_merge = false, - $packages = 'USE_DEFAULTS', - $permit_root_login = 'yes', - $purge_keys = true, - $manage_firewall = false, - $ssh_package_source = 'USE_DEFAULTS', - $ssh_package_adminfile = 'USE_DEFAULTS', - $ssh_config_hash_known_hosts = 'USE_DEFAULTS', - $ssh_config_path = '/etc/ssh/ssh_config', - $ssh_config_owner = 'root', - $ssh_config_group = 'root', - $ssh_config_mode = '0644', - $ssh_config_forward_x11 = undef, - $ssh_config_forward_x11_trusted = 'USE_DEFAULTS', - $ssh_config_forward_agent = undef, - $ssh_config_server_alive_interval = undef, - $ssh_config_sendenv_xmodifiers = false, - $ssh_hostbasedauthentication = undef, - $ssh_config_proxy_command = undef, - $ssh_strict_host_key_checking = undef, - $ssh_config_ciphers = undef, - $ssh_config_kexalgorithms = undef, - $ssh_config_macs = undef, - $ssh_config_use_roaming = 'USE_DEFAULTS', - $ssh_config_template = 'ssh/ssh_config.erb', - $ssh_sendenv = 'USE_DEFAULTS', - $ssh_gssapiauthentication = 'yes', - $ssh_gssapidelegatecredentials = undef, - $sshd_config_path = '/etc/ssh/sshd_config', - $sshd_config_owner = 'root', - $sshd_config_group = 'root', - $sshd_config_loglevel = 'INFO', - $sshd_config_mode = 'USE_DEFAULTS', - $sshd_config_permitemptypasswords = undef, - $sshd_config_permituserenvironment = undef, - $sshd_config_compression = undef, - $sshd_config_port = '22', - $sshd_config_syslog_facility = 'AUTH', - $sshd_config_template = 'ssh/sshd_config.erb', - $sshd_config_login_grace_time = '120', - $sshd_config_challenge_resp_auth = 'yes', - $sshd_config_print_motd = 'yes', - $sshd_config_print_last_log = undef, - $sshd_config_use_dns = 'USE_DEFAULTS', - $sshd_config_authkey_location = undef, - $sshd_config_strictmodes = undef, - $sshd_config_serverkeybits = 'USE_DEFAULTS', - $sshd_config_banner = 'none', - $sshd_config_ciphers = undef, - $sshd_config_kexalgorithms = undef, - $sshd_config_macs = undef, - $ssh_enable_ssh_keysign = undef, - $sshd_config_allowgroups = [], - $sshd_config_allowusers = [], - $sshd_config_denygroups = [], - $sshd_config_denyusers = [], - $sshd_config_maxauthtries = undef, - $sshd_config_maxstartups = undef, - $sshd_config_maxsessions = undef, - $sshd_config_chrootdirectory = undef, - $sshd_config_forcecommand = undef, - $sshd_config_match = undef, - $sshd_authorized_keys_command = undef, - $sshd_authorized_keys_command_user = undef, - $sshd_banner_content = undef, - $sshd_banner_owner = 'root', - $sshd_banner_group = 'root', - $sshd_banner_mode = '0644', - $sshd_config_xauth_location = 'USE_DEFAULTS', - $sshd_config_subsystem_sftp = 'USE_DEFAULTS', - $sshd_kerberos_authentication = undef, - $sshd_password_authentication = 'yes', - $sshd_allow_tcp_forwarding = 'yes', - $sshd_x11_forwarding = 'yes', - $sshd_x11_use_localhost = 'yes', - $sshd_use_pam = 'USE_DEFAULTS', - $sshd_client_alive_count_max = '3', - $sshd_client_alive_interval = '0', - $sshd_gssapiauthentication = 'yes', - $sshd_gssapikeyexchange = 'USE_DEFAULTS', - $sshd_pamauthenticationviakbdint = 'USE_DEFAULTS', - $sshd_gssapicleanupcredentials = 'USE_DEFAULTS', - $sshd_acceptenv = 'USE_DEFAULTS', - $sshd_config_hostkey = 'USE_DEFAULTS', - $sshd_listen_address = undef, - $sshd_hostbasedauthentication = 'no', - $sshd_pubkeyacceptedkeytypes = undef, - $sshd_pubkeyauthentication = 'yes', - $sshd_ignoreuserknownhosts = 'no', - $sshd_ignorerhosts = 'yes', - $manage_service = true, - $sshd_addressfamily = 'USE_DEFAULTS', - $service_ensure = 'running', - $service_name = 'USE_DEFAULTS', - $service_enable = true, - $service_hasrestart = true, - $service_hasstatus = 'USE_DEFAULTS', - $ssh_key_ensure = 'present', - $ssh_key_import = true, - $ssh_key_type = 'ssh-rsa', - $ssh_config_global_known_hosts_file = '/etc/ssh/ssh_known_hosts', - $ssh_config_global_known_hosts_list = undef, - $ssh_config_global_known_hosts_owner = 'root', - $ssh_config_global_known_hosts_group = 'root', - $ssh_config_global_known_hosts_mode = '0644', - $ssh_config_user_known_hosts_file = undef, - $keys = undef, - $manage_root_ssh_config = false, - $root_ssh_config_content = "# This file is being maintained by Puppet.\n# DO NOT EDIT\n", - $sshd_config_tcp_keepalive = undef, - $sshd_config_use_privilege_separation = undef, - $sshd_config_permittunnel = undef, - $sshd_config_hostcertificate = undef, - $sshd_config_trustedusercakeys = undef, + $hiera_merge = false, + $packages = 'USE_DEFAULTS', + $permit_root_login = 'yes', + $purge_keys = true, + $manage_firewall = false, + $ssh_package_source = 'USE_DEFAULTS', + $ssh_package_adminfile = 'USE_DEFAULTS', + $ssh_config_hash_known_hosts = 'USE_DEFAULTS', + $ssh_config_path = '/etc/ssh/ssh_config', + $ssh_config_owner = 'root', + $ssh_config_group = 'root', + $ssh_config_mode = '0644', + $ssh_config_forward_x11 = undef, + $ssh_config_forward_x11_trusted = 'USE_DEFAULTS', + $ssh_config_forward_agent = undef, + $ssh_config_server_alive_interval = undef, + $ssh_config_sendenv_xmodifiers = false, + $ssh_hostbasedauthentication = undef, + $ssh_config_proxy_command = undef, + $ssh_strict_host_key_checking = undef, + $ssh_config_ciphers = undef, + $ssh_config_kexalgorithms = undef, + $ssh_config_macs = undef, + $ssh_config_use_roaming = 'USE_DEFAULTS', + $ssh_config_template = 'ssh/ssh_config.erb', + $ssh_sendenv = 'USE_DEFAULTS', + $ssh_gssapiauthentication = 'yes', + $ssh_gssapidelegatecredentials = undef, + $sshd_config_path = '/etc/ssh/sshd_config', + $sshd_config_owner = 'root', + $sshd_config_group = 'root', + $sshd_config_loglevel = 'INFO', + $sshd_config_mode = 'USE_DEFAULTS', + $sshd_config_permitemptypasswords = undef, + $sshd_config_permituserenvironment = undef, + $sshd_config_compression = undef, + $sshd_config_port = '22', + $sshd_config_syslog_facility = 'AUTH', + $sshd_config_template = 'ssh/sshd_config.erb', + $sshd_config_login_grace_time = '120', + $sshd_config_challenge_resp_auth = 'yes', + $sshd_config_print_motd = 'yes', + $sshd_config_print_last_log = undef, + $sshd_config_use_dns = 'USE_DEFAULTS', + $sshd_config_authkey_location = undef, + $sshd_config_strictmodes = undef, + $sshd_config_serverkeybits = 'USE_DEFAULTS', + $sshd_config_banner = 'none', + $sshd_config_ciphers = undef, + $sshd_config_kexalgorithms = undef, + $sshd_config_macs = undef, + $ssh_enable_ssh_keysign = undef, + $sshd_config_allowgroups = [], + $sshd_config_allowusers = [], + $sshd_config_denygroups = [], + $sshd_config_denyusers = [], + $sshd_config_maxauthtries = undef, + $sshd_config_maxstartups = undef, + $sshd_config_maxsessions = undef, + $sshd_config_chrootdirectory = undef, + $sshd_config_forcecommand = undef, + $sshd_config_match = undef, + $sshd_authorized_keys_command = undef, + $sshd_authorized_keys_command_user = undef, + $sshd_banner_content = undef, + $sshd_banner_owner = 'root', + $sshd_banner_group = 'root', + $sshd_banner_mode = '0644', + $sshd_config_xauth_location = 'USE_DEFAULTS', + $sshd_config_subsystem_sftp = 'USE_DEFAULTS', + $sshd_kerberos_authentication = undef, + $sshd_password_authentication = 'yes', + $sshd_allow_tcp_forwarding = 'yes', + $sshd_x11_forwarding = 'yes', + $sshd_x11_use_localhost = 'yes', + $sshd_use_pam = 'USE_DEFAULTS', + $sshd_client_alive_count_max = '3', + $sshd_client_alive_interval = '0', + $sshd_gssapiauthentication = 'yes', + $sshd_gssapikeyexchange = 'USE_DEFAULTS', + $sshd_pamauthenticationviakbdint = 'USE_DEFAULTS', + $sshd_gssapicleanupcredentials = 'USE_DEFAULTS', + $sshd_acceptenv = 'USE_DEFAULTS', + $sshd_config_hostkey = 'USE_DEFAULTS', + $sshd_listen_address = undef, + $sshd_hostbasedauthentication = 'no', + $sshd_pubkeyacceptedkeytypes = undef, + $sshd_pubkeyauthentication = 'yes', + $sshd_ignoreuserknownhosts = 'no', + $sshd_ignorerhosts = 'yes', + $manage_service = true, + $sshd_addressfamily = 'USE_DEFAULTS', + $service_ensure = 'running', + $service_name = 'USE_DEFAULTS', + $service_enable = true, + $service_hasrestart = true, + $service_hasstatus = 'USE_DEFAULTS', + $ssh_key_ensure = 'present', + $ssh_key_import = true, + $ssh_key_type = 'ssh-rsa', + $ssh_config_global_known_hosts_file = '/etc/ssh/ssh_known_hosts', + $ssh_config_global_known_hosts_list = undef, + $ssh_config_global_known_hosts_owner = 'root', + $ssh_config_global_known_hosts_group = 'root', + $ssh_config_global_known_hosts_mode = '0644', + $ssh_config_user_known_hosts_file = undef, + $keys = undef, + $manage_root_ssh_config = false, + $root_ssh_config_content = "# This file is being maintained by Puppet.\n# DO NOT EDIT\n", + $sshd_config_tcp_keepalive = undef, + $sshd_config_use_privilege_separation = undef, + $sshd_config_permittunnel = undef, + $sshd_config_hostcertificate = undef, + $sshd_config_trustedusercakeys = undef, + $sshd_config_authorized_principals_file = undef, ) { case $::osfamily { @@ -500,6 +501,11 @@ class ssh ( default: { $sshd_config_trustedusercakeys_real = $sshd_config_trustedusercakeys } } + case $sshd_config_authorized_principals_file { + 'unset', undef: { $sshd_config_authorized_principals_file_real = undef } + default: { $sshd_config_authorized_principals_file_real = $sshd_config_authorized_principals_file } + } + # validate params if $ssh_config_ciphers != undef { validate_array($ssh_config_ciphers) @@ -850,6 +856,10 @@ class ssh ( } } + if $sshd_config_authorized_principals_file_real != undef { + validate_string($sshd_config_authorized_principals_file_real) + } + package { $packages_real: ensure => installed, source => $ssh_package_source_real, diff --git a/spec/classes/init_spec.rb b/spec/classes/init_spec.rb index 76868b2..f224b85 100644 --- a/spec/classes/init_spec.rb +++ b/spec/classes/init_spec.rb @@ -1097,6 +1097,20 @@ describe 'sshd_config_print_last_log param' do end end + context 'with sshd_config_authorized_principals_file param' do + ['unset', '.ssh/authorized_principals'].each do |value| + context "set to #{value}" do + let (:params) { { :sshd_config_authorized_principals_file => value } } + + if value == 'unset' + it { should contain_file('sshd_config').without_content(/^\s*AuthorizedPrincipalsFile/)} + else + it { should contain_file('sshd_config').with_content(/^AuthorizedPrincipalsFile \.ssh\/authorized_principals/)} + end + end + end + end + describe 'sshd_config_trustedusercakeys param' do ['unset', '/etc/ssh/authorized_users_ca.pub', 'none'].each do |value| context "set to #{value}" do diff --git a/templates/sshd_config.erb b/templates/sshd_config.erb index e88b27b..0bc1881 100644 --- a/templates/sshd_config.erb +++ b/templates/sshd_config.erb @@ -271,3 +271,6 @@ HostCertificate <%= cert %> <% if @sshd_config_trustedusercakeys_real -%> TrustedUserCAKeys <%= @sshd_config_trustedusercakeys_real %> <% end -%> +<% if @sshd_config_authorized_principals_file_real -%> +AuthorizedPrincipalsFile <%= @sshd_config_authorized_principals_file_real %> +<% end -%> \ No newline at end of file From 50ddf070ed758f8a75da453a312d6a11f00b5822 Mon Sep 17 00:00:00 2001 From: David Hollinger Date: Fri, 21 Jul 2017 16:55:00 -0500 Subject: [PATCH 3/6] Update README --- README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 35a7a02..0a9709e 100644 --- a/README.md +++ b/README.md @@ -598,7 +598,7 @@ ssh::sshd_config_match: sshd_config_hostcertificate --------------------------- -Absolute path to the OpenSSH Host CA Certificate (HostCertificate) for use with SSH CA validation for Host Certificates. +An Array of Absolute Paths to the Host CA Public Key. Each entry *MUST* be tied 1:1 to a Host CA Private Key (see [sshd_config_hostkey](#sshd_config_hostkey)) - *Default*: undefined @@ -608,6 +608,14 @@ Absolute path to the OpenSSH User CA Certificate (TrustedUserCAKeys) for use wit - *Default*: undefined +sshd_config_authorized_principals_file +-------------------------------------- +String path (relative or absolute) to the `authorized_principals` file. Sets the `AuthorizedPrincipalsFile` setting in `sshd_config` + +See `sshd_config(5)` for more details + +- *Default*: undefined + keys ---- Hash of keys for user's ~/.ssh/authorized_keys From 0ac138213ed5a18a29d3f8d8cf9a8f25422f90e0 Mon Sep 17 00:00:00 2001 From: David Hollinger Date: Mon, 24 Jul 2017 14:25:34 -0500 Subject: [PATCH 4/6] Fix puppetversion check logic puppetversion was checking for puppet < '5.0' even if nil. This caused an error when attempting to run bundler commands. Added logic to check if puppetversion !nil and is < "5.0" --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 2ae20fb..f8bdb02 100644 --- a/Gemfile +++ b/Gemfile @@ -33,6 +33,6 @@ gem 'puppetlabs_spec_helper', '2.0.2', :require => false if RUBY_VERSION >= ' gem 'puppetlabs_spec_helper', '>= 2.0.0', :require => false if RUBY_VERSION >= '1.9' gem 'parallel_tests', '<= 2.9.0', :require => false if RUBY_VERSION < '2.0.0' -if puppetversion < '5.0' +if puppetversion && puppetversion < '5.0' gem 'semantic_puppet', :require => false end From 4cefc650697e913a59092ce2180907c1d72fb09c Mon Sep 17 00:00:00 2001 From: David Hollinger Date: Mon, 24 Jul 2017 14:26:57 -0500 Subject: [PATCH 5/6] Update hostcertificated to take both Strings and Arrays --- manifests/init.pp | 4 +++- spec/classes/init_spec.rb | 14 ++++++++------ templates/sshd_config.erb | 4 +++- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/manifests/init.pp b/manifests/init.pp index e15e608..5f6a972 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -845,7 +845,9 @@ class ssh ( } if $sshd_config_hostcertificate_real != undef { - validate_array($sshd_config_hostcertificate_real) + if is_array($sshd_config_hostcertificate_real) { + validate_array($sshd_config_hostcertificate_real) + } validate_absolute_path($sshd_config_hostcertificate_real) } diff --git a/spec/classes/init_spec.rb b/spec/classes/init_spec.rb index f224b85..256d52c 100644 --- a/spec/classes/init_spec.rb +++ b/spec/classes/init_spec.rb @@ -1075,7 +1075,7 @@ describe 'sshd_config_print_last_log param' do end context 'with a certificate' do - let(:params) { { :sshd_config_hostcertificate => ['/etc/ssh/ssh_host_key-cert.pub'] } } + let(:params) { { :sshd_config_hostcertificate => '/etc/ssh/ssh_host_key-cert.pub' } } it { should contain_file('sshd_config').with_content(/^HostCertificate \/etc\/ssh\/ssh_host_key-cert\.pub/) } end @@ -1088,12 +1088,14 @@ describe 'sshd_config_print_last_log param' do end context 'with sshd_config_hostcertificate set to invalid value on valid osfamily' do - let(:params) { { :sshd_config_hostcertificate => 'invalid' } } + context 'with string' do + let(:params) { { :sshd_config_hostcertificate => 'invalid' } } - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::PreformattedError,/"invalid" is not an Array/) + it 'should fail' do + expect { + should contain_class('ssh') + }.to raise_error(Puppet::Error,/"invalid" is not an absolute path/) + end end end diff --git a/templates/sshd_config.erb b/templates/sshd_config.erb index 0bc1881..b3b9ca1 100644 --- a/templates/sshd_config.erb +++ b/templates/sshd_config.erb @@ -263,10 +263,12 @@ Match <%= key %> <% end -%> <% end -%> <% end -%> -<% if @sshd_config_hostcertificate_real -%> +<% if @sshd_config_hostcertificate_real.class == Array -%> <% @sshd_config_hostcertificate_real.each do |cert| -%> HostCertificate <%= cert %> <% end -%> +<% elsif @sshd_config_hostcertificate_real.class == String -%> +HostCertificate <%= @sshd_config_hostcertificate_real %> <% end -%> <% if @sshd_config_trustedusercakeys_real -%> TrustedUserCAKeys <%= @sshd_config_trustedusercakeys_real %> From 6f68aa6aba2ffe65bfc44e3f245696841bd7c754 Mon Sep 17 00:00:00 2001 From: David Hollinger Date: Mon, 24 Jul 2017 14:41:49 -0500 Subject: [PATCH 6/6] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0a9709e..605785c 100644 --- a/README.md +++ b/README.md @@ -598,7 +598,7 @@ ssh::sshd_config_match: sshd_config_hostcertificate --------------------------- -An Array of Absolute Paths to the Host CA Public Key. Each entry *MUST* be tied 1:1 to a Host CA Private Key (see [sshd_config_hostkey](#sshd_config_hostkey)) +An Absolute Path or Array of Absolute Paths to the Host CA Public Key. Each entry *MUST* be tied 1:1 to a Host CA Private Key (see [sshd_config_hostkey](#sshd_config_hostkey)) - *Default*: undefined