diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d04d2c..7f1d3d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,5 +2,12 @@ ## Development -## 0.1.0 -Initial release +## v0.1.1 (2021-01-15) +* Fixed bug in client install where /etc/nsswitch.conf was declared twice for file_line + Contributed by Nick Maludy (@nmaludy) + +* Fixed/added ciphers for RHEL/CentOS 8. Also allowed ciphers to be passed in empty for debugging. + Contributed by Nick Maludy (@nmaludy) + +## v0.1.0 (2021-01-14) +* Initial release diff --git a/README.md b/README.md index 210bb7b..487776d 100644 --- a/README.md +++ b/README.md @@ -163,6 +163,64 @@ If true, then the parameter '--no-ui-redirect' is passed to the IPA server insta #### `realm` The name of the IPA realm to create or join (UPPERCASE). +### Cipher hardening on CentOS/RHEL 8 + +**NOTE:** These settings are automatically applied inside of `ipa::params`, +they are documented here as a reference. + +```puppet + # IPA on RHEL/CentOS 8 switched to mod_ssl, away from mod_nss + # mod_ssl in RHEL/CentOS 8 uses the "system" cryto policy for its ciphers and protocols + # see: + # https://www.redhat.com/en/blog/how-customize-crypto-policies-rhel-82 + # https://access.redhat.com/articles/3642912 + # https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/security_hardening/using-the-system-wide-cryptographic-policies_security-hardening + $nss_ssl_ciphers = [] + $nss_ssl_protocols = [] + + $ds_ssl_ciphers = [ + # TLS 1.2 + '+TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256', + '+TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384', + '+TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256', + '+TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384', + # TLS 1.3 + '+TLS_AES_128_GCM_SHA256', + '+TLS_AES_256_GCM_SHA384', + '+TLS_CHACHA20_POLY1305_SHA256', + ] + $ds_ssl_min_version = 'TLS1.2' + + # Dogtag PKI Tomcat + # you _must_ set both the TLS 1.2 and 1.3 ciphers here though, otherwise you'll get an error + # when registering your clients: + # Joining realm failed: HTTP POST to URL 'https://freeipa.maludy.home:443/ipa/xml' failed. libcurl failed even to execute the HTTP transaction, explaining: SSL certificate problem: EE certificate key too weak + $pki_ssl_ciphers = [ + # TLS 1.2 + '+TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256', + '+TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384', + '+TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256', + '+TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384', + # TLS 1.3 + '+TLS_AES_128_GCM_SHA256', + '+TLS_AES_256_GCM_SHA384', + '+TLS_CHACHA20_POLY1305_SHA256', + ] + # PKI Tomcat doesn't, yet, support tls1_3 protocol, so leave it to 1.2 + # if you try to set it to tls1_2:tls1_3 pki-tomcatd@pki-tomcat.service service will fail to start + $pki_ssl_protocol_range = 'tls1_2:tls1_2' + + class { 'ipa': + ipa_role => 'master', + # nss ciphers and protocols not used in CentOS 8 + nss_ssl_ciphers => $nss_ssl_ciphers, + nss_ssl_protocols => $nss_ssl_protocols, + ds_ssl_ciphers => $ds_ssl_ciphers, + ds_ssl_min_version => $ds_ssl_min_version, + pki_ssl_ciphers => $pki_ssl_ciphers, + pki_ssl_protocol_range => $pki_ssl_protocol_range, + } +``` ## Limitations diff --git a/manifests/init.pp b/manifests/init.pp index f46f7af..c444125 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -194,13 +194,8 @@ Array[String] $custom_dns_forwarders = [], String $sssd_debug_level = '3', String $ds_password = '', - Array[String] $ds_ssl_ciphers = [ - '+TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256', - '+TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384', - '+TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256', - '+TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384', - ], - Enum['TLS1.0','TLS1.1','TLS1.2'] $ds_ssl_min_version = 'TLS1.2', + Optional[Array[String]] $ds_ssl_ciphers = $ipa::params::ds_ssl_ciphers, + Optional[Enum['', 'TLS1.0','TLS1.1','TLS1.2', 'TLS1.3']] $ds_ssl_min_version = $ipa::params::ds_ssl_min_version, String $domain = '', String $domain_join_password = '', String $domain_join_principal = '', @@ -224,23 +219,11 @@ Boolean $mkhomedir = false, Boolean $no_dnssec_validation = false, Boolean $no_ui_redirect = false, - Optional[Array[String]] $nss_ssl_ciphers = [ - '+ecdhe_ecdsa_aes_128_gcm_sha_256', - '+ecdhe_ecdsa_aes_256_gcm_sha_384', - '+ecdhe_ecdsa_chacha20_poly1305_sha_256', - '+ecdhe_rsa_aes_128_gcm_sha_256', - '+ecdhe_rsa_aes_256_gcm_sha_384', - '+ecdhe_rsa_chacha20_poly1305_sha_256', - ], - Optional[Array[String]] $nss_ssl_protocols = ['TLSv1.2'], + Optional[Array[String]] $nss_ssl_ciphers = $ipa::params::nss_ssl_ciphers, + Optional[Array[String]] $nss_ssl_protocols = $ipa::params::nss_ssl_protocols, Optional[String] $override_homedir = undef, - Optional[Array[String]] $pki_ssl_ciphers = [ - '+TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256', - '+TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384', - '+TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256', - '+TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384', - ], - Optional[String] $pki_ssl_protocol_range = 'tls1_2:tls1_2', + Optional[Array[String]] $pki_ssl_ciphers = $ipa::params::pki_ssl_ciphers, + Optional[String] $pki_ssl_protocol_range = $ipa::params::pki_ssl_protocol_range, String $realm = '', Boolean $server_install_ldaputils = true, Array[String] $sssd_services = ['nss','sudo','pam','ssh','autofs'], diff --git a/manifests/install/client.pp b/manifests/install/client.pp index 4f11b98..abf129f 100644 --- a/manifests/install/client.pp +++ b/manifests/install/client.pp @@ -107,7 +107,7 @@ } # Update nsswitch if autofs enabled. - ~> file_line { '/etc/nsswitch.conf': + ~> file_line { '/etc/nsswitch.conf_automount': path => '/etc/nsswitch.conf', line => 'automount: files sss', match => '^automount: ', @@ -116,7 +116,7 @@ } # Update nsswitch with sudoers config - file_line { '/etc/nsswitch.conf': + file_line { '/etc/nsswitch.conf_sudoers': path => '/etc/nsswitch.conf', line => 'sudoers: files sss', match => '^sudoers: ', diff --git a/manifests/install/server/dirsrv.pp b/manifests/install/server/dirsrv.pp index bdd5b5c..192d982 100644 --- a/manifests/install/server/dirsrv.pp +++ b/manifests/install/server/dirsrv.pp @@ -1,8 +1,8 @@ # Private class to manage IPA directory services class ipa::install::server::dirsrv ( String $admin_password = $ipa::admin_password, - Array[String] $ds_ssl_ciphers = $ipa::ds_ssl_ciphers, - String $ds_ssl_min_version = $ipa::ds_ssl_min_version, + Optional[Array[String]] $ds_ssl_ciphers = $ipa::ds_ssl_ciphers, + Optional[String] $ds_ssl_min_version = $ipa::ds_ssl_min_version, String $ds_password = $ipa::ds_password, String $ipa_realm = $ipa::final_realm, ) inherits ipa { @@ -17,62 +17,65 @@ $_ipa_realm_dash = regsubst($ipa_realm, '\.', '-', 'G') ## Idempotent check for change - $chk_ds_ssl_protocols = @("EOC") - grep -q 'sslVersionMin: ${ds_ssl_min_version}' \ - /etc/dirsrv/slapd-${_ipa_realm_dash}/dse.ldif - | EOC + if $ds_ssl_min_version and !$ds_ssl_min_version.empty() { + $chk_ds_ssl_protocols = @("EOC") + grep -q 'sslVersionMin: ${ds_ssl_min_version}' \ + /etc/dirsrv/slapd-${_ipa_realm_dash}/dse.ldif + | EOC - ## dirsrv command to modify 'sslVersionMin' parameter - $configure_ds_ssl_protocols = @("EOC") - ldapmodify -h localhost -p 389 -D 'cn=directory manager' -w '${_ds_password}' << EOF - dn: cn=encryption,cn=config - changeType: modify - replace: sslVersionMin - sslVersionMin: ${ds_ssl_min_version} - EOF - | EOC + ## dirsrv command to modify 'sslVersionMin' parameter + $configure_ds_ssl_protocols = @("EOC") + ldapmodify -h localhost -p 389 -D 'cn=directory manager' -w '${_ds_password}' << EOF + dn: cn=encryption,cn=config + changeType: modify + replace: sslVersionMin + sslVersionMin: ${ds_ssl_min_version} + EOF + | EOC - ## Configure DS SSL minimum version - exec { 'ds_ssl_config': - command => $configure_ds_ssl_protocols, - path => '/bin', - unless => $chk_ds_ssl_protocols, - notify => Service["dirsrv@${_ipa_realm_dash}"], + ## Configure DS SSL minimum version + exec { 'ds_ssl_config': + command => $configure_ds_ssl_protocols, + path => '/bin', + unless => $chk_ds_ssl_protocols, + notify => Service["dirsrv@${_ipa_realm_dash}"], + } } - ## Harden SSL/TLS ciphers for dirsrv # # Reference: # https://directory.fedoraproject.org/docs/389ds/design/nss-cipher-design.html - $ds_ssl_ciphers_str = $ds_ssl_ciphers.join(',') + if $ds_ssl_ciphers and !$ds_ssl_ciphers.empty() { + $ds_ssl_ciphers_str = $ds_ssl_ciphers.join(',') - ## Idempotent check for change - ### -LLL : supresses a lot of verbose output - ### -o ldif-wrap=no : Turns off line wrapping on the results so we can grep - ### the full cipher suite string in one go. - $chk_ds_ssl_ciphers = @("EOC") - ldapsearch -LLL -o ldif-wrap=no -h localhost -p 389 -D 'cn=directory manager' \ - -w '${_ds_password}' -b "cn=encryption,cn=config" 'nsSSL3Ciphers' \ - | grep -q 'nsSSL3Ciphers: ${ds_ssl_ciphers_str}' - | EOC + ## Idempotent check for change + ### -LLL : supresses a lot of verbose output + ### -o ldif-wrap=no : Turns off line wrapping on the results so we can grep + ### the full cipher suite string in one go. + $chk_ds_ssl_ciphers = @("EOC") + ldapsearch -LLL -o ldif-wrap=no -h localhost -p 389 -D 'cn=directory manager' \ + -w '${_ds_password}' -b "cn=encryption,cn=config" 'nsSSL3Ciphers' \ + | grep -q 'nsSSL3Ciphers: ${ds_ssl_ciphers_str}' + | EOC - ## dirsrv command to modify 'nsSSL3Ciphers' parameter - $configure_ds_ssl_ciphers = @("EOC") - ldapmodify -h localhost -p 389 -D 'cn=directory manager' -w '${_ds_password}' << EOF - dn: cn=encryption,cn=config - changeType: modify - replace: nsSSL3Ciphers - nsSSL3Ciphers: ${ds_ssl_ciphers_str} - EOF - | EOC + ## dirsrv command to modify 'nsSSL3Ciphers' parameter + $configure_ds_ssl_ciphers = @("EOC") + ldapmodify -h localhost -p 389 -D 'cn=directory manager' -w '${_ds_password}' << EOF + dn: cn=encryption,cn=config + changeType: modify + replace: nsSSL3Ciphers + nsSSL3Ciphers: ${ds_ssl_ciphers_str} + EOF + | EOC - ## Configure DS SSL minimum version - exec { 'ds_ssl_ciphers': - command => $configure_ds_ssl_ciphers, - path => '/bin', - unless => $chk_ds_ssl_ciphers, - notify => Service["dirsrv@${_ipa_realm_dash}"], + ## Configure DS SSL minimum version + exec { 'ds_ssl_ciphers': + command => $configure_ds_ssl_ciphers, + path => '/bin', + unless => $chk_ds_ssl_ciphers, + notify => Service["dirsrv@${_ipa_realm_dash}"], + } } ## Restart dirsrv if changed diff --git a/manifests/install/server/pki.pp b/manifests/install/server/pki.pp index 5f5acf0..b32e63e 100644 --- a/manifests/install/server/pki.pp +++ b/manifests/install/server/pki.pp @@ -1,12 +1,12 @@ # Private class to manage IPA PKI certificate server (Dogtag) class ipa::install::server::pki ( - String $ssl_protocol_range = $ipa::pki_ssl_protocol_range, + Optional[String] $ssl_protocol_range = $ipa::pki_ssl_protocol_range, Optional[Array[String]] $ssl_ciphers = $ipa::pki_ssl_ciphers, ) inherits ipa { $config_file = '/etc/pki/pki-tomcat/server.xml' # Setup PKI CA service (Dogtag) with secure SSL settings - if $ssl_protocol_range { + if $ssl_protocol_range and !$ssl_protocol_range.empty() { exec { '/etc/pki/pki-tomcat/server.xml:sslVersionRangeStream': command => "sed -i 's/sslVersionRangeStream=\"[^\"]*\"/sslVersionRangeStream=\"${ssl_protocol_range}\"/g' ${config_file}", path => ['/bin', '/sbin', '/usr/sbin'], @@ -21,7 +21,7 @@ } } - if $ssl_ciphers { + if $ssl_ciphers and !$ssl_ciphers.empty() { $ciphers = $ssl_ciphers.join(',') exec { '/etc/pki/pki-tomcat/server.xml:sslRangeCiphers': diff --git a/manifests/params.pp b/manifests/params.pp index 59905a5..3c826b1 100644 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -11,16 +11,92 @@ $autofs_service = 'autofs' $sssd_service = 'sssd' + $ds_ssl_min_version_tls12 = 'TLS1.2' + $ds_ssl_ciphers_tls12 = [ + '+TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256', + '+TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384', + '+TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256', + '+TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384', + ] + $ds_ssl_ciphers_tls13 = [ + '+TLS_AES_128_GCM_SHA256', + '+TLS_AES_256_GCM_SHA384', + '+TLS_CHACHA20_POLY1305_SHA256', + ] + $pki_ssl_ciphers_tls12 = $ds_ssl_ciphers_tls12 + $pki_ssl_ciphers_tls13 = $ds_ssl_ciphers_tls13 + $pki_ssl_protocol_range_tls12 = 'tls1_2:tls1_2' + + $nss_ssl_ciphers_tls12 = [ + '+ecdhe_ecdsa_aes_128_gcm_sha_256', + '+ecdhe_ecdsa_aes_256_gcm_sha_384', + '+ecdhe_ecdsa_chacha20_poly1305_sha_256', + '+ecdhe_rsa_aes_128_gcm_sha_256', + '+ecdhe_rsa_aes_256_gcm_sha_384', + '+ecdhe_rsa_chacha20_poly1305_sha_256', + ] + $nss_ssl_protocols_tls12 = ['TLSv1.2'] + case $facts['os']['family'] { 'RedHat': { case $facts['os']['release']['major'] { - /(7)/, /(8)/: { - $service_stop_epp = 'systemctl stop <%= $service %>' - $service_restart_epp = 'systemctl restart <%= $service %>' - } /(6)/: { $service_stop_epp = 'service <%= $service %> stop' $service_restart_epp = 'service <%= $service %> restart' + + $ds_ssl_ciphers = undef + $ds_ssl_min_version = undef + $nss_ssl_ciphers = undef + $nss_ssl_protocols = undef + $pki_ssl_ciphers = undef + $pki_ssl_protocol_range = undef + } + /(7)/: { + $service_stop_epp = 'systemctl stop <%= $service %>' + $service_restart_epp = 'systemctl restart <%= $service %>' + + $ds_ssl_ciphers = $ds_ssl_ciphers_tls12 + $ds_ssl_min_version = $ds_ssl_min_version_tls12 + $nss_ssl_ciphers = $nss_ssl_ciphers_tls12 + $nss_ssl_protocols = $nss_ssl_protocols_tls12 + $pki_ssl_ciphers = $pki_ssl_ciphers_tls12 + $pki_ssl_protocol_range = $pki_ssl_protocol_range_tls12 + } + /(8)/: { + $service_stop_epp = 'systemctl stop <%= $service %>' + $service_restart_epp = 'systemctl restart <%= $service %>' + + # dirsrv allows for TLS 1.2 and 1.3 + # note: if you don't have TLS 1.3 enabled, you'll get an SSL error when trying to register clients: + # Joining realm failed: Unable to initialize STARTTLS session + # Connect error: error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure + # Failed to bind to server! + # Retrying with pre-4.0 keytab retrieval method... + # Unable to initialize STARTTLS session + # Connect error: error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure + # Failed to bind to server! + # Failed to get keytab + # child exited with 9 + $ds_ssl_ciphers = $ds_ssl_ciphers_tls12 + $ds_ssl_ciphers_tls13 + $ds_ssl_min_version = $ds_ssl_min_version_tls12 + + # IPA on RHEL/CentOS 8 switched to mod_ssl, away from mod_nss + # mod_ssl in RHEL/CentOS 8 uses the "system" cryto policy for its ciphers and protocols + # see: + # https://www.redhat.com/en/blog/how-customize-crypto-policies-rhel-82 + # https://access.redhat.com/articles/3642912 + # https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/security_hardening/using-the-system-wide-cryptographic-policies_security-hardening + $nss_ssl_ciphers = [] + $nss_ssl_protocols = [] + + # Dogtag PKI Tomcat + # you _must_ set both the TLS 1.2 and 1.3 ciphers here though, otherwise you'll get an error + # when registering your clients: + # Joining realm failed: HTTP POST to URL 'https://freeipa.maludy.home:443/ipa/xml' failed. libcurl failed even to execute the HTTP transaction, explaining: SSL certificate problem: EE certificate key too weak + $pki_ssl_ciphers = $pki_ssl_ciphers_tls12 + $pki_ssl_ciphers_tls13 + # PKI Tomcat doesn't, yet, support tls1_3 protocol, so leave it to 1.2 + # if you try to set it to tls1_2:tls1_3 pki-tomcatd@pki-tomcat.service service will fail to start + $pki_ssl_protocol_range = $pki_ssl_protocol_range_tls12 } default: { fail("ERROR: Unsupported RHEL version: ${facts['os']['full']}") } } @@ -33,6 +109,13 @@ /(16.04)/: { $service_stop_epp = 'systemctl stop <%= $service %>' $service_restart_epp = 'systemctl restart <%= $service %>' + + $ds_ssl_ciphers = undef + $ds_ssl_min_version = undef + $nss_ssl_ciphers = undef + $nss_ssl_protocols = undef + $pki_ssl_ciphers = undef + $pki_ssl_protocol_range = undef } default: { fail("ERROR: Unsupported Ubuntu version: ${facts['os']['full']}") } } diff --git a/metadata.json b/metadata.json index a6db722..dbb6136 100644 --- a/metadata.json +++ b/metadata.json @@ -1,6 +1,6 @@ { "name": "encore-ipa", - "version": "0.1.0", + "version": "0.1.1", "author": "Encore Technologies", "summary": "Manages IPA servers and clients.", "license": "Apache-2.0",