Commit 46e16fab authored by Leigh B Stoller's avatar Leigh B Stoller

Continue switch to URNs, further deprecating UUIDs. Add urn argument

to all of the API functions, and prefer that to any UUID argument.
There are a lot of little changes.

At this point, the CH and SA will no longer accept certificates that
do not have URNs in them. The CH will send email to the email address
listed in the certificate.
parent ee615600
...@@ -26,6 +26,7 @@ use emutil qw(TBGetUniqueIndex); ...@@ -26,6 +26,7 @@ use emutil qw(TBGetUniqueIndex);
use English; use English;
use overload ('""' => 'Stringify'); use overload ('""' => 'Stringify');
use XML::Simple; use XML::Simple;
use Date::Parse;
# Configure variables # Configure variables
my $TB = "@prefix@"; my $TB = "@prefix@";
...@@ -63,11 +64,6 @@ sub Lookup($$) ...@@ -63,11 +64,6 @@ sub Lookup($$)
elsif ($token =~ /^\w+\-\w+\-\w+\-\w+\-\w+$/) { elsif ($token =~ /^\w+\-\w+\-\w+\-\w+\-\w+$/) {
$uuid = $token; $uuid = $token;
} }
elsif ($token =~ /^P([\w]+)$/) {
# Only SAs are looked up this way.
# This will be flushed after URNs are fully pushed out.
return GeniAuthority->LookupByPrefix($1);
}
elsif ($token =~ /^[\w\.]*$/) { elsif ($token =~ /^[\w\.]*$/) {
$query_result = $query_result =
DBQueryWarn("select uuid from geni_authorities ". DBQueryWarn("select uuid from geni_authorities ".
...@@ -180,6 +176,22 @@ sub version($) { return field($_[0], "version"); } ...@@ -180,6 +176,22 @@ sub version($) { return field($_[0], "version"); }
sub cert($) { return $_[0]->{'CERT'}->cert(); } sub cert($) { return $_[0]->{'CERT'}->cert(); }
sub GetCertificate($) { return $_[0]->{'CERT'}; } sub GetCertificate($) { return $_[0]->{'CERT'}; }
#
# Expired?
#
sub IsExpired($)
{
my ($self) = @_;
my $expires = $self->expires();
return 1
if (!defined($expires) || $expires eq "");
my $when = strptime($expires);
return ($when < time());
}
# #
# Delete from the DB. # Delete from the DB.
# #
...@@ -205,36 +217,39 @@ sub Delete($) ...@@ -205,36 +217,39 @@ sub Delete($)
} }
# #
# Check to see if there is an existing authority with the same prefix. # Check to see if there is an existing authority with the same urn.
# #
sub CheckExisting($$$$) sub CheckExisting($$)
{ {
my ($class, $type, $uuid, $hrn) = @_; my ($class, $certificate) = @_;
my $urn = $certificate->urn();
my ($prefix) = ($uuid =~ /^\w+\-\w+\-\w+\-\w+\-(\w+)$/); my (undef, undef, $type) = GeniHRN::Parse($urn);
$type = lc($type); return -1
if (!defined($type));
my $safe_urn = DBQuoteSpecial($urn);
my $query_result = my $query_result =
DBQueryWarn("select uuid,type from geni_authorities ". DBQueryWarn("select urn,type from geni_authorities ".
"where uuid_prefix='$prefix'"); "where urn=$safe_urn");
return -1 return -1
if (!$query_result); if (!$query_result);
return 0 return 0
if (!$query_result->numrows); if (!$query_result->numrows);
while (my ($DBuuid,$DBtype) = $query_result->fetchrow_array()) { while (my ($DBurn,$DBtype) = $query_result->fetchrow_array()) {
# Look for an exact match, which means its just a replacement. # Look for an exact match, which means its just a replacement.
next next
if ($uuid eq $DBuuid && $type eq $DBtype); if ($urn eq $DBurn && $type eq $DBtype);
# Same uuid, different type. # Same urn, different type.
return 1 return 1
if ($uuid eq $DBuuid && $type ne $DBtype); if ($urn eq $DBurn && $type ne $DBtype);
# Different uuid, same type. # Different urn, same type.
return 1 return 1
if ($uuid ne $DBuuid && $type eq $DBtype); if ($urn ne $DBurn && $type eq $DBtype);
} }
return 0; return 0;
} }
...@@ -312,56 +327,20 @@ sub Version($) ...@@ -312,56 +327,20 @@ sub Version($)
} }
# #
# Does the uuid prefix match. # Check that the authority is the issuer of the given certificate.
# This check is not quite complete yet.
# #
sub PrefixMatch($$) sub CheckValidIssuer($$)
{ {
my ($self, $uuid) = @_; my ($self, $certificate) = @_;
my ($hisauthority, undef, undef) = GeniHRN::Parse($self->urn());
my ($herauthority, undef, undef) = GeniHRN::Parse($certificate->urn());
return 0 return 0
if (!ref($self)); if (! (defined($hisauthority) && defined($herauthority) &&
$hisauthority eq $herauthority));
my $uuid_prefix = $self->uuid_prefix();
if ($uuid =~ /^\w+\-\w+\-\w+\-\w+\-(\w+)$/) {
return 1
if ("$uuid_prefix" eq "$1");
}
return 0;
}
#
# Find an authority by looking for the prefix. This will eventually go
# away when we fully switch to URNs
#
# Note tha only SAs are looked up this way.
#
sub LookupByPrefix($$)
{
my ($class, $uuid) = @_;
my $prefix;
if ($uuid =~ /^\w+\-\w+\-\w+\-\w+\-(\w+)$/) {
$prefix = $1;
}
elsif ($uuid =~ /^(\w+)$/) {
$prefix = $1;
}
else {
print STDERR "Could no parse uuid for prefix\n";
return undef;
}
my $query_result =
DBQueryWarn("select uuid from geni_authorities ".
"where uuid_prefix='$prefix' and type='sa'");
return undef
if (! $query_result || !$query_result->numrows);
($uuid) = $query_result->fetchrow_array();
return GeniAuthority->Lookup($uuid); return 1;
} }
# #
......
This diff is collapsed.
...@@ -167,7 +167,7 @@ sub Resolve($) ...@@ -167,7 +167,7 @@ sub Resolve($)
# In this implementation, the caller must hold a valid slice # In this implementation, the caller must hold a valid slice
# credential for the slice being looked up. # credential for the slice being looked up.
# #
if (! ($admin || $slice->uuid() eq $credential->target_uuid())) { if (! ($admin || $slice->urn() eq $credential->target_urn())) {
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN()); return GeniResponse->Create(GENIRESPONSE_FORBIDDEN());
} }
# Return a blob. # Return a blob.
...@@ -191,7 +191,7 @@ sub Resolve($) ...@@ -191,7 +191,7 @@ sub Resolve($)
# or sliver credential for the slice being looked up. # or sliver credential for the slice being looked up.
# #
if (! ($admin || if (! ($admin ||
$sliver->uuid() eq $credential->target_uuid() || $sliver->urn() eq $credential->target_urn() ||
$sliver->slice_uuid() eq $credential->target_uuid())) { $sliver->slice_uuid() eq $credential->target_uuid())) {
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN); return GeniResponse->Create(GENIRESPONSE_FORBIDDEN);
} }
...@@ -212,18 +212,18 @@ sub Resolve($) ...@@ -212,18 +212,18 @@ sub Resolve($)
# In this implementation, the caller must hold a valid slice # In this implementation, the caller must hold a valid slice
# or sliver credential to get the ticket. # or sliver credential to get the ticket.
# #
my $slice = GeniSlice->Lookup($ticket->slice_uuid()); my $slice = GeniSlice->Lookup($ticket->slice_urn());
if (!defined($slice)) { if (!defined($slice)) {
print STDERR "Could not find slice for $ticket\n"; print STDERR "Could not find slice for $ticket\n";
return GeniResponse->Create(GENIRESPONSE_ERROR); return GeniResponse->Create(GENIRESPONSE_ERROR);
} }
if (! ($admin || $slice->uuid() eq $credential->target_uuid())) { if (! ($admin || $slice->urn() eq $credential->target_urn())) {
# #
# See if its the sliver credential. # See if its the sliver credential.
# #
my $aggregate = GeniAggregate->SliceAggregate($slice); my $aggregate = GeniAggregate->SliceAggregate($slice);
if (!defined($aggregate) || if (!defined($aggregate) ||
$aggregate->uuid() ne $credential->target_uuid()) { $aggregate->urn() ne $credential->target_urn()) {
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN()); return GeniResponse->Create(GENIRESPONSE_FORBIDDEN());
} }
} }
...@@ -318,7 +318,7 @@ sub CreateSliver($) ...@@ -318,7 +318,7 @@ sub CreateSliver($)
# up by the daemon. This is mostly cause I am reaching into # up by the daemon. This is mostly cause I am reaching into
# the V1 code, and its messy. # the V1 code, and its messy.
# #
my $slice = GeniSlice->Lookup($credential->target_uuid()); my $slice = GeniSlice->Lookup($credential->target_urn());
if ($slice->Lock() != 0) { if ($slice->Lock() != 0) {
print STDERR "CreateSliver: Could not lock $slice before delete\n"; print STDERR "CreateSliver: Could not lock $slice before delete\n";
return $response; return $response;
...@@ -330,7 +330,7 @@ sub CreateSliver($) ...@@ -330,7 +330,7 @@ sub CreateSliver($)
# #
# Leave the slice intact on error, so we can go look at it. # Leave the slice intact on error, so we can go look at it.
# #
$slice = GeniSlice->Lookup($credential->target_uuid()); $slice = GeniSlice->Lookup($credential->target_urn());
if (!defined($slice)) { if (!defined($slice)) {
print STDERR "CreateSliver: Could not find slice for $credential\n"; print STDERR "CreateSliver: Could not find slice for $credential\n";
return GeniResponse->Create(GENIRESPONSE_ERROR, undef, return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
...@@ -394,7 +394,7 @@ sub DeleteSliver($) ...@@ -394,7 +394,7 @@ sub DeleteSliver($)
# #
my $authority = GeniCertificate->LoadFromFile($EMULAB_PEMFILE); my $authority = GeniCertificate->LoadFromFile($EMULAB_PEMFILE);
if (!defined($authority)) { if (!defined($authority)) {
print STDERR " Could not get uuid from $EMULAB_PEMFILE\n"; print STDERR " Could not load $EMULAB_PEMFILE\n";
return GeniResponse->Create(GENIRESPONSE_ERROR); return GeniResponse->Create(GENIRESPONSE_ERROR);
} }
...@@ -1050,7 +1050,7 @@ sub UpdateTicket($) ...@@ -1050,7 +1050,7 @@ sub UpdateTicket($)
# #
# Make sure the ticket was issued to the caller. # Make sure the ticket was issued to the caller.
# #
if ($ticket->owner_uuid() ne $ENV{'GENIUUID'}) { if ($ticket->owner_urn() ne $ENV{'GENIURN'}) {
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN, undef, return GeniResponse->Create(GENIRESPONSE_FORBIDDEN, undef,
"This is not your ticket"); "This is not your ticket");
} }
...@@ -1058,7 +1058,7 @@ sub UpdateTicket($) ...@@ -1058,7 +1058,7 @@ sub UpdateTicket($)
return GeniResponse->Create(GENIRESPONSE_REFUSED(), undef, return GeniResponse->Create(GENIRESPONSE_REFUSED(), undef,
"Not an active ticket"); "Not an active ticket");
} }
if ($ticket->slice_uuid() ne $slice->uuid()) { if ($ticket->slice_urn() ne $slice->urn()) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef, return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"This ticket is for another slice"); "This ticket is for another slice");
} }
...@@ -1182,7 +1182,7 @@ sub RedeemTicket($) ...@@ -1182,7 +1182,7 @@ sub RedeemTicket($)
# #
# Make sure the ticket was issued to the caller. # Make sure the ticket was issued to the caller.
# #
if ($ticket->owner_uuid() ne $ENV{'GENIUUID'}) { if ($ticket->owner_urn() ne $ENV{'GENIURN'}) {
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN, undef, return GeniResponse->Create(GENIRESPONSE_FORBIDDEN, undef,
"This is not your ticket"); "This is not your ticket");
} }
...@@ -1311,7 +1311,7 @@ sub ReleaseTicket($) ...@@ -1311,7 +1311,7 @@ sub ReleaseTicket($)
# And of course, the ticket has to be for the slice indicated # And of course, the ticket has to be for the slice indicated
# by the provided credential. # by the provided credential.
# #
if ($ticket->slice_uuid() ne $slice->uuid()) { if ($ticket->slice_urn() ne $slice->urn()) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef, return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"This ticket is for another slice"); "This ticket is for another slice");
} }
...@@ -1367,10 +1367,20 @@ sub CheckCredentials($) ...@@ -1367,10 +1367,20 @@ sub CheckCredentials($)
return GeniResponse->Create(GENIRESPONSE_ERROR, undef, return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Could not create credential object"); "Could not create credential object");
} }
#
# Well formed credentials must now have URNs.
#
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Malformed credentials; missing URNs")
if (! (defined($credential->owner_urn()) &&
defined($credential->target_urn()) &&
GeniHRN::IsValid($credential->owner_urn()) &&
GeniHRN::IsValid($credential->target_urn())));
# #
# Make sure the credential was issued to the caller. # Make sure the credential was issued to the caller.
# #
if ($credential->owner_uuid() ne $ENV{'GENIUUID'}) { if ($credential->owner_urn() ne $ENV{'GENIURN'}) {
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN, undef, return GeniResponse->Create(GENIRESPONSE_FORBIDDEN, undef,
"This is not your credential"); "This is not your credential");
} }
...@@ -1384,10 +1394,20 @@ sub CheckCredential($) ...@@ -1384,10 +1394,20 @@ sub CheckCredential($)
return GeniResponse->Create(GENIRESPONSE_ERROR, undef, return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Could not create credential object"); "Could not create credential object");
} }
#
# Well formed credentials must now have URNs.
#
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Malformed credentials; missing URNs")
if (! (defined($credential->owner_urn()) &&
defined($credential->target_urn()) &&
GeniHRN::IsValid($credential->owner_urn()) &&
GeniHRN::IsValid($credential->target_urn())));
# #
# Make sure the credential was issued to the caller. # Make sure the credential was issued to the caller.
# #
if ($credential->owner_uuid() ne $ENV{'GENIUUID'}) { if ($credential->owner_urn() ne $ENV{'GENIURN'}) {
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN, undef, return GeniResponse->Create(GENIRESPONSE_FORBIDDEN, undef,
"This is not your credential"); "This is not your credential");
} }
......
...@@ -28,6 +28,7 @@ use emutil qw(TBGetUniqueIndex); ...@@ -28,6 +28,7 @@ use emutil qw(TBGetUniqueIndex);
use English; use English;
use overload ('""' => 'Stringify'); use overload ('""' => 'Stringify');
use XML::Simple; use XML::Simple;
use Date::Parse;
# Configure variables # Configure variables
my $TB = "@prefix@"; my $TB = "@prefix@";
...@@ -178,6 +179,22 @@ sub cert($) { return $_[0]->{'CERT'}->cert(); } ...@@ -178,6 +179,22 @@ sub cert($) { return $_[0]->{'CERT'}->cert(); }
sub GetCertificate($) { return $_[0]->{'CERT'}; } sub GetCertificate($) { return $_[0]->{'CERT'}; }
sub GetManager($) { return $_[0]->{'MANAGER'}; } sub GetManager($) { return $_[0]->{'MANAGER'}; }
#
# Expired?
#
sub IsExpired($)
{
my ($self) = @_;
my $expires = $self->expires();
return 1
if (!defined($expires) || $expires eq "");
my $when = strptime($expires);
return ($when < time());
}
# #
# Return the URN. This is complicated by the fact that the DB does not # Return the URN. This is complicated by the fact that the DB does not
# store the urn, but is in the certificate. Further, it might be a # store the urn, but is in the certificate. Further, it might be a
......
...@@ -20,6 +20,7 @@ use GeniDB; ...@@ -20,6 +20,7 @@ use GeniDB;
use GeniCertificate; use GeniCertificate;
use GeniUtil; use GeniUtil;
use GeniXML; use GeniXML;
use GeniHRN;
use emutil qw(TBGetUniqueIndex); use emutil qw(TBGetUniqueIndex);
use English; use English;
use XML::Simple; use XML::Simple;
...@@ -332,6 +333,10 @@ sub CreateFromSigned($$;$) ...@@ -332,6 +333,10 @@ sub CreateFromSigned($$;$)
print STDERR "Invalid hrn in credential\n"; print STDERR "Invalid hrn in credential\n";
return undef; return undef;
} }
if (!GeniHRN::IsValid($target_certificate->urn())) {
print STDERR "Invalid urn in target certificate of credential\n";
return undef;
}
# Dig out the owner certificate. # Dig out the owner certificate.
($cert_node) = $doc->getElementsByTagName("owner_gid"); ($cert_node) = $doc->getElementsByTagName("owner_gid");
...@@ -351,6 +356,10 @@ sub CreateFromSigned($$;$) ...@@ -351,6 +356,10 @@ sub CreateFromSigned($$;$)
print STDERR "Invalid hrn in credential\n"; print STDERR "Invalid hrn in credential\n";
return undef; return undef;
} }
if (!GeniHRN::IsValid($owner_certificate->urn())) {
print STDERR "Invalid urn in owner certificate of credential\n";
return undef;
}
my $self = {}; my $self = {};
$self->{'capabilities'} = undef; $self->{'capabilities'} = undef;
...@@ -542,7 +551,13 @@ sub Sign($$) ...@@ -542,7 +551,13 @@ sub Sign($$)
$certificate = "-c $TB/etc/genicm.pem"; $certificate = "-c $TB/etc/genicm.pem";
} }
elsif ($how == $LOCALMA_FLAG) { elsif ($how == $LOCALMA_FLAG) {
$certificate = "-c $TB/etc/genich.pem"; if (defined($main::GENI_CHPEMFILE)) {
# See xmlrpc/protogeni-ch.pl.in
$certificate = "-c $main::GENI_CHPEMFILE";
}
else {
$certificate = "-c $TB/etc/genich.pem";
}
} }
else { else {
print STDERR "Invalid 'how' argument to Sign()\n"; print STDERR "Invalid 'how' argument to Sign()\n";
......
...@@ -101,7 +101,7 @@ sub RegisterExperiment($$) ...@@ -101,7 +101,7 @@ sub RegisterExperiment($$)
# Create and register the slice. Slice is returned locked # Create and register the slice. Slice is returned locked
# #
print STDERR "Creating new slice for $experiment\n"; print STDERR "Creating new slice for $experiment\n";
$slice = GeniSlice->CreateFromLocal($experiment, $user); $slice = GeniSlice->CreateFromLocal($experiment, $geniuser);
if (!defined($slice)) { if (!defined($slice)) {
print STDERR "Could not create local slice from $experiment\n"; print STDERR "Could not create local slice from $experiment\n";
return -1; return -1;
......
...@@ -123,6 +123,7 @@ sub idx($) { return field($_[0], "idx"); } ...@@ -123,6 +123,7 @@ sub idx($) { return field($_[0], "idx"); }
sub hrn($) { return field($_[0], "hrn"); } sub hrn($) { return field($_[0], "hrn"); }
sub uuid($) { return field($_[0], "uuid"); } sub uuid($) { return field($_[0], "uuid"); }
sub creator_uuid($) { return field($_[0], "creator_uuid"); } sub creator_uuid($) { return field($_[0], "creator_uuid"); }
sub creator_urn($) { return field($_[0], "creator_urn"); }
sub created($) { return field($_[0], "created"); } sub created($) { return field($_[0], "created"); }
sub shutdown($) { return field($_[0], "shutdown"); } sub shutdown($) { return field($_[0], "shutdown"); }
sub expires($) { return field($_[0], "expires"); } sub expires($) { return field($_[0], "expires"); }
...@@ -138,7 +139,7 @@ sub LOCKED($) { return $_[0]->{'LOCKED'}; } ...@@ -138,7 +139,7 @@ sub LOCKED($) { return $_[0]->{'LOCKED'}; }
# #
sub Create($$$$;$$) sub Create($$$$;$$)
{ {
my ($class, $certificate, $creator_uuid, $authority, $exptidx, $lock) = @_; my ($class, $certificate, $creator, $authority, $exptidx, $lock) = @_;
my @insert_data = (); my @insert_data = ();
# Every slice gets a new unique index. # Every slice gets a new unique index.
...@@ -162,10 +163,12 @@ sub Create($$$$;$$) ...@@ -162,10 +163,12 @@ sub Create($$$$;$$)
my $safe_hrn = DBQuoteSpecial($certificate->hrn()); my $safe_hrn = DBQuoteSpecial($certificate->hrn());
my $safe_uuid = DBQuoteSpecial($certificate->uuid()); my $safe_uuid = DBQuoteSpecial($certificate->uuid());
my $safe_cuuid = DBQuoteSpecial($creator_uuid); my $safe_cuuid = DBQuoteSpecial($creator->uuid());
my $safe_curn = DBQuoteSpecial($creator->urn());
push(@insert_data, "hrn=$safe_hrn"); push(@insert_data, "hrn=$safe_hrn");
push(@insert_data, "uuid=$safe_uuid"); push(@insert_data, "uuid=$safe_uuid");
push(@insert_data, "creator_uuid=$safe_cuuid"); push(@insert_data, "creator_uuid=$safe_cuuid");
push(@insert_data, "creator_urn=$safe_curn");
if ($certificate->Store() != 0) { if ($certificate->Store() != 0) {
print STDERR "Could not store certificate for new slice.\n"; print STDERR "Could not store certificate for new slice.\n";
...@@ -202,24 +205,20 @@ sub Delete($) ...@@ -202,24 +205,20 @@ sub Delete($)
} }
# #
# Class method to check for an existing user that has the same # Return the URN. This is complicated by the fact that the DB does
# uid/email. Lets not allow this for now. Return the number of # not store the urn, but is in the certificate. Further, it might
# users that match or -1 if an error. # be a slice from an SA not doing URNs yet, in which case set it to
# the uuid and hope for the best.
# #
sub CheckExisting($$$) sub urn($)
{ {
my ($class, $hrn, $uuid) = @_; my ($self) = @_;
my $urn = $self->GetCertificate()->urn();
my $safe_hrn = DBQuoteSpecial($hrn);
my $safe_uuid = DBQuoteSpecial($uuid);
my $query_result = return $urn
DBQueryFatal("select idx from geni_slices ". if (defined($urn) && $urn ne "");
"where hrn=$safe_hrn or uuid=$safe_uuid");
return -1
if (!defined($query_result));
return $query_result->numrows; return $self->uuid();
} }
# #
...@@ -560,6 +559,9 @@ sub Resolve($$$$) ...@@ -560,6 +559,9 @@ sub Resolve($$$$)
if ($token =~ /^\w+\-\w+\-\w+\-\w+\-\w+$/) { if ($token =~ /^\w+\-\w+\-\w+\-\w+\-\w+$/) {
$which = "uuid"; $which = "uuid";
} }
elsif (GeniHRN::IsValid($token)) {
$which = "urn";