From 3ebffb34166812f5073e6a057b5b84655aef9ad3 Mon Sep 17 00:00:00 2001 From: Leigh B Stoller <stoller@flux.utah.edu> Date: Tue, 1 Mar 2016 16:17:25 -0700 Subject: [PATCH] Some tweaks to credential handling: 1) Anytime we need to generate a slice credential, and the slice has expired, bump the slice expiration so we can create a valid credential and then reset the expiration. Consider if the slice expires but we missed it and its still active; we gotta be able to control it. 2) From the beginning, we have done almost all RPC operations as the creator of the experiment. Made sense when the portal interface was not project aware, but now other users in the project can see and mess with experiments in their project. But we are still doing all the RPC operations as the creator of the experiment, which will need to change at some point, but in the short term I am seeing a lot of credential errors caused by an expired speaks-for credential for that creator (if they have not logged into the portal in a while). When this happens, lets generate a plain slice credential, issued to the SA, so that we can complete the operation. Eventually we have to make the backend project aware, and issue the operations as the web user doing the driving. Maybe as part of the larger portalization project. --- apt/APT_Geni.pm.in | 62 ++++++++-- apt/APT_Instance.pm.in | 255 +++++++++++++++++------------------------ apt/create_instance.in | 2 +- apt/manage_dataset.in | 20 ++-- apt/manage_instance.in | 56 +++++---- www/aptui/status.ajax | 12 +- 6 files changed, 204 insertions(+), 203 deletions(-) diff --git a/apt/APT_Geni.pm.in b/apt/APT_Geni.pm.in index 4f96632b19..992248ff43 100644 --- a/apt/APT_Geni.pm.in +++ b/apt/APT_Geni.pm.in @@ -56,10 +56,10 @@ my $USEABACCREDS = 0; # # Generate the credentials we need. # -sub GenCredentials($$;$) +sub GenCredentials($$;$$) { - my ($target, $geniuser, $privs) = @_; - my ($speaksfor, $credential); + my ($target, $geniuser, $privs, $allowexpiredspeaksfor) = @_; + my ($speaksfor, $credential, $oldexpires); # If the caller does not want a speaksfor, do not generate. my $wantspeaksfor = wantarray; @@ -72,11 +72,21 @@ sub GenCredentials($$;$) if (!$geniuser->IsLocal() && $MAINSITE) { $speaker_signer = "/usr/testbed/etc/utah-apt.sa"; } - + my $cachetag = $target->urn() . "::" . $geniuser->urn(); + + # + # If the target is a slice, and expired, change the expiration so + # that the credential we generate is not also expired (and invalid). + # + if (ref($target) eq "GeniSlice" && $target->IsExpired()) { + $oldexpires = $target->expires(); + $target->SetExpiration(time() + 600); + delete($credcache{$cachetag}) + if (exists($credcache{$cachetag})); + } # # Check cache. # - my $cachetag = $target->urn() . "::" . $geniuser->urn(); if (exists($credcache{$cachetag})) { ($credential,$speaksfor) = @{ $credcache{$cachetag} }; goto cached; @@ -102,6 +112,25 @@ sub GenCredentials($$;$) goto bad; } } + # + # Ick, if the speaks for credential has expired, we cannot + # operate as the user. We have no choice but to throw away + # these credentials and generate a new one issued to the local + # SA instead of the user and not bother with a speaksfor. + # + if ($speaksfor->IsExpired()) { + print STDERR "speaksfor credential for $geniuser has expired\n"; + goto bad + if (!$allowexpiredspeaksfor); + + print STDERR "-> Generating an SA credential instead\n"; + $credential = APT_Geni::GenAuthCredential($target, $privs); + if (!defined($credential)) { + print STDERR "-> Could not generate SA credential!\n"; + goto bad; + } + goto cached; + } my $certificate = GeniCertificate->LoadFromString($certificate_string); if (!defined($certificate)) { @@ -167,11 +196,15 @@ sub GenCredentials($$;$) $credcache{$cachetag} = [$credential, $speaksfor]; } cached: + $target->SetExpiration($oldexpires) + if (defined($oldexpires)); if (wantarray) { return ($credential, $speaksfor); } return $credential; bad: + $target->SetExpiration($oldexpires) + if (defined($oldexpires)); return (); } @@ -212,16 +245,25 @@ sub GeniContext() sub GenAuthCredential($;$) { my ($target, $privs) = @_; + my $oldexpires; my $owner = GeniCertificate->LoadFromFile($SACERT); if (!defined($owner)) { print STDERR "Could not load certificate from $SACERT\n"; return undef; } + # + # If the target is a slice, and expired, change the expiration so + # that the credential we generate is not also expired (and invalid). + # + if (ref($target) eq "GeniSlice" && $target->IsExpired()) { + $oldexpires = $target->expires(); + $target->SetExpiration(time() + 600); + } my $credential = GeniCredential->Create($target, $owner); if (!defined($credential)) { print STDERR "Could not create credential for $target\n"; - return undef; + goto bad; } # Add optional privs. if (defined($privs)) { @@ -233,9 +275,15 @@ sub GenAuthCredential($;$) if ($credential->Sign($GeniCredential::LOCALSA_FLAG) != 0) { $credential->Delete(); print STDERR "Could not sign $target credential\n"; - return undef + goto bad; } + $target->SetExpiration($oldexpires) + if (defined($oldexpires)); return $credential; + bad: + $target->SetExpiration($oldexpires) + if (defined($oldexpires)); + return undef; } # diff --git a/apt/APT_Instance.pm.in b/apt/APT_Instance.pm.in index 197f365a76..4dfa7ded19 100644 --- a/apt/APT_Instance.pm.in +++ b/apt/APT_Instance.pm.in @@ -57,6 +57,7 @@ use Genixmlrpc; use GeniResponse; use GeniCertificate; use GeniCredential; +use GeniUser; use GeniHRN; use GeniXML; use WebTask; @@ -67,6 +68,7 @@ use overload ('""' => 'Stringify'); my $TB = "@prefix@"; my $TBOPS = "@TBOPSEMAIL@"; my $GENEXTENDCRED = "$TB/sbin/protogeni/genextendcred"; +my $GENIUSER = "geniuser"; # Cache of instances to avoid regenerating them. my %instances = (); @@ -80,7 +82,7 @@ sub devurl($) if ($usemydevtree) { $cmurl =~ s/protogeni/protogeni\/stoller/; - $cmurl =~ s/12369/12396/; +# $cmurl =~ s/12369/12396/; } return $cmurl; } @@ -1333,18 +1335,11 @@ sub Terminate($) my $geniuser = $self->instance()->GetGeniUser(); my $slice = $self->instance()->GetGeniSlice(); my $context = APT_Geni::GeniContext(); + return undef if (! (defined($geniuser) && defined($authority) && defined($slice) && defined($context))); - # - # If the slice is expired, it is most likely gone at the cluster, - # but we want to make sure, so change the expiration so that the - # credential we generate is not also expired. - # - if ($slice->IsExpired()) { - $slice->SetExpiration(time() + 3600); - } # We might change this below. my $cmurl = $authority->url(); @@ -1360,30 +1355,13 @@ sub Terminate($) else { my $credentials; my ($slice_credential, $speaksfor_credential) = - APT_Geni::GenCredentials($slice, $geniuser); + APT_Geni::GenCredentials($slice, $geniuser, undef, 1); return undef - if (! (defined($speaksfor_credential) && - defined($slice_credential))); - # - # Special case; if the speaksfor_credential has expired cause it - # was for a nonlocal user, we have no choice but to throw away - # these credentials and generate a new one issued to the local SA - # instead of the user. - # - if ($speaksfor_credential->IsExpired()) { - print STDERR - "speaksfor credential has expired, generating a new one\n"; + if (!defined($slice_credential)); - $slice_credential = APT_Geni::GenAuthCredential($slice); - if (!defined($slice_credential)) { - print STDERR "Could not generate slice credential\n"; - return undef; - } - $credentials = [$slice_credential->asString()]; - } - else { - $credentials = [$slice_credential->asString(), - $speaksfor_credential->asString()]; + $credentials = [$slice_credential->asString()]; + if (defined($speaksfor_credential)) { + $credentials = [@$credentials, $speaksfor_credential->asString()]; } $method = "DeleteSliver"; @params = ($slice->urn(), $credentials, @@ -1464,31 +1442,15 @@ sub Extend($$) } else { my ($slice_credential, $speaksfor_credential) = - APT_Geni::GenCredentials($slice, $geniuser); + APT_Geni::GenCredentials($slice, $geniuser, undef, 1); return undef - if (! (defined($speaksfor_credential) && - defined($slice_credential))); - - # - # Special case; if the speaksfor_credential has expired cause it - # was for a nonlocal user, we have no choice but to throw away - # these credentials and generate a new one issued to the local SA - # instead of the user. - # - if ($speaksfor_credential->IsExpired()) { - print STDERR "speaksfor credential expired, generating a new one\n"; + if (!defined($slice_credential)); - $slice_credential = APT_Geni::GenAuthCredential($slice); - if (!defined($slice_credential)) { - print STDERR "Could not generate slice credential\n"; - return undef; - } - $credentials = [$slice_credential->asString()]; - } - else { - $credentials = [$slice_credential->asString(), - $speaksfor_credential->asString()]; + $credentials = [$slice_credential->asString()]; + if (defined($speaksfor_credential)) { + $credentials = [@$credentials, $speaksfor_credential->asString()]; } + # # We need a special credentential in case the aggregate is enforcing # limits (as do Utah aggregates). @@ -1502,10 +1464,11 @@ sub Extend($$) # But if a nonlocal user from Geni, then the user we have in # the database is not in the same domain as the speaksfor, so # we use the geni certificate that the trusted signer gave us - # and is stored in the DB. - # + # and is stored in the DB. Note that of the speaksfor was + # expired, it will not be defined (see above). + # if ($geniuser->IsLocal() && $geniuser->emulab_user()->IsNonLocal() && - !$speaksfor_credential->IsExpired()) { + defined($speaksfor_credential)) { my (undef, $certificate_string) = $geniuser->emulab_user()->GetStoredCredential(); if (! defined($certificate_string)) { @@ -1583,28 +1546,25 @@ sub SliceStatus($) my $geniuser = $self->instance()->GetGeniUser(); my $slice = $self->instance()->GetGeniSlice(); my $context = APT_Geni::GeniContext(); + return undef if (! (defined($geniuser) && defined($authority) && defined($slice) && defined($context))); + # + # Use an SA credential here so that we can always get status. + # + my $slice_credential = APT_Geni::GenAuthCredential($slice); + if (!defined($slice_credential)) { + print STDERR "Could not generate slice credential\n"; + return undef; + } if ($self->isAL2S()) { - my $slice_credential = APT_Geni::GenAuthCredential($slice); - if (!defined($slice_credential)) { - print STDERR "Could not generate slice credential\n"; - return undef; - } @params = ($slice->urn(), [$slice_credential->asString()], {}); } else { - my ($slice_credential, $speaksfor_credential) = - APT_Geni::GenCredentials($slice, $geniuser); - return undef - if (! (defined($speaksfor_credential) && - defined($slice_credential))); - @params = ({"slice_urn" => $slice->urn(), - "credentials" => [$slice_credential->asString(), - $speaksfor_credential->asString()], + "credentials" => [$slice_credential->asString()], }); } my $cmurl = $authority->url(); @@ -1639,8 +1599,8 @@ sub GetManifest($) my $method; my @params; my $authority = $self->GetGeniAuthority(); - my $urn = $self->aggregate_urn(); my $geniuser = $self->instance()->GetGeniUser(); + my $urn = $self->aggregate_urn(); my $slice = $self->instance()->GetGeniSlice(); my $context = APT_Geni::GeniContext(); return undef @@ -1664,16 +1624,20 @@ sub GetManifest($) }); } else { + my $credentials; + my ($slice_credential, $speaksfor_credential) = - APT_Geni::GenCredentials($slice, $geniuser); + APT_Geni::GenCredentials($slice, $geniuser, undef, 1); return undef - if (! (defined($speaksfor_credential) && - defined($slice_credential))); + if (!defined($slice_credential)); + $credentials = [$slice_credential->asString()]; + if (defined($speaksfor_credential)) { + $credentials = [@$credentials, $speaksfor_credential->asString()]; + } $method = "Resolve"; @params = ({"urn" => $slice->urn(), - "credentials" => [$slice_credential->asString(), - $speaksfor_credential->asString()]}); + "credentials" => $credentials}); } my $cmurl = $authority->url(); $cmurl = devurl($cmurl) if ($usemydevtree); @@ -1721,7 +1685,7 @@ sub Provision($$$$) defined($slice) && defined($context))); my ($slice_credential, $speaksfor_credential) = - APT_Geni::GenCredentials($slice, $geniuser); + APT_Geni::GenCredentials($slice, $geniuser, undef, 0); return -1 if (! (defined($speaksfor_credential) && defined($slice_credential))); @@ -1786,24 +1750,26 @@ sub ConsoleInfo($$) { my ($self, $sliver_urn) = @_; my $authority = $self->GetGeniAuthority(); - my $geniuser = $self->instance()->GetGeniUser(); my $slice = $self->instance()->GetGeniSlice(); my $context = APT_Geni::GeniContext(); + my $geniuser = $self->instance()->GetGeniUser(); return undef if (! (defined($geniuser) && defined($authority) && defined($slice) && defined($context))); my ($slice_credential, $speaksfor_credential) = - APT_Geni::GenCredentials($slice, $geniuser); + APT_Geni::GenCredentials($slice, $geniuser, undef, 1); return undef - if (! (defined($speaksfor_credential) && - defined($slice_credential))); + if (! defined($slice_credential)); + my $credentials = [$slice_credential->asString()]; + if (defined($speaksfor_credential)) { + $credentials = [@$credentials, $speaksfor_credential->asString()]; + } my $args = { "slice_urn" => $slice->urn(), "sliver_urn" => $sliver_urn, - "credentials" => [$slice_credential->asString(), - $speaksfor_credential->asString()], + "credentials" => $credentials, }; my $cmurl = $authority->url(); $cmurl = devurl($cmurl) if ($usemydevtree); @@ -1826,16 +1792,18 @@ sub ConsoleURL($$) defined($slice) && defined($context))); my ($slice_credential, $speaksfor_credential) = - APT_Geni::GenCredentials($slice, $geniuser); + APT_Geni::GenCredentials($slice, $geniuser, undef, 1); return undef - if (! (defined($speaksfor_credential) && - defined($slice_credential))); + if (!defined($slice_credential)); + my $credentials = [$slice_credential->asString()]; + if (defined($speaksfor_credential)) { + $credentials = [@$credentials, $speaksfor_credential->asString()]; + } my $args = { "slice_urn" => $slice->urn(), "sliver_urn" => $sliver_urn, - "credentials" => [$slice_credential->asString(), - $speaksfor_credential->asString()], + "credentials" => $credentials, }; my $cmurl = $authority->url(); $cmurl = devurl($cmurl) if ($usemydevtree); @@ -1851,15 +1819,19 @@ sub CreateImage($$$$;$$$) my ($self, $sliver_urn, $imagename, $update_prepare, $copyback_uuid, $bsname) = @_; my $authority = $self->GetGeniAuthority(); - my $geniuser = $self->instance()->GetGeniUser(); + my$geniuser = $self->instance()->GetGeniUser(); my $slice = $self->instance()->GetGeniSlice(); my $context = APT_Geni::GeniContext(); return undef if (! (defined($geniuser) && defined($authority) && defined($slice) && defined($context))); + # + # Only the creator is allowed to do this, so if the speaksfor is + # expired, a permission check went wrong. + # my ($slice_credential, $speaksfor_credential) = - APT_Geni::GenCredentials($slice, $geniuser); + APT_Geni::GenCredentials($slice, $geniuser, undef, 0); return undef if (! (defined($speaksfor_credential) && defined($slice_credential))); @@ -1888,14 +1860,14 @@ sub CreateImage($$$$;$$$) # # Reboot some nodes # -sub SliverAction($$$@) +sub SliverAction($$$;@) { my ($self, $perrmsg, $which, @slivers) = @_; my $method = ($which eq "reboot" ? "RestartSliver" : ($which eq "start" ? "StartSliver" : "ReloadSliver")); my $authority = $self->GetGeniAuthority(); - my $urn = $self->aggregate_urn(); my $geniuser = $self->instance()->GetGeniUser(); + my $urn = $self->aggregate_urn(); my $slice = $self->instance()->GetGeniSlice(); my $context = APT_Geni::GeniContext(); return undef @@ -1903,14 +1875,16 @@ sub SliverAction($$$@) defined($slice) && defined($context))); my ($slice_credential, $speaksfor_credential) = - APT_Geni::GenCredentials($slice, $geniuser); + APT_Geni::GenCredentials($slice, $geniuser, undef, 1); return undef - if (! (defined($speaksfor_credential) && - defined($slice_credential))); + if (!defined($slice_credential)); + my $credentials = [$slice_credential->asString()]; + if (defined($speaksfor_credential)) { + $credentials = [@$credentials, $speaksfor_credential->asString()]; + } my $args = { - "credentials" => [$slice_credential->asString(), - $speaksfor_credential->asString()], + "credentials" => $credentials, }; if (@slivers) { $args->{"sliver_urns"} = \@slivers; @@ -1960,15 +1934,6 @@ sub Lockdown($$) if (! (defined($authority) && defined($slice) && defined($context))); - # - # If the slice is expired, then the credential we generate will - # not be valid. So extend the slice so we can clear the lockdown. - # - if ($clear && $slice->IsExpired()) { - $oldexpires = $slice->expires(); - $slice->SetExpiration(time() + 3600); - } - my $slice_credential = APT_Geni::GenAuthCredential($slice); goto bad if (! defined($slice_credential)); @@ -2001,22 +1966,12 @@ sub Panic($$) my $authority = $self->GetGeniAuthority(); my $slice = $self->instance()->GetGeniSlice(); my $context = APT_Geni::GeniContext(); - my $oldexpires; return undef if (! (defined($authority) && defined($slice) && defined($context))); - # - # If the slice is expired, then the credential we generate will - # not be valid. So extend the slice so we can clear the panic. - # - if ($clear && $slice->IsExpired()) { - $oldexpires = $slice->expires(); - $slice->SetExpiration(time() + 3600); - } - my $slice_credential = APT_Geni::GenAuthCredential($slice); - goto bad + return undef if (! defined($slice_credential)); my $args = { @@ -2029,13 +1984,7 @@ sub Panic($$) $cmurl = devurl($cmurl) if ($usemydevtree); my $response = Genixmlrpc::CallMethod($cmurl, $context, "Panic", $args); - $slice->SetExpiration($oldexpires) - if (defined($oldexpires)); return $response; - bad: - $slice->SetExpiration($oldexpires) - if (defined($oldexpires)); - return undef; } # @@ -2045,8 +1994,8 @@ sub RunLinktest($$$) { my ($self, $action, $level) = @_; my $authority = $self->GetGeniAuthority(); - my $urn = $self->aggregate_urn(); my $geniuser = $self->instance()->GetGeniUser(); + my $urn = $self->aggregate_urn(); my $slice = $self->instance()->GetGeniSlice(); my $context = APT_Geni::GeniContext(); return undef @@ -2054,15 +2003,17 @@ sub RunLinktest($$$) defined($slice) && defined($context))); my ($slice_credential, $speaksfor_credential) = - APT_Geni::GenCredentials($slice, $geniuser); + APT_Geni::GenCredentials($slice, $geniuser, undef, 1); return undef - if (! (defined($speaksfor_credential) && - defined($slice_credential))); - + if (!defined($slice_credential)); + + my $credentials = [$slice_credential->asString()]; + if (defined($speaksfor_credential)) { + $credentials = [@$credentials, $speaksfor_credential->asString()]; + } my $args = { "slice_urn" => $slice->urn(), - "credentials" => [$slice_credential->asString(), - $speaksfor_credential->asString()], + "credentials" => $credentials, }; if ($action eq "stop") { $args->{"action"} = "stop"; @@ -2100,15 +2051,17 @@ sub ImageInfo($$) defined($slice) && defined($context))); my ($slice_credential, $speaksfor_credential) = - APT_Geni::GenCredentials($slice, $geniuser); + APT_Geni::GenCredentials($slice, $geniuser, undef, 1); return undef - if (! (defined($speaksfor_credential) && - defined($slice_credential))); + if (!defined($slice_credential)); + my $credentials = [$slice_credential->asString()]; + if (defined($speaksfor_credential)) { + $credentials = [@$credentials, $speaksfor_credential->asString()]; + } my $args = { "image_urn" => $image_urn, - "credentials" => [$slice_credential->asString(), - $speaksfor_credential->asString()], + "credentials" => $credentials, }; my $cmurl = $authority->url(); $cmurl = devurl($cmurl) if ($usemydevtree); @@ -2123,8 +2076,8 @@ sub UpdateKeys($$) { my ($self, $users) = @_; my $authority = $self->GetGeniAuthority(); - my $urn = $self->aggregate_urn(); my $geniuser = $self->instance()->GetGeniUser(); + my $urn = $self->aggregate_urn(); my $slice = $self->instance()->GetGeniSlice(); my $context = APT_Geni::GeniContext(); return -1 @@ -2132,28 +2085,30 @@ sub UpdateKeys($$) defined($slice) && defined($context))); my ($slice_credential, $speaksfor_credential) = - APT_Geni::GenCredentials($slice, $geniuser); + APT_Geni::GenCredentials($slice, $geniuser, undef, 1); return -1 - if (! (defined($speaksfor_credential) && - defined($slice_credential))); + if (!defined($slice_credential)); + + my $options = {"geni_users" => $users}; + my $credentials = [{"geni_type" => "geni_sfa", + "geni_version" => 3, + "geni_value" => $slice_credential->asString()}]; + if (defined($speaksfor_credential)) { + $credentials = [{"geni_type" => "geni_sfa", + "geni_version" => 3, + "geni_value" => $speaksfor_credential->asString()}, + @$credentials]; + $options->{"speaking_for"} = $geniuser->urn(); + $options->{"geni_speaking_for"} = $geniuser->urn(); + } # # AM V3 API. # my @params = ([$slice->urn()], - [{"geni_type" => "geni_sfa", - "geni_version" => 3, - "geni_value" => $speaksfor_credential->asString()}, - {"geni_type" => "geni_sfa", - "geni_version" => 3, - "geni_value" => $slice_credential->asString()}, - ], + $credentials, "geni_update_users", - # Options array. - {"speaking_for" => $geniuser->urn(), - "geni_speaking_for" => $geniuser->urn(), - "geni_users" => $users, - }); + $options); my $cmurl = $authority->url(); # Convert URL. diff --git a/apt/create_instance.in b/apt/create_instance.in index c4b9370a94..33b6e08e45 100755 --- a/apt/create_instance.in +++ b/apt/create_instance.in @@ -682,7 +682,7 @@ if ($tmp) { # Generate credentials we need. # my ($slice_credential, $speaksfor_credential) = - APT_Geni::GenCredentials($slice, $geniuser); + APT_Geni::GenCredentials($slice, $geniuser, undef, 0); if (! (defined($speaksfor_credential) && defined($slice_credential))) { fatal("Could not generate credentials"); diff --git a/apt/manage_dataset.in b/apt/manage_dataset.in index 33445ff5bb..1a5afd946c 100644 --- a/apt/manage_dataset.in +++ b/apt/manage_dataset.in @@ -46,6 +46,8 @@ my $optlist = "dt:"; my $debug = 0; my $webtask_id; my $webtask; +my $this_user; +my $geniuser; # # Configure variables @@ -80,6 +82,7 @@ use WebTask; use Blockstore; use GeniResponse; use GeniXML; +use GeniUser; # Protos sub fatal($); @@ -117,16 +120,19 @@ if (defined($options{"t"})) { if (@ARGV < 1) { usage(); } +my $action = shift(@ARGV); -# The web interface (and in the future the xmlrpc interface) sets this. -my $this_user = User->ImpliedUser(); -if (! defined($this_user)) { +if (getpwuid($UID) eq "nobody") { + $this_user = User->ImpliedUser(); +} +else { $this_user = User->ThisUser(); - if (!defined($this_user)) { - fatal("You ($UID) do not exist!"); - } } -my $action = shift(@ARGV); +# No guests allowed. +if (! defined($this_user)) { + fatal("You ($UID) do not exist!"); +} +$geniuser = GeniUser->CreateFromLocal($this_user); if ($action eq "create") { exit(DoCreate()); diff --git a/apt/manage_instance.in b/apt/manage_instance.in index 1893b99a00..34e5d80adb 100644 --- a/apt/manage_instance.in +++ b/apt/manage_instance.in @@ -56,6 +56,8 @@ my $debug = 0; my $silent = 0; my $webtask_id; my $webtask; +my $this_user; +my $geniuser; # # Configure variables @@ -101,6 +103,7 @@ use EmulabFeatures; # Protos sub fatal($); +sub UserError($); sub DoSnapshot(); sub DoConsole(); sub DoTerminate(); @@ -147,6 +150,16 @@ if (!defined($instance)) { if (!defined($instance)) { fatal("No such instance $uuid"); } +if (getpwuid($UID) eq "nobody") { + $this_user = User->ImpliedUser(); +} +else { + $this_user = User->ThisUser(); +} +# If a guest user, we will not have an actual user, which is okay. +if (defined($this_user)) { + $geniuser = GeniUser->CreateFromLocal($this_user); +} if ($action eq "snapshot") { DoSnapshot(); @@ -252,15 +265,6 @@ sub DoSnapshot() fatal("No slice for quick VM: $uuid"); } - # The web interface (and in the future the xmlrpc interface) sets this. - my $this_user = User->ImpliedUser(); - if (! defined($this_user)) { - $this_user = User->ThisUser(); - if (!defined($this_user)) { - fatal("You ($UID) do not exist!"); - } - } - # # Might be a clone (manage_profile). # @@ -1183,11 +1187,6 @@ sub DoExtend() if (!defined($slice)) { fatal("No slice for instance!"); } - # The web interface (and in the future the xmlrpc interface) sets this. - my $this_user = User->ImpliedUser(); - if (! defined($this_user)) { - $this_user = User->ThisUser(); - } # # Lock the slice in case it is doing something else, like taking @@ -1795,12 +1794,6 @@ sub DoLockdownInternal($$) { my ($setclr,$which) = @_; - # The web interface (and in the future the xmlrpc interface) sets this. - my $this_user = User->ImpliedUser(); - if (! defined($this_user)) { - $this_user = User->ThisUser(); - } - my $slice = $instance->GetGeniSlice(); if (!defined($slice)) { fatal("No slice for instance"); @@ -2021,11 +2014,6 @@ sub DoLinktest() if (!defined($slice)) { fatal("No slice for instance!"); } - # The web interface (and in the future the xmlrpc interface) sets this. - my $this_user = User->ImpliedUser(); - if (! defined($this_user)) { - $this_user = User->ThisUser(); - } # # Lock the slice in case it is doing something else, like taking @@ -2232,11 +2220,6 @@ sub DoUpdateKeys() if (!defined($slice)) { fatal("No slice for instance!"); } - # The web interface (and in the future the xmlrpc interface) sets this. - my $this_user = User->ImpliedUser(); - if (! defined($this_user)) { - $this_user = User->ThisUser(); - } # This returns in CM format. my $sshkeys; @@ -2369,6 +2352,19 @@ sub fatal($) exit(-1); } +sub UserError($) +{ + my ($mesg) = @_; + + if (defined($webtask)) { + $webtask->output($mesg); + $webtask->code(1); + } + print STDERR "*** $0:\n". + " $mesg\n"; + exit(1); +} + sub escapeshellarg($) { my ($str) = @_; diff --git a/www/aptui/status.ajax b/www/aptui/status.ajax index b685c53ef9..187d27ae17 100644 --- a/www/aptui/status.ajax +++ b/www/aptui/status.ajax @@ -934,15 +934,11 @@ function Do_Refresh() # # Guest users can do this. # - if (StatusSetupAjax(1)) { + if (StatusSetupAjax(0)) { return; } $this_idx = $this_user->uid_idx(); $uuid = $ajax_args["uuid"]; - if ($this_idx != $instance->creator_idx() && !ISADMIN()) { - SPITAJAX_ERROR(1, "Not enough permission. Maybe Clone instead?"); - return; - } # # Call out to the backend. # @@ -1014,7 +1010,7 @@ function Do_RebootOrReload($which) # Call out to the backend. # $webtask_id = WebTask::GenerateID(); - $retval = SUEXEC($this_user->uid(), "nobody", + $retval = SUEXEC("nobody", "nobody", "webmanage_instance -t $webtask_id -- ". " $which $uuid " . escapeshellarg($node_id), SUEXEC_ACTION_IGNORE); @@ -1243,7 +1239,7 @@ function Do_Linktest() return; } $webtask_id = WebTask::GenerateID(); - $retval = SUEXEC($this_user->uid(), "nobody", + $retval = SUEXEC("nobody", "nobody", "webmanage_instance -t $webtask_id -- ". "linktest $uuid $level", SUEXEC_ACTION_IGNORE); @@ -1296,7 +1292,7 @@ function Do_Linktest() return; } $webtask_id = WebTask::GenerateID(); - $retval = SUEXEC($this_user->uid(), "nobody", + $retval = SUEXEC("nobody", "nobody", "webmanage_instance -t $webtask_id -- ". "linktest $uuid -k", SUEXEC_ACTION_IGNORE); -- GitLab