Commit b9df9923 authored by Jonathon Duerig's avatar Jonathon Duerig

Checkpoint for MA/SA standard.

parent c72ef653
......@@ -41,7 +41,8 @@ LIB_SCRIPTS = GeniDB.pm GeniUser.pm \
GeniAuthority.pm GeniCertificate.pm GeniAggregate.pm \
GeniUtil.pm GeniRegistry.pm GeniUsage.pm GeniHRN.pm \
GeniSES.pm GeniResource.pm GeniXML.pm GeniAM.pm \
GeniEmulab.pm GeniFoam.pm GeniStitch.pm
GeniEmulab.pm GeniFoam.pm GeniStitch.pm \
GeniStd.pm GeniMA.pm GeniStdSA.pm
SBIN_SCRIPTS = plabnodewrapper plabslicewrapper
SCRIPTS = genischemacheck.pl
......
......@@ -40,6 +40,7 @@ use vars qw(@ISA @EXPORT);
@ISA = "Exporter";
@EXPORT = qw ( );
use GeniStd;
use GeniCMV2;
use GeniResponse;
use GeniCredential;
......@@ -49,7 +50,6 @@ use emutil;
use Compress::Zlib;
use MIME::Base64;
use XML::LibXML;
use URI;
use Date::Parse;
use Data::Dumper;
use Frontier::RPC2;
......@@ -258,7 +258,7 @@ sub ListResources()
my $credentials = $credential_args;
if ($API_VERSION >= 3) {
$credentials = FilterCredentials($credential_args);
$credentials = GeniStd::FilterCredentials($credential_args);
}
my $xml = undef;
......@@ -330,128 +330,6 @@ sub ListResources()
return GeniResponse->Create(GENIRESPONSE_SUCCESS, $xml);
}
sub auto_add_sa($)
{
my ($cred_str) = @_;
my $verify_sig = 1;
my $cred = GeniCredential->CreateFromSigned($cred_str, $verify_sig);
my $signers = $cred->signer_certs();
return
if ($cred->type() eq "speaksfor");
# The credential has been verified, so the signer derives from a
# trusted root.
my $sa_cert = @$signers[0];
# These are borrowed from protogeni/scripts/addauthority
my $certificate = GeniCertificate->LoadFromString($sa_cert);
if (!defined($certificate)) {
print STDERR "auto_add_sa: could not get certificate from $sa_cert\n";
return;
}
if (! ($certificate->uuid() =~ /\w*-(\w*)$/)) {
print STDERR "auto_add_sa: could not get prefix from uuid\n";
return;
}
my $url = $certificate->URL();
if (!defined($url)) {
print STDERR "auto_add_sa: certificate does not have a URL extension\n";
}
my $urn = $certificate->urn();
if (!defined($urn)) {
print STDERR "auto_add_sa: certificate does not have a URN extension\n";
return;
}
# Look to see if already registered.
my $authority = GeniAuthority->Lookup($urn);
if (defined($authority)) {
#
# See if the certificate has changed. If so we want to replace it.
#
return
if ($certificate->SameCert($authority->GetCertificate()));
#
# Want to reuse the old uuid since we use it as a table cross
# reference index. Eventually need to use the URN. Anyway, change
# the uuid in the new certificate so that it goes into the DB
# with the original one. Then update the Authority record with
# the new certificate.
#
print STDERR "Updating $authority with new certificate: $certificate\n";
$certificate->setuuid($authority->uuid());
if ($authority->UpdateCertificate($certificate)) {
print STDERR "Failed to update $authority with $certificate\n";
return;
}
return;
}
#
# We want the URL!
#
goto goturl
if (defined($url));
# First get the list of registries from PLC.
my $registry = GeniRegistry::PLC->Create();
if (!defined($registry)) {
print STDERR "Cannot create a PLC registry object\n";
return;
}
my $blob;
if ($registry->GetRegistries(\$blob)) {
print STDERR "Cannot get PLC registry listing\n";
return;
}
print STDERR Dumper($blob);
#
# Now look at the last signer certificate; this is the actual authority.
#
my $authcertstr = @$signers[scalar(@$signers) - 1];
my $authcert = GeniCertificate->LoadFromString($authcertstr);
if (!defined($authcert)) {
print STDERR
"auto_add_sa: could not get certificate from $authcertstr\n";
return;
}
my $authurn = $authcert->urn();
if (!defined($authurn)) {
print STDERR "auto_add_sa: $authcert does not have a URN extension\n";
return;
}
#
# Now search ...
#
foreach my $ref (@$blob) {
if ($ref->{'urn'} eq $authurn) {
$url = $ref->{'url'};
last;
}
}
if (!defined($url)) {
print STDERR "auto_add_sa: could not get a URL for $authcert\n";
return;
}
#
# Gack. Replace the URL with a modified URL which says https.
# Why does PLC set the scheme to http?
#
goturl:
my $uri = URI->new($url);
$uri->scheme("https");
$url = "$uri";
if (!GeniAuthority->Create($certificate, $url, "sa")) {
print STDERR "auto_add_sa: unable to add authority\n";
return;
}
return $certificate;
}
###############################################################################
# AM API V2
###############################################################################
......@@ -471,7 +349,7 @@ sub CreateSliver()
# onto a list here and remove them at the end of this
# function. The other AM calls do not need the dynamically
# added SA.
auto_add_sa($cred);
GeniStd::auto_add_sa($cred);
}
# Package the caller_keys in a list of hashes the way the CM wants
......@@ -731,7 +609,7 @@ sub CreateImage()
my $credentials = $credential_args;
if ($API_VERSION >= 3) {
$credentials = FilterCredentials($credential_args);
$credentials = GeniStd::FilterCredentials($credential_args);
}
my $args = {
......@@ -800,9 +678,9 @@ sub Describe
return GeniResponse->MalformedArgsResponse("Missing arguments");
}
my @urns = @{ $urn_args };
my $credentials = FilterCredentials($credential_args);
my $credentials = GeniStd::FilterCredentials($credential_args);
my $cred = GeniCMV2::CheckCredentials($credentials);
my $cred = GeniStd::CheckCredentials($credentials);
return $cred
if (GeniResponse::IsResponse($cred));
......@@ -907,8 +785,8 @@ sub Update
return GeniResponse->MalformedArgsResponse("Missing arguments");
}
my @urns = @{ $urn_args };
my $credentials = FilterCredentials($credential_args);
my $cred = GeniCMV2::CheckCredentials($credentials);
my $credentials = GeniStd::FilterCredentials($credential_args);
my $cred = GeniStd::CheckCredentials($credentials);
return $cred
if (GeniResponse::IsResponse($cred));
......@@ -1048,7 +926,7 @@ sub Renew
! defined($expiration_time) || ! defined($options)) {
return GeniResponse->MalformedArgsResponse("Missing arguments");
}
my $credentials = FilterCredentials($credential_args);
my $credentials = GeniStd::FilterCredentials($credential_args);
my @urns = @{ $urn_args};
return GeniResponse->MalformedArgsResponse("Empty URN List")
if (scalar(@urns) < 1);
......@@ -1080,7 +958,7 @@ sub Provision
my @urns = @{ $urn_args };
return GeniResponse->MalformedArgsResponse("Empty URN List")
if (scalar(@urns) < 1);
my $credentials = FilterCredentials($credential_args);
my $credentials = GeniStd::FilterCredentials($credential_args);
my $users = $options->{'geni_users'};
my $sliver_keys = [];
if (defined($users) && @$users) {
......@@ -1098,7 +976,7 @@ sub Provision
}
}
my $cred = GeniCMV2::CheckCredentials($credentials);
my $cred = GeniStd::CheckCredentials($credentials);
return $cred
if (GeniResponse::IsResponse($cred));
......@@ -1163,12 +1041,12 @@ sub PerformOperationalAction
return GeniResponse->MalformedArgsResponse("Empty URN List")
if (scalar(@urns) < 1);
my $credentials = FilterCredentials($credential_args);
my $credentials = GeniStd::FilterCredentials($credential_args);
my $args = {
'credentials' => $credentials
};
my $cred = GeniCMV2::CheckCredentials($credentials);
my $cred = GeniStd::CheckCredentials($credentials);
return $cred
if (GeniResponse::IsResponse($cred));
......@@ -1262,7 +1140,7 @@ sub Delete
push(@{ $slivers }, $blob);
}
my $credentials = FilterCredentials($credential_args);
my $credentials = GeniStd::FilterCredentials($credential_args);
my $args = {
'slice_urn' => $urns[0],
'credentials' => $credentials
......@@ -1281,8 +1159,8 @@ sub Cancel
return GeniResponse->MalformedArgsResponse("Empty URN List")
if (scalar(@urns) < 1);
my $credentials = FilterCredentials($credential_args);
my $cred = GeniCMV2::CheckCredentials($credentials);
my $credentials = GeniStd::FilterCredentials($credential_args);
my $cred = GeniStd::CheckCredentials($credentials);
return $cred
if (GeniResponse::IsResponse($cred));
......@@ -1290,7 +1168,7 @@ sub Cancel
my $response;
my $ticket = GeniTicket->SliceTicket($slice);
if (defined($ticket)) {
my $credentials = FilterCredentials($credential_args);
my $credentials = GeniStd::FilterCredentials($credential_args);
my $args = {
'slice_urn' => $urns[0],
'ticket' => $ticket->ticket_string(),
......@@ -1304,23 +1182,6 @@ sub Cancel
return $response;
}
# Filter out any credentials of an uknown type leaving only geni_sfa
# version 2 and version 3 credentials in a list. Also invokes
# auto_add_sa on each credential.
sub FilterCredentials
{
my ($credentials) = @_;
my $result = [];
foreach my $cred (@{ $credentials }) {
if ($cred->{'geni_type'} eq "geni_sfa" &&
($cred->{'geni_version'} eq 2 || $cred->{'geni_version'} eq 3)) {
push(@{ $result }, $cred->{'geni_value'});
auto_add_sa($cred->{'geni_value'});
}
}
return $result;
}
# Determines operational state based on the state/status of a sliver.
sub GetOpState
{
......
This diff is collapsed.
......@@ -30,8 +30,7 @@
package GeniMA;
#
# The server side of the CM interface on remote sites. Also communicates
# with the GMC interface at Geni Central as a client.
# Shim for implementing standard GENI MA interface.
#
use strict;
use Exporter;
......@@ -40,16 +39,20 @@ use vars qw(@ISA @EXPORT);
@ISA = "Exporter";
@EXPORT = qw ( );
use GeniStd;
use GeniSA;
use GeniResponse;
use GeniCredential;
use GeniRegistry;
use emutil;
use Data::Dumper;
my $coder = Frontier::RPC2->new('use_objects' => 1);
sub GetVersion()
{
my $blob = {
"VERSION" => "0.1",
"VERSION" => $coder->string("0.1"),
"CREDENTIAL_TYPES" => ["SFA"]
};
return GeniResponse->Create(GENIRESPONSE_SUCCESS, $blob);
......@@ -58,24 +61,20 @@ sub GetVersion()
sub LookupPublic($)
{
my ($options) = @_;
my $match = $options->{'match'};
my $filter = $options->{'filter'};
my ($match, $filter) = GeniStd::GetMatchFilter($options);
my $members = {};
if (exists($match) && defined($match)) {
foreach my $key (@{ $match }) {
my $geniuser = GeniUser->Lookup($key, 0);
if (defined($geniuser)) {
my $blob = {};
GeniStd::addField($blob, "MEMBER_URN", $geniuser->urn(),
$filter);
GeniStd::addField($blob, "MEMBER_UID", $geniuser->uid(),
$filter);
GeniStd::addField($blob, "MEMBER_USERNAME", $geniuser->hrn(),
$filter);
$members->{$geniuser->urn()} = $blob;
}
foreach my $key (@{ $match }) {
my $geniuser = GeniUser->Lookup($key, 1);
if (defined($geniuser)) {
my $completeblob = {
"MEMBER_URN" => $geniuser->urn(),
"MEMBER_UID" => $geniuser->uid(),
"MEMBER_USERNAME" => $geniuser->hrn()
};
my $blob = GeniStd::FilterFields($completeblob, $filter);
$members->{$geniuser->urn()} = $blob;
}
}
return GeniResponse->Create(GENIRESPONSE_SUCCESS, $members);
......@@ -84,26 +83,32 @@ sub LookupPublic($)
sub LookupPrivate($$)
{
my ($credential_args, $options) = @_;
my $credential = GeniStd::CheckCredentials($credential_args);
my ($credential) = GeniStd::CheckCredentials(GeniStd::FilterCredentials($credential_args));
return $credential
if (GeniResponse::IsResponse($credential));
#
# We need to enforce Emulab permissions here, since the credential
# allows anyone with a credential for this registry to lookup anyone
# else. Good feature of the Geni API.
#
my $this_user = GeniUser->Lookup($ENV{'GENIURN'}, 1);
if (!defined($this_user)) {
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN, undef,
"Permission denied. Only local users are allowed to make private lookups.");
}
$credential->HasPrivilege( "authority" ) or
$credential->HasPrivilege( "resolve" ) or
return GeniResponse->Create( GENIRESPONSE_FORBIDDEN, undef,
"Insufficient privilege" );
my $match = $options->{'match'};
my $filter = $options->{'filter'};
my ($match, $filter) = GeniStd::GetMatchFilter($options);
my $members = {};
if (exists($match) && defined($match)) {
foreach my $key (@{ $match }) {
my $geniuser = GeniUser->Lookup($key, 0);
if (defined($geniuser)) {
my $blob = {};
$members->{$geniuser->urn()} = $blob;
}
foreach my $key (@{ $match }) {
my $geniuser = GeniUser->Lookup($key, 1);
if (defined($geniuser)) {
my $blob = {};
$members->{$geniuser->urn()} = $blob;
}
}
return GeniResponse->Create(GENIRESPONSE_SUCCESS, $members);
......@@ -113,36 +118,42 @@ sub LookupIdentifying($$)
{
my ($credential_args, $options) = @_;
my $credential = GeniStd::CheckCredentials($credential_args);
my ($credential) = GeniStd::CheckCredentials(GeniStd::FilterCredentials($credential_args));
return $credential
if (GeniResponse::IsResponse($credential));
#
# We need to enforce Emulab permissions here, since the credential
# allows anyone with a credential for this registry to lookup anyone
# else. Good feature of the Geni API.
#
my $this_user = GeniUser->Lookup($ENV{'GENIURN'}, 1);
if (!defined($this_user)) {
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN, undef,
"Permission denied. Only local users are allowed to make identifying lookups.");
}
$credential->HasPrivilege( "authority" ) or
$credential->HasPrivilege( "resolve" ) or
return GeniResponse->Create( GENIRESPONSE_FORBIDDEN, undef,
"Insufficient privilege" );
my $match = $options->{'match'};
my $filter = $options->{'filter'};
my ($match, $filter) = GeniStd::GetMatchFilter($options);
my $members = {};
if (exists($match) && defined($match)) {
foreach my $key (@{ $match }) {
my $geniuser = GeniUser->Lookup($key, 0);
if (defined($geniuser)) {
my @namelist = split(/ /, $neinuser->name());
my $lastname = pop(@namelist);
my $firstname = join(" ", @namelist);
my $blob = {};
GeniStd::addField($blob, "MEMBER_URN", $geniuser->urn(),
$filter);
GeniStd::addField($blob, "MEMBER_FIRSTNAME", $firstname,
$filter);
GeniStd::addField($blob, "MEMBER_LASTNAME", $lastname,
$filter);
GeniStd::addField($blob, "MEMBER_EMAIL", $geniuser->email(),
$filter);
}
foreach my $key (@{ $match }) {
my $geniuser = GeniUser->Lookup($key, 1);
if (defined($geniuser)) {
my @namelist = split(/ /, $geniuser->name());
my $lastname = pop(@namelist);
my $firstname = join(" ", @namelist);
my $completeblob = {
"MEMBER_FIRSTNAME" => $firstname,
"MEMBER_LASTNAME" => $lastname,
"MEMBER_EMAIL" => $geniuser->email()
};
my $blob = GeniStd::FilterFields($completeblob, $filter);
$members->{$geniuser->urn()} = $blob;
}
}
return GeniResponse->Create(GENIRESPONSE_SUCCESS, $members);
......@@ -165,9 +176,29 @@ sub GetCredentials($$$)
my $blob = {
"geni_type" => "sfa",
"geni_type" => "3",
"geni_version" => $coder->string("3"),
"geni_credential" => $credential->value()
};
return GeniResponse->Create(GENIRESPONSE_SUCCESS, [$blob]);
}
sub CreateKey($$$)
{
my ($member_urn, $credential_args, $options) = @_;
}
sub DeleteKey($$$$)
{
my ($member_urn, $key_id, $credentials, $options) = @_;
}
sub UpdateKey($$$$)
{
my ($member_urn, $key_id, $credentials, $options) = @_;
}
sub LookupKeys($$)
{
my ($credentials, $options) = @_;
}
This diff is collapsed.
This diff is collapsed.
#! /usr/bin/env python
#
# Copyright (c) 2012 University of Utah and the Flux Group.
#
# {{{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.
#
# }}}
#
import sys
import pwd
import getopt
import os
import re
import xmlrpclib
from M2Crypto import X509
def Usage():
print "usage: " + sys.argv[ 0 ] + " [option...] [authority]"
print """Options:
-d, --debug be verbose about XML methods invoked
-h, --help show options and usage
-r file, --read-commands=file specify additional configuration file"""
execfile( "test-common.py" )
if len( args ) > 1:
Usage()
sys.exit( 1 )
elif len( args ) == 1:
authority = args[ 0 ]
else:
authority = "geni-sa"
try:
response = do_method(authority, "get_version", [],
response_handler=geni_am_response_handler)
print response
except xmlrpclib.Fault, e:
Fatal("Could not obtain the API version: %s" % (str(e)))
#! /usr/bin/env python
#
# Copyright (c) 2008-2011 University of Utah and the Flux Group.
#
# {{{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.
#
# }}}
#
#
#
import sys
import pwd
import getopt
import time
import os
import re
import xmlrpclib
from M2Crypto import X509
ACCEPTSLICENAME=1
OtherUser = None
Expiration = (60 * 300)
execfile( "test-common.py" )
if len(REQARGS) == 1:
OtherUser = REQARGS[0]
pass
#
# Get a credential for myself, that allows me to do things at the SA.
#
mycredential = get_self_credential()
print "Got my SA credential"
#
# Lookup slice.
#
#params = {}
#params["credential"] = mycredential
#params["type"] = "Slice"
#params["hrn"] = SLICENAME
#rval,response = do_method("sa", "Resolve", params)
#if rval == 0:
# print "Slice already exists."
# sys.exit(0)
# pass
#
# Set up expiration.
#
valid_until = time.strftime("%Y%m%dT%H:%M:%S",
time.gmtime(time.time() + Expiration))