grantnodetype.in 6.27 KB
Newer Older
Leigh B. Stoller's avatar
Leigh B. Stoller committed
1 2 3
#!/usr/bin/perl -wT

#
4
# Copyright (c) 2003-2012, 2014 University of Utah and the Flux Group.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
# 
# {{{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 B. Stoller's avatar
Leigh B. Stoller committed
24 25 26 27 28 29 30 31 32 33 34 35 36
#

use English;
use Getopt::Std;

#
# Grant permission to use types/class of nodes. If given a specific
# "type", then grant permission to use just that type. If its a class, then
# permission to use all of the types in that class, the class itself, and any
# aux nodetypes for the type/class (node_types_auxtypes table). 
#
sub usage()
{
37
    print STDERR "Usage: grantnodetype [-h] [-r] [-m] -p <pid> <type> [count]\n";
38
    print STDERR "       grantnodetype [-h] -R <type>\n";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
39
    print STDERR "	-h   This message\n";
40
    print STDERR "	-r   Revoke access instead of grant\n";
41
    print STDERR "	-m   Force insert of missing minus policy\n";
42
    print STDERR "      -R   Remove all projects for type, and minus policy\n";
43
    print STDERR "   count   Overdide default count of 999999\n";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
44 45
    exit(-1);
}
46
my $optlist  = "hp:dnrmR";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
47 48
my $impotent = 0;
my $debug    = 0;
49
my $revoke   = 0;
50
my $revokeall= 0;
51
my $addminus = 0;
Leigh B. Stoller's avatar
Leigh B. Stoller committed
52 53
my %newtypes = ();
my $pid;
54
my $count    = 999999;
Leigh B. Stoller's avatar
Leigh B. Stoller committed
55 56 57 58 59 60

#
# Please do not run as root. Hard to track what has happened.
#
if ($UID == 0) {
    die("*** $0:\n".
61
	"    Please do not run this as root!\n");
Leigh B. Stoller's avatar
Leigh B. Stoller committed
62 63 64 65 66
}

#
# Configure variables
#
67 68
my $TB		 = "@prefix@";
my $update_perms = "$TB/sbin/update_permissions";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
69 70 71 72 73 74 75

#
# Testbed Support libraries
#
use lib "@prefix@/lib";
use libdb;
use libtestbed;
76 77
use Project;
use Group;
Leigh B. Stoller's avatar
Leigh B. Stoller committed
78

79 80 81
# Be careful not to exit on transient error
$libdb::DBQUERY_MAXTRIES = 30;

Leigh B. Stoller's avatar
Leigh B. Stoller committed
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
#
# Turn off line buffering on output
#
$| = 1;

#
# Untaint the path
# 
$ENV{'PATH'} = "/bin:/sbin:/usr/bin:";

#
# Parse command arguments. Once we return from getopts, all that should be
# left are the required arguments.
#
%options = ();
if (! getopts($optlist, \%options)) {
    usage();
}
if (defined($options{h})) {
    usage();
}
103 104 105
if (defined($options{m})) {
    $addminus = 1;
}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
106 107 108
if (defined($options{n})) {
    $impotent = 1;
}
109 110 111
if (defined($options{r})) {
    $revoke = 1;
}
112 113 114
if (defined($options{R})) {
    $revokeall = 1;
}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
115 116 117 118 119 120
if (defined($options{d})) {
    $debug = 1;
}
if (defined($options{p})) {
    $pid = $options{p};
}
121 122
if (!$revokeall &&
    (scalar(@ARGV) < 1 || scalar(@ARGV) > 2 || !defined($pid))) {
Leigh B. Stoller's avatar
Leigh B. Stoller committed
123 124 125
    usage();
}
my $type = $ARGV[0];
126
$count   = $ARGV[1] if (@ARGV == 2);
Leigh B. Stoller's avatar
Leigh B. Stoller committed
127 128 129 130 131 132 133 134 135 136 137

#
# Untaint the arguments.
#
if ($type =~ /^([-\w]+)$/) {
    $type = $1;
}
else {
    die("Tainted type name: $type");
}

138 139 140 141 142 143 144 145 146 147 148 149 150
#
# Clear the type from the group_policies table, including the minus policy,
# which allows the type to be used by everyone.
#
if ($revokeall) {
    DBQueryFatal("delete from group_policies ".
		 "where policy='type' and auxdata='$type'")
	if (!$impotent);

    system($update_perms);
    exit($? >> 8);
}

Leigh B. Stoller's avatar
Leigh B. Stoller committed
151 152 153 154 155 156 157 158 159 160 161 162 163
if ($pid =~ /^([-\w]+)$/) {
    $pid = $1;
}
else {
    die("Tainted pid name: $pid");
}

# Only admin types can do this.
if (!TBAdmin($UID)) {
    die("*** $0:\n".
	"    You are not allowed to grant permission to use node types!\n");
}

164 165 166 167 168 169 170 171
my $project = Project->Lookup($pid);
if (!defined($project)) {
    die("*** $0:\n".
	"    Cannot map project $pid to its object\n");
}
# Need this below.
my $pid_idx = $project->pid_idx();

Leigh B. Stoller's avatar
Leigh B. Stoller committed
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
#
# Check to make sure a valid type in the node_types table.
#
my $query_result =
    DBQueryFatal("select distinct type,class from node_types ".
		 "where type='$type' or class='$type'");

if (! $query_result->num_rows) {
    die("*** $0:\n".
	"    No such type/class $type in the types table!\n");
}

while (my ($nodetype,$nodeclass) = $query_result->fetchrow_array()) {
    if ($nodeclass eq $type) {
	#
	# Grant permission to this class/type, and all of the aux types for it.
	#
	$newtypes{$nodetype} = 1
	    if (!defined($newtypes{$nodetype}));
	$newtypes{$nodeclass} = 1
	    if ($nodeclass ne $nodetype && !defined($newtypes{$nodeclass}));

	my $aux_result =
	    DBQueryFatal("select auxtype from node_types_auxtypes ".
196
			 "where type='$nodetype' or type='$nodeclass'");
Leigh B. Stoller's avatar
Leigh B. Stoller committed
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215

	while (my ($auxtype) = $aux_result->fetchrow_array()) {
	    $newtypes{$auxtype} = 1
		if (!defined($newtypes{$auxtype}));
	}
    }
    else {
	#
	# A single type. Just grant permission to the type itself.
	#
	$newtypes{$type} = 1
	    if (!defined($newtypes{$type}));
    }
}

#
# Run the queries.
# 
foreach my $newtype (keys(%newtypes)) {
216 217 218
    print STDERR
	($revoke ? "Revoking" : "Granting") . " " .
	"permission to use type $newtype\n"
Leigh B. Stoller's avatar
Leigh B. Stoller committed
219
	if ($debug);
220 221 222 223 224 225 226 227 228 229 230 231 232 233

    #
    # Make sure there is a minus policy in the group_policies table;
    # If not, then granting permission to use this type is silly, and
    # probably means that the group_policies table needs updating.
    #
    $query_result =
	DBQueryFatal("select * from group_policies ".
		     "where pid='-' and policy='type' and auxdata='$newtype'");
    
    exit(0)
	if (!$query_result);

    if (!$query_result->num_rows) {
234 235 236 237 238 239 240 241 242 243 244
	if ($addminus) {
	    DBQueryFatal("replace into group_policies ".
			 "(pid_idx,gid_idx,pid,gid,policy,auxdata,count) ".
			 "values (0, 0, '-', '-','type','$newtype', 0)")
		if (!$impotent);
	}
	else {
	    die("*** $0:\n".
		"    There is no '-' policy for node type $newtype!\n".
		"    Use the -m option if you want to add the minux policy.\n");
	}
245 246 247 248 249
    }

    #
    # Add generic rules that say the project is allowed to use "infinite"
    # number of nodes of each type. 
250
    #
251
    my $count = ($revoke ? 0 : $count);
252
    
253
    DBQueryFatal("replace into group_policies ".
254 255
		 "(pid_idx, gid_idx, pid, gid, policy, auxdata, count) ".
		 "values ($pid_idx, $pid_idx, '$pid', '$pid', ".
256
		 "        'type', '$newtype', $count)")
Leigh B. Stoller's avatar
Leigh B. Stoller committed
257 258 259
	if (!$impotent);
}

260 261 262 263 264 265
#
# Now update the permissions table. 
#
system($update_perms);
exit($? >> 8)
    if ($?);
Leigh B. Stoller's avatar
Leigh B. Stoller committed
266
exit(0);