Commit d1516912 authored by Leigh Stoller's avatar Leigh Stoller

Deal with user privs (issue #309):

* Make user privs work across remote clusters (including stitching). I
  took a severe shortcut on this; I do not expect the Cloudlab portal
  will ever talk to anything but an Emulab based aggregate, so I just
  added the priv indicator to the user keys array we send over. If I am
  ever proved wrong on this, I will come out of retirement and fix
  it (for a nominal fee of course).

* Do not show the root password for the console to users with user
  privs.

* Make sure users with user privs cannot start experiments.

* Do show the user trust values on the user dashboard membership tab.

* Update tmcd to use the new privs slot in the nonlocal_user_accounts
  table.

This closes issue #309.
parent b8a86a6a
......@@ -708,6 +708,14 @@ sub GetProject($)
return Project->Lookup($self->pid_idx());
}
sub GetGroup($)
{
my ($self) = @_;
require Group;
return Group->Lookup($self->gid_idx());
}
#
# Warn creator that the experiment is going to expire. This is hooked
# in from the sa_daemon, so we can send a message that is less geni like
......@@ -980,6 +988,9 @@ sub GetSSHKeys($$;$)
my $project = $self->GetProject();
return -1
if (!defined($project));
my $group = $self->GetGroup();
return -1
if (!defined($group));
if ($geniuser->GetKeyBundle(\@keys, 1) < 0 || !@keys) {
print STDERR "No ssh keys for $geniuser\n";
......@@ -991,6 +1002,8 @@ sub GetSSHKeys($$;$)
#
$rval = [{'urn' => $geniuser->urn(),
'login' => $geniuser->uid(),
# Creator clearly has root privs!
'privs' => 'root',
'keys' => [ @keys ]
}];
......@@ -1017,6 +1030,20 @@ sub GetSSHKeys($$;$)
next
if (!defined($guser));
#
# Watch for local Emulab users with user privs.
# Only Emulab based CMs will do anything with this,
# but that is all we talk to.
#
my $privs = "root";
if ($guser->IsLocal()) {
my $trust = $group->Trust($guser->emulab_user());
if (! TBMinTrust($trust, PROJMEMBERTRUST_LOCALROOT())) {
$privs = "user";
}
}
#
# So, users coming in from the trusted signer have their keys
# at their home portal. We download those keys whenever they
......@@ -1034,6 +1061,7 @@ sub GetSSHKeys($$;$)
}
push(@{$rval}, {'urn' => $guser->urn(),
'login' => $guser->uid(),
'privs' => $privs,
'keys' => [ @keys ]
});
}
......
......@@ -4777,9 +4777,9 @@ sub UnBindNonLocalUsers($)
#
# Bind nonlocal user to experiment (slice, in Geni).
#
sub BindNonLocalUser($$$$$$)
sub BindNonLocalUser($$$$$$;$)
{
my ($self, $keys, $uid, $urn, $name, $email) = @_;
my ($self, $keys, $uid, $urn, $name, $email, $privs) = @_;
return -1
if (! ref($self));
......@@ -4824,6 +4824,10 @@ sub BindNonLocalUser($$$$$$)
push(@insert_data, "name=$safe_name");
push(@insert_data, "email=$safe_email");
push(@insert_data, "uid_uuid=uuid()");
if (defined($privs)) {
my $safe_privs = DBQuoteSpecial($privs);
push(@insert_data, "privs=$safe_privs");
}
# Insert into DB.
my $insert_result =
......
#!/usr/bin/perl -wT
#
# Copyright (c) 2008-2016 University of Utah and the Flux Group.
# Copyright (c) 2008-2017 University of Utah and the Flux Group.
#
# {{{GENIPUBLIC-LICENSE
#
......@@ -393,8 +393,12 @@ sub CreateSliver()
chomp($key);
push(@user_keys, {'type' => 'ssh', 'key' => $key});
}
push(@{$sliver_keys}, {'urn' => $user_urn,
'keys' => \@user_keys});
my $blob = {'urn' => $user_urn,
'keys' => \@user_keys};
if (exists($user->{'privs'})) {
$blob->{'privs'} = $user->{'privs'};
}
push(@{$sliver_keys}, $blob);
}
}
# Invoke CreateSliver
......@@ -1104,8 +1108,12 @@ sub Provision
chomp($key);
push(@user_keys, {'type' => 'ssh', 'key' => $key});
}
push(@{$sliver_keys}, {'urn' => $user_urn,
'keys' => \@user_keys});
my $blob = {'urn' => $user_urn,
'keys' => \@user_keys};
if (exists($user->{'privs'})) {
$blob->{'privs'} = $user->{'privs'};
}
push(@{$sliver_keys}, $blob);
}
}
......
......@@ -7322,6 +7322,7 @@ sub AddKeys($$$)
my $uid;
my $name;
my $email;
my $privs = "local_root";
if (exists($ref->{'urn'})) {
$urn = $ref->{'urn'};
......@@ -7344,6 +7345,10 @@ sub AddKeys($$$)
}
# Allow user to override urn token.
$uid = $ref->{'login'} if (exists($ref->{'login'}));
# Optional specification of privs.
if (exists($ref->{'privs'}) && $ref->{'privs'} eq "user") {
$privs = "user";
}
# The slice owner is easy.
if (defined($urn) && $urn eq $owner->urn()) {
......@@ -7382,7 +7387,7 @@ sub AddKeys($$$)
}
$slice_experiment->BindNonLocalUser(\@keylist,
$uid, $urn,
$name, $email)
$name, $email, $privs)
== 0 or goto error;
}
}
......
......@@ -3523,7 +3523,7 @@ COMMAND_PROTOTYPE(doaccounts)
" u.uid,'*', "
" u.unix_uid+20000,"
" u.name, "
" 'local_root',g.pid,g.gid,g.unix_gid,0, "
" u.privs,g.pid,g.gid,g.unix_gid,0, "
" NULL,NULL, "
" UNIX_TIMESTAMP(u.updated), "
" u.email,'bash', "
......
......@@ -260,6 +260,10 @@ class Instance
function Project() {
return Project::Lookup($this->pid_idx());
}
# Group of instance.
function Group() {
return Group::Lookup($this->gid_idx());
}
#
# Class function to create a new Instance
......
......@@ -847,7 +847,7 @@ function needAdminApproval($wanted, $granted, $reason, $message)
function Do_ConsoleURL()
{
global $instance, $creator, $this_user, $suexec_output;
global $ajax_args;
global $ajax_args, $TBDB_TRUST_LOCALROOT;
if (StatusSetupAjax(0)) {
return;
......@@ -876,10 +876,19 @@ function Do_ConsoleURL()
$webtask->Refresh();
if ($retval == 0) {
#
# If the user has 'user' privs in the current project/group
# then we do not return the root password. They can still look
# at the console though.
#
$group = $instance->Group();
$trust = $group->UserTrust($this_user);
$taskdata = $webtask->TaskData();
$blob = array();
$blob["url"] = $taskdata["url"];
if (isset($taskdata["password"])) {
if (isset($taskdata["password"]) &&
TBMinTrust($trust, $TBDB_TRUST_LOCALROOT)) {
$blob["password"] = $taskdata["password"];
}
if (isset($taskdata["logurl"])) {
......
......@@ -4,6 +4,7 @@
<tr>
<th>Project</th>
<th>Group</th>
<th>Trust</th>
<th>Leader</th>
<th>Description</th>
</tr>
......@@ -14,6 +15,7 @@
<td><a href='show-project.php?project=<%- value.pid %>'>
<%= value.pid %></a></td>
<td><%= value.pid %></td>
<td><%= value.trust %></td>
<td style='white-space: nowrap;'>
<a href='user-dashboard.php?user=<%- value.leader_idx %>'>
<%- value.leader_name %></a></td>
......@@ -26,6 +28,7 @@
<%= value.pid %></a></td>
<td><a href='show-group.php?group=<%- group.gid_idx %>'>
<%= group.gid %></a></td>
<td><%= group.trust %></td>
<td style='white-space: nowrap;'>
<a href='user-dashboard.php?user=<%- group.leader_idx %>'>
<%- group.leader_name %></a></td>
......
<?php
#
# Copyright (c) 2000-2016 University of Utah and the Flux Group.
# Copyright (c) 2000-2017 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
......@@ -139,7 +139,7 @@ function Do_ClassicDatasetList()
function Do_ProjectList()
{
global $this_user, $target_user;
global $TB_PROJECT_CREATEEXPT;
global $TB_PROJECT_READINFO, $newTrustMap;
if (CheckPageArgs()) {
return;
......@@ -147,7 +147,7 @@ function Do_ProjectList()
$target_idx = $target_user->uid_idx();
$target_uuid = $target_user->uuid();
$results = array();
$projlist = $target_user->ProjectAccessList($TB_PROJECT_CREATEEXPT);
$projlist = $target_user->ProjectAccessList($TB_PROJECT_READINFO);
#
# Cull out the nonlocal projects, we do not want to show those
......@@ -163,6 +163,8 @@ function Do_ProjectList()
$blob["leader"] = $leader->uid();
$blob["leader_name"] = $leader->name();
$blob["leader_idx"] = $leader->idx();
$membership = $proj->MemberShipInfo($this_user);
$blob["trust"] = $newTrustMap[$membership["trust"]];
#
# User membership in subgroups
......@@ -181,7 +183,8 @@ function Do_ProjectList()
$glob["leader"] = $leader->uid();
$glob["leader_idx"] = $leader->idx();
$glob["leader_name"] = $leader->name();
$membership = $group->MemberShipInfo($this_user);
$glob["trust"] = $newTrustMap[$membership["trust"]];
$blob["subgroups"][] = $glob;
}
}
......
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