diff --git a/xCAT-test/unit/cmdlog_response_redact.t b/xCAT-test/unit/cmdlog_response_redact.t index e79f4cd85..4bcc7054e 100644 --- a/xCAT-test/unit/cmdlog_response_redact.t +++ b/xCAT-test/unit/cmdlog_response_redact.t @@ -3,14 +3,18 @@ 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 Test::More; -my $xcatd = "$FindBin::Bin/../../xCAT-server/sbin/xcatd"; +use XCAT::Test::File qw(repo_path slurp_repo_file); +use xCAT::xcatd; + +my $xcatd = repo_path('xCAT-server/sbin/xcatd'); plan skip_all => 'xcatd not found' unless -r $xcatd; -open my $fh, '<', $xcatd or die $!; -my $src = do { local $/; <$fh> }; -close $fh; +my $src = slurp_repo_file('xCAT-server/sbin/xcatd'); # Extract the three command-log response subs and load them. xcatd is present, # so a sub that cannot be extracted is a hard failure, not a skip. @@ -36,6 +40,8 @@ die "eval of command-log subs failed: $@" if $@; # Classification from the request. ok(cmdlog_response_is_sensitive({ command => ['getcredentials'], arg => [] }, ''), 'getcredentials is a sensitive-response command'); +ok(cmdlog_response_is_sensitive({ command => ['lsvm'], arg => [] }, 0), + 'lsvm returns the directory entry with its passwords, so it is sensitive'); ok(cmdlog_response_is_sensitive({ command => ['gettab'], arg => ['key=xcat', 'passwd.password'] }, ''), 'gettab of a passwd column is sensitive'); ok(cmdlog_response_is_sensitive({ command => ['tabdump'], arg => ['passwd'] }, ''), @@ -45,6 +51,35 @@ ok(cmdlog_response_is_sensitive({ command => ['rspconfig'], arg => [] }, 1), ok(!cmdlog_response_is_sensitive({ command => ['rpower'], arg => ['n1', 'stat'] }, 0), 'a benign request is not sensitive'); +# A secret attribute with no "passw" in its name must classify through the +# shared secret set, not the text heuristic. +ok(cmdlog_response_is_sensitive({ command => ['gettab'], arg => ['node=pdu01', 'pdu.authkey'] }, 0), + 'gettab of an authentication key is sensitive'); +ok(cmdlog_response_is_sensitive({ command => ['gettab'], arg => ['node=pdu01', 'pdu.privkey'] }, 0), + 'gettab of a privacy key is sensitive'); +ok(cmdlog_response_is_sensitive({ command => ['gettab'], arg => ['key=snmpc', 'site.value'] }, 0), + 'gettab of the snmpc site value is sensitive'); +ok(!cmdlog_response_is_sensitive({ command => ['gettab'], arg => ['key=domain', 'site.value'] }, 0), + 'gettab of a plain site value is not sensitive'); + +# A dump of a whole table that owns a secret column returns the bare values. +ok(cmdlog_response_is_sensitive({ command => ['tabdump'], arg => ['token'] }, 0), + 'tabdump of the token table is sensitive'); +ok(cmdlog_response_is_sensitive({ command => ['tabdump'], arg => ['prodkey'] }, 0), + 'tabdump of the prodkey table is sensitive'); +ok(cmdlog_response_is_sensitive({ command => ['tabdump'], arg => ['site'] }, 0), + 'tabdump of the site table is sensitive'); +ok(cmdlog_response_is_sensitive({ command => ['tabdump'], arg => ['-w', 'key==snmpc', 'site'] }, 0), + 'a filtered site dump is sensitive'); +ok(!cmdlog_response_is_sensitive({ command => ['tabdump'], arg => ['networks'] }, 0), + 'tabdump of the networks table is not sensitive'); +ok(cmdlog_response_is_sensitive({ command => ['nodels'], noderange => ['node01'], arg => ['prodkey'] }, 0), + 'nodels of a whole secret table is sensitive'); +ok(!cmdlog_response_is_sensitive({ command => ['nodels'], noderange => ['switches'], arg => [] }, 0), + 'a group named like a secret table is not sensitive'); +ok(!cmdlog_response_is_sensitive({ command => ['nodels'], noderange => ['node01'], arg => ['nodetype'] }, 0), + 'nodels of a benign table is not sensitive'); + # Drive collect(s) then finalize, returning what was appended to the log. sub run { my ($sensitive, @responses) = @_; @@ -77,6 +112,15 @@ my $benign = run(0, "node01: on"); like($benign, qr/node01: on/, 'a benign response is logged verbatim'); unlike($benign, qr/\*REDACTED\*/, 'a benign response is not redacted'); +# A detailed object listing expands attributes the request never named. +my $lsdef = run(0, 'Object name: pdu01', ' authkey=AUTH_SECRET', ' privkey=PRIV_SECRET'); +unlike($lsdef, qr/AUTH_SECRET|PRIV_SECRET/, 'implicit lsdef secrets are not logged'); +like($lsdef, qr/\*REDACTED\*/, 'lsdef response containing secret attributes is redacted'); +my $colon = run(0, 'node01: prodkey.key: AAAAA-BBBBB'); +unlike($colon, qr/AAAAA/, 'a colon separated secret column is redacted'); +my $plain = run(0, 'Object name: node01', ' groups=compute', ' mgt=ipmi'); +unlike($plain, qr/\*REDACTED\*/, 'a benign object listing is not redacted'); + # Two requests on one connection: the finalizer runs at the next command's # start. The earlier response must be preserved (redacted), the flag reset, and # the next benign response neither lost nor over-redacted.