Merge pull request #240 from dhollinger/sshca

Add more SSH CA related fixes and paramaters
This commit is contained in:
Garrett Honeycutt 2017-07-24 16:21:25 -04:00 committed by GitHub
commit a9be160560
5 changed files with 181 additions and 131 deletions

View File

@ -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

View File

@ -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 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
@ -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

View File

@ -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)
@ -839,6 +845,9 @@ class ssh (
}
if $sshd_config_hostcertificate_real != undef {
if is_array($sshd_config_hostcertificate_real) {
validate_array($sshd_config_hostcertificate_real)
}
validate_absolute_path($sshd_config_hostcertificate_real)
}
@ -849,6 +858,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,

View File

@ -1068,26 +1068,48 @@ 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
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::Error,/"invalid" is not an absolute path/)
it 'should fail' do
expect {
should contain_class('ssh')
}.to raise_error(Puppet::Error,/"invalid" is not an absolute path/)
end
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

View File

@ -263,9 +263,16 @@ 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 %>
<% end -%>
<% if @sshd_config_authorized_principals_file_real -%>
AuthorizedPrincipalsFile <%= @sshd_config_authorized_principals_file_real %>
<% end -%>