Commit 1822694e authored by Leigh B Stoller's avatar Leigh B Stoller

Change to ssh key handling for registered APT/Cloud users; show the ssh key

box, but as a collapsible. Warn user if they do not have a key (provided on
signup page) that they are restricted to browser shell. Whenever user
provides a key, replace in the database (if its changed). This keeps the
user out of the Emulab interface to edit their ssh keys. Might have to
revisit this if APT/Cloud users need/want more then the one key.
parent 4784e571
...@@ -44,9 +44,10 @@ sub usage() ...@@ -44,9 +44,10 @@ sub usage()
print "Usage: quickvm -k <uuid>\n"; print "Usage: quickvm -k <uuid>\n";
print "Usage: quickvm -e <seconds> <uuid>\n"; print "Usage: quickvm -e <seconds> <uuid>\n";
print "Usage: quickvm -s <uuid> <sliver_urn> <imagename>\n"; print "Usage: quickvm -s <uuid> <sliver_urn> <imagename>\n";
print "Usage: quickvm -c <uuid> <sliver_urn>\n";
exit(1); exit(1);
} }
my $optlist = "dkve:u:a:st:f"; my $optlist = "dkve:u:a:st:fc";
my $debug = 0; my $debug = 0;
my $verbose = 1; my $verbose = 1;
my $killit = 0; my $killit = 0;
...@@ -57,6 +58,7 @@ my $extend; ...@@ -57,6 +58,7 @@ my $extend;
my $webtask; my $webtask;
my $webtask_id; my $webtask_id;
my $snapshot; my $snapshot;
my $consoleurl;
my $foreground = 0; my $foreground = 0;
my $localuser = 0; my $localuser = 0;
my $quickuuid; my $quickuuid;
...@@ -70,6 +72,7 @@ sub Terminate($); ...@@ -70,6 +72,7 @@ sub Terminate($);
sub Extend($$); sub Extend($$);
sub SnapShot($$$); sub SnapShot($$$);
sub GenCredentials($$$$); sub GenCredentials($$$$);
sub ConsoleURL($$);
# #
# Configure variables # Configure variables
...@@ -84,6 +87,7 @@ my $SACERT = "$TB/etc/genisa.pem"; ...@@ -84,6 +87,7 @@ my $SACERT = "$TB/etc/genisa.pem";
my $CMCERT = "$TB/etc/genicm.pem"; my $CMCERT = "$TB/etc/genicm.pem";
my $SSHKEYGEN = "/usr/bin/ssh-keygen"; my $SSHKEYGEN = "/usr/bin/ssh-keygen";
my $SSHSETUP = "$TB/sbin/aptssh-setup"; my $SSHSETUP = "$TB/sbin/aptssh-setup";
my $ADDPUBKEY = "$TB/sbin/addpubkey";
my $UPDATEGENIUSER= "$TB/sbin/protogeni/updategeniuser"; my $UPDATEGENIUSER= "$TB/sbin/protogeni/updategeniuser";
my $VERSIONING = @PROFILEVERSIONS@; my $VERSIONING = @PROFILEVERSIONS@;
...@@ -131,6 +135,9 @@ if (defined($options{"a"})) { ...@@ -131,6 +135,9 @@ if (defined($options{"a"})) {
if (defined($options{"d"})) { if (defined($options{"d"})) {
$debug = 1; $debug = 1;
} }
if (defined($options{"c"})) {
$consoleurl = 1;
}
if (defined($options{"v"})) { if (defined($options{"v"})) {
$verbose = 1; $verbose = 1;
} }
...@@ -170,6 +177,12 @@ elsif ($snapshot) { ...@@ -170,6 +177,12 @@ elsif ($snapshot) {
$quickuuid = shift(@ARGV); $quickuuid = shift(@ARGV);
} }
elsif ($consoleurl) {
usage()
if (@ARGV != 2);
$quickuuid = shift(@ARGV);
}
else { else {
$xmlfile = shift(@ARGV); $xmlfile = shift(@ARGV);
...@@ -271,6 +284,9 @@ elsif ($extend) { ...@@ -271,6 +284,9 @@ elsif ($extend) {
elsif ($snapshot) { elsif ($snapshot) {
exit(SnapShot($quickuuid, $ARGV[0], $ARGV[1])); exit(SnapShot($quickuuid, $ARGV[0], $ARGV[1]));
} }
elsif ($consoleurl) {
exit(ConsoleURL($quickuuid, $ARGV[0]));
}
# #
# Must wrap the parser in eval since it exits on error. # Must wrap the parser in eval since it exits on error.
...@@ -353,6 +369,8 @@ if (exists($xmlparse->{'attribute'}->{"sshkey"}) && ...@@ -353,6 +369,8 @@ if (exists($xmlparse->{'attribute'}->{"sshkey"}) &&
UserError("Could not parse ssh key!"); UserError("Could not parse ssh key!");
} }
} }
close($fh);
unlink($keyfile);
} }
chomp($sshkey) chomp($sshkey)
if (defined($sshkey)); if (defined($sshkey));
...@@ -450,6 +468,18 @@ if ($localuser) { ...@@ -450,6 +468,18 @@ if ($localuser) {
fatal("Could not update ssh keys for nonlocal user"); fatal("Could not update ssh keys for nonlocal user");
} }
} }
elsif (!$emulab_user->isEmulab() && defined($sshkey) &&
!$emulab_user->LookupSSHKey($sshkey)) {
$emulab_user->DeleteSSHKeys();
my ($fh, $keyfile) = tempfile(UNLINK => 0);
print $fh $sshkey;
if (system("$ADDPUBKEY -u $user_uid -f $keyfile")) {
fatal("Could not add new ssh pubkey");
}
close($fh);
unlink($keyfile);
}
} }
elsif (!$localuser && defined($sshkey)) { elsif (!$localuser && defined($sshkey)) {
# #
...@@ -1202,3 +1232,71 @@ sub SnapShot($$$) ...@@ -1202,3 +1232,71 @@ sub SnapShot($$$)
done: done:
exit(0); exit(0);
} }
#
# Ask for a console URL for a node
#
sub ConsoleURL($$)
{
my ($uuid, $sliver_urn) = @_;
my $instance = APT_Instance->Lookup($uuid);
if (! defined($instance)) {
fatal("No such quick VM: $uuid");
}
if (defined($instance->aggregate_urn()) &&
$instance->aggregate_urn() ne $CMURN) {
$CMURN = $instance->aggregate_urn();
$cm_authority = GeniAuthority->Lookup($CMURN);
if (!defined($cm_authority)) {
$cm_authority = GeniAuthority->CreateFromRegistry("cm", $CMURN);
if (!defined($cm_authority)) {
fatal("Could not load CM authority object");
}
}
}
my $geniuser = GeniUser->Lookup($instance->creator_uuid(), 1);
if (!defined($geniuser)) {
fatal("No creator for quick VM: $uuid");
}
my $slice = GeniSlice->Lookup($instance->slice_uuid());
if (!defined($slice)) {
if ($instance->status() eq "failed") {
goto done;
}
fatal("No slice for quick VM: $uuid");
}
#
# Generate credentials we need.
#
my ($slice_credential, $speaksfor_credential) =
GenCredentials($slice, $geniuser, $sa_authority, $speaker_signer);
if (! (defined($speaksfor_credential) &&
defined($slice_credential))) {
fatal("Could not generate credentials");
}
my $response =
Genixmlrpc::CallMethod($cm_authority->url(), undef,
"ConsoleURL",
{ "slice_urn" => $slice->urn(),
"sliver_urn" => $sliver_urn,
"credentials" =>
[$slice_credential->asString(),
$speaksfor_credential->asString()]});
if (!defined($response) || $response->code() != GENIRESPONSE_SUCCESS) {
if ($response->code() == GENIRESPONSE_REFUSED) {
UserError($response->output());
}
fatal("ConsoleURL failed: ".
(defined($response) ? $response->output() : "") . "\n");
}
my $url = $response->value();
AuditAbort();
print "$url\n";
exit(0);
}
...@@ -55,7 +55,7 @@ $optargs = OptionalPageArguments("create", PAGEARG_STRING, ...@@ -55,7 +55,7 @@ $optargs = OptionalPageArguments("create", PAGEARG_STRING,
"asguest", PAGEARG_BOOLEAN, "asguest", PAGEARG_BOOLEAN,
"formfields", PAGEARG_ARRAY); "formfields", PAGEARG_ARRAY);
if ($ISAPT) { if ($ISAPT && !$this_user) {
# #
# If user appears to have an account, go to login page. # If user appears to have an account, go to login page.
# Continue as guest on that page. # Continue as guest on that page.
...@@ -69,7 +69,7 @@ if ($ISAPT) { ...@@ -69,7 +69,7 @@ if ($ISAPT) {
ClearRememberedID(); ClearRememberedID();
} }
else { else {
header("Location: login.php"); header("Location: login.php?from=instantiate");
} }
} }
} }
...@@ -194,8 +194,9 @@ else { ...@@ -194,8 +194,9 @@ else {
function SPITFORM($formfields, $newuser, $errors) function SPITFORM($formfields, $newuser, $errors)
{ {
global $TBBASE, $APTMAIL; global $TBBASE, $APTMAIL, $ISCLOUD;
global $profile_array, $this_user, $profilename, $profile, $am_array; global $profile_array, $this_user, $profilename, $profile, $am_array;
$showabout = ($ISCLOUD || !$this_user ? 1 : 0);
# XSS prevention. # XSS prevention.
while (list ($key, $val) = each ($formfields)) { while (list ($key, $val) = each ($formfields)) {
...@@ -241,15 +242,23 @@ function SPITFORM($formfields, $newuser, $errors) ...@@ -241,15 +242,23 @@ function SPITFORM($formfields, $newuser, $errors)
echo "<form id='quickvm_form' role='form' echo "<form id='quickvm_form' role='form'
enctype='multipart/form-data' enctype='multipart/form-data'
method='post' action='instantiate.php'>\n"; method='post' action='instantiate.php'>\n";
echo "<div class='panel panel-default'> if (!$this_user) {
<div class='panel-heading'> echo "<div class='panel panel-default'>
<h3 class='panel-title'> <div class='panel-heading'>
Run an Experiment"; <h3 class='panel-title'>\n";
}
else {
echo "<h3 style='margin-top: 0px;'>";
}
echo "<center>Run an Experiment";
if (isset($profilename)) { if (isset($profilename)) {
echo " using profile &quot;$profilename&quot"; echo " using profile &quot;$profilename&quot";
} }
echo "</h3></div> echo "</center></h3>\n";
<div class='panel-body'>\n"; if (!$this_user) {
echo " </div>
<div class='panel-body'>\n";
}
# #
# If linked to a specific profile, description goes here # If linked to a specific profile, description goes here
...@@ -293,10 +302,36 @@ function SPITFORM($formfields, $newuser, $errors) ...@@ -293,10 +302,36 @@ function SPITFORM($formfields, $newuser, $errors)
value='" . $formfields["email"] . "' value='" . $formfields["email"] . "'
class='form-control' class='form-control'
placeholder='Your email address' type='text'>"); placeholder='Your email address' type='text'>");
}
# We put the ssh stuff in two different places, so make it a function.
$spitsshkeystuff = function() use ($formfields, $formatter) {
if ($formfields["sshkey"] == "") {
$title_text = "<span class='text-warning'>
No SSH key, browser shell only!<span>";
$expand_text = "Add Key";
}
else {
$title_text = "<span class='text-info'>
Your SSH key</span>";
$expand_text = "Update";
}
echo "<div class='form-group row' style='margin-bottom: 0px;'>";
echo " <div class='col-md-12'>
<div class='panel panel-default'>\n";
echo " <div class='panel-heading'>$title_text
<a class='pull-right'
data-toggle='collapse' href='#mysshkey'>
$expand_text</a>\n";
echo " </div>\n";
echo " <div id='mysshkey' class='panel-collapse collapse'>\n";
echo " <div class='panel-body'>";
$formatter("keyfile", $formatter("keyfile",
"<span class='help-block'> "<span class='help-block'>
Optional: Your SSH public key (upload a file or paste it in the text box)</span>". Upload a file or paste it in the text box. This will ".
"allow you to login using your favorite ssh client. Without ".
"a SSH key, you will be limited to using a shell window in ".
"your browser.</span>".
"<input type=file name='keyfile'>"); "<input type=file name='keyfile'>");
$formatter("sshkey", $formatter("sshkey",
...@@ -305,6 +340,15 @@ function SPITFORM($formfields, $newuser, $errors) ...@@ -305,6 +340,15 @@ function SPITFORM($formfields, $newuser, $errors)
class='form-control' class='form-control'
rows=4 cols=45>" . $formfields["sshkey"] . rows=4 cols=45>" . $formfields["sshkey"] .
"</textarea>"); "</textarea>");
echo " </div>";
echo " <div class='clearfix'></div>";
echo " </div>";
echo " </div>";
echo "</div></div>"; # End of panel/row.
};
if (!isset($this_user)) {
$spitsshkeystuff();
} }
# #
...@@ -312,7 +356,7 @@ function SPITFORM($formfields, $newuser, $errors) ...@@ -312,7 +356,7 @@ function SPITFORM($formfields, $newuser, $errors)
# profile # profile
# #
if (!isset($profile)) { if (!isset($profile)) {
echo "<div class='form-group row'>"; echo "<div class='form-group row' style='margin-bottom: 0px;'>";
echo "<input id='selected_profile' type='hidden' echo "<input id='selected_profile' type='hidden'
name='formfields[profile]'/>"; name='formfields[profile]'/>";
echo "<div class='col-md-12'><div class='panel panel-default'>\n"; echo "<div class='col-md-12'><div class='panel panel-default'>\n";
...@@ -337,8 +381,7 @@ function SPITFORM($formfields, $newuser, $errors) ...@@ -337,8 +381,7 @@ function SPITFORM($formfields, $newuser, $errors)
</button>"; </button>";
echo "<div class='clearfix'></div>"; echo "<div class='clearfix'></div>";
echo "</div>"; echo "</div>";
echo "</div></div>"; # End of panel echo "</div></div></div>"; # End of panel/row.
} }
else { else {
echo "<input id='selected_profile' type='hidden' echo "<input id='selected_profile' type='hidden'
...@@ -349,8 +392,11 @@ function SPITFORM($formfields, $newuser, $errors) ...@@ -349,8 +392,11 @@ function SPITFORM($formfields, $newuser, $errors)
# Needs more work. # Needs more work.
echo "<input type='hidden' name='profile' value='$profile'>\n"; echo "<input type='hidden' name='profile' value='$profile'>\n";
} }
if (isset($this_user)) {
$spitsshkeystuff();
}
if (isset($this_user) && ISADMIN()) { if (isset($this_user) && (ISADMIN() || STUDLY())) {
$am_options = ""; $am_options = "";
while (list($am, $urn) = each($am_array)) { while (list($am, $urn) = each($am_array)) {
$selected = ""; $selected = "";
...@@ -361,21 +407,22 @@ function SPITFORM($formfields, $newuser, $errors) ...@@ -361,21 +407,22 @@ function SPITFORM($formfields, $newuser, $errors)
"<option $selected value='$am'>$am</option>\n"; "<option $selected value='$am'>$am</option>\n";
} }
$formatter("where", $formatter("where",
"<br><select name=\"formfields[where]\" "<select name=\"formfields[where]\"
id='profile_where' class='form-control'>". id='profile_where' class='form-control'>".
"$am_options</select>"); "$am_options</select>");
} }
echo "</fieldset> echo "</fieldset>
<div class='form-group row'>
<div class='col-md-6 col-md-offset-3'> <div class='col-md-6 col-md-offset-3'>
<button class='btn btn-success btn-block' id='instantiate_submit' <button class='btn btn-success btn-block' id='instantiate_submit'
type='submit' name='create'>Create! type='submit' name='create'>Create!
</button> </button>
</div> </div>
</div> </div>
</div>
</div>
</div>\n"; </div>\n";
if (!isset($this_user)) { if (!isset($this_user)) {
echo "</div>
</div>\n";
SpitVerifyModal("verify_modal", "Create"); SpitVerifyModal("verify_modal", "Create");
if ($newuser) { if ($newuser) {
...@@ -394,14 +441,16 @@ function SPITFORM($formfields, $newuser, $errors) ...@@ -394,14 +441,16 @@ function SPITFORM($formfields, $newuser, $errors)
echo "<input type='hidden' name='stuffing' value='$stuffing' />"; echo "<input type='hidden' name='stuffing' value='$stuffing' />";
} }
} }
echo "</div>\n";
echo "</form>\n"; echo "</form>\n";
SpitTopologyViewModal("quickvm_topomodal", $profile_array); SpitTopologyViewModal("quickvm_topomodal", $profile_array);
SpitWaitModal("waitwait"); SpitWaitModal("waitwait");
echo "<script type='text/javascript'>\n"; echo "<script type='text/javascript'>\n";
echo " window.PROFILE = '" . $formfields["profile"] . "';\n"; echo " window.PROFILE = '" . $formfields["profile"] . "';\n";
echo " window.AJAXURL = 'server-ajax.php';\n"; echo " window.AJAXURL = 'server-ajax.php';\n";
echo " window.SHOWABOUT = $showabout;\n";
if ($newuser) { if ($newuser) {
echo "window.APT_OPTIONS.isNewUser = true;\n"; echo "window.APT_OPTIONS.isNewUser = true;\n";
} }
...@@ -425,6 +474,12 @@ if (!isset($create)) { ...@@ -425,6 +474,12 @@ if (!isset($create)) {
if ($this_user) { if ($this_user) {
$defaults["username"] = $this_user->uid(); $defaults["username"] = $this_user->uid();
$defaults["email"] = $this_user->email(); $defaults["email"] = $this_user->email();
if (1 || $this_user->IsAPT() || $this_user->IsCloud()) {
$sshkeys = $this_user->GetSSHKeys();
if (count($sshkeys)) {
$defaults["sshkey"] = $sshkeys[0];
}
}
} }
elseif (isset($_COOKIE['quickvm_user'])) { elseif (isset($_COOKIE['quickvm_user'])) {
$geniuser = GeniUser::Lookup("sa", $_COOKIE['quickvm_user']); $geniuser = GeniUser::Lookup("sa", $_COOKIE['quickvm_user']);
......
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