Commit 44de59fe authored by Leigh Stoller's avatar Leigh Stoller

Binding additional users to slices now works.

parent 0298b117
......@@ -366,6 +366,7 @@ sub Register($)
}
if ($type eq "Slice") {
my $creator_uuid = $info->{'creator_uuid'};
my $userbindings = $info->{'userbindings'};
if (! ($creator_uuid =~ /^[-\w]*$/)) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
......@@ -379,6 +380,20 @@ sub Register($)
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"creator_uuid: No such User");
}
#
# Ditto any users bound to the slice.
#
if (defined($userbindings)) {
foreach my $binding_uuid (@{ $userbindings }) {
my $binding_user = GeniUser->Lookup($binding_uuid);
if (!defined($binding_user)) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"$binding_user: No such User");
}
}
}
#
# Need to verify the UUID is permitted for the SA making the request.
#
......@@ -400,6 +415,16 @@ sub Register($)
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"$hrn/$uuid could not be registered");
}
#
# Add the bindings now.
#
if (defined($userbindings)) {
foreach my $binding_uuid (@{ $userbindings }) {
my $binding_user = GeniUser->Lookup($binding_uuid);
$newslice->BindUser($binding_user);
}
}
return GeniResponse->Create(GENIRESPONSE_SUCCESS, undef,
"$hrn/$uuid has been registered");
......@@ -516,118 +541,3 @@ sub DiscoverResources($)
return GeniResponse->Create(GENIRESPONSE_SUCCESS, \@results);
}
#
# Bind user to slice
#
sub BindUser($)
{
my ($argref) = @_;
my $slice_uuid = $argref->{'slice_uuid'};
my $user_uuid = $argref->{'user_uuid'};
if (! (defined($slice_uuid) && defined($user_uuid))) {
return GeniResponse->MalformedArgsResponse();
}
#
# Use the Emulab checkslot routines.
#
if (! ($slice_uuid =~ /^[-\w]*$/)) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"uuid: Invalid characters");
}
if (! ($user_uuid =~ /^[-\w]*$/)) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"uuid: Invalid characters");
}
#
# The SA UUID comes from the SSL environment (certificate). Verify it
# and the prefix match for the uuid.
#
# Need to verify the UUID is permitted for the SA making the request.
#
my $sa_uuid = $ENV{'GENIUUID'};
my $authority = GeniAuthority->Lookup($sa_uuid);
if (!defined($authority)) {
return GeniResponse->Create(GENIRESPONSE_SEARCHFAILED, undef,
"No slice authority record for $sa_uuid");
}
my $slice = GeniSlice->Lookup($slice_uuid);
if (!defined($slice)) {
return GeniResponse->Create(GENIRESPONSE_SEARCHFAILED, undef,
"No such slice $slice_uuid");
}
my $user = GeniUser->Lookup($user_uuid);
if (!defined($slice)) {
return GeniResponse->Create(GENIRESPONSE_SEARCHFAILED, undef,
"No such user $user_uuid");
}
DBQueryWarn("replace into geni_bindings set ".
" slice_uuid='$slice_uuid', user_uuid='$user_uuid', ".
" created=now()")
or return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Error binding user to slice");
return GeniResponse->Create(GENIRESPONSE_SUCCESS, undef,
"$user_uuid has been bound to slice");
}
#
# UnBind user from slice
#
sub UnBindUser($)
{
my ($argref) = @_;
my $slice_uuid = $argref->{'slice_uuid'};
my $user_uuid = $argref->{'user_uuid'};
if (! (defined($slice_uuid) && defined($user_uuid))) {
return GeniResponse->MalformedArgsResponse();
}
#
# Use the Emulab checkslot routines.
#
if (! ($slice_uuid =~ /^[-\w]*$/)) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"uuid: Invalid characters");
}
if (! ($user_uuid =~ /^[-\w]*$/)) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"uuid: Invalid characters");
}
#
# The SA UUID comes from the SSL environment (certificate). Verify it
# and the prefix match for the uuid.
#
# Need to verify the UUID is permitted for the SA making the request.
#
my $sa_uuid = $ENV{'GENIUUID'};
my $authority = GeniAuthority->Lookup($sa_uuid);
if (!defined($authority)) {
return GeniResponse->Create(GENIRESPONSE_SEARCHFAILED, undef,
"No slice authority record for $sa_uuid");
}
my $slice = GeniSlice->Lookup($slice_uuid);
if (!defined($slice)) {
return GeniResponse->Create(GENIRESPONSE_SEARCHFAILED, undef,
"No such slice $slice_uuid");
}
my $user = GeniUser->Lookup($user_uuid);
if (!defined($slice)) {
return GeniResponse->Create(GENIRESPONSE_SEARCHFAILED, undef,
"No such user $user_uuid");
}
DBQueryWarn("delete from geni_bindings ".
"where slice_uuid='$slice_uuid' and user_uuid='$user_uuid'")
or return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Error unbinding user from slice");
return GeniResponse->Create(GENIRESPONSE_SUCCESS, undef,
"$user_uuid has been unbound from slice");
}
......@@ -170,11 +170,12 @@ sub RegisterUser($$$$$)
#
# Register a slice at the Clearinghouse.
#
sub RegisterSlice($$$)
sub RegisterSlice($$$$)
{
my ($hrn, $creator_uuid, $cert) = @_;
my ($hrn, $creator_uuid, $cert, $bindings) = @_;
my $info = { "creator_uuid" => $creator_uuid };
my $info = { "creator_uuid" => $creator_uuid,
"userbindings" => $bindings };
return Register($hrn, "Slice", $cert, $info);
}
......
......@@ -666,9 +666,7 @@ sub CreateSliceFromRegistry($)
next;
}
}
DBQueryWarn("replace into geni_bindings set ".
" created=now(), slice_uuid='$slice_uuid', ".
" user_uuid='$uuid'")
$slice->BindUser($user) == 0
or print STDERR
"Could not insert user binding for $uuid to slice $slice_uuid\n";
}
......@@ -702,9 +700,7 @@ sub UpdateSliceFromRegistry($)
next;
}
}
DBQueryWarn("replace into geni_bindings set ".
" created=now(), slice_uuid='$slice_uuid', ".
" user_uuid='$uuid'")
$slice->BindUser($user) == 0
or print STDERR
"Could not insert user binding for $uuid to slice $slice_uuid\n";
}
......
......@@ -64,21 +64,10 @@ sub GetCredential($)
return GeniResponse->MalformedArgsResponse();
}
my $geniuser = GeniUser->Lookup($ENV{'GENIUUID'});
my $geniuser = GeniUser->Lookup($ENV{'GENIUUID'}, 1);
if (!defined($geniuser)) {
#
# Check Emulab users table.
#
my $user = User->LookupByUUID($ENV{'GENIUUID'});
if (!defined($user)) {
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN,
undef, "Who are you?");
}
$geniuser = GeniUser->CreateFromLocal($user);
if (!defined($geniuser)) {
print STDERR "Could not create geniuser from $user\n";
return GeniResponse->Create(GENIRESPONSE_ERROR);
}
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN,
undef, "Who are you?");
}
#
# This credential is for access to this SA.
......@@ -167,39 +156,30 @@ sub Resolve($)
# allows anyone with a credential for this registry to lookup anyone
# else. Good feature of the Geni API.
#
my $this_user = GeniUser->Lookup($credential->owner_uuid());
my $this_user = GeniUser->Lookup($credential->owner_uuid(), 1);
if (!defined($this_user)) {
#
# Check Emulab users table.
#
my $user = User->LookupByUUID($credential->owner_uuid());
if (!defined($user)) {
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN,
undef, "Who are you?");
}
$this_user = GeniUser->CreateFromLocal($user);
if (!defined($this_user)) {
print STDERR "Could not create geniuser from $user\n";
return GeniResponse->Create(GENIRESPONSE_ERROR);
}
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN,
undef, "Who are you?");
}
if ($type eq "User") {
my $geniuser = GeniUser->Lookup($uuid);
if (!defined($geniuser)) {
my $geniuser;
if (defined($uuid)) {
$geniuser = GeniUser->Lookup($uuid, 1);
}
else {
#
# Check Emulab users table.
# XXX Form hrn from the uid and domain. This is backwards.
#
my $user = User->LookupByUUID($uuid);
if (!defined($user)) {
return GeniResponse->Create(GENIRESPONSE_SEARCHFAILED,
undef, "No one here by that name");
}
$geniuser = GeniUser->CreateFromLocal($user);
if (!defined($geniuser)) {
print STDERR "Could not create geniuser from $user\n";
return GeniResponse->Create(GENIRESPONSE_ERROR);
if (! ($hrn =~ /\./)) {
$hrn = "${OURDOMAIN}.users.${hrn}";
}
$geniuser = GeniUser->Lookup($hrn, 1);
}
if (!defined($geniuser)) {
return GeniResponse->Create(GENIRESPONSE_SEARCHFAILED,
undef, "No one here by that name");
}
# Grab keys.
my @sliverkeys;
......@@ -312,28 +292,43 @@ sub Register($)
# allows anyone with a credential for this registry to lookup anyone
# else. Good feature of the Geni API.
#
my $this_user = GeniUser->Lookup($credential->owner_uuid());
my $this_user = GeniUser->Lookup($credential->owner_uuid(), 1);
if (!defined($this_user)) {
#
# Check Emulab users table.
#
my $user = User->LookupByUUID($credential->owner_uuid());
if (!defined($user)) {
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN,
undef, "Who are you?");
}
$this_user = GeniUser->CreateFromLocal($user);
if (!defined($this_user)) {
print STDERR "Could not create geniuser from $user\n";
return GeniResponse->Create(GENIRESPONSE_ERROR);
}
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN,
undef, "Who are you?");
}
if ($type eq "Slice") {
my $userbindings = $argref->{'userbindings'};
if (! ($hrn =~ /^\w*$/)) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"hrn: Single token only please");
}
#
# Make sure the user creating the slice is registered at the
# clearinghouse. Ditto for anyone bound to the slice.
#
if ($this_user->Register() != 0) {
print STDERR "Could not register $this_user at clearinghouse\n";
return GeniResponse->Create(GENIRESPONSE_ERROR);
}
if (defined($userbindings)) {
foreach my $binding_uuid (@{ $userbindings }) {
my $binding_user = GeniUser->Lookup($binding_uuid, 1);
if (!defined($binding_user)) {
print STDERR "No user $binding_uuid to bind to slice\n";
return GeniResponse->Create(GENIRESPONSE_ERROR);
}
if ($binding_user->Register() != 0) {
print STDERR
"Could not register $binding_user at clearinghouse\n";
return GeniResponse->Create(GENIRESPONSE_ERROR);
}
}
}
#
# When using this interface, the HRN does not correspond to an
# existing experiment in a project. It is just a token to call
......@@ -386,6 +381,16 @@ sub Register($)
return GeniResponse->Create(GENIRESPONSE_ERROR);
}
#
# Add the bindings locally before registration.
#
if (defined($userbindings)) {
foreach my $binding_uuid (@{ $userbindings }) {
my $binding_user = GeniUser->Lookup($binding_uuid, 1);
$slice->BindUser($binding_user);
}
}
#
# Register new slice at the clearinghouse.
#
......@@ -395,7 +400,7 @@ sub Register($)
print STDERR "Could not register new slice at the clearinghouse\n";
return GeniResponse->Create(GENIRESPONSE_ERROR);
}
return GeniResponse->Create(GENIRESPONSE_SUCCESS,
$slice_credential->asString());
}
......@@ -461,21 +466,10 @@ sub Remove($)
# allows anyone with a credential for this registry to lookup anyone
# else. Good feature of the Geni API.
#
my $this_user = GeniUser->Lookup($credential->owner_uuid());
my $this_user = GeniUser->Lookup($credential->owner_uuid(), 1);
if (!defined($this_user)) {
#
# Check Emulab users table.
#
my $user = User->LookupByUUID($credential->owner_uuid());
if (!defined($user)) {
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN,
undef, "Who are you?");
}
$this_user = GeniUser->CreateFromLocal($user);
if (!defined($this_user)) {
print STDERR "Could not create geniuser from $user\n";
return GeniResponse->Create(GENIRESPONSE_ERROR);
}
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN,
undef, "Who are you?");
}
if ($type eq "Slice") {
......
......@@ -109,8 +109,8 @@ sub Lookup($$)
print STDERR "Could not find certificate for slice $idx ($uuid)\n";
return undef;
}
$self->{'CERT'} = $certificate;
$self->{'USERS'} = undef;
$self->{'CERT'} = $certificate;
$self->{'BINDINGS'} = undef;
# Add to cache.
$slices{$self->{'SLICE'}->{'idx'}} = $self;
......@@ -256,8 +256,17 @@ sub Register($)
return 0
if (GeniCHClient::LookupSlice($self->uuid(), \$blob) == 0);
# Bind the other users too.
my @userbindings;
if ($self->UserBindings(\@userbindings) != 0) {
print STDERR "Could not get user bindings for $self\n";
return -1;
}
GeniCHClient::RegisterSlice($self->hrn(),
$self->creator_uuid(), $self->cert())
$self->creator_uuid(),
$self->cert(),
\@userbindings)
== 0 or return -1;
return 0;
......@@ -376,9 +385,8 @@ sub IsSliceAuthority($$)
}
#
# Client side methods to bind and unbind users from slices
#
# We issue this using the local SA as the authority.
# Server side of binding users to slices; insert entries into the bindings
# table.
#
sub BindUser($$)
{
......@@ -387,8 +395,13 @@ sub BindUser($$)
return -1
if (! (ref($self) && ref($target_user)));
GeniCHClient::BindUser($self->uuid(), $target_user->uuid())
== 0 or return -1;
my $slice_uuid = $self->uuid();
my $user_uuid = $target_user->uuid();
DBQueryWarn("replace into geni_bindings set ".
" created=now(), slice_uuid='$slice_uuid', ".
" user_uuid='$user_uuid'")
or return -1;
return 0;
}
......@@ -400,15 +413,19 @@ sub UnBindUser($$)
return -1
if (! (ref($self) && ref($target_user)));
GeniCHClient::UnBindUser($self->uuid(), $target_user->uuid())
== 0 or return -1;
my $slice_uuid = $self->uuid();
my $user_uuid = $target_user->uuid();
DBQueryWarn("delete from geni_bindings ".
"where slice_uuid='$slice_uuid' and user_uuid='$user_uuid'")
or return -1;
return 0;
}
#
# Return the user bindings for a slice, as a list. Used on client and server
# to get the geni_bindings table entries for a slice.
# Return the user bindings for a slice, as a list of uuids. Do not look
# them up here since this routine is called from the CH.
#
sub UserBindings($$)
{
......@@ -419,25 +436,21 @@ sub UserBindings($$)
my $uuid = $self->uuid();
if (!defined($self->{'USERS'})) {
if (!defined($self->{'BINDINGS'})) {
my $query_result =
DBQueryWarn("select user_uuid from geni_bindings ".
"where slice_uuid='$uuid'");
return -1
if (!$query_result);
$self->{'USERS'} = {};
my @bindings = ();
while (my ($user_uuid) = $query_result->fetchrow_array()) {
my $user = GeniUser->Lookup($user_uuid);
if (!defined($user)) {
print STDERR "Bindings: No mapping for user $user_uuid\n";
next;
}
$self->{'USERS'}->{$user_uuid} = $user;
push(@bindings, $user_uuid);
}
$self->{'BINDINGS'} = \@bindings;
}
@$pref = keys(%{ $self->{'USERS'} });
@$pref = @{ $self->{'BINDINGS'} };
return 0;
}
......
......@@ -53,12 +53,15 @@ sub mysystem($)
#
# Lookup by idx, or uuid.
#
sub Lookup($$)
sub Lookup($$;$)
{
my ($class, $token) = @_;
my ($class, $token, $includelocal) = @_;
my $query_result;
my $idx;
$includelocal = 0
if (!defined($includelocal));
if ($token =~ /^\d+$/) {
$idx = $token;
}
......@@ -66,10 +69,47 @@ sub Lookup($$)
$query_result =
DBQueryWarn("select idx from geni_users ".
"where uuid='$token' and status='active'");
return undef
if (!$query_result);
if (!$query_result->numrows) {
return undef
if (!$includelocal);
#
# Check Emulab users table.
#
my $user = User->LookupByUUID($token);
return undef
if (!defined($user));
return GeniUser->CreateFromLocal($user);
}
($idx) = $query_result->fetchrow_array();
}
elsif ($token =~ /^[\w\.]*$/) {
$query_result =
DBQueryWarn("select idx from geni_users ".
"where hrn='$token' and status='active'");
return undef
if (!$query_result);
if (!$query_result->numrows) {
return undef
if (! $query_result || !$query_result->numrows);
if (!$includelocal);
($idx) = $query_result->fetchrow_array();
#
# Check Emulab users table for last part of hrn.
#
($token) = ($token =~ /\.(\w*)$/);
my $user = User->Lookup($token);
return undef
if (!defined($user));
return GeniUser->CreateFromLocal($user);
}
($idx) = $query_result->fetchrow_array();
}
else {
return undef;
......@@ -81,6 +121,7 @@ sub Lookup($$)
$query_result =
DBQueryWarn("select * from geni_users where idx='$idx'");
return undef
if (!$query_result || !$query_result->numrows);
......@@ -204,7 +245,8 @@ sub Create($$$$$$$$$;$)
DBQueryWarn("replace into geni_userkeys set ".
" uuid=$safe_uuid, created=now(), ".
" key=$safe_key, type=$safe_type") or return undef;
" `key`=$safe_key, `type`=$safe_type")
or return undef;
}
}
......@@ -267,7 +309,7 @@ sub GetSSHKeys($$)
my $uuid = $self->uuid();
my $query_result =
DBQueryWarn("select key from geni_userkeys ".
DBQueryWarn("select `key` from geni_userkeys ".
"where uuid='$uuid' and type='ssh'");
return -1
if (!$query_result);
......@@ -292,7 +334,7 @@ sub GetKeys($$)
my $uuid = $self->uuid();
my $query_result =
DBQueryWarn("select type,key from geni_userkeys ".
DBQueryWarn("select `type`,`key` from geni_userkeys ".
"where uuid='$uuid'");
return -1
if (!$query_result);
......@@ -436,7 +478,7 @@ sub email($) { return $_[0]->{'USER'}->email(); }
sub GetSSHKeys($$) { return $_[0]->{'USER'}->GetSSHKeys($_[1]); }
# Need to construct this since not in User structure.
sub hrn($) { return $OURDOMAIN . "." . $_[0]->uid(); }
sub hrn($) { return $OURDOMAIN . ".users." . $_[0]->uid(); }
# And this is in another structure.
sub cert($) { return $_[0]->{'CERT'}->cert(); }
......
......@@ -127,7 +127,8 @@ print "Got my SA credential"
# Look me up just for the hell of it. I can see why the hrn is "useful"
#
params = {}
params["uuid"] = "7450199a-b6eb-102b-a5ad-001143e43770"
#params["uuid"] = "7450199a-b6eb-102b-a5ad-001143e43770"
params["hrn"] = "stoller"
params["credential"] = mycredential
params["type"] = "User"
rval,response = do_method("sa", "Resolve", params)
......@@ -137,6 +138,20 @@ if rval:
print "Found my record at the SA"
#print str(response)
#
# Look up leebee alter ego so I can bind him to the slice.
#
params = {}
params["hrn"] = "leebee"
params["credential"] = mycredential
params["type"] = "User"
rval,response = do_method("sa", "Resolve", params)
if rval:
Fatal("Could not resolve leebee")
pass
print "Found leebee's record at the SA"
leebee = response["value"]
#
# Lookup slice, delete before proceeding.
#
......@@ -168,6 +183,7 @@ params = {}
params["credential"] = mycredential
params["type"] = "Slice"
params["hrn"] = "myslice1"
params["userbindings"] = (leebee["uuid"],)
rval,response = do_method("sa", "Register", params)
if rval:
Fatal("Could not get my slice")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment