creategeniuser.in 5.48 KB
Newer Older
1 2
#!/usr/bin/perl -w
#
3
# Copyright (c) 2008-2015 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 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
# 
# {{{GENIPUBLIC-LICENSE
# 
# GENI Public License
# 
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and/or hardware specification (the "Work") to
# deal in the Work without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Work, and to permit persons to whom the Work
# is furnished to do so, subject to the following conditions:
# 
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Work.
# 
# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS
# IN THE WORK.
# 
# }}}
#
use strict;
use English;
use Getopt::Std;
use Data::Dumper;

#
# Create a geni user. This is a nonlocal user, derived from the
# only info we have which is the urn/email. We use this from CloudLab
# web interface (geni-login) to create a stub local account for a
# geni user. 
#
sub usage()
{
43
    print STDERR "Usage: $0 [-n] [-p project] <urn> <email>\n";
44 45
    exit(1);
}
46
my $optlist  = "nrp:";
47 48
my $impotent = 0;
my $delete   = 0;
49
my $project;
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102

# Configure ...
my $TB		  = "@prefix@";
my $TBACCT	  = "$TB/sbin/tbacct";
my $MKUSERCERT    = "$TB/sbin/mkusercert";
my $MODGROUPS     = "$TB/sbin/modgroups";

use lib '@prefix@/lib';
use emutil;
use User;
use Project;
use GeniCertificate;
use GeniHRN;
use EmulabConstants;

# Protos.
sub DeleteGeniUser($);

sub fatal($)
{
    my ($msg) = @_;

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

#
# Parse command arguments. Once we return from getopts, all that should be
# left are the required arguments.
#
my %options = ();
if (! getopts($optlist, \%options)) {
    usage();
}
if (defined($options{"n"})) {
    $impotent = 1;
}
if (defined($options{"r"})) {
    usage()
	if (@ARGV != 1);
    $delete = 1;
}
else {
    usage()
	if (@ARGV != 2);
}
my $urn     = $ARGV[0];
fatal("Invalid urn")
    if (! GeniHRN::IsValid($urn));
if ($delete) {
    exit(DeleteGeniUser($urn));
}

103 104 105 106 107 108 109 110
# Make sure we can get this project.
if (defined($options{"p"})) {
    my $pid  = $options{"p"};
    $project = Project->Lookup($pid);
    if (!defined($project)) {
	fatal("No such project!");
    }
}
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
my $email   = $ARGV[1];
my $usr_uid;
fatal("Invalid email")
    if (! User->ValidEmail($email));

# Must not be a user with same nonlocal ID.
if (User->LookupNonLocal($urn)) {
    fatal("We already have a user with that nonlocal ID (urn)");
}

#
# Parse urn and email, maybe we can get a unique uid out of one.
#
my (undef,undef,$uid) = GeniHRN::Parse($urn);
fatal("Could not parse urn")
    if (!defined($uid));
127
if (User->ValidUID($uid)) {
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
    $usr_uid = $uid;
}
else {
    #
    # Split email and try that.
    #
    my ($token) = split("@", $email);
    if (defined($token) &&
	User->ValidUID($token) && !User->Lookup($token)) {
	$usr_uid = $token;
    }
}
#
# Neither worked, so need to generate something. Ick.
#
if (!defined($usr_uid)) {
144 145 146 147 148 149 150 151 152 153 154 155 156 157
    # Random
    $usr_uid = "g" . substr(lc(emutil::GenHash()), 0, 6);
}

#
# Now generate a unique uid. We append a two digit integer to
# avoid using up local uid space.
#
my $i;
$uid = substr($uid, 0, 6);
for ($i = 0 ; $i <= 99; $i++) {
    if (!User->Lookup("${uid}${i}")) {
	$usr_uid = "${uid}${i}";
	last;
158 159
    }
}
160 161 162
if ($i > 99) {
    $usr_uid = "g" . substr(lc(emutil::GenHash()), 0, 6);
}
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
if ($impotent) {
    print "Would create nolocal user '$usr_uid' ...\n";
    exit(0);
}

#
# Okay, create new account in the DB.
#
my $user = User->Create($usr_uid,
			$User::NEWUSER_FLAGS_NONLOCAL,
			{"usr_name"      => "Geni User $usr_uid",
			 "usr_email"     => $email,
			 "nonlocal_id"   => $urn,
			 "nonlocal_type" => "geni",
			});
fatal("Could not create user!")
    if (!defined($user));

#
# Add them to the holding project. This will need more thought.
#
184 185
if (defined($project) &&
    $project->AddMemberShip($user, $Group::MemberShip::TRUSTSTRING_LOCALROOT)) {
186 187 188 189 190 191 192
    $user->Delete();
    fatal("Could not add new user to project");
}

# And then instantiate the user.
system("$TBACCT add $usr_uid");
if ($?) {
Leigh B Stoller's avatar
Leigh B Stoller committed
193
    $project->GetProjectGroup()->DeleteMemberShip($user)
194
	if (defined($project));
195 196 197 198 199 200 201 202 203
    $user->Delete();
    fatal("Could not instantiate user account!")
}

# We need to generate the encrypted ssl certificate to keep
# things happy.
my $certpass = substr(lc(emutil::GenHash()), 0, 10);
system("$MKUSERCERT -p $certpass $usr_uid");
if ($?) {
Leigh B Stoller's avatar
Leigh B Stoller committed
204
    $project->GetProjectGroup()->DeleteMemberShip($user)
205
	if (defined($project));
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
    $user->Delete();
    fatal("Could not create local SSL certificate");
}
exit(0);

#
# Delete (purge!) geni user. Not to be used generally, please use
# the normal archive path. This is for debugging.
#
sub DeleteGeniUser($)
{
    my ($urn) = @_;
    my $user = User->LookupNonLocal($urn);
    if (!defined($user)) {
	fatal("No such local user!");
    }
    my $uid = $user->uid();
223 224 225 226 227
    my $project = $user->DefaultProject();
    if (defined($project)) {
	my $pid = $project->pid();
	system("$MODGROUPS -r $pid:$pid $uid");
    }
228 229 230 231 232 233
    system("$TBACCT -f del $uid") == 0 or
	fatal("$TBACCT $uid failed!");

    $user->Delete();
    return 0;
}