Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 26 additions & 6 deletions xCAT-genesis-scripts/usr/bin/bmcsetup
Original file line number Diff line number Diff line change
Expand Up @@ -481,9 +481,27 @@ for user in $BMCUS; do
if [ "$user" = "" ]; then
continue
fi
DISABLEUSERS=$(ipmitool user list $LANCHAN|awk '{print $1}'|grep -v ID)
if USERLIST=$(ipmitool -d $idev user list "$LANCHAN") && [ -n "$USERLIST" ]; then
DISABLEUSERS=$(echo "$USERLIST" | awk '$1 != "ID" && $1 ~ /^[0-9]+$/ {print $1}')
ENABLEDUSERS=$(echo "$USERLIST" | awk '
$1 == "ID" { next }
$1 !~ /^[0-9]+$/ { next }
{
ipmi_msg = $(NF - 1)
if ($(NF - 1) == "NO" && $NF == "ACCESS") {
ipmi_msg = $(NF - 2)
}
if (ipmi_msg == "true") {
print $1
}
}')
else
DISABLEUSERS=$(ipmitool user list "$LANCHAN"|awk '{print $1}'|grep -v ID)
ENABLEDUSERS="$DISABLEUSERS"
logger -s -t $log_label -p local4.warning "Could not read IPMI user list for device $idev, falling back to disabling all non-target users"
fi
# Get the User Slots
USERSLOT=`ipmitool -d $idev user list $LANCHAN |grep -v ^ID|awk '{print $1 " " $2}'|grep -w "$BMCUS"|awk '{print $1}'`
USERSLOT=$(echo "$USERLIST" | awk -v user="$user" '$1 != "ID" && $2 == user {print $1; exit}')
if [ -z "$USERSLOT" ]; then
USERSLOT=$((`ipmitool raw 6 0x44 1 1|awk '{print $3}'` + 1))
fi
Expand All @@ -498,7 +516,7 @@ for user in $BMCUS; do
done
fi
# fall back to userslot 2 as a last resort
if [ "$USERSLOT" == 0 ]; then $USERSLOT = 2; fi
if [ "$USERSLOT" = 0 ]; then USERSLOT=2; fi
if [ "$ISITE" = 1 ]; then
allowcred.awk &
CREDPID=$!
Expand All @@ -510,13 +528,15 @@ for user in $BMCUS; do
fi

# Get the specified user
CURRENTUSER=`ipmitool -d $idev user list $LANCHAN|grep ^$USERSLOT|awk '{print $2}'`
DISABLEUSERS=`echo $DISABLEUSERS|sed -e s/$USERSLOT//`
CURRENTUSER=$(echo "$USERLIST" | awk -v slot="$USERSLOT" '$1 == slot {print $2; exit}')
DISABLEUSERS=$(echo "$DISABLEUSERS" | awk -v slot="$USERSLOT" '$1 != slot {print $1}')
logger -s -t $log_label -p local4.info "CURRENTUSER=$CURRENTUSER, DISABLEUSERS=$DISABLEUSERS"
for userid in $DISABLEUSERS; do
TRIES=0
# user disable is not idempotent on several BMCs; skip slots already disabled.
echo "$ENABLEDUSERS" | grep -q "^${userid}$" || continue
# Disable the non-specified user
while ! ipmitool -d $idev user disable $userid; do
while ! ipmitool -d $idev user disable "$userid"; do
sleep 1
let TRIES=TRIES+1
if [ $TRIES -gt $TIMEOUT ]; then break; fi
Expand Down
165 changes: 165 additions & 0 deletions xCAT-test/unit/bmcsetup_disable_users.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
#!/usr/bin/env perl
use strict;
use warnings;

use File::Path qw(make_path);
use File::Temp qw(tempdir);
use FindBin;
use Test::More;

my $bmcsetup = "$FindBin::Bin/../../xCAT-genesis-scripts/usr/bin/bmcsetup";
plan skip_all => 'bmcsetup script not found' unless -x $bmcsetup;

my $ipmicfg = '/tmp/ipmicfg.xml';
my $cleanup_ipmicfg = !-e $ipmicfg;
plan skip_all => "$ipmicfg already exists" unless $cleanup_ipmicfg;
END {
unlink $ipmicfg if $cleanup_ipmicfg && -e $ipmicfg;
}

my $tmpdir = tempdir(CLEANUP => 1);
my $bindir = "$tmpdir/bin";
make_path($bindir);

write_executable(
"$bindir/ipmitool",
<<'EOF'
#!/bin/sh
echo "$@" >> "$IPMITOOL_CALL_LOG"

if [ "$1" = "-V" ]; then
echo "ipmitool version 1.8.19"
exit 0
fi

if [ "$1" = "-d" ]; then
shift 2
fi

case "$1" in
mc)
if [ "$2" = "info" ]; then
cat <<MCINFO
IPMI Version : 2.0
Manufacturer ID : 10876
Product ID : 2437
MCINFO
exit 0
fi
;;
channel)
if [ "$2" = "info" ]; then
echo "Channel Medium Type : 802.3"
exit 0
fi
if [ "$2" = "getaccess" ]; then
echo "Fixed Name : No"
exit 0
fi
;;
user)
case "$2" in
list)
cat "$IPMITOOL_USER_LIST"
exit 0
;;
disable)
echo "$3" >> "$IPMITOOL_DISABLE_LOG"
exit 0
;;
enable|priv|set)
exit 0
;;
esac
;;
raw|lan|chassis)
exit 0
;;
esac

exit 0
EOF
);

write_executable("$bindir/logger", "#!/bin/sh\nexit 0\n");
write_executable("$bindir/modprobe", "#!/bin/sh\nexit 0\n");
write_executable("$bindir/sleep", "#!/bin/sh\nexit 0\n");
write_executable("$bindir/updateflag.awk", "#!/bin/sh\nexit 0\n");
write_executable("$bindir/remoteimmsetup", "#!/bin/sh\nexit 0\n");
write_executable("$bindir/allowcred.awk", "#!/bin/sh\nexit 0\n");
write_executable(
"$bindir/getipmi",
<<'EOF'
#!/bin/sh
cat > /tmp/ipmicfg.xml <<IPMICFG
<bmcip>10.0.0.2</bmcip>
<taggedvlan>off</taggedvlan>
<gateway>10.0.0.1</gateway>
<netmask>255.255.255.0</netmask>
<username>USERID</username>
<password>passw0rd</password>
<ipcfgmethod>static</ipcfgmethod>
IPMICFG
exit 0
EOF
);

my $user_list = "$tmpdir/user-list.txt";
write_file(
$user_list,
<<'EOF'
ID Name Callin Link Auth IPMI Msg Channel Priv Limit
1 true false false NO ACCESS
2 USERID true true true ADMINISTRATOR
3 true false false NO ACCESS
4 olduser true true true ADMINISTRATOR
5 viewer true true false NO ACCESS
EOF
);

my $call_log = "$tmpdir/ipmitool-calls.log";
my $disable_log = "$tmpdir/disabled-users.log";

local $ENV{PATH} = "$bindir:$ENV{PATH}";
local $ENV{IPMITOOL_USER_LIST} = $user_list;
local $ENV{IPMITOOL_CALL_LOG} = $call_log;
local $ENV{IPMITOOL_DISABLE_LOG} = $disable_log;

my $output = `bash "$bmcsetup" 2>&1`;
my $rc = $? >> 8;
is($rc, 0, 'bmcsetup exits successfully with stubbed IPMI commands')
or diag($output);

my @disabled = read_lines($disable_log);
is_deeply(\@disabled, ['4'], 'bmcsetup disables only enabled non-target user slots');

my @calls = read_lines($call_log);
ok(
!grep({ /user disable (1|3|5)\b/ } @calls),
'bmcsetup does not retry user disable for slots that are already disabled'
);

done_testing();

sub write_executable {
my ($path, $content) = @_;
write_file($path, $content);
chmod 0755, $path or die "chmod $path: $!";
}

sub write_file {
my ($path, $content) = @_;
open(my $fh, '>', $path) or die "open $path: $!";
print {$fh} $content;
close($fh) or die "close $path: $!";
}

sub read_lines {
my ($path) = @_;
return () unless -e $path;
open(my $fh, '<', $path) or die "open $path: $!";
my @lines = <$fh>;
close($fh) or die "close $path: $!";
chomp @lines;
return @lines;
}