Commit 10b1dbd2 authored by Leigh B Stoller's avatar Leigh B Stoller

Add support for secure image download using a credential to grant

permission to the image being requested. Added for image backed
datasets. The key to this commit is being able to abort the logging and
return STDOUT/STDERR to apache so that the image can be streamed.
There is a corresponding change on the caller side, that adds a new
method CallMethodStream() that takes a file descriptor to send the
data to.
parent b58cf13b
......@@ -48,7 +48,8 @@ all: Genixmlrpc.pm GeniResponse.pm \
protogeni-ch.pm protogeni-sa.pm protogeni-cm.pm protogeni-emulab.pm \
protogeni-ses.pm geni-am.pm geni-ma.pm geni-sa.pm \
protogeni-wrapper.pl protogeni-console.pl protogeni-portal.pm \
protogeni-ims.pm cluster-wrapper.pl ClusterWrapper.pm ProtoGeniDefs.pm
protogeni-ims.pm cluster-wrapper.pl ClusterWrapper.pm ProtoGeniDefs.pm \
protogeni-cluster.pm
include $(TESTBED_SRCDIR)/GNUmakerules
......@@ -61,6 +62,7 @@ install-libs: $(INSTALL_LIBDIR)/Genixmlrpc.pm \
$(INSTALL_LIBDIR)/protogeni-ims.pm \
$(INSTALL_LIBDIR)/protogeni-ses.pm \
$(INSTALL_LIBDIR)/protogeni-emulab.pm \
$(INSTALL_LIBDIR)/protogeni-cluster.pm \
$(INSTALL_LIBDIR)/ClusterWrapper.pm \
$(INSTALL_LIBDIR)/ProtoGeniDefs.pm \
$(INSTALL_LIBDIR)/geni-am.pm \
......
......@@ -188,6 +188,20 @@ BEGIN {
sub CallMethod($$$@)
{
my ($httpURL, $context, $method, @args) = @_;
return CallMethodInternal($httpURL, $context, undef, $method, @args);
}
sub CallMethodStream($$$$@)
{
my ($httpURL, $context, $fp, $method, @args) = @_;
return CallMethodInternal($httpURL, $context, $fp, $method, @args);
}
sub CallMethodInternal($$$$@)
{
my ($httpURL, $context, $fp, $method, @args) = @_;
my $xmlgoo;
require RPC::XML;
require RPC::XML::Parser;
require HTTP::Request::Common;
......@@ -205,6 +219,20 @@ sub CallMethod($$$@)
"Must provide an rpc context");
}
# Callback to write the data, when streaming to a file.
my $callback = sub {
my ($data) = @_;
if ($data =~ /^\<\?xml/) {
$xmlgoo = $data;
return;
}
my $retval = syswrite($fp, $data);
if (!defined($retval)) {
die("Error writing data to output stream");
}
print ".";
};
my $FBSD_MAJOR = 4;
my $FBSD_MINOR = 10;
if (`/usr/bin/uname -r` =~ /^(\d+)\.(\d+)/) {
......@@ -300,7 +328,9 @@ sub CallMethod($$$@)
$hreq->content_type('text/xml');
$hreq->content($reqstr);
$hreq->protocol('HTTP/1.0') if ($FBSD_MAJOR >= 8);
my $hresp = $ua->request($hreq);
my $hresp = (defined($fp) ?
$ua->request($hreq, $callback, 0x20000) :
$ua->request($hreq));
# Do this or the next call gets messed up.
delete($ENV{'HTTPS_CERT_FILE'});
......@@ -317,12 +347,17 @@ sub CallMethod($$$@)
return GeniResponse->new(GENIRESPONSE_RPCERROR,
$hresp->code(), $hresp->message());
}
# Streamed the data okay, we are done.
if (defined($fp) && !defined($xmlgoo)) {
return GeniResponse->new(GENIRESPONSE_SUCCESS);
}
#
# Read back the xmlgoo from the child.
#
my $xmlgoo = $hresp->content();
if (!defined($xmlgoo)) {
$xmlgoo = $hresp->content();
}
if ($debug > 1) {
print STDERR "xmlgoo: " . $xmlgoo;
print STDERR "\n";
......
......@@ -160,6 +160,7 @@ $V2_METHODS = {
"DeleteDataset" => \&GeniCMV2::DeleteDataset,
"DescribeDataset" => \&GeniCMV2::DescribeDataset,
"ModifyDataset" => \&GeniCMV2::ModifyDataset,
"GetDatasetCredential" => \&GeniCMV2::GetDatasetCredential,
"Lockdown" => \&GeniCMV2::Lockdown,
"TriggerImageUpdate"=> \&GeniCMV2::TriggerImageUpdate,
"AddNodes" => \&GeniCMV2::AddNodes,
......
#!/usr/bin/perl -w
#
# Copyright (c) 2008-2015 University of Utah and the Flux Group.
# Copyright (c) 2008-2016 University of Utah and the Flux Group.
#
# {{{GENIPUBLIC-LICENSE
#
......@@ -113,6 +113,9 @@ elsif ($GENI_VERSION eq "2.0") {
"DeleteDataset" => \&GeniCMV2::DeleteDataset,
"DescribeDataset" => \&GeniCMV2::DescribeDataset,
"ModifyDataset" => \&GeniCMV2::ModifyDataset,
"GetDatasetCredential" => \&GeniCMV2::GetDatasetCredential,
# This will not work in the fcgid world without more work.
"SecureImageDownload" => \&GeniCMV2::SecureImageDownload,
"Lockdown" => \&GeniCMV2::Lockdown,
"TriggerImageUpdate"=> \&GeniCMV2::TriggerImageUpdate,
"AddNodes" => \&GeniCMV2::AddNodes,
......
......@@ -130,6 +130,7 @@ my %GENI_MODULES = ( "cm" => "@prefix@/lib/protogeni-cm.pm",
"ses" => "@prefix@/lib/protogeni-ses.pm",
"portal" => "@prefix@/lib/protogeni-portal.pm",
"ims" => "@prefix@/lib/protogeni-ims.pm",
"cluster" => "@prefix@/lib/protogeni-cluster.pm",
# XXX This is temporary!
"instools" =>
"@prefix@/lib/instools/protogeni-instools.pm",
......@@ -164,6 +165,7 @@ my $noanything = 0;
# Flag for XMLERROR.
my $logging = 0;
my $logforked = 0;
my $logaborted = 0;
my $iserror = 0;
my $rpcerror = 0;
my $logfile = undef;
......@@ -501,6 +503,11 @@ sub AddLogfileMetaDataFromSpeaksFor($)
AddLogfileMetaData("speaking_urn", $speaksfor->owner_urn());
AddLogfileMetaData("speaking_uuid", $speaksfor->owner_uuid());
}
sub AbortLogging()
{
LogEnd(0);
$logaborted = 1;
}
#
# Okay, we want to catch warning, specifically uninitialized
......@@ -730,20 +737,22 @@ else {
push(@metadata, ["Code", $result->{'code'}])
}
}
# Add first line of result output to metadata. Bigger stuff
# will land at the end of the file.
if (ref($result) && defined($result->{'output'}) &&
$result->{'output'} ne "") {
push(@metadata, ["Output", ( split /\n/, $result->{'output'} )[0]]);
}
# Purge old data; if we forked we want latest.
$logfile->SetMetadata(\@metadata, 1);
if (!$logaborted) {
# Add first line of result output to metadata. Bigger stuff
# will land at the end of the file.
if (ref($result) && defined($result->{'output'}) &&
$result->{'output'} ne "") {
push(@metadata, ["Output", ( split /\n/, $result->{'output'} )[0]]);
}
# Purge old data; if we forked we want latest.
$logfile->SetMetadata(\@metadata, 1);
foreach my $foo (@metadata) {
my ($key,$val) = @{$foo};
$message .= sprintf("%-15s: %s\n", $key, $val);
foreach my $foo (@metadata) {
my ($key,$val) = @{$foo};
$message .= sprintf("%-15s: %s\n", $key, $val);
}
AddAuditInfo("message", $message);
}
AddAuditInfo("message", $message);
# Do not send debugging mail for these two errors and do not save
# the logfiles.
......@@ -812,7 +821,8 @@ else {
# Abort the log capture so that we can print the response to STDOUT
# for the web server. But first deal with the email.
#
LogAbort();
LogAbort()
if (!$logaborted);
#
# If nothing in the log and no error, then we just store the metadata
......@@ -839,7 +849,7 @@ if (!$logforked) {
}
print "Content-Type: text/xml \n\n" . $response
if (defined($response));
if (defined($response) && !$logaborted);
exit(0);
#
......
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