mirror of
https://github.com/xcat2/xcat-core.git
synced 2026-10-21 07:08:12 +00:00
test(dhcp): cover conditional SHA client requirements
This commit is contained in:
@@ -0,0 +1,199 @@
|
||||
#!/usr/bin/env perl
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/../lib";
|
||||
use lib "$FindBin::Bin/../../perl-xCAT";
|
||||
use lib "$FindBin::Bin/../../xCAT-server/lib/perl";
|
||||
use Config;
|
||||
use File::Path qw(make_path);
|
||||
use File::Slurper qw(read_text write_text);
|
||||
use File::Temp qw(tempdir);
|
||||
use Test::More;
|
||||
use XCAT::Test::File qw(repo_path);
|
||||
|
||||
BEGIN {
|
||||
$ENV{XCATROOT} = repo_path('xCAT-server');
|
||||
$ENV{XCATCFG} = 'SQLite:' . tempdir(CLEANUP => 1);
|
||||
}
|
||||
|
||||
use xCAT::DHCP::OmapiPolicy;
|
||||
use xCAT::DHCP::OmapiRunner;
|
||||
|
||||
my $directory = tempdir(CLEANUP => 1);
|
||||
my $client = "$directory/custom-omshell";
|
||||
write_text($client, "#!$Config{perlpath}\n" . <<'PERL');
|
||||
use strict;
|
||||
use warnings;
|
||||
my $input = do { local $/; <STDIN> };
|
||||
open(my $trace, '>>', $ENV{OMAPI_TRACE}) or die $!;
|
||||
print {$trace} $input or die $!;
|
||||
close($trace) or die $!;
|
||||
if ($input eq "key-algorithm\n") {
|
||||
if ($ENV{OMAPI_CLIENT} eq 'legacy') {
|
||||
warn "unknown token: key-algorithm\n";
|
||||
print '> ';
|
||||
} elsif ($ENV{OMAPI_CLIENT} eq 'silent') {
|
||||
exit 0;
|
||||
} else {
|
||||
$| = 1;
|
||||
my $command = $ENV{OMAPI_CLIENT} eq 'corrected' ? 'key-algorithm' : 'key-algoritm';
|
||||
print "> missing or invalid algorithm name\nusage: $command <algorithm name>\n> ";
|
||||
exit 1 if $ENV{OMAPI_CLIENT} eq 'failed';
|
||||
if ($ENV{OMAPI_CLIENT} eq 'stalled') {
|
||||
$SIG{TERM} = 'IGNORE';
|
||||
open(my $pid, '>', $ENV{OMAPI_PID}) or die $!;
|
||||
print {$pid} $$;
|
||||
close($pid);
|
||||
sleep 60;
|
||||
}
|
||||
}
|
||||
}
|
||||
PERL
|
||||
chmod 0755, $client or die $!;
|
||||
local $ENV{OMAPI_TRACE} = "$directory/trace";
|
||||
local $ENV{OMAPI_PID} = "$directory/pid";
|
||||
|
||||
{
|
||||
package FastCapabilityRunner;
|
||||
use parent 'xCAT::DHCP::OmapiRunner';
|
||||
sub _completion_delay { die 'a probe has no server state to settle'; }
|
||||
sub _poll_interval { return 0.01; }
|
||||
sub _completion_attempts { return 500; }
|
||||
sub _termination_attempts { return 10; }
|
||||
}
|
||||
|
||||
sub settings {
|
||||
my ($algorithm, $fips) = @_;
|
||||
return xCAT::DHCP::OmapiPolicy->settings(
|
||||
fips_mode => $fips || 0,
|
||||
site_values => { dhcpomapialgorithm => $algorithm, dhcpomshellpath => $client }
|
||||
);
|
||||
}
|
||||
|
||||
for my $algorithm (undef, 'hmac-md5') {
|
||||
local $ENV{OMAPI_CLIENT} = 'legacy';
|
||||
unlink $ENV{OMAPI_TRACE};
|
||||
is(FastCapabilityRunner->key_algorithm_error(settings($algorithm)), undef,
|
||||
'legacy MD5 does not require a SHA-capable client');
|
||||
ok(!-e $ENV{OMAPI_TRACE}, 'MD5 does not execute the probe');
|
||||
}
|
||||
for my $mode (qw(modern corrected legacy silent failed stalled)) {
|
||||
local $ENV{OMAPI_CLIENT} = $mode;
|
||||
write_text($ENV{OMAPI_TRACE}, '');
|
||||
my $error = FastCapabilityRunner->key_algorithm_error(settings('hmac-sha256'));
|
||||
if ($mode eq 'modern' || $mode eq 'corrected') {
|
||||
is($error, undef, "$mode omshell supports SHA selection");
|
||||
} else {
|
||||
like($error, qr/\Q$client\E.*hmac-sha256.*dhcpomshellpath/,
|
||||
"$mode omshell is rejected with a remediation message");
|
||||
}
|
||||
is(read_text($ENV{OMAPI_TRACE}), "key-algorithm\n",
|
||||
"$mode probe sends no connection command or secret");
|
||||
}
|
||||
my $stalled_pid = read_text($ENV{OMAPI_PID});
|
||||
ok(!kill(0, $stalled_pid), 'the timed-out probe is reaped');
|
||||
{
|
||||
my $missing = settings('hmac-sha512');
|
||||
$missing->{omshell_path} = "$directory/missing";
|
||||
like(FastCapabilityRunner->key_algorithm_error($missing), qr/Cannot verify/,
|
||||
'a missing custom client fails closed');
|
||||
}
|
||||
|
||||
my $plugin = repo_path('xCAT-server/lib/xcat/plugins/dhcp.pm');
|
||||
require $plugin;
|
||||
{
|
||||
package CapabilityBackend;
|
||||
sub name { return $_[0]->{name}; }
|
||||
sub check_services { return {error => 'service boundary'}; }
|
||||
}
|
||||
{
|
||||
no warnings qw(redefine once);
|
||||
local *xCAT::Utils::isServiceNode = sub { return 0; };
|
||||
local *xCAT::Utils::isLinux = sub { return 1; };
|
||||
local *xCAT::Utils::isFIPS = sub { return 0; };
|
||||
local *xCAT::Utils::checkservicestatus = sub { return 1; };
|
||||
local %::XCATSITEVALS = (dhcpomapialgorithm => 'hmac-sha256', dhcpomshellpath => $client);
|
||||
for my $site (
|
||||
['rhels8.0', '', 1],
|
||||
['ubuntu20.04', '', 0], ['ubuntu20.04', '192.0.2.1', 1],
|
||||
['ubuntu22.04', '', 0], ['ubuntu22.04', '192.0.2.1', 1]
|
||||
) {
|
||||
local $xCAT_plugin::dhcp::distro = $site->[0];
|
||||
local $::XCATSITEVALS{externaldhcpservers} = $site->[1];
|
||||
for my $backend (qw(isc kea)) {
|
||||
local *xCAT::DHCP::Backend::new_backend = sub { return bless {name => $backend}, 'CapabilityBackend'; };
|
||||
for my $mode (qw(legacy modern)) {
|
||||
local $ENV{OMAPI_CLIENT} = $mode;
|
||||
write_text($ENV{OMAPI_TRACE}, '');
|
||||
my @messages;
|
||||
my $mask = umask;
|
||||
xCAT_plugin::dhcp::process_request({arg => ['-q'], node => ['node01']},
|
||||
sub { push @messages, map { @{$_->{error} || []}, @{$_->{data} || []} } @_; });
|
||||
umask $mask;
|
||||
my $messages = join ' ', @messages;
|
||||
my $probe = $backend eq 'isc' && $site->[2];
|
||||
my $label = "$site->[0] external=$site->[1] $backend $mode";
|
||||
if ($probe && $mode eq 'legacy') {
|
||||
like($messages, qr/Cannot verify key-algorithm/, "$label rejects an unsupported SHA client");
|
||||
} else {
|
||||
like($messages, qr/dhcp server is not running|service boundary/,
|
||||
"$label reaches the service check");
|
||||
}
|
||||
is(read_text($ENV{OMAPI_TRACE}), $probe ? "key-algorithm\n" : '',
|
||||
"$label probes only when the query uses OMAPI");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my $root = "$directory/root";
|
||||
make_path("$root/lib/perl/xCAT/DHCP", "$directory/commands");
|
||||
write_text("$root/lib/perl/xCAT/DHCP/Backend.pm", <<'PERL');
|
||||
package xCAT::DHCP::Backend;
|
||||
sub new_backend { return bless {}, __PACKAGE__; }
|
||||
sub name { return 'isc'; }
|
||||
1;
|
||||
PERL
|
||||
write_text("$root/lib/perl/xCAT/Table.pm", <<'PERL');
|
||||
package xCAT::Table;
|
||||
sub new { return bless {}, __PACKAGE__; }
|
||||
sub getAttribs { return {password => 'dGVzdA=='}; }
|
||||
1;
|
||||
PERL
|
||||
my $wrapper = "$directory/dhcpop-wrapper";
|
||||
write_text($wrapper, <<'PERL');
|
||||
use xCAT::DHCP::OmapiRunner;
|
||||
use xCAT::Utils;
|
||||
no warnings 'redefine';
|
||||
*xCAT::Utils::isFIPS = sub { return $ENV{OMAPI_FIPS}; };
|
||||
*xCAT::DHCP::OmapiRunner::_completion_delay = sub { return 0; };
|
||||
*xCAT::DHCP::OmapiRunner::_command_directory = sub { return $ENV{OMAPI_DIRECTORY}; };
|
||||
our %XCATSITEVALS = (dhcpomapialgorithm => $ENV{OMAPI_ALGORITHM}, dhcpomshellpath => $ENV{OMAPI_PATH});
|
||||
my $script = shift @ARGV;
|
||||
do $script;
|
||||
die $@ if $@;
|
||||
PERL
|
||||
for my $case (['hmac-md5', 0, 'legacy', 0], ['hmac-sha256', 0, 'legacy', 1],
|
||||
['hmac-sha256', 0, 'modern', 0], ['', 1, 'legacy', 1]) {
|
||||
local @ENV{qw(XCATROOT OMAPI_ALGORITHM OMAPI_FIPS OMAPI_CLIENT OMAPI_DIRECTORY OMAPI_PATH)} =
|
||||
($root, $case->[0], $case->[1], $case->[2], "$directory/commands", $client);
|
||||
write_text($ENV{OMAPI_TRACE}, '');
|
||||
open(my $child, '-|', $Config{perlpath}, "-I$root/lib/perl",
|
||||
'-I' . repo_path('perl-xCAT'), '-I' . repo_path('xCAT-server/lib/perl'),
|
||||
'-I' . repo_path('xCAT-test/lib'), $wrapper,
|
||||
repo_path('xCAT-server/share/xcat/tools/dhcpop'), '-r', '-n', 'node01') or die $!;
|
||||
my $output = do { local $/; <$child> };
|
||||
close($child);
|
||||
is($? >> 8, $case->[3], "dhcpop: algorithm=$case->[0] FIPS=$case->[1] client=$case->[2]");
|
||||
if ($case->[3]) {
|
||||
like($output, qr/Cannot verify key-algorithm/, 'dhcpop reports the capability error');
|
||||
unlike(read_text($ENV{OMAPI_TRACE}), qr/\bconnect\b|dGVzdA==/,
|
||||
'dhcpop stops before sending a secret or changing a lease');
|
||||
} else {
|
||||
like(read_text($ENV{OMAPI_TRACE}), qr/connect\nnew host/, 'dhcpop continues with the lease operation');
|
||||
}
|
||||
}
|
||||
|
||||
done_testing();
|
||||
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env perl
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/../lib";
|
||||
use Test::More;
|
||||
|
||||
use XCAT::Test::File qw(repo_path);
|
||||
|
||||
my $rpmspec = qx(command -v rpmspec 2>/dev/null);
|
||||
chomp($rpmspec);
|
||||
plan skip_all => 'rpmspec is required' unless $rpmspec && -x $rpmspec;
|
||||
|
||||
foreach my $spec ('xCAT/xCAT.spec', 'xCATsn/xCATsn.spec') {
|
||||
foreach my $build (
|
||||
['EL8', 'rhel 8'], ['EL9', 'rhel 9'], ['EL10', 'rhel 10'],
|
||||
['SLES15', 'suse_version 1500'], ['openEuler', 'openEuler 1'],
|
||||
) {
|
||||
foreach my $arch (qw(x86_64 ppc64le aarch64 s390x riscv64)) {
|
||||
open(my $fh, '-|', $rpmspec, '-q', '--requires', '--target', $arch,
|
||||
'--define', 'version 2.20.0', '--define', 'release 1',
|
||||
'--undefine', 'rhel', '--undefine', 'suse_version',
|
||||
'--undefine', 'openEuler', '--define', $build->[1],
|
||||
repo_path($spec)) or die "run rpmspec: $!";
|
||||
my @requires = <$fh>;
|
||||
close($fh) or BAIL_OUT("rpmspec failed for $spec on $build->[0]/$arch");
|
||||
chomp @requires;
|
||||
is_deeply(
|
||||
[grep { /\bdhcp-server\b/ } @requires], [],
|
||||
"$spec built on $build->[0]/$arch adds no SHA-only DHCP package floor"
|
||||
);
|
||||
is(scalar(grep { m{/usr/sbin/dhcpd} } @requires), 1,
|
||||
"$spec built on $build->[0]/$arch retains its DHCP backend requirement");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done_testing();
|
||||
Reference in New Issue
Block a user