diff --git a/docs/source/advanced/security/ssl_config.rst b/docs/source/advanced/security/ssl_config.rst index fe640e06c..13ce9ac3a 100644 --- a/docs/source/advanced/security/ssl_config.rst +++ b/docs/source/advanced/security/ssl_config.rst @@ -1,28 +1,51 @@ -OpenSSL Configuration -===================== +TLS configuration +================= -xCAT does not ship OpenSSL RPMS nor does it statically link to any OpenSSL libraries. Communication between the xCAT client and daemon utilizes OpenSSL and the administrator can configure the SSL_version and SSL_cipher that should be used by xCAT daemons. +xCAT does not ship OpenSSL RPMs and does not statically link OpenSSL. xCAT client and daemon connections use TLS through the system OpenSSL library. Some site table attribute names still contain ``ssl`` for backward compatibility, but they configure TLS behavior. -The configuration is stored in the xCAT site table using the ``site.xcatsslversion`` and ``site.xcatsslciphers`` attributes. +Use these site table attributes to configure xCAT TLS behavior: -Configuration -------------- +* ``site.xcattlspolicy`` +* ``site.xcatsslversion`` +* ``site.xcatsslciphers`` -``site.xcatsslversion`` is the ``SSL_version`` option used by ``xcatd`` and passed to ``IO::Socket::SSL->start_SSL()``. See https://metacpan.org/pod/IO::Socket::SSL for more information. By default, xCAT ships with an empty value for ``site.xcatsslversion``. In this case, ``xcatd`` will use ``SSLv23:!SSLv2:!SSLv3:!TLSv1`` internally. +Protocol policy +--------------- -Here is an example of changing ``site.xcatsslversion`` to a different value, ``TLSv1_2``, for example. :: +``site.xcattlspolicy`` controls the default xCAT TLS protocol policy when ``site.xcatsslversion`` is empty. + +The default policy is ``modern``. It permits TLS 1.2 and newer. Internally, ``xcatd`` passes this value to ``IO::Socket::SSL``: :: + + SSLv23:!SSLv2:!SSLv3:!TLSv1:!TLSv1_1 + +The ``SSLv23`` token is legacy OpenSSL naming for a version-flexible handshake. It does not mean that SSLv2 or SSLv3 are allowed. The exclusions determine which protocols can be negotiated. + +Use ``legacy`` only when older nodes or service nodes cannot negotiate TLS 1.2, for example EL6 and older, SLES 11 and older, or Ubuntu 12.04 and older. The legacy policy allows TLS 1.0 and newer while still disabling SSLv2 and SSLv3: :: + + chtab key=xcattlspolicy site.value=legacy + +Administrator overrides +----------------------- + +``site.xcatsslversion`` overrides the ``SSL_version`` option that ``xcatd`` passes to ``IO::Socket::SSL->start_SSL()``. Most sites should leave it empty and use ``site.xcattlspolicy`` instead. If this value is non-empty, it takes precedence over ``site.xcattlspolicy``. See https://metacpan.org/pod/IO::Socket::SSL for the accepted syntax. + +To force the ``IO::Socket::SSL`` setting to ``TLSv1_2``: :: chtab key=xcatsslversion site.value=TLSv1_2 -If running > ``TLSv1``, it is possible to disable insecure ciphers. Here's an example of one possible configuration: :: +``site.xcatsslciphers`` is an administrator override for the TLS cipher list. By default, leave it empty so xCAT uses the OpenSSL library defaults. If a local security policy requires an explicit cipher list, here is an example of one possible configuration: :: "xcatsslciphers","kDH:kEDH:kRSA:!SSLv3:!SSLv2:!aNULL:!eNULL:!MEDIUM:!LOW:!MD5:!EXPORT:!CAMELLIA:!ECDH",, After making any changes to these configuration values, ``xcatd`` must be restarted: :: - service restart xcatd + systemctl restart xcatd -If any mistakes have been made and communication is lost to xCAT, use ``XCATBYPASS`` to fix the bad configuration: :: +On non-systemd systems, use: :: + + service xcatd restart + +If a bad TLS value blocks xCAT client connections, use ``XCATBYPASS`` to edit the site table locally: :: XCATBYPASS=1 tabedit site @@ -30,13 +53,15 @@ If any mistakes have been made and communication is lost to xCAT, use ``XCATBYPA Validation ---------- -Use the ``openssl`` command to validate the SSL configuration is valid and expected. +Use ``openssl`` to check what ``xcatd`` will negotiate. -* To check whether TLSv1 is supported by xcatd: :: +* To check that the default modern policy rejects TLSv1: :: openssl s_client -connect 127.0.0.1:3001 -tls1 -* To check if SSLv3 is disabled on ``xcatd``: :: + The handshake should fail unless ``site.xcattlspolicy`` is set to ``legacy`` or ``site.xcatsslversion`` explicitly allows TLSv1. + +* To check that ``xcatd`` rejects SSLv3: :: openssl s_client -connect localhost:3001 -ssl3 diff --git a/docs/source/guides/admin-guides/basic_concepts/global_cfg/index.rst b/docs/source/guides/admin-guides/basic_concepts/global_cfg/index.rst index 5101f8cf0..bdbd679e9 100644 --- a/docs/source/guides/admin-guides/basic_concepts/global_cfg/index.rst +++ b/docs/source/guides/admin-guides/basic_concepts/global_cfg/index.rst @@ -130,11 +130,11 @@ xCAT Daemon attributes * xcatlport: The port used by xcatd command log writer process to collect command output. +* xcattlspolicy: + The TLS protocol policy used by xcatd when xcatsslversion is empty. Valid values are ``modern`` and ``legacy``. Default is ``modern``, which allows TLS 1.2 or newer. Use ``legacy`` only for older nodes or service nodes that cannot negotiate TLS 1.2. + * xcatsslversion: - The ssl version by xcatd. Default is ``SSLv3``. + Administrator override for the SSL_version option passed to IO::Socket::SSL by xcatd. Default is empty, which makes xcatd use xcattlspolicy. * xcatsslciphers: - The ssl cipher by xcatd. Default is ``3DES``. - - - + Administrator override for the TLS cipher list used by xcatd. Default is empty, which makes xcatd use the OpenSSL library defaults. diff --git a/docs/source/guides/admin-guides/references/man5/site.5.rst b/docs/source/guides/admin-guides/references/man5/site.5.rst index 0e37ed404..4d890f22f 100644 --- a/docs/source/guides/admin-guides/references/man5/site.5.rst +++ b/docs/source/guides/admin-guides/references/man5/site.5.rst @@ -473,13 +473,21 @@ site Attributes: xcatiport: The port used by xcatd to receive install status updates from nodes. xcatlport: The port used by xcatd command log writer process to collect command output. - - xcatsslversion: This is the SSL_version option xcatd used and passed to - IO::Socket::SSL->start_SSL(). By default, this value is set to empty. - In this case, xcatd will use SSLv23:!SSLv2:!SSLv3:!TLSv1 internally. - For more detail, see https://metacpan.org/pod/IO::Socket::SSL - - xcatsslciphers: The ssl cipher by xcatd. Default is 3DES. + + xcattlspolicy: The TLS protocol policy used by xcatd when xcatsslversion + is empty. Valid values are modern and legacy. The modern + policy is the default and allows TLS 1.2 or newer. The + legacy policy allows TLS 1.0 or newer for older nodes or + service nodes that cannot negotiate TLS 1.2. + + xcatsslversion: Administrator override for the SSL_version option xcatd + passes to IO::Socket::SSL->start_SSL(). By default, this + value is empty and xcatd uses xcattlspolicy. For more + detail, see https://metacpan.org/pod/IO::Socket::SSL + + xcatsslciphers: Administrator override for the TLS cipher list used by + xcatd. By default, this value is empty and xcatd uses the + OpenSSL library defaults. @@ -509,4 +517,3 @@ SEE ALSO \ **nodels(1)**\ , \ **chtab(8)**\ , \ **tabdump(8)**\ , \ **tabedit(8)**\ - diff --git a/perl-xCAT/xCAT/Schema.pm b/perl-xCAT/xCAT/Schema.pm index d03689218..10098ed31 100644 --- a/perl-xCAT/xCAT/Schema.pm +++ b/perl-xCAT/xCAT/Schema.pm @@ -1337,11 +1337,19 @@ passed as argument rather than by table value', " xcatdport: The port used by the xcatd daemon for client/server communication.\n\n" . " xcatiport: The port used by xcatd to receive install status updates from nodes.\n\n" . " xcatlport: The port used by xcatd command log writer process to collect command output.\n\n" . -" xcatsslversion: This is the SSL_version option xcatd used and passed to \n" . -" IO::Socket::SSL->start_SSL(). By default, this value is set to empty.\n" . -" In this case, xcatd will use SSLv23:!SSLv2:!SSLv3:!TLSv1 internally.\n" . -" For more detail, see https://metacpan.org/pod/IO::Socket::SSL\n\n" . -" xcatsslciphers: The ssl cipher by xcatd. Default is 3DES.\n\n", +" xcattlspolicy: The TLS protocol policy used by xcatd when xcatsslversion\n" . +" is empty. Valid values are modern and legacy. The modern\n" . +" policy is the default and allows TLS 1.2 or newer. The\n" . +" legacy policy allows TLS 1.0 or newer for older nodes or\n" . +" service nodes that cannot negotiate TLS 1.2.\n\n" . +" xcatsslversion: Administrator override for the SSL_version option xcatd\n" . +" passes to IO::Socket::SSL->start_SSL(). By default, this\n" . +" value is empty and xcatd uses xcattlspolicy. For more\n" . +" detail, see\n" . +" https://metacpan.org/pod/IO::Socket::SSL\n\n" . +" xcatsslciphers: Administrator override for the TLS cipher list used by\n" . +" xcatd. By default, this value is empty and xcatd uses the\n" . +" OpenSSL library defaults.\n\n", value => 'The value of the attribute specified in the "key" column.', comments => 'Any user-written notes.', disable => "Set to 'yes' or '1' to comment out this row.", diff --git a/perl-xCAT/xCAT/TLSPolicy.pm b/perl-xCAT/xCAT/TLSPolicy.pm new file mode 100644 index 000000000..947398d11 --- /dev/null +++ b/perl-xCAT/xCAT/TLSPolicy.pm @@ -0,0 +1,145 @@ +# IBM(c) 2026 EPL license http://www.eclipse.org/legal/epl-v10.html +package xCAT::TLSPolicy; + +use strict; +use warnings; + +use Exporter qw(import); + +our @EXPORT_OK = qw( + MODERN_TLS_VERSION + LEGACY_TLS_VERSION + DEFAULT_TLS_POLICY + resolve_xcatd_tls_settings + tls_setting_warnings +); + +use constant MODERN_TLS_VERSION => 'SSLv23:!SSLv2:!SSLv3:!TLSv1:!TLSv1_1'; +use constant LEGACY_TLS_VERSION => 'SSLv23:!SSLv2:!SSLv3'; +use constant DEFAULT_TLS_POLICY => 'modern'; + +sub _site_value { + my ($site, $key) = @_; + + return '' unless $site && defined $site->{$key}; + + my $value = $site->{$key}; + $value =~ s/^\s+|\s+$//g; + return $value; +} + +sub _normalize_policy { + my $policy = shift || ''; + $policy =~ s/^\s+|\s+$//g; + return lc($policy); +} + +sub resolve_xcatd_tls_settings { + my $site = shift || {}; + + my $override = _site_value($site, 'xcatsslversion'); + if ($override ne '') { + return { + policy => 'override', + ssl_version => $override, + source => 'xcatsslversion', + }; + } + + my $policy_value = _site_value($site, 'xcattlspolicy'); + my $policy = _normalize_policy($policy_value); + my $source = ($policy ne '') ? 'xcattlspolicy' : 'default'; + $policy = DEFAULT_TLS_POLICY unless $policy ne ''; + + if ($policy eq 'legacy') { + return { + policy => 'legacy', + ssl_version => LEGACY_TLS_VERSION, + source => $source, + }; + } + + return { + policy => DEFAULT_TLS_POLICY, + ssl_version => MODERN_TLS_VERSION, + source => ($policy eq DEFAULT_TLS_POLICY) ? $source : 'default', + }; +} + +sub _enabled_protocols { + my $ssl_version = shift || ''; + my %enabled; + + foreach my $token (split /:/, $ssl_version) { + $token =~ s/^\s+|\s+$//g; + next if $token eq ''; + next if $token =~ /^!/; + $enabled{lc($token)} = 1; + } + + return \%enabled; +} + +sub _explicitly_disables { + my ($ssl_version, $protocol) = @_; + + foreach my $token (split /:/, ($ssl_version || '')) { + $token =~ s/^\s+|\s+$//g; + return 1 if lc($token) eq '!' . lc($protocol); + } + + return 0; +} + +sub _deprecated_protocol_enabled { + my $ssl_version = shift || ''; + my $enabled = _enabled_protocols($ssl_version); + + return 1 if $enabled->{sslv2} || $enabled->{sslv3} || $enabled->{tlsv1} || $enabled->{tlsv1_1} || $enabled->{tlsv11}; + + if ($enabled->{sslv23}) { + return 1 unless _explicitly_disables($ssl_version, 'SSLv2'); + return 1 unless _explicitly_disables($ssl_version, 'SSLv3'); + return 1 unless _explicitly_disables($ssl_version, 'TLSv1'); + return 1 unless _explicitly_disables($ssl_version, 'TLSv1_1') || _explicitly_disables($ssl_version, 'TLSv11'); + } + + return 0; +} + +sub _deprecated_cipher_enabled { + my $ciphers = shift || ''; + + foreach my $token (split /:/, $ciphers) { + $token =~ s/^\s+|\s+$//g; + next if $token eq '' || $token =~ /^!/; + return 1 if $token =~ /(?:^|[+_-])(?:3DES|DES-CBC3|RC4)(?:$|[+_-])/i; + return 1 if $token =~ /^(?:LOW|EXP|EXPORT)$/i; + } + + return 0; +} + +sub tls_setting_warnings { + my $site = shift || {}; + my @warnings; + + my $policy = _normalize_policy(_site_value($site, 'xcattlspolicy')); + if ($policy ne '' && $policy ne 'modern' && $policy ne 'legacy') { + push @warnings, "Unsupported site.xcattlspolicy '$policy'; xcatd will use the modern TLS policy."; + } + + my $ssl_version = _site_value($site, 'xcatsslversion'); + if ($ssl_version ne '' && _deprecated_protocol_enabled($ssl_version)) { + push @warnings, "site.xcatsslversion enables deprecated protocols; clear it or use site.xcattlspolicy=modern for TLS 1.2 or newer."; + } + + my $ciphers = _site_value($site, 'xcatsslciphers'); + if (_deprecated_cipher_enabled($ciphers)) { + push @warnings, "site.xcatsslciphers contains legacy cipher selectors; clear it unless a legacy estate explicitly requires it."; + } + + return @warnings; +} + +1; diff --git a/xCAT-server/sbin/xcatconfig b/xCAT-server/sbin/xcatconfig index cbe7877e3..7984efb21 100755 --- a/xCAT-server/sbin/xcatconfig +++ b/xCAT-server/sbin/xcatconfig @@ -25,6 +25,7 @@ use strict; use xCAT::Utils; use xCAT::SvrUtils; use xCAT::DHCP::Backend; +use xCAT::TLSPolicy qw(tls_setting_warnings); use xCAT::NetworkUtils; use Getopt::Long; use xCAT::MsgUtils; @@ -1255,6 +1256,7 @@ sub initDB $chtabcmds .= "$::XCATROOT/sbin/chtab key=dhcplease site.value=43200;"; $chtabcmds .= "$::XCATROOT/sbin/chtab key=auditnosyslog site.value=0;"; $chtabcmds .= "$::XCATROOT/sbin/chtab key=xcatsslversion site.value=;"; + $chtabcmds .= "$::XCATROOT/sbin/chtab key=xcattlspolicy site.value=modern;"; $chtabcmds .= "$::XCATROOT/sbin/chtab key=auditskipcmds site.value=ALL;"; #$chtabcmds .= "$::XCATROOT/sbin/chtab key=useflowcontrol site.value=yes;"; # need to fix 4031 @@ -1546,6 +1548,18 @@ sub initDB xCAT::MsgUtils->message('I', " ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::+-+-+-+-+-+-+-+"); } + + my %sitevalues; + my $sitetab = xCAT::Table->new('site', -create => 0); + if ($sitetab) { + my @records = $sitetab->getAllAttribs(qw/key value/); + foreach my $record (@records) { + $sitevalues{ $record->{key} } = $record->{value}; + } + } + foreach my $warning (tls_setting_warnings(\%sitevalues)) { + xCAT::MsgUtils->message('W', $warning); + } } # remove xcatserver,xcatclient diff --git a/xCAT-server/sbin/xcatd b/xCAT-server/sbin/xcatd index 72a72eb08..d1e27025d 100755 --- a/xCAT-server/sbin/xcatd +++ b/xCAT-server/sbin/xcatd @@ -46,6 +46,7 @@ use lib "$::XCATROOT/lib/perl"; use Storable qw(freeze thaw nstore_fd store_fd fd_retrieve); use Sys::Hostname; use xCAT::Utils; +use xCAT::TLSPolicy qw(resolve_xcatd_tls_settings); use xCAT::TableUtils; use xCAT::NetworkUtils; use xCAT::MsgUtils; @@ -1550,8 +1551,8 @@ until ($quit) { populate_site_hash(); my %extrasslargs; - if ($::XCATSITEVALS{xcatsslversion}) { $extrasslargs{SSL_version} = $::XCATSITEVALS{xcatsslversion}; } - $extrasslargs{SSL_version} = "SSLv23:!SSLv2:!SSLv3:!TLSv1" unless length $extrasslargs{SSL_version}; + my $tls_settings = resolve_xcatd_tls_settings(\%::XCATSITEVALS); + $extrasslargs{SSL_version} = $tls_settings->{ssl_version}; if ($::XCATSITEVALS{xcatsslciphers}) { $extrasslargs{SSL_cipher_list} = $::XCATSITEVALS{xcatsslciphers}; } use Data::Dumper; @@ -3675,4 +3676,3 @@ sub cmdlog_submitlog() { return 1; } } - diff --git a/xCAT-test/autotest/testcase/xcat_inventory/cases.site b/xCAT-test/autotest/testcase/xcat_inventory/cases.site index d70cb2bac..b9d086088 100644 --- a/xCAT-test/autotest/testcase/xcat_inventory/cases.site +++ b/xCAT-test/autotest/testcase/xcat_inventory/cases.site @@ -12,6 +12,8 @@ cmd:ssh $$DSTMN ' source /etc/profile.d/xcat.sh;lsdef -t site -o clustersite -z check:rc==0 cmd:mnip=$(lsdef -t site -o clustersite -i master -c|awk -F'=' '{print $2}');chdef -t site -o clustersite useSSHonAIX=0 useNFSv4onAIX=0 FQDNfirst=1 SNsyncfiledir='/var/xcat/syncfiles' auditnosyslog=0 auditskipcmds=ALL blademaxp=64 cleanupxcatpost=no consoleondemand=no databaseloc='/var/lib' db2installloc='/mntdb2' dbtracelevel=0 defserialflow=0 defserialport=0 defserialspeed=9600 dhcpinterfaces=eth0 dhcplease=43200 dhcpsetup=n disjointdhcps=1 dnshandler=ddns dnsinterfaces='xcatmn|eth1,eth2;service|bond0' dnsupdaters=dnsupdaters domain='pok.stglabs.ibm.com' enableASMI=no excludenodes=excludenodes externaldns=externaldns extntpservers=extntpservers forwarders=$mnip fsptimeout=0 genmacprefix='00:11:aa' genpasswords=genpasswords hierarchicalattrs=hierarchicalattrs httpport=80 hwctrldispatch=y installdir='/install/' installloc='hostname:/path' ipmidispatch=y ipmimaxp=64 ipmiretries=3 ipmisdrcache=no ipmitimeout=2 iscsidir='/iscsidir' managedaddressmode=dhcp master=$mnip maxssh=8 mnroutenames=mnroutenames nameservers=$mnip nmapoptions='--min-rtt-timeout' nodestatus=n nodesyncfiledir='/var/xcat/node/syncfiles' ntpservers=$mnip persistkvmguests=y powerinterval=0 ppcmaxp=64 ppcretry=3 ppctimeout=0 precreatemypostscripts=1 pruneservices=1 runbootscripts=yes setinstallnic=1 sharedinstall=no sharedtftp=1 skiptables=nics skipvalidatelog=1 snmpc=snmpc sshbetweennodes=ALLGROUPS svloglocal=1 syspowerinterval=10 syspowermaxnodes=10 tftpdir='/tftprot/' tftpflags='-v' timezone='America/New_York' useNmapfromMN=no useflowcontrol=no usexhrm=no vcenterautojoin=no vmwarereconfigonpower=no vsftp=n xcatconfdir='/etc/xcat' xcatdebugmode=1 xcatdport=3001 xcatiport=3002 xcatlport=3003 xcatmaxbatchconnections=64 xcatmaxconnections=60 xcatsslciphers='3DES' xcatsslversion=TLSv1 check:rc==0 +cmd:chtab key=xcattlspolicy site.value=modern +check:rc==0 cmd:lsdef -t site -o clustersite -z|sort -t'=' -k1 |tee /tmp/export_import_site_by_yaml/srcsite.stanza check:rc==0 cmd:xcat-inventory export --format=yaml -t site -o clustersite |tee /tmp/export_import_site_by_yaml/export_site_yaml.inv @@ -59,6 +61,8 @@ cmd:ssh $$DSTMN ' source /etc/profile.d/xcat.sh;lsdef -t site -o clustersite -z check:rc==0 cmd:mnip=$(lsdef -t site -o clustersite -i master -c|awk -F'=' '{print $2}');chdef -t site -o clustersite useSSHonAIX=0 useNFSv4onAIX=0 FQDNfirst=1 SNsyncfiledir='/var/xcat/syncfiles' auditnosyslog=0 auditskipcmds=ALL blademaxp=64 cleanupxcatpost=no consoleondemand=no databaseloc='/var/lib' db2installloc='/mntdb2' dbtracelevel=0 defserialflow=0 defserialport=0 defserialspeed=9600 dhcpinterfaces=eth0 dhcplease=43200 dhcpsetup=n disjointdhcps=1 dnshandler=ddns dnsinterfaces='xcatmn|eth1,eth2;service|bond0' dnsupdaters=dnsupdaters domain='pok.stglabs.ibm.com' enableASMI=no excludenodes=excludenodes externaldns=externaldns extntpservers=extntpservers forwarders=$mnip fsptimeout=0 genmacprefix='00:11:aa' genpasswords=genpasswords hierarchicalattrs=hierarchicalattrs httpport=80 hwctrldispatch=y installdir='/install/' installloc='hostname:/path' ipmidispatch=y ipmimaxp=64 ipmiretries=3 ipmisdrcache=no ipmitimeout=2 iscsidir='/iscsidir' managedaddressmode=dhcp master=$mnip maxssh=8 mnroutenames=mnroutenames nameservers=$mnip nmapoptions='--min-rtt-timeout' nodestatus=n nodesyncfiledir='/var/xcat/node/syncfiles' ntpservers=$mnip persistkvmguests=y powerinterval=0 ppcmaxp=64 ppcretry=3 ppctimeout=0 precreatemypostscripts=1 pruneservices=1 runbootscripts=yes setinstallnic=1 sharedinstall=no sharedtftp=1 skiptables=nics skipvalidatelog=1 snmpc=snmpc sshbetweennodes=ALLGROUPS svloglocal=1 syspowerinterval=10 syspowermaxnodes=10 tftpdir='/tftprot/' tftpflags='-v' timezone='America/New_York' useNmapfromMN=no useflowcontrol=no usexhrm=no vcenterautojoin=no vmwarereconfigonpower=no vsftp=n xcatconfdir='/etc/xcat' xcatdebugmode=1 xcatdport=3001 xcatiport=3002 xcatlport=3003 xcatmaxbatchconnections=64 xcatmaxconnections=60 xcatsslciphers='3DES' xcatsslversion=TLSv1 check:rc==0 +cmd:chtab key=xcattlspolicy site.value=modern +check:rc==0 cmd:lsdef -t site -o clustersite -z|sort -t'=' -k1 |tee /tmp/export_import_site_by_json/srcsite.stanza check:rc==0 cmd:xcat-inventory export --format=json -t site -o clustersite |tee /tmp/export_import_site_by_json/export_site_json.inv @@ -101,6 +105,8 @@ cmd: lsdef -t site -o clustersite -z >/tmp/xcat_inventory_try_to_export_all_type check:rc==0 cmd:mnip=$(lsdef -t site -o clustersite -i master -c|awk -F'=' '{print $2}');chdef -t site -o clustersite useSSHonAIX=0 useNFSv4onAIX=0 FQDNfirst=1 SNsyncfiledir='/var/xcat/syncfiles' auditnosyslog=0 auditskipcmds=ALL blademaxp=64 cleanupxcatpost=no consoleondemand=no databaseloc='/var/lib' db2installloc='/mntdb2' dbtracelevel=0 defserialflow=0 defserialport=0 defserialspeed=9600 dhcpinterfaces=eth0 dhcplease=43200 dhcpsetup=n disjointdhcps=1 dnshandler=ddns dnsinterfaces='xcatmn|eth1,eth2;service|bond0' dnsupdaters=dnsupdaters domain='pok.stglabs.ibm.com' enableASMI=no excludenodes=excludenodes externaldns=externaldns extntpservers=extntpservers forwarders=$mnip fsptimeout=0 genmacprefix='00:11:aa' genpasswords=genpasswords hierarchicalattrs=hierarchicalattrs httpport=80 hwctrldispatch=y installdir='/install/' installloc='hostname:/path' ipmidispatch=y ipmimaxp=64 ipmiretries=3 ipmisdrcache=no ipmitimeout=2 iscsidir='/iscsidir' managedaddressmode=dhcp master=$mnip maxssh=8 mnroutenames=mnroutenames nameservers=$mnip nmapoptions='--min-rtt-timeout' nodestatus=n nodesyncfiledir='/var/xcat/node/syncfiles' ntpservers=$mnip persistkvmguests=y powerinterval=0 ppcmaxp=64 ppcretry=3 ppctimeout=0 precreatemypostscripts=1 pruneservices=1 runbootscripts=yes setinstallnic=1 sharedinstall=no sharedtftp=1 skiptables=nics skipvalidatelog=1 snmpc=snmpc sshbetweennodes=ALLGROUPS svloglocal=1 syspowerinterval=10 syspowermaxnodes=10 tftpdir='/tftprot/' tftpflags='-v' timezone='America/New_York' useNmapfromMN=no useflowcontrol=no usexhrm=no vcenterautojoin=no vmwarereconfigonpower=no vsftp=n xcatconfdir='/etc/xcat' xcatdebugmode=1 xcatdport=3001 xcatiport=3002 xcatlport=3003 xcatmaxbatchconnections=64 xcatmaxconnections=60 xcatsslciphers='3DES' xcatsslversion=TLSv1 check:rc==0 +cmd:chtab key=xcattlspolicy site.value=modern +check:rc==0 cmd:echo " schema_version: '2.0' site: @@ -192,6 +198,7 @@ site: xcatmaxconnections: '60' xcatsslciphers: 3DES xcatsslversion: TLSv1 + xcattlspolicy: modern " > /tmp/xcat_inventory_try_to_export_all_type_is_site_default_format/site.org cmd:mnip=$(lsdef -t site -o clustersite -i master -c|awk -F'=' '{print $2}');sed -i "s/10.3.1.13/$mnip/g" /tmp/xcat_inventory_try_to_export_all_type_is_site_default_format/site.org check:rc==0 @@ -215,6 +222,8 @@ cmd: lsdef -t site -o clustersite -z >/tmp/xcat_inventory_try_to_export_all_type check:rc==0 cmd:mnip=$(lsdef -t site -o clustersite -i master -c|awk -F'=' '{print $2}');chdef -t site -o clustersite useSSHonAIX=0 useNFSv4onAIX=0 FQDNfirst=1 SNsyncfiledir='/var/xcat/syncfiles' auditnosyslog=0 auditskipcmds=ALL blademaxp=64 cleanupxcatpost=no consoleondemand=no databaseloc='/var/lib' db2installloc='/mntdb2' dbtracelevel=0 defserialflow=0 defserialport=0 defserialspeed=9600 dhcpinterfaces=eth0 dhcplease=43200 dhcpsetup=n disjointdhcps=1 dnshandler=ddns dnsinterfaces='xcatmn|eth1,eth2;service|bond0' dnsupdaters=dnsupdaters domain='pok.stglabs.ibm.com' enableASMI=no excludenodes=excludenodes externaldns=externaldns extntpservers=extntpservers forwarders=$mnip fsptimeout=0 genmacprefix='00:11:aa' genpasswords=genpasswords hierarchicalattrs=hierarchicalattrs httpport=80 hwctrldispatch=y installdir='/install/' installloc='hostname:/path' ipmidispatch=y ipmimaxp=64 ipmiretries=3 ipmisdrcache=no ipmitimeout=2 iscsidir='/iscsidir' managedaddressmode=dhcp master=$mnip maxssh=8 mnroutenames=mnroutenames nameservers=$mnip nmapoptions='--min-rtt-timeout' nodestatus=n nodesyncfiledir='/var/xcat/node/syncfiles' ntpservers=$mnip persistkvmguests=y powerinterval=0 ppcmaxp=64 ppcretry=3 ppctimeout=0 precreatemypostscripts=1 pruneservices=1 runbootscripts=yes setinstallnic=1 sharedinstall=no sharedtftp=1 skiptables=nics skipvalidatelog=1 snmpc=snmpc sshbetweennodes=ALLGROUPS svloglocal=1 syspowerinterval=10 syspowermaxnodes=10 tftpdir='/tftprot/' tftpflags='-v' timezone='America/New_York' useNmapfromMN=no useflowcontrol=no usexhrm=no vcenterautojoin=no vmwarereconfigonpower=no vsftp=n xcatconfdir='/etc/xcat' xcatdebugmode=1 xcatdport=3001 xcatiport=3002 xcatlport=3003 xcatmaxbatchconnections=64 xcatmaxconnections=60 xcatsslciphers='3DES' xcatsslversion=TLSv1 check:rc==0 +cmd:chtab key=xcattlspolicy site.value=modern +check:rc==0 cmd:#!/bin/bash echo '{ "schema_version": "1.0", @@ -306,7 +315,8 @@ echo '{ "xcatmaxbatchconnections": "64", "xcatmaxconnections": "60", "xcatsslciphers": "3DES", - "xcatsslversion": "TLSv1" + "xcatsslversion": "TLSv1", + "xcattlspolicy": "modern" } } }' > /tmp/xcat_inventory_try_to_export_all_type_is_site_json_format/site.org @@ -332,6 +342,8 @@ cmd: lsdef -t site -o clustersite -z >/tmp/xcat_inventory_try_to_export_all_type check:rc==0 cmd:mnip=$(lsdef -t site -o clustersite -i master -c|awk -F'=' '{print $2}');chdef -t site -o clustersite useSSHonAIX=0 useNFSv4onAIX=0 FQDNfirst=1 SNsyncfiledir='/var/xcat/syncfiles' auditnosyslog=0 auditskipcmds=ALL blademaxp=64 cleanupxcatpost=no consoleondemand=no databaseloc='/var/lib' db2installloc='/mntdb2' dbtracelevel=0 defserialflow=0 defserialport=0 defserialspeed=9600 dhcpinterfaces=eth0 dhcplease=43200 dhcpsetup=n disjointdhcps=1 dnshandler=ddns dnsinterfaces='xcatmn|eth1,eth2;service|bond0' dnsupdaters=dnsupdaters domain='pok.stglabs.ibm.com' enableASMI=no excludenodes=excludenodes externaldns=externaldns extntpservers=extntpservers forwarders=$mnip fsptimeout=0 genmacprefix='00:11:aa' genpasswords=genpasswords hierarchicalattrs=hierarchicalattrs httpport=80 hwctrldispatch=y installdir='/install/' installloc='hostname:/path' ipmidispatch=y ipmimaxp=64 ipmiretries=3 ipmisdrcache=no ipmitimeout=2 iscsidir='/iscsidir' managedaddressmode=dhcp master=$mnip maxssh=8 mnroutenames=mnroutenames nameservers=$mnip nmapoptions='--min-rtt-timeout' nodestatus=n nodesyncfiledir='/var/xcat/node/syncfiles' ntpservers=$mnip persistkvmguests=y powerinterval=0 ppcmaxp=64 ppcretry=3 ppctimeout=0 precreatemypostscripts=1 pruneservices=1 runbootscripts=yes setinstallnic=1 sharedinstall=no sharedtftp=1 skiptables=nics skipvalidatelog=1 snmpc=snmpc sshbetweennodes=ALLGROUPS svloglocal=1 syspowerinterval=10 syspowermaxnodes=10 tftpdir='/tftprot/' tftpflags='-v' timezone='America/New_York' useNmapfromMN=no useflowcontrol=no usexhrm=no vcenterautojoin=no vmwarereconfigonpower=no vsftp=n xcatconfdir='/etc/xcat' xcatdebugmode=1 xcatdport=3001 xcatiport=3002 xcatlport=3003 xcatmaxbatchconnections=64 xcatmaxconnections=60 xcatsslciphers='3DES' xcatsslversion=TLSv1 check:rc==0 +cmd:chtab key=xcattlspolicy site.value=modern +check:rc==0 cmd:#!/bin/bash echo "schema_version: '1.0' site: @@ -422,7 +434,8 @@ site: xcatmaxbatchconnections: '64' xcatmaxconnections: '60' xcatsslciphers: 3DES - xcatsslversion: TLSv1" > /tmp/xcat_inventory_try_to_export_all_type_is_site_yaml_format/site.org + xcatsslversion: TLSv1 + xcattlspolicy: modern" > /tmp/xcat_inventory_try_to_export_all_type_is_site_yaml_format/site.org cmd:mnip=$(lsdef -t site -o clustersite -i master -c|awk -F'=' '{print $2}');sed -i "s/10.3.5.8/$mnip/g" /tmp/xcat_inventory_try_to_export_all_type_is_site_yaml_format/site.org check:rc==0 cmd:xcat-inventory export --format=yaml -t site|sed -e '/^\s*$/d' |tee /tmp/xcat_inventory_try_to_export_all_type_is_site_yaml_format/site.export @@ -740,7 +753,8 @@ cmd:echo '{ "xcatmaxbatchconnections": "64", "xcatmaxconnections": "60", "xcatsslciphers": "3DES", - "xcatsslversion": "TLSv1" + "xcatsslversion": "TLSv1", + "xcattlspolicy": "modern" } } }' > /tmp/xcat_inventory_try_to_import_all_type_is_site_json_format/json.test @@ -832,7 +846,8 @@ cmd:echo "Object name: clustersite xcatmaxbatchconnections=64 xcatmaxconnections=60 xcatsslciphers=3DES - xcatsslversion=TLSv1"> /tmp/xcat_inventory_try_to_import_all_type_is_site_json_format/site.org + xcatsslversion=TLSv1 + xcattlspolicy=modern"> /tmp/xcat_inventory_try_to_import_all_type_is_site_json_format/site.org check:rc==0 cmd:mnip=$(lsdef -t site -o clustersite -i master -c|awk -F'=' '{print $2}');sed -i "s/10.3.5.8/$mnip/g" /tmp/xcat_inventory_try_to_import_all_type_is_site_json_format/site.org check:rc==0 @@ -1108,7 +1123,8 @@ site: xcatmaxbatchconnections: '64' xcatmaxconnections: '60' xcatsslciphers: 3DES - xcatsslversion: TLSv1" > /tmp/xcat_inventory_try_to_import_all_type_is_site_yaml_format/yaml.test + xcatsslversion: TLSv1 + xcattlspolicy: modern" > /tmp/xcat_inventory_try_to_import_all_type_is_site_yaml_format/yaml.test check:rc==0 cmd:echo "Object name: clustersite FQDNfirst=1 @@ -1197,7 +1213,8 @@ cmd:echo "Object name: clustersite xcatmaxbatchconnections=64 xcatmaxconnections=60 xcatsslciphers=3DES - xcatsslversion=TLSv1"> /tmp/xcat_inventory_try_to_import_all_type_is_site_yaml_format/site.org + xcatsslversion=TLSv1 + xcattlspolicy=modern"> /tmp/xcat_inventory_try_to_import_all_type_is_site_yaml_format/site.org check:rc==0 cmd:mnip=$(lsdef -t site -o clustersite -i master -c|awk -F'=' '{print $2}');sed -i "s/10.3.5.8/$mnip/g" /tmp/xcat_inventory_try_to_import_all_type_is_site_yaml_format/site.org check:rc==0 @@ -1246,6 +1263,8 @@ cmd:ssh $$DSTMN ' source /etc/profile.d/xcat.sh;lsdef -t site -o clustersite -z check:rc==0 cmd:mnip=$(lsdef -t site -o clustersite -i master -c|awk -F'=' '{print $2}');chdef -t site -o clustersite useSSHonAIX=1111 useNFSv4onAIX=1111 FQDNfirst=1111 SNsyncfiledir='/var/xcat/1111' auditnosyslog=1111 auditskipcmds=ALL blademaxp=641111 cleanupxcatpost=1111 consoleondemand=1111 databaseloc='/var/lib1111' db2installloc='/mntdb1111' dbtracelevel=0 defserialflow=1111 defserialport=1111 defserialspeed=9611111111 dhcpinterfaces=eth1111 dhcplease=43211111111 dhcpsetup=1111 disjointdhcps=0 dnshandler=ddns1111 dnsinterfaces='xcatmn|eth1,eth2;service|bond1111' dnsupdaters=dnsupdaters1111 domain='pok1111.stglabs.ibm.com' enableASMI=1111 excludenodes=1111 externaldns=1111 extntpservers=1111 forwarders=$mnip fsptimeout=1111 genmacprefix='11111111:11:aa' genpasswords=1111 hierarchicalattrs=1111 httpport=81111 hwctrldispatch=1111 installdir='/install1111/' installloc='hostname:/path1111' ipmidispatch=1111 ipmimaxp=641111 ipmiretries=31111 ipmisdrcache=1111 ipmitimeout=21111 iscsidir='/iscsidir1111' managedaddressmode=dhcp master=$mnip maxssh=81111 mnroutenames=1111 nameservers=$mnip nmapoptions='--min-rtt-timeout 1111' nodestatus=n nodesyncfiledir='/var/xcat/node/syncfiles1111' ntpservers=$mnip persistkvmguests=1111 powerinterval=1111 ppcmaxp=641111 ppcretry=31111 ppctimeout=1111 precreatemypostchdef -t site -o clustersite useSSHonAIX=1111 useNFSv4onAIX=1111 FQDNfirst=1111 SNsyncfiledir='/var/xcat/1111' auditnosyslog=1111 auditskipcmds=ALL blademaxp=641111 pruneservices=1111 runbootscripts=1111 setinstallnic=1111 sharedinstall=no sharedtftp=1111 skiptables=nics1111 skipvalidatelog=1111 snmpc=xc1111 sshbetweennodes=ALLGROUPS svloglocal=1111 syspowerinterval=11111 syspowermaxnodes=11111 tftpdir='/tftprot1111/' tftpflags='-v1111' timezone='America/New_York1111' useNmapfromMN=1111 useflowcontrol=1111 usexhrm=1111 vcenterautojoin=1111 vmwarereconfigonpower=1111 vsftp=1111 xcatconfdir='/etc/xcat1111' xcatdebugmode=0 xcatdport=3001 xcatiport=3002 xcatlport=3003 xcatmaxbatchconnections=641111 xcatmaxconnections=61111 xcatsslciphers='3DES' xcatsslversion=TLSv1 check:rc==0 +cmd:chtab key=xcattlspolicy site.value=modern +check:rc==0 cmd:lsdef -t site -o clustersite -z|sed 's/=0$/=1/g' |sort -t'=' -k1 |tee /tmp/export_site_table_then_modify_yaml_then_import/srcsite.stanza check:rc==0 cmd:sed -i 's/1111/2222/g' /tmp/export_site_table_then_modify_yaml_then_import/srcsite.stanza @@ -1310,6 +1329,8 @@ cmd:ssh $$DSTMN ' source /etc/profile.d/xcat.sh;lsdef -t site -o clustersite -z check:rc==0 cmd:mnip=$(lsdef -t site -o clustersite -i master -c|awk -F'=' '{print $2}');chdef -t site -o clustersite useSSHonAIX=1111 useNFSv4onAIX=1111 FQDNfirst=1111 SNsyncfiledir='/var/xcat/1111' auditnosyslog=1111 auditskipcmds=ALL blademaxp=641111 cleanupxcatpost=1111 consoleondemand=1111 databaseloc='/var/lib1111' db2installloc='/mntdb1111' dbtracelevel=0 defserialflow=1111 defserialport=1111 defserialspeed=9611111111 dhcpinterfaces=eth1111 dhcplease=43211111111 dhcpsetup=1111 disjointdhcps=0 dnshandler=ddns1111 dnsinterfaces='xcatmn|eth1,eth2;service|bond1111' dnsupdaters=dnsupdaters1111 domain='pok1111.stglabs.ibm.com' enableASMI=1111 excludenodes=1111 externaldns=1111 extntpservers=1111 forwarders=$mnip fsptimeout=1111 genmacprefix='11111111:11:aa' genpasswords=1111 hierarchicalattrs=1111 httpport=81111 hwctrldispatch=1111 installdir='/install1111/' installloc='hostname:/path1111' ipmidispatch=1111 ipmimaxp=641111 ipmiretries=31111 ipmisdrcache=1111 ipmitimeout=21111 iscsidir='/iscsidir1111' managedaddressmode=dhcp master=$mnip maxssh=81111 mnroutenames=1111 nameservers=$mnip nmapoptions='--min-rtt-timeout 1111' nodestatus=n nodesyncfiledir='/var/xcat/node/syncfiles1111' ntpservers=$mnip persistkvmguests=1111 powerinterval=1111 ppcmaxp=641111 ppcretry=31111 ppctimeout=1111 precreatemypostchdef -t site -o clustersite useSSHonAIX=1111 useNFSv4onAIX=1111 FQDNfirst=1111 SNsyncfiledir='/var/xcat/1111' auditnosyslog=1111 auditskipcmds=ALL blademaxp=641111 pruneservices=1111 runbootscripts=1111 setinstallnic=1111 sharedinstall=no sharedtftp=1111 skiptables=nics1111 skipvalidatelog=1111 snmpc=xc1111 sshbetweennodes=ALLGROUPS svloglocal=1111 syspowerinterval=11111 syspowermaxnodes=11111 tftpdir='/tftprot1111/' tftpflags='-v1111' timezone='America/New_York1111' useNmapfromMN=1111 useflowcontrol=1111 usexhrm=1111 vcenterautojoin=1111 vmwarereconfigonpower=1111 vsftp=1111 xcatconfdir='/etc/xcat1111' xcatdebugmode=0 xcatdport=3001 xcatiport=3002 xcatlport=3003 xcatmaxbatchconnections=641111 xcatmaxconnections=61111 xcatsslciphers='3DES' xcatsslversion=TLSv1 check:rc==0 +cmd:chtab key=xcattlspolicy site.value=modern +check:rc==0 cmd:lsdef -t site -o clustersite -z|sed 's/=0$/=1/g' |sort -t'=' -k1 |tee /tmp/export_site_table_then_modify_json_then_import/srcsite.stanza check:rc==0 cmd:sed -i 's/1111/2222/g' /tmp/export_site_table_then_modify_json_then_import/srcsite.stanza @@ -1360,4 +1381,3 @@ cmd:rm -rf /tmp/export_site_table_then_modify_json_then_import check:rc==0 end - diff --git a/xCAT-test/unit/tls_policy.t b/xCAT-test/unit/tls_policy.t new file mode 100644 index 000000000..518ea9ca6 --- /dev/null +++ b/xCAT-test/unit/tls_policy.t @@ -0,0 +1,75 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +use FindBin; +use lib "$FindBin::Bin/../../perl-xCAT"; + +use Test::More; + +use xCAT::TLSPolicy qw( + MODERN_TLS_VERSION + LEGACY_TLS_VERSION + DEFAULT_TLS_POLICY + resolve_xcatd_tls_settings + tls_setting_warnings +); + +is(DEFAULT_TLS_POLICY, 'modern', 'modern TLS policy is the default'); +is(MODERN_TLS_VERSION, 'SSLv23:!SSLv2:!SSLv3:!TLSv1:!TLSv1_1', 'modern policy allows TLS 1.2 or newer'); +unlike(MODERN_TLS_VERSION, qr/!TLSv1_?3/i, 'modern policy leaves TLS 1.3 available when supported'); +is(LEGACY_TLS_VERSION, 'SSLv23:!SSLv2:!SSLv3', 'legacy policy preserves TLS 1.0 era compatibility without SSLv2 or SSLv3'); + +my $default = resolve_xcatd_tls_settings({}); +is($default->{policy}, 'modern', 'empty site settings use modern policy'); +is($default->{ssl_version}, MODERN_TLS_VERSION, 'empty site settings resolve to modern SSL_version syntax'); +is($default->{source}, 'default', 'empty site settings are reported as default policy source'); + +my $modern = resolve_xcatd_tls_settings({ xcattlspolicy => ' Modern ' }); +is($modern->{policy}, 'modern', 'modern policy is case and whitespace tolerant'); +is($modern->{ssl_version}, MODERN_TLS_VERSION, 'explicit modern policy resolves to TLS 1.2 or newer'); +is($modern->{source}, 'xcattlspolicy', 'explicit modern policy is reported as site policy source'); + +my $legacy = resolve_xcatd_tls_settings({ xcattlspolicy => 'legacy' }); +is($legacy->{policy}, 'legacy', 'legacy policy is accepted'); +is($legacy->{ssl_version}, LEGACY_TLS_VERSION, 'legacy policy resolves to TLS 1.0 era compatibility'); + +my $override = resolve_xcatd_tls_settings({ xcattlspolicy => 'modern', xcatsslversion => ' TLSv12 ' }); +is($override->{policy}, 'override', 'xcatsslversion remains an administrator override'); +is($override->{ssl_version}, 'TLSv12', 'xcatsslversion override is trimmed and preserved'); + +my $invalid = resolve_xcatd_tls_settings({ xcattlspolicy => 'bogus' }); +is($invalid->{policy}, 'modern', 'invalid policy falls back to modern'); +is($invalid->{ssl_version}, MODERN_TLS_VERSION, 'invalid policy does not weaken TLS defaults'); + +my @bad_policy = tls_setting_warnings({ xcattlspolicy => 'bogus' }); +like($bad_policy[0], qr/Unsupported site\.xcattlspolicy/, 'invalid policy produces a warning'); + +my @old_protocol = tls_setting_warnings({ xcatsslversion => 'TLSv1' }); +like($old_protocol[0], qr/deprecated protocols/, 'explicit TLSv1 override produces a warning'); + +my @flexible_legacy = tls_setting_warnings({ xcatsslversion => 'SSLv23:!SSLv2:!SSLv3' }); +like($flexible_legacy[0], qr/deprecated protocols/, 'flexible override that allows TLSv1 produces a warning'); + +my @flexible_ssl = tls_setting_warnings({ xcatsslversion => 'SSLv23:!TLSv1:!TLSv1_1' }); +like($flexible_ssl[0], qr/deprecated protocols/, 'flexible override that allows SSLv2 or SSLv3 produces a warning'); + +my @modern_override = tls_setting_warnings({ xcatsslversion => 'SSLv23:!SSLv2:!SSLv3:!TLSv1:!TLSv1_1' }); +is(scalar @modern_override, 0, 'modern explicit override does not warn'); + +my @modern_override_tlsv11 = tls_setting_warnings({ xcatsslversion => 'SSLv23:!SSLv2:!SSLv3:!TLSv1:!TLSv11' }); +is(scalar @modern_override_tlsv11, 0, 'modern explicit override accepts TLSv11 spelling'); + +my @old_cipher = tls_setting_warnings({ xcatsslciphers => '3DES' }); +like($old_cipher[0], qr/legacy cipher/, 'legacy cipher selector produces a warning'); + +my @compound_old_cipher = tls_setting_warnings({ xcatsslciphers => 'ALL:!ADH:RC4+RSA:+HIGH' }); +like($compound_old_cipher[0], qr/legacy cipher/, 'compound legacy cipher selector produces a warning'); + +my @openssl_3des_cipher = tls_setting_warnings({ xcatsslciphers => 'ECDHE-RSA-DES-CBC3-SHA' }); +like($openssl_3des_cipher[0], qr/legacy cipher/, 'OpenSSL 3DES cipher name produces a warning'); + +my @disabled_old_cipher = tls_setting_warnings({ xcatsslciphers => 'HIGH:!RC4:!3DES:!LOW:!EXP:!EXPORT' }); +is(scalar @disabled_old_cipher, 0, 'disabled legacy cipher selectors do not warn'); + +done_testing();