mirror of
https://github.com/xcat2/xcat-core.git
synced 2026-10-21 07:08:12 +00:00
test(dhcp): cover shared FIPS defaults and BIND signing
This commit is contained in:
@@ -3,25 +3,21 @@ use strict;
|
||||
use warnings;
|
||||
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/../lib";
|
||||
use lib "$FindBin::Bin/../../xCAT-server/lib";
|
||||
use lib "$FindBin::Bin/../../xCAT-server/lib/perl";
|
||||
use lib "$FindBin::Bin/../../perl-xCAT";
|
||||
|
||||
use File::Temp qw(tempfile);
|
||||
use File::Slurper qw(read_text);
|
||||
use File::Temp qw(tempfile tempdir);
|
||||
use Test::More;
|
||||
use XCAT::Test::File qw(repo_path);
|
||||
|
||||
$ENV{XCATCFG} ||= 'SQLite:/tmp';
|
||||
$ENV{XCATROOT} ||= "$FindBin::Bin/../../xCAT-server";
|
||||
$ENV{XCATROOT} ||= repo_path('xCAT-server');
|
||||
|
||||
my $ddns_plugin_path =
|
||||
"$FindBin::Bin/../../xCAT-server/lib/xcat/plugins/ddns.pm";
|
||||
if ( -f $ddns_plugin_path ) {
|
||||
require $ddns_plugin_path;
|
||||
}
|
||||
else {
|
||||
require xCAT_plugin::ddns;
|
||||
$ddns_plugin_path = $INC{'xCAT_plugin/ddns.pm'};
|
||||
}
|
||||
my $ddns_plugin_path = repo_path('xCAT-server/lib/xcat/plugins/ddns.pm');
|
||||
require $ddns_plugin_path;
|
||||
|
||||
sub omapi_settings {
|
||||
my (%overrides) = @_;
|
||||
@@ -65,11 +61,131 @@ is(
|
||||
'default DDNS key remains xcat_key with hmac-md5'
|
||||
);
|
||||
|
||||
my $fips_defaults = xCAT::DHCP::OmapiPolicy->settings(
|
||||
site_values => {
|
||||
dhcpomapialgorithm => undef,
|
||||
dhcpomapikeyname => undef,
|
||||
dhcpomshellpath => undef,
|
||||
},
|
||||
fips_mode => 1,
|
||||
);
|
||||
{
|
||||
no warnings qw(redefine once);
|
||||
local *xCAT::Utils::isFIPS = sub { return 1; };
|
||||
my $detected_fips = xCAT::DHCP::OmapiPolicy->settings(
|
||||
site_values => {
|
||||
dhcpomapialgorithm => undef,
|
||||
dhcpomapikeyname => undef,
|
||||
dhcpomshellpath => undef,
|
||||
},
|
||||
);
|
||||
is( $detected_fips->{algorithm}, 'hmac-sha256',
|
||||
'runtime FIPS detection selects the SHA-256 default' );
|
||||
}
|
||||
is(
|
||||
xCAT_plugin::ddns::ddns_tsig_algorithm(
|
||||
{ omapi_settings => $fips_defaults }
|
||||
),
|
||||
'hmac-sha256',
|
||||
'FIPS DDNS defaults to the same algorithm as OMAPI'
|
||||
);
|
||||
is(
|
||||
xCAT_plugin::ddns::ddns_key_contents(
|
||||
{
|
||||
omapi_settings => $fips_defaults,
|
||||
privkey => 'fips-secret',
|
||||
}
|
||||
),
|
||||
"key \"xcat_key\" {\n\talgorithm hmac-sha256;\n\tsecret \"fips-secret\";\n};\n\n",
|
||||
'FIPS DDNS key uses hmac-sha256'
|
||||
);
|
||||
is_deeply(
|
||||
xCAT_plugin::ddns::ddns_reconcile_key_algorithm(
|
||||
$fips_defaults, ' HMAC-SHA512 '
|
||||
),
|
||||
{ algorithm => 'hmac-sha256', replace => 1 },
|
||||
'FIPS mode aligns an implicit existing key with the OMAPI default'
|
||||
);
|
||||
is_deeply(
|
||||
xCAT_plugin::ddns::ddns_reconcile_key_algorithm(
|
||||
$fips_defaults, 'hmac-md5'
|
||||
),
|
||||
{ algorithm => 'hmac-sha256', replace => 1 },
|
||||
'FIPS mode replaces an existing MD5 key'
|
||||
);
|
||||
is_deeply(
|
||||
xCAT_plugin::ddns::ddns_reconcile_key_algorithm(
|
||||
$fips_defaults, 'hmac-unknown'
|
||||
),
|
||||
{ algorithm => 'hmac-sha256', replace => 1 },
|
||||
'FIPS mode replaces an unsupported key algorithm'
|
||||
);
|
||||
is_deeply(
|
||||
xCAT_plugin::ddns::ddns_reconcile_key_algorithm(
|
||||
$fips_defaults, undef
|
||||
),
|
||||
{ algorithm => 'hmac-sha256', replace => 1 },
|
||||
'FIPS mode repairs a key block without an algorithm'
|
||||
);
|
||||
is(
|
||||
xCAT_plugin::ddns::ddns_tsig_algorithm(
|
||||
{
|
||||
omapi_settings => $fips_defaults,
|
||||
tsig_algorithm => 'hmac-sha512',
|
||||
}
|
||||
),
|
||||
'hmac-sha256',
|
||||
'FIPS DDNS signs with the algorithm OMAPI uses'
|
||||
);
|
||||
|
||||
my $sha512 = omapi_settings(
|
||||
dhcpomapialgorithm => 'hmac-sha512',
|
||||
dhcpomapikeyname => 'provider.key',
|
||||
);
|
||||
|
||||
is_deeply(
|
||||
xCAT_plugin::ddns::ddns_reconcile_key_algorithm(
|
||||
$sha512, 'hmac-sha256'
|
||||
),
|
||||
{ algorithm => 'hmac-sha512', replace => 1 },
|
||||
'an explicit site algorithm replaces a different existing algorithm'
|
||||
);
|
||||
is_deeply(
|
||||
xCAT_plugin::ddns::ddns_reconcile_key_algorithm(
|
||||
$defaults, 'hmac-sha512'
|
||||
),
|
||||
{ algorithm => 'hmac-sha512', replace => 0 },
|
||||
'the existing algorithm is preserved outside FIPS mode'
|
||||
);
|
||||
|
||||
foreach my $case (
|
||||
[ $defaults, ' HMAC-SHA512 ', 'hmac-sha512',
|
||||
'implicit policy preserves a normalized existing algorithm' ],
|
||||
[ $fips_defaults, "\tHMAC-SHA256 ", 'hmac-sha256',
|
||||
'FIPS policy does not replace a matching normalized algorithm' ],
|
||||
[ $sha512, " HMAC-SHA512\t", 'hmac-sha512',
|
||||
'explicit policy does not replace a matching normalized algorithm' ],
|
||||
) {
|
||||
my ( $settings, $current, $algorithm, $description ) = @{$case};
|
||||
is_deeply(
|
||||
xCAT_plugin::ddns::ddns_reconcile_key_algorithm($settings, $current),
|
||||
{ algorithm => $algorithm, replace => 0 },
|
||||
$description
|
||||
);
|
||||
}
|
||||
|
||||
is(
|
||||
xCAT_plugin::ddns::ddns_key_contents(
|
||||
{
|
||||
omapi_settings => $defaults,
|
||||
tsig_algorithm => ' HMAC-SHA512 ',
|
||||
privkey => 'legacy-secret',
|
||||
}
|
||||
),
|
||||
"key \"xcat_key\" {\n\talgorithm hmac-sha512;\n\tsecret \"legacy-secret\";\n};\n\n",
|
||||
'DDNS renders the normalized existing algorithm outside FIPS mode'
|
||||
);
|
||||
|
||||
is(
|
||||
xCAT_plugin::ddns::ddns_tsig_algorithm(
|
||||
{
|
||||
@@ -166,6 +282,55 @@ subtest 'Net::DNS threshold controls named key reconciliation' => sub {
|
||||
"Net::DNS $version leaves named alone"
|
||||
);
|
||||
}
|
||||
|
||||
my ( $harvested_key, $harvested_restart ) =
|
||||
reconcile_named_key( '1.35', privkey => undef );
|
||||
like(
|
||||
$harvested_key,
|
||||
qr/^\s*algorithm\s+hmac-sha256\s*;/m,
|
||||
'a harvested key keeps its algorithm on old Net::DNS'
|
||||
);
|
||||
ok( !$harvested_restart,
|
||||
'harvesting an unchanged key does not restart named' );
|
||||
};
|
||||
|
||||
subtest 'FIPS named key migration and signing agree' => sub {
|
||||
foreach my $case (
|
||||
['hmac-md5', 'hmac-sha256', 1, 163],
|
||||
['hmac-sha512', 'hmac-sha256', 1, 163],
|
||||
) {
|
||||
my ($current, $expected, $restart, $rr_type) = @{$case};
|
||||
foreach my $version ('1.35', '1.47') {
|
||||
foreach my $harvest (0, 1) {
|
||||
my $key_dir = tempdir(CLEANUP => 1);
|
||||
local $xCAT_plugin::ddns::ddns_key_path = "$key_dir/ddns.key";
|
||||
my ($named, $restarted, $ctx) = reconcile_named_key(
|
||||
$version, fips_mode => 1, current_algorithm => $current,
|
||||
privkey => $harvest ? undef : 'legacy-secret',
|
||||
);
|
||||
like($named, qr/^\s*algorithm\s+\Q$expected\E\s*;/m,
|
||||
"FIPS reconciles $current on Net::DNS $version, harvest=$harvest");
|
||||
is($restarted ? 1 : 0, $restart,
|
||||
'named restarts only when its algorithm changes');
|
||||
is($ctx->{privkey}, 'legacy-secret', 'migration preserves the shared secret');
|
||||
my $update = Local::DDNS::Update->new();
|
||||
with_net_dns_version($version, sub {
|
||||
xCAT_plugin::ddns::ddns_sign_update($ctx, $update);
|
||||
});
|
||||
my $arguments = $update->{sign_tsig_calls}->[0];
|
||||
if ($version eq '1.35') {
|
||||
is($arguments->[0]->algorithm, $rr_type,
|
||||
'old Net::DNS signs with the reconciled algorithm');
|
||||
} else {
|
||||
is_deeply($arguments, ["$key_dir/ddns.key"],
|
||||
'new Net::DNS uses the reconciled key file');
|
||||
like(read_text($arguments->[0]),
|
||||
qr/^\s*algorithm\s+\Q$expected\E\s*;/m,
|
||||
'the signing key file agrees with named and OMAPI');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
done_testing();
|
||||
@@ -178,20 +343,32 @@ sub with_net_dns_version {
|
||||
}
|
||||
|
||||
sub reconcile_named_key {
|
||||
my ($version) = @_;
|
||||
my ( $version, %args ) = @_;
|
||||
my $current = $args{current_algorithm} || 'hmac-sha256';
|
||||
my $key_dir = tempdir(CLEANUP => 1);
|
||||
local $xCAT_plugin::ddns::ddns_key_path =
|
||||
$xCAT_plugin::ddns::ddns_key_path eq '/etc/xcat/ddns.key'
|
||||
? "$key_dir/ddns.key" : $xCAT_plugin::ddns::ddns_key_path;
|
||||
|
||||
my ( $named_fh, $named_path ) = tempfile(UNLINK => 1);
|
||||
print {$named_fh}
|
||||
"options {\n};\n"
|
||||
. "key \"xcat_key\" {\n"
|
||||
. "\talgorithm hmac-sha256;\n"
|
||||
. "\talgorithm $current;\n"
|
||||
. "\tsecret \"legacy-secret\";\n"
|
||||
. "};\n";
|
||||
close($named_fh) or die "Unable to close $named_path: $!";
|
||||
|
||||
my $ctx = {
|
||||
omapi_settings => omapi_settings(),
|
||||
privkey => 'legacy-secret',
|
||||
omapi_settings => xCAT::DHCP::OmapiPolicy->settings(
|
||||
site_values => {
|
||||
dhcpomapialgorithm => undef,
|
||||
dhcpomapikeyname => undef,
|
||||
dhcpomshellpath => undef,
|
||||
},
|
||||
fips_mode => $args{fips_mode} || 0,
|
||||
),
|
||||
privkey => exists $args{privkey} ? $args{privkey} : 'legacy-secret',
|
||||
zonesdir => '/tmp',
|
||||
dbdir => '/tmp',
|
||||
zonestotouch => {},
|
||||
@@ -203,7 +380,6 @@ sub reconcile_named_key {
|
||||
|
||||
no warnings qw(redefine once);
|
||||
local *xCAT_plugin::ddns::get_conf = sub { return $named_path; };
|
||||
local *xCAT_plugin::ddns::ensure_ddns_key_file = sub { return; };
|
||||
local *xCAT::TableUtils::get_site_attribute = sub { return; };
|
||||
local *xCAT::Utils::runcmd = sub { return (); };
|
||||
local *xCAT::Utils::isAIX = sub { return 0; };
|
||||
@@ -217,13 +393,7 @@ sub reconcile_named_key {
|
||||
sub { xCAT_plugin::ddns::update_namedconf( $ctx, 0 ); }
|
||||
);
|
||||
|
||||
open( my $result_fh, '<', $named_path )
|
||||
or die "Unable to read $named_path: $!";
|
||||
local $/;
|
||||
my $contents = <$result_fh>;
|
||||
close($result_fh) or die "Unable to close $named_path: $!";
|
||||
|
||||
return ( $contents, $ctx->{restartneeded} );
|
||||
return ( read_text($named_path), $ctx->{restartneeded}, $ctx );
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -53,6 +53,41 @@ is(
|
||||
'default omshell preamble keeps legacy key command without key-algorithm'
|
||||
);
|
||||
|
||||
my $fips_defaults = xCAT::DHCP::OmapiPolicy->settings(
|
||||
site_values => {
|
||||
dhcpomapialgorithm => undef,
|
||||
dhcpomapikeyname => undef,
|
||||
dhcpomshellpath => undef,
|
||||
},
|
||||
fips_mode => 1,
|
||||
);
|
||||
is( $fips_defaults->{algorithm}, 'hmac-sha256',
|
||||
'FIPS mode defaults OMAPI to hmac-sha256' );
|
||||
ok( !$fips_defaults->{algorithm_explicit},
|
||||
'FIPS default remains distinct from an administrator override' );
|
||||
ok( $fips_defaults->{needs_omshell_key_algorithm},
|
||||
'FIPS default emits the omshell key algorithm' );
|
||||
is(
|
||||
xCAT::DHCP::OmapiPolicy->omshell_preamble(
|
||||
$fips_defaults, secret => 'fips-secret'
|
||||
),
|
||||
"key-algorithm hmac-sha256\nkey xcat_key \"fips-secret\"\n",
|
||||
'FIPS omshell preamble selects hmac-sha256'
|
||||
);
|
||||
|
||||
like(
|
||||
xCAT::DHCP::OmapiPolicy->settings(
|
||||
site_values => {
|
||||
dhcpomapialgorithm => 'hmac-md5',
|
||||
dhcpomapikeyname => undef,
|
||||
dhcpomshellpath => undef,
|
||||
},
|
||||
fips_mode => 1,
|
||||
)->{error},
|
||||
qr/hmac-md5 is not allowed while FIPS mode is enabled/,
|
||||
'FIPS mode rejects an explicit hmac-md5 override'
|
||||
);
|
||||
|
||||
is(
|
||||
xCAT::DHCP::OmapiPolicy->new_install_default_algorithm(
|
||||
is_new_install => 1,
|
||||
@@ -69,6 +104,23 @@ is(
|
||||
undef,
|
||||
'new EL8 installations retain the implicit MD5 default'
|
||||
);
|
||||
foreach my $platform ('el8', 'el9', 'sles15', 'ubuntu') {
|
||||
my $algorithm = xCAT::DHCP::OmapiPolicy->new_install_default_algorithm(
|
||||
is_new_install => 1, platform => $platform, fips_mode => 1,
|
||||
);
|
||||
is($algorithm, 'hmac-sha256', "new FIPS $platform sites save SHA-256");
|
||||
foreach my $fips_mode (0, 1) {
|
||||
my $settings = xCAT::DHCP::OmapiPolicy->settings(
|
||||
site_values => { dhcpomapialgorithm => $algorithm },
|
||||
fips_mode => $fips_mode,
|
||||
);
|
||||
is($settings->{algorithm}, 'hmac-sha256',
|
||||
"the shared $platform site selects SHA-256 on a host with FIPS=$fips_mode");
|
||||
}
|
||||
is(xCAT::DHCP::OmapiPolicy->new_install_default_algorithm(
|
||||
is_new_install => 0, platform => $platform, fips_mode => 1,
|
||||
), undef, "existing $platform sites are not overwritten");
|
||||
}
|
||||
is(
|
||||
xCAT::DHCP::OmapiPolicy->new_install_default_algorithm(
|
||||
is_new_install => 1,
|
||||
|
||||
Reference in New Issue
Block a user