All new accounts created on Gitlab now require administrator approval. If you invite any collaborators, please let Flux staff know so they can approve the accounts.

Commit ae3ea197 authored by Leigh B Stoller's avatar Leigh B Stoller

Add speaksfor to GeniSA/MA/StdSA modules, and add/fix things to

support the genidesktop.
parent 9064171a
......@@ -54,6 +54,7 @@ use File::Temp qw(tempfile);
use Date::Parse;
use POSIX qw(strftime);
use Time::Local;
use Carp qw(cluck carp);
use overload ('""' => 'Stringify');
# Exported variables
......@@ -412,6 +413,11 @@ sub CreateFromSigned($$;$)
$nosig = 0
if (!defined($nosig));
if (!defined($string)) {
$msg = "No string";
goto bad;
}
# First verify the credential
if (! $nosig) {
my ($fh, $filename) = tempfile(UNLINK => 0);
......@@ -675,6 +681,7 @@ sub CreateFromSigned($$;$)
$msg = "Internal error creating credential object";
}
print STDERR "$msg\n";
cluck("$msg");
$CreateFromSignedError = $msg;
return undef;
}
......@@ -1130,6 +1137,27 @@ sub CheckCredential($;$$)
return $credential;
}
#
# Load a certificate from a file. This creates an object, but does
# not store it in the DB.
#
sub LoadFromFile($$)
{
my ($class, $filename) = @_;
my $contents = "";
if (! open(CRED, $filename)) {
print STDERR "Could not open $filename: $!\n";
return undef;
}
while (<CRED>) {
$contents .= $_;
}
close(CRED);
return GeniCredential->CreateFromSigned($contents);
}
########################################################################
# ABAC version of a credential. This a total hack job, will need to
# be flushed and redone later.
......
......@@ -84,18 +84,25 @@ sub LookupPublic($)
sub LookupPrivate($$)
{
my ($credential_args, $options) = @_;
my ($credential) = GeniStd::CheckCredentials(GeniStd::FilterCredentials($credential_args));
my ($credential,$speaksfor) =
GeniStd::CheckCredentials(GeniStd::FilterCredentials($credential_args));
return $credential
if (GeniResponse::IsResponse($credential));
return GeniResponse->MalformedArgsResponse("Missing self credential")
if (!defined($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);
my $this_user =
GeniUser->Lookup((defined($speaksfor) ?
$speaksfor->target_urn() : $ENV{'GENIURN'}), 1);
if (!defined($this_user)) {
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN, undef,
"Permission denied. Only local users are allowed to make private lookups.");
"Permission denied. Only local users are allowed ".
"to make private lookups.");
}
$credential->HasPrivilege( "authority" ) or
......@@ -119,19 +126,25 @@ sub LookupIdentifying($$)
{
my ($credential_args, $options) = @_;
my ($credential) = GeniStd::CheckCredentials(GeniStd::FilterCredentials($credential_args));
my ($credential,$speaksfor) =
GeniStd::CheckCredentials(GeniStd::FilterCredentials($credential_args));
return $credential
if (GeniResponse::IsResponse($credential));
return GeniResponse->MalformedArgsResponse("Missing self credential")
if (!defined($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);
my $this_user =
GeniUser->Lookup((defined($speaksfor) ?
$speaksfor->target_urn() : $ENV{'GENIURN'}), 1);
if (!defined($this_user)) {
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN, undef,
"Permission denied. Only local users are allowed to make identifying lookups.");
"Permission denied. Only local users are allowed ".
"to make identifying lookups.");
}
$credential->HasPrivilege( "authority" ) or
......@@ -171,7 +184,19 @@ sub GetCredentials($$$)
{
my ($member_urn, $credential_args, $options) = @_;
my $credential = GeniSA::GetCredential({ "urn" => $member_urn });
#
# Need to know if only a speaksfor is provided.
#
my ($credential,$speaksfor) =
GeniStd::CheckCredentials(GeniStd::FilterCredentials($credential_args));
return $credential
if (GeniResponse::IsResponse($credential));
my $args = { "urn" => $member_urn };
if (defined($speaksfor)) {
$args->{"credential"} = $speaksfor->asString();
}
$credential = GeniSA::GetCredential($args);
return $credential
if (GeniResponse::IsError($credential));
......@@ -207,7 +232,44 @@ sub UpdateKey($$$$)
sub LookupKeys($$)
{
my ($credentials, $options) = @_;
my ($credential_args, $options) = @_;
return GeniResponse->Create(GENIRESPONSE_NOT_IMPLEMENTED);
my ($credential,$speaksfor) =
GeniStd::CheckCredentials(GeniStd::FilterCredentials($credential_args));
return $credential
if (GeniResponse::IsResponse($credential));
return GeniResponse->MalformedArgsResponse("Missing self credential")
if (0 && !defined($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((defined($speaksfor) ?
$speaksfor->target_urn() : $ENV{'GENIURN'}), 1);
if (!defined($this_user)) {
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN, undef,
"Permission denied.");
}
defined($credential) &&
($credential->HasPrivilege( "authority" ) or
$credential->HasPrivilege( "resolve" ) or
return GeniResponse->Create( GENIRESPONSE_FORBIDDEN, undef,
"Insufficient privilege" ));
my @keys;
if ($this_user->GetKeyBundle(\@keys) != 0) {
print STDERR "Could not get keys for $this_user\n";
return GeniResponse->Create(GENIRESPONSE_ERROR);
}
my @list = ();
foreach my $key (@keys) {
push(@list, {"KEY_PUBLIC" => $key->{'key'} });
}
my $blob = { $this_user->urn() => \@list };
return GeniResponse->Create(GENIRESPONSE_SUCCESS, $blob);
}
This diff is collapsed.
#!/usr/bin/perl -wT
#
# Copyright (c) 2008-2013 University of Utah and the Flux Group.
# Copyright (c) 2008-2014 University of Utah and the Flux Group.
#
# {{{GENIPUBLIC-LICENSE
#
......@@ -47,6 +47,7 @@ use GeniRegistry;
use emutil;
use URI;
use Data::Dumper;
use Carp qw(cluck carp);
# Filter out any credentials of an uknown type leaving only geni_sfa
# version 2 and version 3 credentials in a list. Also invokes
......@@ -58,8 +59,11 @@ sub FilterCredentials
if (defined($credentials)) {
foreach my $cred (@{ $credentials }) {
if (ref($cred) eq "HASH" &&
$cred->{'geni_type'} eq "geni_sfa" &&
($cred->{'geni_version'} eq 2 || $cred->{'geni_version'} eq 3)) {
(($cred->{'geni_type'} eq "geni_sfa" &&
($cred->{'geni_version'} eq 2 ||
$cred->{'geni_version'} eq 3)) ||
($cred->{'geni_type'} eq "geni_abac" &&
($cred->{'geni_version'} eq 1)))) {
push(@{ $result }, $cred->{'geni_value'});
auto_add_sa($cred->{'geni_value'});
}
......@@ -76,7 +80,7 @@ sub auto_add_sa($)
my $signers = $cred->signer_certs();
return
if ($cred->type() eq "speaksfor");
if ($cred->type() eq "speaksfor" || $cred->type() eq "abac");
# The credential has been verified, so the signer derives from a
# trusted root.
......@@ -193,11 +197,18 @@ sub auto_add_sa($)
#
# Initial credential check.
#
sub CheckCredentials($)
sub CheckCredentials($;$)
{
my ($arg, $target_authority) = @_;
my ($speakee, $speaksfor);
my @rest = ();
my $error;
if (!defined($arg)) {
cluck("CheckCredentials: No credentials!");
$error = GeniResponse->Create(GENIRESPONSE_ERROR);
goto bad;
}
if (ref($_[0]) ne "ARRAY") {
$error = GeniResponse->MalformedArgsResponse("Credentials should be a ".
......@@ -206,14 +217,6 @@ sub CheckCredentials($)
}
else {
my @credential_strings = @{ $_[0] };
if (scalar(@credential_strings) == 1) {
#
# Must be a speaks-as credential.
#
$speakee = GeniCredential::CheckCredential($credential_strings[0]);
}
else {
#
# The only other case is that we get multiple credentials. One
# is the speaks-for credential and another one is the real
......@@ -242,7 +245,8 @@ sub CheckCredentials($)
# just the way I want it.
#
$speakee = shift(@credentials);
$speakee = GeniCredential::CheckCredential($speakee);
$speakee = GeniCredential::CheckCredential($speakee,
$target_authority);
if (GeniResponse::IsError($speakee)) {
$error = $speakee;
goto bad;
......@@ -253,7 +257,9 @@ sub CheckCredentials($)
# The rest of the credentials have to be valid too.
#
foreach my $credential (@rest) {
$credential = GeniCredential::CheckCredential($credential);
$credential =
GeniCredential::CheckCredential($credential,
$target_authority);
if (GeniResponse::IsError($credential)) {
$error = $credential;
goto bad;
......@@ -319,8 +325,9 @@ sub CheckCredentials($)
# by the user, so the owners must match.
#
foreach my $credential (@credentials) {
my $cred = GeniCredential::CheckCredential($credential,
undef, 1);
my $cred =
GeniCredential::CheckCredential($credential,
$target_authority, 1);
if (GeniResponse::IsError($cred)) {
$error = $cred;
goto bad;
......@@ -340,7 +347,7 @@ sub CheckCredentials($)
$speakee = shift(@credentials);
@rest = @credentials;
}
}
}
if (wantarray()) {
return ($speakee, $speaksfor, @rest);
......
......@@ -43,6 +43,8 @@ use vars qw(@ISA @EXPORT);
use GeniStd;
use GeniSA;
use GeniSlice;
use GeniUser;
use User;
use GeniResponse;
use GeniCredential;
use GeniRegistry;
......@@ -73,12 +75,9 @@ sub CreateSlice($$)
return GeniResponse->MalformedArgsResponse('Requires a list of credentials, an options field, and a SLICE_NAME in the options field');
}
my $credential = GeniStd::CheckCredentials(GeniStd::FilterCredentials($credential_args));
return $credential
if (GeniResponse::IsResponse($credential));
my $hrn = $options->{'fields'}->{'SLICE_NAME'};
my $args = {
"credential" => $credential->asString(),
"credentials" => GeniStd::FilterCredentials($credential_args),
"hrn" => $hrn,
"type" => "slice"
};
......@@ -156,9 +155,6 @@ sub LookupSlices()
sub UpdateSlice()
{
my ($slice_urn, $credential_args, $options) = @_;
my $credential = GeniStd::CheckCredentials(GeniStd::FilterCredentials($credential_args));
return $credential
if (GeniResponse::IsResponse($credential));
# TODO: Make sure that slice URN is the same as the credential URN
my $slice = GeniSlice->Lookup($slice_urn);
......@@ -168,8 +164,8 @@ sub UpdateSlice()
}
if (exists($options->{'fields'}->{'SLICE_EXPIRES'})) {
my $args = {
"credential" => $credential->asString(),
"expiration" => $options->{'fields'}->{'SLICE_EXPIRES'}
"credentials" => GeniStd::FilterCredentials($credential_args),
"expiration" => $options->{'fields'}->{'SLICE_EXPIRES'}
};
$response = GeniSA::RenewSlice($args);
}
......@@ -190,13 +186,9 @@ sub GetCredentials()
return GeniResponse->MalformedArgsResponse('Requires a slice urn, a list of credentials, and an options field');
}
my $user_credential = GeniStd::CheckCredentials(GeniStd::FilterCredentials($credential_args));
return $user_credential
if (GeniResponse::IsResponse($user_credential));
my $credential = GeniSA::GetCredential({
"urn" => $slice_urn,
"credential" => $user_credential });
"credentials" => GeniStd::FilterCredentials($credential_args) });
return $credential
if (GeniResponse::IsError($credential));
......@@ -219,8 +211,6 @@ sub ModifySliceMembership()
return GeniResponse->MalformedArgsResponse('Requires a slice urn, a list of credentials, and an options field');
}
my ($credential) = GeniStd::CheckCredentials(GeniStd::FilterCredentials($credential_args));
my $adding = $options->{'members_to_add'};
my $removing = $options->{'members_to_remove'};
my $changing = $options ->{'members_to_change'};
......@@ -240,7 +230,7 @@ sub ModifySliceMembership()
}
my $params = {
"credential" => $credential->asString()
"credentials" => GeniStd::FilterCredentials($credential_args),
};
my $i = 0;
......@@ -266,8 +256,8 @@ sub LookupSliceMembers()
return GeniResponse->MalformedArgsResponse('Requires a slice urn, a list of credentials, and an options field');
}
my ($cred) = GeniStd::CheckCredentials(GeniStd::FilterCredentials($credential_args));
my $credential = GeniCredential::CheckCredential($cred->asString());
my ($credential, $speaksfor) =
GeniStd::CheckCredentials(GeniStd::FilterCredentials($credential_args));
return $credential
if (GeniResponse::IsResponse($credential));
......@@ -276,7 +266,9 @@ sub LookupSliceMembers()
return GeniResponse->Create( GENIRESPONSE_FORBIDDEN, undef,
"Insufficient privilege" );
my $this_user = GeniUser->Lookup($ENV{'GENIURN'}, 1);
my $this_user =
GeniUser->Lookup((defined($speaksfor) ?
$speaksfor->target_urn() : $ENV{'GENIURN'}), 1);
if (!defined($this_user)) {
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN, undef,
"Who are you? No local record");
......@@ -323,21 +315,22 @@ sub LookupSlicesForMember($$$)
return GeniResponse->MalformedArgsResponse('Requires a member urn, a list of credentials, and an options field');
}
my ($cred) = GeniStd::CheckCredentials(GeniStd::FilterCredentials($credential_args));
my $credential = GeniCredential::CheckCredential($cred->asString());
my ($credential, $speaksfor) =
GeniStd::CheckCredentials(GeniStd::FilterCredentials($credential_args));
return $credential
if (GeniResponse::IsResponse($credential));
if ($ENV{'GENIURN'} ne $member_urn) {
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN, undef,
"You are not allowed to lookup slices for other members");
}
my $this_user = GeniUser->Lookup($ENV{'GENIURN'}, 1);
my $this_user =
GeniUser->Lookup((defined($speaksfor) ?
$speaksfor->target_urn() : $ENV{'GENIURN'}), 1);
if (!defined($this_user)) {
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN, undef,
"Who are you? No local record");
}
if ($this_user->urn() ne $member_urn) {
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN, undef,
"You are not allowed to lookup slices for other members");
}
my $result = [];
......@@ -345,9 +338,9 @@ sub LookupSlicesForMember($$$)
my @bound = GeniSlice->BoundToUser($this_user);
addSlicesToMemberList(\@created, $result)
if (defined(@created));
if (@created);
addSlicesToMemberList(\@bound, $result)
if (defined(@bound));
if (@bound);
return GeniResponse->Create(GENIRESPONSE_SUCCESS, $result);
}
......@@ -374,7 +367,6 @@ sub CreateSliverInfo($$$$)
return GeniResponse->MalformedArgsResponse('Requires a list of credentials, and an options field');
}
my ($credential) = GeniStd::CheckCredentials(GeniStd::FilterCredentials($credential_args));
if (! defined($options->{'SLIVER_INFO_SLICE_URN'}) ||
! defined($options->{'SLIVER_INFO_URN'}) ||
! defined($options->{'SLIVER_INFO_AGGREGATE_URN'}) ||
......@@ -384,7 +376,7 @@ sub CreateSliverInfo($$$$)
return GeniResponse->MalformedArgsResponse('Required option is missing. Make sure to include SLIVER_INFO_SLICE_URN, SLIVER_INFO_URN, SLIVER_INFO_AGGREGATE_URN, SLIVER_INFO_CREATOR_URN, CREATION, and EXPIRATION');
}
my $params = {
'credential' => $credential->asString(),
'credentials' => GeniStd::FilterCredentials($credential_args),
'slice_urn' => $options->{'SLIVER_INFO_SLICE_URN'},
'creator_urn' => $options->{'SLIVER_INFO_CREATOR_URN'},
'urn' => $options->{'SLIVER_INFO_URN'},
......@@ -412,9 +404,8 @@ sub DeleteSliverInfo()
return GeniResponse->MalformedArgsResponse('Requires a slice urn, an aggregate url, a list of credentials, and an options field');
}
my ($credential) = GeniStd::CheckCredentials(GeniStd::FilterCredentials($credential_args));
my $params = {
'credential' => $credential->asString(),
'credentials' => GeniStd::FilterCredentials($credential_args),
'slice_urn' => $slice_urn
};
return GeniSA::UnRegisterSliver($params);
......@@ -423,8 +414,60 @@ sub DeleteSliverInfo()
sub LookupSliverInfo($$)
{
my ($credential_args, $options) = @_;
return GeniResponse->Create(GENIRESPONSE_NOT_IMPLEMENTED, undef,
"Lookup Sliver Info is not implemented");
if (! (defined($credential_args) && defined($options))) {
return
GeniResponse->MalformedArgsResponse('Requires a list of '.
'credentials, and an options field');
}
my ($credential, $speaksfor) =
GeniStd::CheckCredentials(GeniStd::FilterCredentials($credential_args));
return $credential
if (GeniResponse::IsResponse($credential));
return GeniResponse->MalformedArgsResponse()
if (!defined($credential));
my $this_user =
GeniUser->Lookup((defined($speaksfor) ?
$speaksfor->target_urn() : $ENV{'GENIURN'}), 1);
if (!defined($this_user)) {
return GeniResponse->Create(GENIRESPONSE_FORBIDDEN, undef,
"Who are you? No local record");
}
my ($match, $filter) = GeniStd::GetMatchFilter($options);
if (! (defined($options->{'match'}) &&
defined($options->{'match'}->{'SLIVER_INFO_SLICE_URN'}))) {
return
GeniResponse->MalformedArgsResponse('Required match is missing: '.
'SLIVER_INFO_SLICE_URN');
}
my $slice = GeniSlice->Lookup($options->{'match'}{'SLIVER_INFO_SLICE_URN'});
return GeniResponse->Create(GENIRESPONSE_SEARCHFAILED)
if (!defined($slice));
if ($slice->Lock() != 0) {
return GeniResponse->BusyResponse("slice");
}
my @slivers = GeniSlice::ClientSliver->LookupBySlice($slice);
my $blob = {};
foreach my $sliver (@slivers) {
$blob->{$sliver->urn()} = {
'SLIVER_INFO_AGGREGATE_URN' => $sliver->manager_urn(),
'SLIVER_INFO_URN' => $sliver->urn(),
'SLIVER_INFO_SLICE_URN' => $slice->urn(),
'SLIVER_INFO_CREATION' => $sliver->created(),
'SLIVER_INFO_EXPIRATION' => $sliver->expires()
};
my $user = User->Lookup($sliver->creator_idx());
if (defined($user)) {
$user = GeniUser->CreateFromLocal($user);
}
if (defined($user)) {
$blob->{$sliver->urn()}->{'SLIVER_INFO_CREATOR_URN'} = $user->urn();
}
}
$slice->UnLock();
return GeniResponse->Create(GENIRESPONSE_SUCCESS, $blob);
}
sub CreateProject()
......
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