Commit f1206314 authored by Mike Hibler's avatar Mike Hibler

More tightly connect the notion of a firewall and the security level.

If you specify an explicit firewall, you are implicitly assigned security
level 2 and you cannot explicitly specify the security level.  Likewise,
if you specify a security level, you cannot also specify a firewall.

The reason for this is that security level 1 (aka "Blue") now has a slightly
different meaning.  It is intended for protecting the inside from the outside
rather than visa-versa.  The only practical implication of this is that for
level 1, we don't do all the fancy power-off-boot-into-MFS-zapbootblock stuff
that we do for higher levels.

Anyway, I wanted to make sure that if you specify your own firewall, you
DO have to go through the full cleansing swapout since we can't trust a
firewall that the Average Joe sets up.
parent 6090e114
......@@ -210,8 +210,8 @@ use vars qw(@ISA @EXPORT);
TBGetUniqueIndex
TBExptMinMaxNodes TBExptSecurityLevel TBExptIDX
TBDB_SECLEVEL_GREEN TBDB_SECLEVEL_YELLOW
TBDB_SECLEVEL_ORANGE TBDB_SECLEVEL_RED
TBDB_SECLEVEL_GREEN TBDB_SECLEVEL_BLUE TBDB_SECLEVEL_YELLOW
TBDB_SECLEVEL_ORANGE TBDB_SECLEVEL_RED TBDB_SECLEVEL_ZAPDISK
TBExptSetPanicBit TBExptGetPanicBit TBExptClearPanicBit
......@@ -657,9 +657,13 @@ sub TBDB_CHECKDBSLOT_ERROR() { 0x2; }
# Security Levels.
sub TBDB_SECLEVEL_GREEN() { 0; }
sub TBDB_SECLEVEL_YELLOW() { 1; }
sub TBDB_SECLEVEL_ORANGE() { 2; }
sub TBDB_SECLEVEL_RED() { 3; }
sub TBDB_SECLEVEL_BLUE() { 1; }
sub TBDB_SECLEVEL_YELLOW() { 2; }
sub TBDB_SECLEVEL_ORANGE() { 3; }
sub TBDB_SECLEVEL_RED() { 4; }
# This is the level at which we get extremely cautious when swapping out
sub TBDB_SECLEVEL_ZAPDISK() { TBDB_SECLEVEL_YELLOW; }
#
# A hash of all tables that contain information about physical nodes - the
......
......@@ -19,6 +19,8 @@ namespace eval GLOBALS {
Firewall instproc init {s} {
global ::GLOBALS::last_class
var_import ::GLOBALS::explicit_firewall
var_import ::GLOBALS::security_level
$self set sim $s
......@@ -36,6 +38,13 @@ Firewall instproc init {s} {
if {[$s add_firewall $self] == 0} {
set ::GLOBALS::last_class $self
}
if {$security_level} {
perror "\[add_firewall] cannot combine firewall with security-level"
}
# avoid conflicts with security_level
set explicit_firewall 1
}
Firewall instproc rename {old new} {
......
......@@ -2,9 +2,17 @@
# This file is intended to be included into another NS file. It is not
# a stand alone file.
#
if {${::GLOBALS::security_level} >= 1} {
if {${::GLOBALS::explicit_firewall}} {
# explicit firewalls require disk zappage
set ::GLOBALS::security_level ${::GLOBALS::security_level_diskzap}
} elseif {${::GLOBALS::security_level} >= 1} {
# Set up a firewall
# XXX hack: have to clear the security level temporarily
set sl ${::GLOBALS::security_level}
set ::GLOBALS::security_level 0
set fw [new Firewall $ns]
set ::GLOBALS::security_level $sl
$fw set-type ipfw2-vlan
if {${::GLOBALS::security_level} == 1} {
......
......@@ -263,8 +263,13 @@ namespace eval GLOBALS {
variable elabinelab_eid {}
variable elabinelab_cvstag {}
# Security level. Defaults to green
# Security level. Defaults to 0 ("green")
# If explicit_firewall is set, then you cannot also give a security level.
# security_level_diskzap is the level at which we need to zap the disk
# at swapout time. This value (2) is encoded in libdb.pm also.
variable security_level 0
variable explicit_firewall 0
variable security_level_diskzap 2
# List of source files.
variable sourcefile_list {}
......
......@@ -368,6 +368,7 @@ Simulator instproc run {} {
var_import ::GLOBALS::elabinelab_eid
var_import ::GLOBALS::elabinelab_cvstag
var_import ::GLOBALS::security_level
var_import ::GLOBALS::explicit_firewall
var_import ::GLOBALS::sourcefile_list
if {$ran == 1} {
......@@ -383,7 +384,7 @@ Simulator instproc run {} {
}
uplevel 1 real_source "@prefix@/lib/ns2ir/${nsfilename}"
}
if {$security_level} {
if {$security_level || $explicit_firewall} {
uplevel 1 real_source "@prefix@/lib/ns2ir/fw.ns"
}
......
......@@ -1492,6 +1492,11 @@ proc tb-set-node-inner-elab-role {node role} {
#
proc tb-set-security-level {level} {
var_import ::GLOBALS::security_level
var_import ::GLOBALS::explicit_firewall
if {$explicit_firewall} {
perror "\[tb-set-security-level] cannot combine with explicit firewall"
}
switch -- $level {
"Green" {
......
......@@ -1081,7 +1081,7 @@ sub doSwapin($) {
#
if ($firewalled) {
tberror "Not retrying, ".
"firewall may be preventing setup.";
"possibly an error in firewall setup or configuration.";
return 1;
}
......@@ -1442,9 +1442,10 @@ sub doFW($$$$) {
#
sub undoFWNodes($$;@) {
my ($pid, $eid, @nodes) = @_;
my $doall = 0;
my $fwerr = 0;
my @fwstate = ();
my $doall = 0;
my $fwerr = 0;
my @fwstate = ();
my $zap = 1;
if (!defined(@nodes) || @nodes == 0) {
@nodes = ExpNodes($pid, $eid, 1);
......@@ -1471,35 +1472,53 @@ sub undoFWNodes($$;@) {
}
#
# First turn off all the machines.
# If we fail, the firewall in left in place, and some nodes may
# be powered off.
# At the lowest level of security, we don't do the diskzap dance
# unless we have paniced.
#
# This level ("blue") is used for experiments where we are trying to
# protect the inside from outside; i.e., there is no bad stuff inside
# to clean up.
#
print STDERR "Powering down firewalled nodes.\n";
TBDebugTimeStamp("Powering down nodes");
system("power off @nodes");
if ($?) {
$fwerr = "Failed to power off all nodes!";
@fwstate = ("Firewall is still in place",
"Some nodes may NOT be powered off",
"Nodes NOT switched to admin MFS");
goto done;
my $paniced;
my $security_level;
if (TBExptGetPanicBit($pid, $eid, \$paniced) && $paniced == 0 &&
TBExptSecurityLevel($pid, $eid, \$security_level) &&
$security_level < TBDB_SECLEVEL_ZAPDISK()) {
$zap = 0;
}
#
# Force all nodes into admin mode.
# If we fail, the firewall is left in place.
# First turn off all the machines.
# If we fail, the firewall in left in place, and some nodes may
# be powered off.
#
my %myargs;
$myargs{'name'} = "tbswap";
$myargs{'on'} = 1;
$myargs{'clearall'} = 1;
if (TBAdminMfsSelect(\%myargs, undef, @nodes)) {
$fwerr = "Failed to force all nodes into admin mode!";
@fwstate = ("Firewall is still in place",
"All nodes are powered off",
"Not all nodes have been switched to admin MFS");
goto done;
if ($zap) {
print STDERR "Powering down firewalled nodes.\n";
TBDebugTimeStamp("Powering down nodes");
system("power off @nodes");
if ($?) {
$fwerr = "Failed to power off all nodes!";
@fwstate = ("Firewall is still in place",
"Some nodes may NOT be powered off",
"Nodes NOT switched to admin MFS");
goto done;
}
#
# Force all nodes into admin mode.
# If we fail, the firewall is left in place.
#
my %myargs;
$myargs{'name'} = "tbswap";
$myargs{'on'} = 1;
$myargs{'clearall'} = 1;
if (TBAdminMfsSelect(\%myargs, undef, @nodes)) {
$fwerr = "Failed to force all nodes into admin mode!";
@fwstate = ("Firewall is still in place",
"All nodes are powered off",
"Not all nodes have been switched to admin MFS");
goto done;
}
}
#
......@@ -1515,8 +1534,8 @@ sub undoFWNodes($$;@) {
if (doFW($pid, $eid, FWTEARDOWN, undef)) {
$fwerr = "Failed to tear down firewall!";
@fwstate = ("Firewall may NOT be in place",
"All nodes are powered off",
"All nodes set to admin mode",
$zap ? ("All nodes are powered off",
"All nodes set to admin mode") : (),
"Switch/DB firewall state could be inconsistent!");
goto done;
}
......@@ -1525,8 +1544,8 @@ sub undoFWNodes($$;@) {
if (doFW($pid, $eid, FWDELNODES, \@deleted)) {
$fwerr = "Failed to remove nodes from firewall VLAN!";
@fwstate = ("Nodes may still be in firewall VLAN",
"All nodes are powered off",
"All nodes set to admin mode");
$zap ? ("All nodes are powered off",
"All nodes set to admin mode") : ());
goto done;
}
}
......@@ -1542,25 +1561,28 @@ sub undoFWNodes($$;@) {
# let the experiment swapout finish, freeing up the nodes that
# did succeed.
#
print STDERR "Booting nodes into admin MFS and zapping bootblocks.\n";
TBDebugTimeStamp("Booting admin MFS/zapping bootblocks");
my @failed = ();
%myargs = ();
$myargs{'name'} = "tbswap";
$myargs{'command'} = "sudo /usr/local/bin/diskzap";
$myargs{'poweron'} = 1;
if (TBAdminMfsRunCmd(\%myargs, \@failed, @nodes)) {
$fwerr = "Failed to invalidate bootblocks on @failed!";
@fwstate = ("Firewall is NOT in place",
"All nodes set to admin mode");
system("power off @nodes");
if ($?) {
push(@fwstate, "Some nodes may NOT be powered off");
} else {
push(@fwstate, "All nodes are powered off");
if ($zap) {
print STDERR "Booting nodes into admin MFS and zapping bootblocks.\n";
TBDebugTimeStamp("Booting admin MFS/zapping bootblocks");
my @failed = ();
%myargs = ();
$myargs{'name'} = "tbswap";
$myargs{'command'} = "sudo /usr/local/bin/diskzap";
$myargs{'poweron'} = 1;
if (TBAdminMfsRunCmd(\%myargs, \@failed, @nodes)) {
$fwerr = "Failed to invalidate bootblocks on @failed!";
@fwstate = ("Firewall is NOT in place",
"All nodes set to admin mode");
system("power off @nodes");
if ($?) {
push(@fwstate, "Some nodes may NOT be powered off");
} else {
push(@fwstate, "All nodes are powered off");
}
push(@fwstate, "MAKE SURE THESE NODES DO NOT BOOT FROM DISK!");
}
push(@fwstate, "MAKE SURE THESE NODES DO NOT BOOT FROM DISK!");
}
done:
#
# If we had a failure when tearing down the firewall completely,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment