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

#
# EMULAB-COPYRIGHT
5
# Copyright (c) 2003-2012 University of Utah and the Flux Group.
Leigh B. Stoller's avatar
Leigh B. Stoller committed
6 7 8 9 10 11 12 13 14 15 16 17 18 19
# All rights reserved.
#

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()
{
20
    print STDERR "Usage: grantnodetype [-h] [-r] [-m] -p <pid> <type> [count]\n";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
21
    print STDERR "	-h   This message\n";
22
    print STDERR "	-r   Revoke access instead of grant\n";
23 24
    print STDERR "	-m   Force insert of missing minus policy\n";
    print STDERR "   count   Overdide default count of 999999\n";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
25 26
    exit(-1);
}
27
my $optlist  = "hp:dnrm";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
28 29
my $impotent = 0;
my $debug    = 0;
30
my $revoke   = 0;
31
my $addminus = 0;
Leigh B. Stoller's avatar
Leigh B. Stoller committed
32 33
my %newtypes = ();
my $pid;
34
my $count    = 999999;
Leigh B. Stoller's avatar
Leigh B. Stoller committed
35 36 37 38 39 40

#
# Please do not run as root. Hard to track what has happened.
#
if ($UID == 0) {
    die("*** $0:\n".
41
	"    Please do not run this as root!\n");
Leigh B. Stoller's avatar
Leigh B. Stoller committed
42 43 44 45 46
}

#
# Configure variables
#
47 48
my $TB		 = "@prefix@";
my $update_perms = "$TB/sbin/update_permissions";
Leigh B. Stoller's avatar
Leigh B. Stoller committed
49 50 51 52 53 54 55

#
# Testbed Support libraries
#
use lib "@prefix@/lib";
use libdb;
use libtestbed;
56 57
use Project;
use Group;
Leigh B. Stoller's avatar
Leigh B. Stoller committed
58

59 60 61
# Be careful not to exit on transient error
$libdb::DBQUERY_MAXTRIES = 30;

Leigh B. Stoller's avatar
Leigh B. Stoller committed
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
#
# 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();
}
83 84 85
if (defined($options{m})) {
    $addminus = 1;
}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
86 87 88
if (defined($options{n})) {
    $impotent = 1;
}
89 90 91
if (defined($options{r})) {
    $revoke = 1;
}
Leigh B. Stoller's avatar
Leigh B. Stoller committed
92 93 94 95 96 97
if (defined($options{d})) {
    $debug = 1;
}
if (defined($options{p})) {
    $pid = $options{p};
}
Mike Hibler's avatar
Mike Hibler committed
98
if (scalar(@ARGV) < 1 || scalar(@ARGV) > 2 || !defined($pid)) {
Leigh B. Stoller's avatar
Leigh B. Stoller committed
99 100 101
    usage();
}
my $type = $ARGV[0];
102
$count   = $ARGV[1] if (@ARGV == 2);
Leigh B. Stoller's avatar
Leigh B. Stoller committed
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126

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

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");
}

127 128 129 130 131 132 133 134
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
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
#
# 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 ".
159
			 "where type='$nodetype' or type='$nodeclass'");
Leigh B. Stoller's avatar
Leigh B. Stoller committed
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178

	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)) {
179 180 181
    print STDERR
	($revoke ? "Revoking" : "Granting") . " " .
	"permission to use type $newtype\n"
Leigh B. Stoller's avatar
Leigh B. Stoller committed
182
	if ($debug);
183 184 185 186 187 188 189 190 191 192 193 194 195 196

    #
    # 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) {
197 198 199 200 201 202 203 204 205 206 207
	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");
	}
208 209 210 211 212
    }

    #
    # Add generic rules that say the project is allowed to use "infinite"
    # number of nodes of each type. 
213
    #
214
    my $count = ($revoke ? 0 : $count);
215
    
216
    DBQueryFatal("replace into group_policies ".
217 218
		 "(pid_idx, gid_idx, pid, gid, policy, auxdata, count) ".
		 "values ($pid_idx, $pid_idx, '$pid', '$pid', ".
219
		 "        'type', '$newtype', $count)")
Leigh B. Stoller's avatar
Leigh B. Stoller committed
220 221 222
	if (!$impotent);
}

223 224 225 226 227 228
#
# Now update the permissions table. 
#
system($update_perms);
exit($? >> 8)
    if ($?);
Leigh B. Stoller's avatar
Leigh B. Stoller committed
229
exit(0);