All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

Commit 3e05832d authored by Leigh B. Stoller's avatar Leigh B. Stoller

The Big group thing!

parent a1f22169
......@@ -1047,7 +1047,8 @@ outfiles="$outfiles Makeconf GNUmakefile \
tbsetup/tbreport tbsetup/named_setup tbsetup/exports_setup \
tbsetup/checkpass/GNUmakefile tbsetup/assign_wrapper tbsetup/ptopgen \
tbsetup/frisbeelauncher tbsetup/node_update tbsetup/webnodeupdate \
tbsetup/savelogs \
tbsetup/savelogs tbsetup/group-update tbsetup/webgroupupdate \
tbsetup/rmgroup tbsetup/webrmgroup tbsetup/mkexpdir \
tip/GNUmakefile \
tmcd/GNUmakefile tmcd/freebsd/GNUmakefile tmcd/linux/GNUmakefile \
tmcd/netbsd/GNUmakefile \
......
......@@ -169,7 +169,8 @@ outfiles="$outfiles Makeconf GNUmakefile \
tbsetup/tbreport tbsetup/named_setup tbsetup/exports_setup \
tbsetup/checkpass/GNUmakefile tbsetup/assign_wrapper tbsetup/ptopgen \
tbsetup/frisbeelauncher tbsetup/node_update tbsetup/webnodeupdate \
tbsetup/savelogs \
tbsetup/savelogs tbsetup/group-update tbsetup/webgroupupdate \
tbsetup/rmgroup tbsetup/webrmgroup tbsetup/mkexpdir \
tip/GNUmakefile \
tmcd/GNUmakefile tmcd/freebsd/GNUmakefile tmcd/linux/GNUmakefile \
tmcd/netbsd/GNUmakefile \
......
......@@ -39,11 +39,13 @@ use libtestbed;
# We don't want to run this script unless its the real version.
#
if ($EUID != 0) {
die("Must be root! Maybe its a development version?\n");
die("*** $0:\n".
" Must be root! Maybe its a development version?\n");
}
# XXX Hacky!
if ($TB ne "/usr/testbed") {
die("Wrong version. Maybe its a development version?\n");
die("*** $0:\n".
" Wrong version. Maybe its a development version?\n");
}
#
......@@ -76,7 +78,8 @@ foreach my $active ( 0, 1 ) {
# All active users on the testbed
if (! ($query_result =
DBQuery("SELECT DISTINCT u.usr_email from experiments as e ".
"left join proj_memb as p on e.pid=p.pid ".
"left join group_membership as p ".
" on e.pid=p.pid and p.pid=p.gid ".
"left join users as u on u.uid=p.uid ".
"where u.status='active' order by u.usr_email"))) {
DBFatal("Getting Active Users!");
......
This diff is collapsed.
......@@ -41,17 +41,20 @@ my @nodes= ();
if ($debug) { print "Expt '$eid', proj '$pid'\n"; }
#
# Make sure the user is a member of the correct project, and that the
# experiment exists
# Experiment must exist.
#
if (!ExpState($pid,$eid)) {
die "There is no experiment $eid in project $pid\n";
}
#
# User must have permission to modify the experiment.
#
if ($UID) {
if (!ProjMember($pid)) {
die "You are not a member of project $pid\n";
if (!TBExptAccessCheck($UID, $pid, $eid, TB_EXPT_MODIFY)) {
die("*** You not have permission to allocate nodes in $pid/$eid!\n");
}
}
if (!ExpState($pid,$eid)) {
die "There is no experiment $eid in project $pid\n";
}
######################################################################
# Step 1 - Make a list of nodes to reserve
......
......@@ -261,7 +261,7 @@ int main(int argc, char *argv[])
{
int userdir = 0; /* ~userdir flag */
uid_t uid; /* user information */
gid_t gid; /* target group placeholder */
gid_t gid, primary_gid; /* target group placeholder */
char *target_uname; /* target user name */
char *target_gname; /* target group name */
char *target_homedir; /* target home directory */
......@@ -411,6 +411,7 @@ int main(int argc, char *argv[])
* Save these for later since initgroups will hose the struct
*/
uid = pw->pw_uid;
primary_gid = pw->pw_gid;
actual_uname = strdup(pw->pw_name);
target_homedir = strdup(pw->pw_dir);
......@@ -441,6 +442,30 @@ int main(int argc, char *argv[])
exit(108);
}
#ifdef TESTBED
{
int groups[NGROUPS], ngroups, i;
ngroups = NGROUPS;
getgrouplist(actual_uname, primary_gid, groups, &ngroups);
if (ngroups == NGROUPS) {
log_err("emerg: failed to getgroups (%ld: %s)\n", gid, cmd);
exit(109);
}
for (i = 0; i < ngroups; i++) {
if (groups[i] == gid)
break;
}
if (i == ngroups)
groups[ngroups++] = gid;
if (((setgid(primary_gid)) != 0) ||
(setgroups(ngroups, groups) != 0)) {
log_err("emerg: failed to setgid (%ld: %s)\n", gid, cmd);
exit(109);
}
}
#else
/*
* Change UID/GID here so that the following tests work over NFS.
*
......@@ -451,6 +476,7 @@ int main(int argc, char *argv[])
log_err("emerg: failed to setgid (%ld: %s)\n", gid, cmd);
exit(109);
}
#endif
/*
* setuid() to the target user. Error out on fail.
......
......@@ -19,12 +19,14 @@ USERBINS = os_load node_reboot nscheck node_update savelogs
SBIN_STUFF = resetvlans console_setup.proxy sched_reload named_setup \
batch_daemon exports_setup reload_daemon sched_reserve \
console_reset db2ns bwconfig frisbeelauncher
console_reset db2ns bwconfig frisbeelauncher group-update \
rmgroup
LIBEXEC_STUFF = mkprojdir rmproj mkacct-ctrl rmacct-ctrl \
os_setup mkexpdir console_setup webnscheck webreport \
webstartexp webendexp webbatchexp webkillbatchexp \
assign_wrapper ptopgen webnodeupdate
assign_wrapper ptopgen webnodeupdate webgroupupdate \
webrmgroup
LIB_STUFF = libtbsetup.pm exitonwarn.pm libtestbed.pm snmpit_intel.pm \
snmpit_cisco.pm snmpit_lib.pm snmpit_apc.pm power_rpc27.pm
......@@ -68,6 +70,8 @@ post-install:
chmod u+s $(INSTALL_LIBEXECDIR)/mkprojdir
chown root $(INSTALL_LIBEXECDIR)/rmproj
chmod u+s $(INSTALL_LIBEXECDIR)/rmproj
chown root $(INSTALL_SBINDIR)/rmgroup
chmod u+s $(INSTALL_SBINDIR)/rmgroup
chown root $(INSTALL_LIBEXECDIR)/mkacct-ctrl
chmod u+s $(INSTALL_LIBEXECDIR)/mkacct-ctrl
chown root $(INSTALL_LIBEXECDIR)/rmacct-ctrl
......@@ -78,6 +82,8 @@ post-install:
chmod u+s $(INSTALL_SBINDIR)/exports_setup
chown root $(INSTALL_BINDIR)/savevlans
chmod u+s $(INSTALL_BINDIR)/savevlans
chown root $(INSTALL_SBINDIR)/group-update
chmod u+s $(INSTALL_SBINDIR)/group-update
chown root $(INSTALL_LIBEXECDIR)/console_setup
chmod u+s $(INSTALL_LIBEXECDIR)/console_setup
chown root $(INSTALL_BINDIR)/node_reboot
......
......@@ -54,6 +54,7 @@ my $dirname;
#
my $eid;
my $pid;
my $gid;
my $logname;
my $nsfile;
my $user_name = "Testbed Operations";
......@@ -209,11 +210,12 @@ sub dosomething($$)
{
my($dowhat) = shift;
my(%exphash) = @_;
my($uid, $gid, $row, $query_result);
my($unix_uid, $unix_gid, $row, $query_result);
# Global vars
$eid = $exphash{'eid'};
$pid = $exphash{'pid'};
$gid = $exphash{'gid'};
print "Doing a '$dowhat' to batch experiment $pid/$eid\n";
......@@ -277,19 +279,19 @@ sub dosomething($$)
# Figure out the unix uid/gid that the experiment configuration is
# going to run as.
#
(undef,undef,$uid) = getpwnam($creator) or
(undef,undef,$unix_uid) = getpwnam($creator) or
fatal("No such user $creator");
(undef,undef,$gid) = getgrnam($pid) or
fatal("No such group $pid");
(undef,undef,$unix_gid) = getgrnam($gid) or
fatal("No such group $gid");
#
# Change the ownership of the log file before we flip.
#
chown($uid, $gid, $logname);
chown($unix_uid, $unix_gid, $logname);
# Flip to the user. We never flip back.
$EGID = $GID = $gid;
$EUID = $UID = $uid;
$EGID = $GID = $unix_gid;
$EUID = $UID = $unix_uid;
$ENV{'USER'} = $creator;
if ($dowhat eq "start") {
......@@ -323,15 +325,16 @@ sub startexp($)
#
$query_result =
DBQueryFatal("insert into experiments ".
"(eid, pid, expt_created, expt_name, ".
"(eid, pid, gid, expt_created, expt_name, ".
"expt_head_uid, expt_expires, state, batchmode) ".
"VALUES ('$eid', '$pid', '$rightnow', '$longname', ".
"'$creator', '$expires', 'new', 1)");
"VALUES ('$eid', '$pid', '$gid', '$rightnow', ".
" '$longname', ".
" '$creator', '$expires', 'new', 1)");
#
# Try to start the experiment. If it fails, the experiment is gone.
#
system("$startexp -b $logname $pid $eid $nsfile");
system("$startexp -b $logname -g $gid $pid $eid $nsfile");
$exit_status = $? >> 8;
$running = 1;
if ($exit_status) {
......
......@@ -5,8 +5,6 @@ use Getopt::Std;
#
# Create a batch experiment.
#
# usage: batchexp <batchfile>
#
sub usage()
{
print STDOUT "Usage: batchexp <batchfile>\n";
......@@ -29,7 +27,7 @@ use libtestbed;
my $tbbindir = "$TB/bin/";
my $batchdir = "$TB/batch";
my $parser = "/usr/testbed/libexec/ns2ir/parse.tcl";
my $parser = "$TB/libexec/ns2ir/parse.tcl";
my $projroot = "/proj";
my $dirname;
......@@ -74,19 +72,21 @@ else {
#
my $eid;
my $pid;
my $gid;
my $dbuid;
my $longname;
my $expires;
my $webnsfile;
parse_batchfile($tempfile) or
fatal("Could not parse batchfile $tempfile");
fatal("*** Could not parse batchfile $tempfile");
#
# Sanity check a few things.
#
if (!defined($eid) || !defined($pid) || !defined($longname) ||
!defined($expires) || !defined($webnsfile)) {
fatal("Batchfile is incomplete!");
fatal("*** Batchfile is incomplete!");
}
$nsfile = "$eid.ns";
......@@ -96,50 +96,33 @@ $nsfile = "$eid.ns";
$dirname = "$batchdir/$pid-$eid";
mkdir($dirname, 0775) or
fatal("Could not mkdir $dirname: $!");
fatal("*** Could not mkdir $dirname: $!");
chdir($dirname) or
fatal("Could not chdir to $dirname: $!");
fatal("*** Could not chdir to $dirname: $!");
#
# Copy in the batch file. Web script is responsible for removing the
# original.
#
if (system("/bin/cp", "$tempfile", "batchfile")) {
fatal("Could not copy $tempfile to $dirname");
fatal("*** Could not copy $tempfile to $dirname");
}
#
# Now a bunch of DB checks.
#
# First off, get some user information.
# Verify user and get his DB uid.
#
$query_result =
DBQuery("SELECT uid from users WHERE unix_uid='$EUID'");
if ($query_result->numrows < 1) {
fatal("Go Away! You do not exist in the Emulab Database.");
if (! UNIX2DBUID($UID, \$dbuid)) {
fatal("*** You do not exist in the Emulab Database!");
}
@row = $query_result->fetchrow_array();
$uid = $row[0];
#
# Make sure UID is allowed to create experiments in this project.
#
$query_result =
DBQuery("SELECT trust from proj_memb WHERE uid='$uid' and pid='$pid'");
if ($query_result->numrows == 0) {
fatal("Go Away! You are not a member of project $pid!");
}
@row = $query_result->fetchrow_array();
$trust = $row[0];
if ($trust ne "local_root" &&
$trust ne "group_root") {
fatal("Go Away! You are not a trusted member of project $pid!");
if (!TBAdmin($UID) &&
!TBProjAccessCheck($dbuid, $pid, $gid, TB_PROJECT_CREATEEXPT)) {
fatal("*** You do not have permission to create experiments ".
"in project $pid";
}
#
......@@ -150,7 +133,7 @@ $query_result =
"WHERE eid='$eid' and pid='$pid'");
if ($query_result->numrows) {
fatal("Experiment $eid in project $pid already exists!");
fatal("*** Experiment $eid in project $pid already exists!");
}
$query_result =
......@@ -158,21 +141,21 @@ $query_result =
"WHERE eid='$eid' and pid='$pid'");
if ($query_result->numrows) {
fatal("Batch experiment $eid in project $pid already exists!");
fatal("*** Batch experiment $eid in project $pid already exists!");
}
#
# Now we can get the NS file!
#
if (system("/bin/cp", "$webnsfile", "$nsfile")) {
fatal("Could not copy $webnsfile to $dirname/$nsfile");
fatal("*** Could not copy $webnsfile to $dirname/$nsfile");
}
# Run parse in impotent mode on the NS file. This has no effect but
# will display any errors.
if (system("$parser -n -a $nsfile") != 0) {
fatal("NS Parse failed!");
fatal("*** NS Parse failed!");
}
#
......@@ -185,10 +168,10 @@ $created = DBDateTime();
# is looking for batch experiments to run. Easy race avoidance.
#
DBQueryFatal("INSERT INTO batch_experiments ".
"(eid, pid, created, expires, ".
"(eid, pid, gid, created, expires, ".
" name, creator_uid, status) ".
"VALUES ('$eid', '$pid', '$created', '$expires', ".
"'$longname', '$uid', 'new')");
"VALUES ('$eid', '$pid', '$gid', '$created', '$expires', ".
"'$longname', '$dbuid', 'new')");
exit 0;
......@@ -224,6 +207,10 @@ sub parse_batchfile()
$pid = $1;
next;
}
if ($_ =~ /^GID:\s+([-\@\w.]*)/) {
$gid = $1;
next;
}
if ($_ =~ /^name:\s+([-\@\w. ]*)/) {
$longname = $1;
next;
......
......@@ -50,7 +50,8 @@ my @nodes = @ARGV;
# nodes are specified since this script always does the right thing.
#
if ($EUID != 0) {
die("Must be root! Maybe its a development version?\n");
die("*** $0:\n".
" Must be root! Maybe its a development version?\n");
}
#
......@@ -83,7 +84,12 @@ foreach my $node (@nodes) {
}
else {
$db_result =
DBQueryFatal("select pid from reserved where node_id='$node'");
DBQueryFatal("select g.unix_name from groups as g ".
"left join experiments as e ".
" on g.pid=e.pid and g.gid=e.gid ".
"left join reserved as r ".
" on e.pid=r.pid and e.eid=r.eid ".
"where r.node_id='$node'");
}
if ($db_result->numrows > 0) {
@row = $db_result->fetchrow_array();
......
#!/usr/bin/perl -w
use English;
# This is a very simple program that convers the virt_* tables in the DB
# into a NS file. Not the original NS file, but a NS file that, if parsed
......@@ -16,17 +17,18 @@ if ($#ARGV != 1) {
($pid,$eid) = @ARGV;
#
# Make sure they have access to the experiment
# Make sure the experiment exists
#
if ((!TBAdmin()) && (!ProjMember($pid))) {
die "You are not a member of project %pid";
if (!ExpState($pid,$eid)) {
die "There is no experiment $eid in project $pid\n";
}
#
# Make sure the experiment exists
# Make sure they have access to the experiment
#
if (!ExpState($pid,$eid)) {
die "There is no experiment $eid in project $pid\n";
if (!TBAdmin($UID) &&
!TBExptAccessCheck($UID, $pid, $eid, TB_EXPT_READINFO)) {
die("*** You do not have permission to access this experiment!\n");
}
print "source tb_compat.tcl\n";
......
......@@ -106,15 +106,12 @@ if (! UserDBInfo($user_login, \$user_name, \$user_email)) {
}
#
# Verify that this person is allowed to end the experiment. Must be
# in the project membership table, or must be an admin type. Note that
# any script down the line has to do an admin check also.
# Verify that this person is allowed to end the experiment.
# Note that any script down the line has to do an admin check also.
#
if ($EUID && !TBAdmin($EUID) &&
ProjMember($pid, $user_login) != PROJMEMBERTRUST_ROOT) {
print STDOUT "Go Away! You do not have permission to end experiments ".
"in project $pid\n";
!TBExptAccessCheck($user_login, $pid, $eid, TB_EXPT_DESTROY)) {
print STDOUT "You do not have permission to end this experiment!\n";
exit(1);
}
......@@ -314,6 +311,12 @@ sub fatal($)
print STDOUT $mesg;
#
# Kill this for convenience later.
#
DBQueryWarn("update experiments set expt_terminating=NULL ".
"WHERE eid='$eid' and pid='$pid'");
#
# In batch mode, exit without sending the email.
#
......
......@@ -33,12 +33,18 @@ my @row;
# We don't want to run this script unless its the real version.
#
if ($EUID != 0) {
die("Must be root! Maybe its a development version?\n");
die("*** $0:\n".
" Must be root! Maybe its a development version?\n");
}
# XXX Hacky!
#if ($TB ne "/usr/testbed") {
# die("Wrong version. Maybe its a development version?\n");
#}
if ($TB ne "/usr/testbed") {
# print STDERR "*** $0:\n".
# " Wrong version. Maybe its a development version?\n";
#
# Let experiment continue setting up.
#
# exit(0);
}
# un-taint path
$ENV{'PATH'} = '/bin:/usr/bin:/usr/sbin:/usr/local/bin';
......@@ -199,16 +205,16 @@ if (@ipseq) {
#
$db_result =
DBQueryFatal("select distinct reserved.node_id,reserved.pid,".
"proj_memb.uid,interfaces.IP from reserved ".
"g.uid,interfaces.IP from reserved ".
"left join exppid_access as a ".
" on a.exp_pid=reserved.pid and a.exp_eid=reserved.eid ".
"left join proj_memb on proj_memb.pid=reserved.pid ".
" or proj_memb.pid=a.pid ".
"left join group_membership as g on g.pid=a.pid or ".
" (g.pid=reserved.pid and g.gid=g.pid) ".
"left join nodes on reserved.node_id=nodes.node_id ".
"left join node_types on node_types.type=nodes.type ".
"left join interfaces on reserved.node_id=interfaces.node_id ".
"and interfaces.card=node_types.control_net ".
"where interfaces.IP!='NULL' and proj_memb.trust!='none' ".
"where interfaces.IP!='NULL' and g.trust!='none' ".
"order by reserved.pid,reserved.node_id");
%iphash = ();
......
#!/usr/bin/perl -wT
use English;
use Errno;
use Fcntl ':flock';
#
......@@ -94,8 +95,9 @@ $mpid =~ s/\n//;
if ($mpid =~ /^([-\@\w.]+)$/) {
$mpid = $1;
}
kill('HUP', $mpid) or
if (kill('HUP', $mpid) == 0) {
fatal("Could not kill(HUP) process $mpid (mountd): $!");
}
#
# Allow time to react since HUP'ing mountd causes all mounts to briefly
......
#!/usr/bin/perl -wT
use English;
use Errno;
use Fcntl ':flock';
#
......@@ -94,8 +95,9 @@ $mpid =~ s/\n//;
if ($mpid =~ /^([-\@\w.]+)$/) {
$mpid = $1;
}
kill('HUP', $mpid) or
if (kill('HUP', $mpid) == 0) {
fatal("Could not kill(HUP) process $mpid (mountd): $!");
}
#
# Allow time to react since HUP'ing mountd causes all mounts to briefly
......
#!/usr/bin/perl -wT
use English;
use Getopt::Std;
#
# Create/Update a group.
#
# usage: group-update [-b] <pid> <gid>
#
sub usage()
{
print STDOUT "Usage: group-update -b <pid> <gid>\n";
exit(-1);
}
my $optlist = "b";
#
# Configure variables
#
my $TB = "@prefix@";
my $TBOPS = "@TBOPSEMAIL@";
my $TBLOGS = "@TBLOGSEMAIL@";
my $CONTROL = "@USERNODE@";
my $PROJROOT = "/proj";
my $SSH = "$TB/bin/sshtb";
my $GROUPADD = "/usr/sbin/pw groupadd";
my $USERMOD = "/usr/sbin/pw usermod";
my $mkacct = "$TB/libexec/mkacct-ctrl";
my $batchmode = 0;
my $dbuid;
my $user;
my @db_row;
my $query_result;
my $leader;
my $groupdir;
my $logname;
my $user_name;
my $user_email;
#
# Note hardwired control node.
#
my $control_node = $CONTROL;
#
# We don't want to run this script unless its the real version.
#
if ($EUID != 0) {
die("*** $0:\n".
" Must be setuid! Maybe its a development version?\n");
}
#
# This script is setuid, so please do not run it as root. Hard to track
# what has happened.
#
if ($UID == 0) {
die("*** $0:\n".
" Please do not run this as root! Its already setuid!\n");
}
#
# Untaint the path
#
$ENV{'PATH'} = "/bin:/usr/bin";
delete @ENV{'IFS', 'CDPATH', 'ENV', '