Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
emulab
emulab-devel
Commits
e6598e50
Commit
e6598e50
authored
Apr 21, 2011
by
Leigh B Stoller
Browse files
Merge branch 'master' of git-public.flux.utah.edu:/flux/git/emulab-devel
parents
77291188
ad21d552
Changes
20
Hide whitespace changes
Inline
Side-by-side
db/Experiment.pm.in
View file @
e6598e50
...
...
@@ -4280,10 +4280,92 @@ sub UnBindNonLocalUsers($)
my $idx = $self->idx();
DBQueryWarn("delete from nonlocal_user_bindings ".
"where exptidx='
$
idx
'")
#
# Need to delete the pubkeys, so need a list of current bindings.
#
my $query_result =
DBQueryWarn("select uid,uid_idx from nonlocal_user_accounts ".
"where exptidx='
$
idx
'");
return -1
if (!$query_result);
while (my ($uid, $uid_idx) = $query_result->fetchrow_array()) {
DBQueryWarn("delete from nonlocal_user_pubkeys ".
"where uid_idx='
$
uid_idx
'")
or return -1;
DBQueryWarn("delete from nonlocal_user_accounts ".
"where uid_idx='
$
uid_idx
'")
or return -1;
}
return 0;
}
#
# Bind nonlocal user to experiment (slice, in Geni).
#
sub BindNonLocalUser($$$$$$)
{
my ($self, $keys, $uid, $urn, $name, $email) = @_;
return -1
if (! ref($self));
my $exptidx = $self->idx();
my $safe_urn = DBQuoteSpecial($urn)
if (defined($urn));
my $safe_uid = DBQuoteSpecial($uid);
my $safe_name = DBQuoteSpecial($name);
my $safe_email = DBQuoteSpecial($email);
my $uid_idx;
#
# User may already exist, as for updating keys.
#
my $query_result =
DBQueryWarn("select uid_idx from nonlocal_user_accounts ".
"where uid=$safe_uid and exptidx='
$
exptidx
'");
return -1
if (!$query_result);
if ($query_result->numrows) {
($uid_idx) = $query_result->fetchrow_array();
}
else {
my @insert_data = ();
$uid_idx = User->NextIDX();
push(@insert_data, "created=now()");
push(@insert_data, "uid_idx='
$
uid_idx
'");
push(@insert_data, "unix_uid=NULL");
push(@insert_data, "exptidx='
$
exptidx
'");
push(@insert_data, "urn=$safe_urn")
if (defined($urn));
push(@insert_data, "uid=$safe_uid");
push(@insert_data, "name=$safe_name");
push(@insert_data, "email=$safe_email");
push(@insert_data, "uid_uuid=uuid()");
# Insert into DB.
my $insert_result =
DBQueryWarn("insert into nonlocal_user_accounts set " .
join(",", @insert_data));
}
#
# Always replace the entire key set; easier to manage.
#
DBQueryWarn("delete from nonlocal_user_pubkeys ".
"where uid_idx='
$
uid_idx
'")
or return -1;
foreach my $key (@{ $keys }) {
my $safe_key = DBQuoteSpecial($key);
DBQueryWarn("insert into nonlocal_user_pubkeys set ".
" uid=$safe_uid, uid_idx='
$
uid_idx
', ".
" idx=NULL, stamp=now(), pubkey=$safe_key")
or return -1;
}
return 0;
}
...
...
db/User.pm.in
View file @
e6598e50
#
!/usr/bin/perl -wT
#
#
EMULAB
-
COPYRIGHT
#
Copyright
(
c
)
2005
-
201
0
University
of
Utah
and
the
Flux
Group
.
#
Copyright
(
c
)
2005
-
201
1
University
of
Utah
and
the
Flux
Group
.
#
All
rights
reserved
.
#
package
User
;
...
...
@@ -542,7 +542,7 @@ sub Delete($)
or
return
-
1
;
DBQueryWarn
(
"delete from users where uid_idx='$uid_idx'"
)
or
return
-
1
;
return
0
;
}
...
...
@@ -1631,243 +1631,6 @@ sub escapeshellarg($)
return $1;
}
#############################################################################
# Non-local users, as for federation/geni.
#
package User::NonLocal;
use emdb;
use User;
use libtestbed;
use English;
use overload ('
""
' => '
Stringify
');
# Cache of instances to avoid regenerating them.
my %nonlocal_users = ();
#
# Lookup by idx.
#
sub Lookup($$)
{
my ($class, $token) = @_;
my $idx;
my $query_result;
if ($token =~ /^\d+$/) {
$idx = $token;
}
elsif ($token =~ /^\w+\-\w+\-\w+\-\w+\-\w+$/) {
$query_result =
DBQueryWarn("select uid_idx from nonlocal_users ".
"where uid_uuid='
$
token
'");
return undef
if (! $query_result || !$query_result->numrows);
($idx) = $query_result->fetchrow_array();
}
else {
return undef;
}
# Look in cache first
return $nonlocal_users{"$idx"}
if (exists($nonlocal_users{"$idx"}));
$query_result =
DBQueryWarn("select * from nonlocal_users where uid_idx='
$
idx
'");
return undef
if (!$query_result || !$query_result->numrows);
my $self = {};
$self->{'
USER
'} = $query_result->fetchrow_hashref();
# Want to know if this is a shadow of a local user.
$self->{'
SHADOW
'} = User->Lookup($idx);
bless($self, $class);
# Add to cache.
$nonlocal_users{$self->{'
USER
'}->{'
uid_idx
'}} = $self;
return $self;
}
# accessors
sub field($$) { return ((! ref($_[0])) ? -1 : $_[0]->{'
USER
'}->{$_[1]}); }
sub uid_idx($) { return field($_[0], "uid_idx"); }
sub idx($) { return field($_[0], "uid_idx"); }
sub uid($) { return field($_[0], "uid"); }
sub uid_uuid($) { return field($_[0], "uid_uuid"); }
sub created($) { return field($_[0], "created"); }
sub name($) { return field($_[0], "name"); }
sub email($) { return field($_[0], "email"); }
sub shadow($) { return $_[0]->{'
SHADOW
'}; }
#
# Stringify for output.
#
sub Stringify($)
{
my ($self) = @_;
my $uid = $self->uid();
my $idx = $self->idx();
return "[NonLocalUser: $uid, IDX: $idx]";
}
#
# Class function to create a new nonlocal user and return object.
#
sub Create($$$$$$;$)
{
my ($class, $idx, $uid, $uuid, $name, $email, $sshkeys) = @_;
my @insert_data = ();
my $islocal = 0;
# Every user gets a new unique index.
if (!defined($idx) || $idx == 0) {
$idx = User->NextIDX();
}
else {
# Sanity check.
my $existing = User->Lookup($idx);
if (defined($existing)) {
if ($uuid eq $existing->uuid()) {
#
# Shadow a local user, strictly for tmcd.
#
$islocal = 1;
}
else {
print STDERR "NonLocal user with $idx exists: $existing\n";
return undef;
}
}
}
# Now tack on other stuff we need.
push(@insert_data, "created=now()");
push(@insert_data, "uid_idx='
$
idx
'");
my $safe_uid = DBQuoteSpecial($uid);
my $safe_name = DBQuoteSpecial($name);
my $safe_email = DBQuoteSpecial($email);
my $safe_uuid = DBQuoteSpecial($uuid);
push(@insert_data, "uid=$safe_uid");
push(@insert_data, "name=$safe_name");
push(@insert_data, "email=$safe_email");
push(@insert_data, "uid_uuid=$safe_uuid");
if (defined($sshkeys)) {
foreach my $sshkey (@{ $sshkeys }) {
my $safe_sshkey = DBQuoteSpecial($sshkey);
DBQueryWarn("insert into nonlocal_user_pubkeys set ".
" uid=$safe_uid, uid_idx='
$
idx
', ".
" idx=NULL, stamp=now(), pubkey=$safe_sshkey")
or return undef;
}
}
# Insert into DB.
if (!DBQueryWarn("insert into nonlocal_users set " .
join(",", @insert_data))) {
DBQueryWarn("delete from nonlocal_user_pubkeys where uid_idx='
$
idx
'")
if (!$islocal);
return undef;
}
return User::NonLocal->Lookup($idx);
}
#
# Modify the keys.
#
sub ModifyKeys($$)
{
my ($self, $sshkeys) = @_;
my $idx = $self->uid_idx();
my $uid = $self->uid();
DBQueryWarn("delete from nonlocal_user_pubkeys where uid_idx='
$
idx
'")
or return -1;
if (defined($sshkeys)) {
foreach my $sshkey (@{ $sshkeys }) {
my $safe_sshkey = DBQuoteSpecial($sshkey);
DBQueryWarn("insert into nonlocal_user_pubkeys set ".
" uid='
$
uid
', uid_idx='
$
idx
', ".
" idx=NULL, stamp=now(), pubkey=$safe_sshkey")
or return -1;
}
}
return 0;
}
#
# Delete the user, as for registration errors.
#
sub Delete($)
{
my ($self) = @_;
return 0
if (! ref($self));
my $idx = $self->idx();
DBQueryWarn("delete from nonlocal_user_pubkeys where uid_idx='
$
idx
'")
or return -1;
DBQueryWarn("delete from nonlocal_user_bindings where uid_idx='
$
idx
'")
or return -1;
DBQueryWarn("delete from nonlocal_users where uid_idx='
$
idx
'")
or return -1;
return 0;
}
#
# Bind nonlocal user to experiment (slice, in Geni).
#
sub BindToExperiment($$)
{
my ($self, $experiment) = @_;
return -1
if (! ref($self));
my $uid = $self->uid();
my $idx = $self->idx();
my $exptidx = $experiment->idx();
# Insert into DB.
DBQueryWarn("replace into nonlocal_user_bindings set " .
" uid='
$
uid
', uid_idx='
$
idx
', exptidx='
$
exptidx
'")
or return -1;
return 0;
}
sub UnBindFromExperiment($$)
{
my ($self, $experiment) = @_;
return -1
if (! ref($self));
my $uid = $self->uid();
my $idx = $self->idx();
my $exptidx = $experiment->idx();
# Insert into DB.
DBQueryWarn("delete from nonlocal_user_bindings " .
"where uid_idx='
$
idx
' and exptidx='
$
exptidx
'")
or return -1;
return 0;
}
# _Always_ make sure that this 1 is at the end of the file...
1;
install/updates/5/18
0 → 100644
View file @
e6598e50
#
# Add perl Digest-SHA1 port.
#
use strict;
use libinstall;
use emdbi;
sub InstallUpdate($$)
{
my ($version, $phase) = @_;
if ($phase eq "pre") {
Phase "p5-Digest-SHA1", "Checking for port p5-Digest-SHA1", sub {
DoneIfPackageInstalled("p5-Digest-SHA1");
ExecQuietFatal("cd $PORTSDIR/security/p5-Digest-SHA1; ".
"make MASTER_SITE_FREEBSD=1 -DBATCH install");
};
}
return 0;
}
1;
protogeni/lib/GeniAM.pm.in
View file @
e6598e50
...
...
@@ -28,6 +28,7 @@ use emutil;
use
Compress
::
Zlib
;
use
MIME
::
Base64
;
use
XML
::
LibXML
;
use
Data
::
Dumper
;
#
Disable
UUID
checks
in
GeniCredential
.
$
GeniCredential
::
CHECK_UUID
=
0
;
...
...
@@ -240,35 +241,25 @@ sub CreateSliver()
auto_add_sa
($
cred
);
}
#
circulate
through
the
users
and
bind
them
to
the
slice
my
$
caller_urn
=
$
ENV
{
'GENIURN'
};
my
$
caller_keys
=
undef
;
foreach
my
$
user
(@$
users
)
{
my
$
user_urn
=
$
user
->{
'urn'
};
#
Skip
if
it
is
not
the
caller
next
if
($
user_urn
ne
$
caller_urn
);
$
caller_keys
=
$
user
->{
keys
};
}
#
Package
the
caller_keys
in
a
list
of
hashes
the
way
the
CM
wants
#
it
.
Each
hash
has
two
keys
(
'type'
and
'key'
).
'type'
is
always
#
'ssh'
for
us
,
and
'key'
is
the
key
.
my
$
sliver_keys
=
undef
;
if
(
defined
($
caller_keys
))
{
$
sliver_keys
=
[];
foreach
my
$
key
(@$
caller_keys
)
{
#
The
CMV2
does
not
like
newlines
at
the
end
of
the
keys
.
chomp
($
key
);
push
(@$
sliver_keys
,
{
'type'
=>
'ssh'
,
'key'
=>
$
key
});
}
if
(@$
users
)
{
$
sliver_keys
=
[];
foreach
my
$
user
(@$
users
)
{
my
$
user_urn
=
$
user
->{
'urn'
};
my
@
user_keys
=
();
foreach
my
$
key
(@{
$
user
->{
keys
}
})
{
#
The
CMV2
does
not
like
newlines
at
the
end
of
the
keys
.
chomp
($
key
);
push
(@
user_keys
,
{
'type'
=>
'ssh'
,
'key'
=>
$
key
});
}
push
(@{$
sliver_keys
},
{
'urn'
=>
$
user_urn
,
'keys'
=>
\@
user_keys
});
}
}
#
This
only
gets
us
part
of
the
way
there
.
For
users
that
are
not
#
*
this
*
user
,
we
need
to
somehow
add
their
keys
,
which
also
#
requires
adding
them
as
a
user
*
without
*
their
certificate
.
Not
#
sure
we
'll be able to do that.
#
Invoke
CreateSliver
my
$
create_args
=
{
'slice_urn'
=>
$
slice_urn
,
...
...
@@ -276,7 +267,6 @@ sub CreateSliver()
'credentials'
=>
$
credentials
,
'keys'
=>
$
sliver_keys
};
my
$
response
=
GeniCMV2
::
CreateSliver
($
create_args
);
if
(
!ref($response)) {
#
This
is
cause
GeniCMV2
::
CreateSliver
does
a
fork
,
and
the
child
...
...
protogeni/lib/GeniCH.pm.in
View file @
e6598e50
...
...
@@ -442,7 +442,6 @@ sub Register($)
if
($
type
eq
"user"
)
{
my
$
name
=
$
info
->{
'name'
};
my
$
email
=
$
info
->{
'email'
};
my
$
keys
=
undef
;
if
(
! TBcheck_dbslot($name, "users", "usr_name",
TBDB_CHECKDBSLOT_ERROR
))
{
...
...
@@ -474,9 +473,9 @@ sub Register($)
"Not allowed to change hrn"
);
}
#
#
Update
operation
,
but
only
name
,
email
,
and
keys
for
now
.
#
Update
operation
,
but
only
name
,
email
#
if
($
existing
->
Modify
($
name
,
$
email
,
$
keys
)
!= 0) {
if
($
existing
->
Modify
($
name
,
$
email
)
!= 0) {
return
GeniResponse
->
Create
(
GENIRESPONSE_ERROR
,
undef
,
"Could not update user"
);
}
...
...
@@ -502,8 +501,7 @@ sub Register($)
return
GeniResponse
->
Create
(
GENIRESPONSE_ERROR
,
undef
,
"user already registered"
);
}
my
$
newuser
=
GeniUser
->
Create
($
certificate
,
$
slice_authority
,
$
info
,
$
keys
);
my
$
newuser
=
GeniUser
->
Create
($
certificate
,
$
slice_authority
,
$
info
);
if
(
!defined($newuser)) {
return
GeniResponse
->
Create
(
GENIRESPONSE_ERROR
,
undef
,
"Could not be registered"
);
...
...
protogeni/lib/GeniCM.pm.in
View file @
e6598e50
...
...
@@ -40,6 +40,7 @@ use emutil;
use
EmulabConstants
;
use
libEmulab
;
use
Lan
;
use
Experiment
;
use
English
;
use
Data
::
Dumper
;
use
XML
::
Simple
;
...
...
@@ -49,6 +50,7 @@ use Time::Local;
use
Compress
::
Zlib
;
use
File
::
Temp
qw
(
tempfile
);
use
MIME
::
Base64
;
use
Digest
::
SHA1
qw
(
sha1_hex
);
#
Configure
variables
my
$
TB
=
"@prefix@"
;
...
...
@@ -1945,21 +1947,6 @@ sub SliverWorkAux($$$$$$$)
"Slice has expired");
}
#
# Create the user.
#
my $owner = CreateUserFromCertificate($owner_cert);
return $owner
if (GeniResponse::IsResponse($owner));
if (defined($keys)) {
$response = CheckKeys($keys);
return $response
if (GeniResponse::IsResponse($response));
$owner->Modify(undef, undef, $keys);
}
my $experiment = GeniExperiment($slice);
if (!defined($experiment)) {
$slice->UnLock();
...
...
@@ -1971,6 +1958,23 @@ sub SliverWorkAux($$$$$$$)
my $pid = $experiment->pid();
my $eid = $experiment->eid();
#
# Create the user.
#
my $owner = CreateUserFromCertificate($owner_cert);
return $owner
if (GeniResponse::IsResponse($owner));
if (defined($keys)) {
$response = AddKeys($slice, $owner, $keys);
if (GeniResponse::IsResponse($response)) {
$slice->UnLock();
$ticket->UnLock()
if (defined($ticket));
return $response;
}
}
#
# Figure out what nodes to allocate or free.
#
...
...
@@ -2184,16 +2188,6 @@ sub SliverWorkAux($$$$$$$)
}
}
#
# Create an emulab nonlocal user for tmcd.
#
if ($owner->BindToSlice($slice)) {
$message = "Error binding user to slice";
print STDERR "$message\n";
goto bad;
}
#
# We are actually an Aggregate, so return an aggregate of slivers,
# even if there is just one node. This makes sliceupdate easier.
...
...
@@ -3564,13 +3558,7 @@ sub BindToSlice($)
my $user = CreateUserFromCertificate($credential->owner_cert());
return $user
if (GeniResponse::IsResponse($user));
if (defined($keys)) {
my $response = CheckKeys($keys);
return $response
if (GeniResponse::IsResponse($response));
$user->Modify(undef, undef, $keys);
}
if ($slice->Lock() != 0) {
return GeniResponse->BusyResponse();
}
...
...
@@ -3580,11 +3568,12 @@ sub BindToSlice($)
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Error binding slice to user");
}
# Bind for existing slivers.
if ($user->BindToSlice($slice) != 0) {
$slice->UnLock();
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Error binding user to slice");
if (defined($keys)) {
my $response = AddKeys($slice, $user, $keys);
if (GeniResponse::IsResponse($response)) {
$slice->UnLock();
return $response;
}
}
$slice->UnLock();
return GeniResponse->Create(GENIRESPONSE_SUCCESS);
...
...
@@ -4229,7 +4218,7 @@ sub CreateUserFromCertificate($)
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Could not create user from your certificate")
if (!defined($user));
return $user;
}
...
...
@@ -4562,7 +4551,6 @@ sub GeniExperiment($)
my $gid = $pid;
my $hrn = $slice->hrn();
my $urn = $slice->urn();
require Experiment;
my $experiment = Experiment->Lookup($uuid);
return $experiment
...
...
@@ -4799,27 +4787,120 @@ sub CheckTicket($)
return $ticket;
}
sub
Check
Keys($)
sub
Add
Keys($
$$
)
{
my ($keys) = @_;
my (
$slice, $owner,
$keys) = @_;
goto bad
if (!ref($keys));
foreach my $keyref (@{ $keys }) {
goto bad
if (!ref($keyref));
my $key = $keyref->{'
key
'};
my $type = $keyref->{'
type
'};
if (! (ref($keys) && ref($keys) eq "ARRAY"));
goto bad
if (! (defined($key) && defined($type) &&
my $slice_experiment = $slice->GetExperiment();
if (!$slice_experiment) {
print STDERR "AddKeys: No experiment for $slice\n";
return GeniResponse->Create(GENIRESPONSE_ERROR);
}
my $keychecker = sub {
my ($arg) = @_;
return -1
if (! (ref($arg) && ref($arg) eq "HASH"));
my $key = $arg->{'
key
'};
my $type = $arg->{'
type
'};
return -1
if (! (defined($arg) && defined($arg) &&