Commit 1822694e authored by Leigh Stoller's avatar Leigh 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()
print "Usage: quickvm -k <uuid>\n";
print "Usage: quickvm -e <seconds> <uuid>\n";
print "Usage: quickvm -s <uuid> <sliver_urn> <imagename>\n";
print "Usage: quickvm -c <uuid> <sliver_urn>\n";
exit(1);
}
my $optlist = "dkve:u:a:st:f";
my $optlist = "dkve:u:a:st:fc";
my $debug = 0;
my $verbose = 1;
my $killit = 0;
......@@ -57,6 +58,7 @@ my $extend;
my $webtask;
my $webtask_id;
my $snapshot;
my $consoleurl;
my $foreground = 0;
my $localuser = 0;
my $quickuuid;
......@@ -70,6 +72,7 @@ sub Terminate($);
sub Extend($$);
sub SnapShot($$$);
sub GenCredentials($$$$);
sub ConsoleURL($$);
#
# Configure variables
......@@ -84,6 +87,7 @@ my $SACERT = "$TB/etc/genisa.pem";
my $CMCERT = "$TB/etc/genicm.pem";
my $SSHKEYGEN = "/usr/bin/ssh-keygen";
my $SSHSETUP = "$TB/sbin/aptssh-setup";
my $ADDPUBKEY = "$TB/sbin/addpubkey";
my $UPDATEGENIUSER= "$TB/sbin/protogeni/updategeniuser";
my $VERSIONING = @PROFILEVERSIONS@;
......@@ -131,6 +135,9 @@ if (defined($options{"a"})) {
if (defined($options{"d"})) {
$debug = 1;
}
if (defined($options{"c"})) {
$consoleurl = 1;
}
if (defined($options{"v"})) {
$verbose = 1;
}
......@@ -170,6 +177,12 @@ elsif ($snapshot) {
$quickuuid = shift(@ARGV);
}
elsif ($consoleurl) {
usage()
if (@ARGV != 2);
$quickuuid = shift(@ARGV);
}
else {
$xmlfile = shift(@ARGV);
......@@ -271,6 +284,9 @@ elsif ($extend) {
elsif ($snapshot) {
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.
......@@ -353,6 +369,8 @@ if (exists($xmlparse->{'attribute'}->{"sshkey"}) &&
UserError("Could not parse ssh key!");
}
}
close($fh);
unlink($keyfile);
}
chomp($sshkey)
if (defined($sshkey));
......@@ -450,6 +468,18 @@ if ($localuser) {
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)) {
#
......@@ -1202,3 +1232,71 @@ sub SnapShot($$$)
done:
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,
"asguest", PAGEARG_BOOLEAN,
"formfields", PAGEARG_ARRAY);
if ($ISAPT) {
if ($ISAPT && !$this_user) {
#
# If user appears to have an account, go to login page.
# Continue as guest on that page.
......@@ -69,7 +69,7 @@ if ($ISAPT) {
ClearRememberedID();
}
else {
header("Location: login.php");
header("Location: login.php?from=instantiate");
}
}
}
......@@ -194,8 +194,9 @@ else {
function SPITFORM($formfields, $newuser, $errors)
{
global $TBBASE, $APTMAIL;
global $TBBASE, $APTMAIL, $ISCLOUD;
global $profile_array, $this_user, $profilename, $profile, $am_array;
$showabout = ($ISCLOUD || !$this_user ? 1 : 0);
# XSS prevention.
while (list ($key, $val) = each ($formfields)) {
......@@ -241,15 +242,23 @@ function SPITFORM($formfields, $newuser, $errors)
echo "<form id='quickvm_form' role='form'
enctype='multipart/form-data'
method='post' action='instantiate.php'>\n";
echo "<div class='panel panel-default'>
<div class='panel-heading'>
<h3 class='panel-title'>
Run an Experiment";
if (!$this_user) {
echo "<div class='panel panel-default'>
<div class='panel-heading'>
<h3 class='panel-title'>\n";
}
else {
echo "<h3 style='margin-top: 0px;'>";
}
echo "<center>Run an Experiment";
if (isset($profilename)) {
echo " using profile &quot;$profilename&quot";
}
echo "</h3></div>
<div class='panel-body'>\n";
echo "</center></h3>\n";
if (!$this_user) {
echo " </div>
<div class='panel-body'>\n";
}
#
# If linked to a specific profile, description goes here
......@@ -293,10 +302,36 @@ function SPITFORM($formfields, $newuser, $errors)
value='" . $formfields["email"] . "'
class='form-control'
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",
"<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'>");
$formatter("sshkey",
......@@ -305,6 +340,15 @@ function SPITFORM($formfields, $newuser, $errors)
class='form-control'
rows=4 cols=45>" . $formfields["sshkey"] .
"</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)
# 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'
name='formfields[profile]'/>";
echo "<div class='col-md-12'><div class='panel panel-default'>\n";
......@@ -337,8 +381,7 @@ function SPITFORM($formfields, $newuser, $errors)
</button>";
echo "<div class='clearfix'></div>";
echo "</div>";
echo "</div></div>"; # End of panel
echo "</div></div></div>"; # End of panel/row.
}
else {
echo "<input id='selected_profile' type='hidden'
......@@ -349,8 +392,11 @@ function SPITFORM($formfields, $newuser, $errors)
# Needs more work.
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 = "";
while (list($am, $urn) = each($am_array)) {
$selected = "";
......@@ -361,21 +407,22 @@ function SPITFORM($formfields, $newuser, $errors)
"<option $selected value='$am'>$am</option>\n";
}
$formatter("where",
"<br><select name=\"formfields[where]\"
"<select name=\"formfields[where]\"
id='profile_where' class='form-control'>".
"$am_options</select>");
}
echo "</fieldset>
<div class='form-group row'>
<div class='col-md-6 col-md-offset-3'>
<button class='btn btn-success btn-block' id='instantiate_submit'
type='submit' name='create'>Create!
</button>
</div>
</div>
</div>
</div>
</div>
</div>\n";
if (!isset($this_user)) {
echo "</div>
</div>\n";
SpitVerifyModal("verify_modal", "Create");
if ($newuser) {
......@@ -394,14 +441,16 @@ function SPITFORM($formfields, $newuser, $errors)
echo "<input type='hidden' name='stuffing' value='$stuffing' />";
}
}
echo "</div>\n";
echo "</form>\n";
SpitTopologyViewModal("quickvm_topomodal", $profile_array);
SpitWaitModal("waitwait");
echo "<script type='text/javascript'>\n";
echo " window.PROFILE = '" . $formfields["profile"] . "';\n";
echo " window.AJAXURL = 'server-ajax.php';\n";
echo " window.PROFILE = '" . $formfields["profile"] . "';\n";
echo " window.AJAXURL = 'server-ajax.php';\n";
echo " window.SHOWABOUT = $showabout;\n";
if ($newuser) {
echo "window.APT_OPTIONS.isNewUser = true;\n";
}
......@@ -425,6 +474,12 @@ if (!isset($create)) {
if ($this_user) {
$defaults["username"] = $this_user->uid();
$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'])) {
$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