rmgroup.in 7.06 KB
Newer Older
1
#!/usr/bin/perl -wT
Leigh Stoller's avatar
Leigh Stoller committed
2
#
3
# Copyright (c) 2000-2018 University of Utah and the Flux Group.
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
# 
# {{{EMULAB-LICENSE
# 
# This file is part of the Emulab network testbed software.
# 
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
# 
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public
# License for more details.
# 
# You should have received a copy of the GNU Affero General Public License
# along with this file.  If not, see <http://www.gnu.org/licenses/>.
# 
# }}}
Leigh Stoller's avatar
Leigh Stoller committed
23
#
Leigh Stoller's avatar
Leigh Stoller committed
24
use English;
25
use strict;
Leigh Stoller's avatar
Leigh Stoller committed
26 27 28

#
# Remove a group. We delete the group directory and the we remove the
29 30 31 32 33 34 35
# group from /etc/group. Actually, the group directory is *renamed*
# since we do not want to be so destructive. This scrip can be called
# with pid=gid, but in that case it has to be a tbadmin, and the
# directory is not renamed. The caller (rmproj) is responsible for that.
#
sub usage()
{
36
    print STDOUT "Usage: rmgroup <gid>\n";
37 38
    exit(-1);
}
39
sub fatal($);
40 41
my  $optlist = "";

Leigh Stoller's avatar
Leigh Stoller committed
42
#
43
# We don't want to run this script unless its the real version.
Leigh Stoller's avatar
Leigh Stoller committed
44
#
45 46 47 48 49 50 51 52 53 54 55 56 57
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");
}
Leigh Stoller's avatar
Leigh Stoller committed
58 59 60 61

#
# Configure variables
#
62 63 64 65
my $TB            = "@prefix@";
my $TBOPS         = "@TBOPSEMAIL@";
my $CONTROL       = "@USERNODE@";
my $BOSSNODE      = "@BOSSNODE@";
66
my $ELABINELAB    = @ELABINELAB@;
67
my $MAILMANSUPPORT= @MAILMANSUPPORT@;
68 69
my $BUGDBSUPPORT  = @BUGDBSUPPORT@;
my $OPSDBSUPPORT  = @OPSDBSUPPORT@;
70
my $OPSVM_ENABLE  = @OPSVM_ENABLE@;
Leigh Stoller's avatar
Leigh Stoller committed
71

72 73 74 75 76
my $SSH           = "$TB/bin/sshtb";
my $GROUPDEL      = "/usr/sbin/pw groupdel";
my $DELMMLIST     = "$TB/sbin/delmmlist";
my $MODGROUPS     = "$TB/sbin/modgroups";
my $OPSDBCONTROL  = "$TB/sbin/opsdb_control";
77
my $ACCOUNTPROXY  = "$TB/sbin/accountsetup";
78
my $EXPORTSSETUP  = "$TB/sbin/exports_setup";
Leigh Stoller's avatar
Leigh Stoller committed
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94

#
# Untaint the path
# 
$ENV{'PATH'} = "/bin:/usr/bin";
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};

#
# Turn off line buffering on output
#
$| = 1;

#
# Load the Testbed support stuff. 
#
use lib "@prefix@/lib";
95
use libaudit;
Leigh Stoller's avatar
Leigh Stoller committed
96
use libdb;
97
use emutil;
Leigh Stoller's avatar
Leigh Stoller committed
98
use libtestbed;
99
use User;
100
use Project;
101
use Group;
102
use EmulabFeatures;
Leigh Stoller's avatar
Leigh Stoller committed
103

104
# Defined in libtestbed;
105 106 107
my $PROJROOT    = PROJROOT();
my $GRPROOT     = GROUPROOT();

Leigh Stoller's avatar
Leigh Stoller committed
108 109 110
#
# Check args.
#
111
if (@ARGV != 1) {
112
    usage();
Leigh Stoller's avatar
Leigh Stoller committed
113 114
}

115 116 117 118
# Map invoking user to object.
my $this_user = User->ThisUser();
if (! defined($this_user)) {
    fatal("You ($UID) do not exist!");
Leigh Stoller's avatar
Leigh Stoller committed
119
}
120 121 122 123 124 125 126 127
my $user_name  = $this_user->name();
my $user_email = $this_user->email();
my $user_uid   = $this_user->uid();

# Map the group to its object.
my $group = Group->Lookup($ARGV[0]);
if (!defined($group)) {
    fatal("Could not lookup group object for $ARGV[0]");
Leigh Stoller's avatar
Leigh Stoller committed
128
}
129
my $project    = $group->GetProject();
130 131 132 133 134
my $unix_gid   = $group->unix_gid();
my $unix_name  = $group->unix_name();
my $pid        = $group->pid();
my $gid        = $group->gid();
my $gid_idx    = $group->gid_idx();
Leigh Stoller's avatar
Leigh Stoller committed
135 136

#
137
# Figure out who called us. 
Leigh Stoller's avatar
Leigh Stoller committed
138
#
139
if (!TBAdmin()) {
140 141 142 143
    #
    # Only admin types can remove the project group. Typically, you won't
    # do this directly, but use rmproj instead.
    #
144
    if ($group->IsProjectGroup()) {
145 146 147
	die("*** $0:\n".
	    "    You do not have permission to remove a project group!\n");
    }
Leigh Stoller's avatar
Leigh Stoller committed
148

149
    if (! $group->AccessCheck($this_user, TB_PROJECT_DELGROUP())) {
150
	die("*** $0:\n".
151
	    "    You do not have permission to remove group $group!\n");
Leigh Stoller's avatar
Leigh Stoller committed
152 153 154 155
    }
}

#
156 157 158 159 160 161 162
# This script is always audited. Mail is sent automatically upon exit.
#
if (AuditStart(0)) {
    #
    # Parent exits normally
    #
    exit(0);
Leigh Stoller's avatar
Leigh Stoller committed
163 164
}

165
#
166
# Removing group-related directories is handled by accountsetup on ops.
167
#
Leigh Stoller's avatar
Leigh Stoller committed
168

169 170 171
#
# Remove all members from the group.
# If there was an error, the DB state is left so that this script can
172
# be run again.
173 174 175 176
#
# Must find out what users/groups to delete so that we can pass off to
# modgroups.
#
177 178 179 180
my @userlist = ();
$group->MemberList(\@userlist,
		   $Group::MEMBERLIST_FLAGS_ALLUSERS |
		   $Group::MEMBERLIST_FLAGS_UIDSONLY);
181

182
foreach my $uid (@userlist) {
183 184 185 186 187 188 189 190
    # For perl
    $EUID = $UID;
    if (system("$MODGROUPS -r $pid:$gid $uid")) {
	fatal("$MODGROUPS -r $pid:$gid $uid failed!");
    }
    $EUID = 0;
}

191 192 193 194 195 196
# If the group isn't in /etc/group yet, it wasn't approved and created.
if (system("grep -q '^${unix_gid}:' /etc/group")) {
    #
    # Now remove the group from the group file on both plastic and paper.
    #
    print "Removing group $unix_name ($unix_gid) on local node.\n";
197

198
    if (runBusyLoop("$GROUPDEL $unix_name")) {
199 200 201
	if (($? >> 8) != 65) {
	    fatal("Could not remove group $unix_name from local node!");
	}
202
    }
Leigh Stoller's avatar
Leigh Stoller committed
203

204 205
    if ($MAILMANSUPPORT && !$ELABINELAB) {
	my $listname = ($pid eq $gid ? "${pid}-users" : "${pid}-${gid}-users");
206

207 208 209 210 211 212
	# For perl
	$EUID = $UID;
	system("$DELMMLIST -a $listname") == 0 or
	    fatal("$DELMMLIST -a $listname failed!");
	$EUID = 0;
    }
213

214 215 216 217 218 219 220
    if ($OPSDBSUPPORT && !$ELABINELAB) {
	# For perl
	$EUID = $UID;
	system("$OPSDBCONTROL delgroup $pid $gid") == 0 or
	    fatal("$OPSDBCONTROL delgroup $pid $gid failed!");
	$EUID = 0;
    }
Leigh Stoller's avatar
Leigh Stoller committed
221

222 223 224 225
    #
    # Be real root for ssh.
    # 
    $UID = 0;
226

227
    if ($OPSVM_ENABLE) {
228
	if ($pid eq $gid) {
229 230 231 232
	    emutil::ClearNoDelete("$PROJROOT/$pid");
	    emutil::ClearNoDelete("$GRPROOT/$pid");
	    # Also the symlink.
	    emutil::ClearNoDelete("$GRPROOT/$pid/$pid");
233

234 235 236
	    foreach my $dir (@Project::PROJDIRECTORIES) {
		emutil::ClearNoDelete("$PROJROOT/$pid/$dir");
	    }
237
	}
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
	else {
	    emutil::ClearNoDelete("$GRPROOT/$pid/$gid");
	    
	    foreach my $dir (@Project::GROUPDIRECTORIES) {
		emutil::ClearNoDelete("$GRPROOT/$pid/$gid/$dir")
	    }
	}
    }

    print "Removing group $unix_name ($unix_gid) on $CONTROL.\n";

    my $cmdstr;
    if ($pid eq $gid) {
	$cmdstr = "delproject $gid $unix_name";
    } else {
	$cmdstr = "delgroup $gid $unix_name $pid";
    }

    print "Removing group $unix_name ($unix_gid) on $CONTROL.\n";
    if (system("$SSH -host $CONTROL $ACCOUNTPROXY $cmdstr")) {
	fatal("Could not remove group $unix_name from $CONTROL!");
259
    }
Leigh Stoller's avatar
Leigh Stoller committed
260

261 262 263 264 265
    #
    # Remove group on the tip servers. 
    #
    foreach my $tipserver ( TBTipServers() ) {
	print "Removing group $unix_name ($unix_gid) on $tipserver.\n";
266

267 268 269 270
	if (system("$SSH -host $tipserver $GROUPDEL $unix_name")) {
	    if (($? >> 8) != 65) {
		fatal("Could not remove group $unix_name from $tipserver!");
	    }
271
	}
272 273 274
    }
}

275 276 277 278 279 280
#
# Kill any features
#
EmulabFeatures->DeleteAll($group) == 0 or
    fatal("Could not delete all features for $group");

281 282 283
# Last step, so we can repeat above actions on failures.
$group->Delete() == 0 or
    fatal("Could not delete group $group");
284

285
print "Group $pid/$gid ($gid_idx) has been removed!\n";
286
exit(0);
Leigh Stoller's avatar
Leigh Stoller committed
287

288 289 290 291 292 293
sub fatal($) {
    my($mesg) = $_[0];

    die("*** $0:\n".
	"    $mesg\n");
}