Retrieve an Instance Identity token when configuring Cloud hosts
This CL updates the Cloud host provisioning path to request an Instance Identity token which will be used for configuring remote access for a specific Compute Engine Instance (and the policies associated with it), rather than relying on the configuration set at the Project level. Bug: 388886766 Change-Id: If796e7a88f862e68412690fbff990f36f4aa7e69 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6270168 Reviewed-by: Gary Kacmarcik <garykac@chromium.org> Commit-Queue: Joe Downing <joedow@chromium.org> Cr-Commit-Position: refs/heads/main@{#1420691}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
acc168ed8b
commit
8032831039
remoting
base
host
proto
google
remoting
cloud
@ -312,6 +312,7 @@ void CloudServiceClient::ProvisionGceInstance(
|
||||
const std::string& display_name,
|
||||
const std::string& public_key,
|
||||
const std::optional<std::string>& existing_directory_id,
|
||||
const std::optional<std::string>& instance_identity_token,
|
||||
ProvisionGceInstanceCallback callback) {
|
||||
constexpr char path[] = "/v1/provisioning:provisionGceInstance";
|
||||
|
||||
@ -323,6 +324,10 @@ void CloudServiceClient::ProvisionGceInstance(
|
||||
if (existing_directory_id.has_value() && !existing_directory_id->empty()) {
|
||||
request->set_existing_directory_id(*existing_directory_id);
|
||||
}
|
||||
if (instance_identity_token.has_value() &&
|
||||
!instance_identity_token->empty()) {
|
||||
request->set_instance_identity_token(*instance_identity_token);
|
||||
}
|
||||
|
||||
ExecuteRequest(kProvisionGceInstanceTrafficAnnotation, path, api_key_,
|
||||
net::HttpRequestHeaders::kPostMethod, std::move(request),
|
||||
|
@ -95,6 +95,7 @@ class CloudServiceClient {
|
||||
const std::string& display_name,
|
||||
const std::string& public_key,
|
||||
const std::optional<std::string>& existing_directory_id,
|
||||
const std::optional<std::string>& instance_identity_token,
|
||||
ProvisionGceInstanceCallback callback);
|
||||
|
||||
void SendHeartbeat(const std::string& directory_id,
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "remoting/base/http_status.h"
|
||||
#include "remoting/base/oauth_token_info.h"
|
||||
#include "remoting/base/passthrough_oauth_token_getter.h"
|
||||
#include "remoting/base/service_urls.h"
|
||||
#include "remoting/host/host_config.h"
|
||||
#include "remoting/host/setup/host_starter.h"
|
||||
#include "remoting/host/setup/host_starter_base.h"
|
||||
@ -43,7 +44,9 @@ class CloudHostStarter : public HostStarterBase {
|
||||
|
||||
~CloudHostStarter() override;
|
||||
|
||||
// ComputeEngineServiceClient callbacks.
|
||||
void OnApiAccessTokenRetrieved(const HttpStatus& status);
|
||||
void OnIdentityTokenRetrieved(const HttpStatus& status);
|
||||
|
||||
// HostStarterBase implementation.
|
||||
void RetrieveApiAccessToken() override;
|
||||
@ -63,6 +66,8 @@ class CloudHostStarter : public HostStarterBase {
|
||||
|
||||
std::unique_ptr<PassthroughOAuthTokenGetter> api_access_token_getter_;
|
||||
|
||||
std::optional<std::string> instance_identity_token_;
|
||||
|
||||
SEQUENCE_CHECKER(sequence_checker_);
|
||||
|
||||
base::WeakPtrFactory<CloudHostStarter> weak_ptr_factory_{this};
|
||||
@ -80,6 +85,27 @@ CloudHostStarter::~CloudHostStarter() = default;
|
||||
void CloudHostStarter::RetrieveApiAccessToken() {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
|
||||
// Try to retrieve an Instance Identity Token before the access token. Making
|
||||
// this query first simplifies the logic a bit as we may end up skipping the
|
||||
// the access token request if an API_KEY is provided but we want to try to
|
||||
// get the identity token for both scenarios.
|
||||
compute_engine_service_client_->GetInstanceIdentityToken(
|
||||
/*audience=*/ServiceUrls::GetInstance()->remoting_cloud_public_endpoint(),
|
||||
base::BindOnce(&CloudHostStarter::OnIdentityTokenRetrieved,
|
||||
weak_ptr_factory_.GetWeakPtr()));
|
||||
}
|
||||
|
||||
void CloudHostStarter::OnIdentityTokenRetrieved(const HttpStatus& status) {
|
||||
if (status.ok() && !status.response_body().empty()) {
|
||||
instance_identity_token_ = status.response_body();
|
||||
} else {
|
||||
int error_code = static_cast<int>(status.error_code());
|
||||
LOG(WARNING) << "Failed to retrieve an Instance Identity token.\n"
|
||||
<< " Error code: " << error_code << "\n"
|
||||
<< " Message: " << status.error_message() << "\n"
|
||||
<< " Body: " << status.response_body();
|
||||
}
|
||||
|
||||
// The two modes to configure a Cloud host are to generate an API_KEY and use
|
||||
// that to access the provisioning RPC or to generate an access token using
|
||||
// the default service-account. If an API_KEY is being used, we can skip the
|
||||
@ -137,7 +163,7 @@ void CloudHostStarter::RegisterNewHost(
|
||||
|
||||
cloud_service_client_->ProvisionGceInstance(
|
||||
params().owner_email, params().name, key_pair().GetPublicKey(),
|
||||
existing_host_id(),
|
||||
existing_host_id(), std::move(instance_identity_token_),
|
||||
base::BindOnce(&CloudHostStarter::OnProvisionGceInstanceResponse,
|
||||
weak_ptr_factory_.GetWeakPtr()));
|
||||
}
|
||||
|
@ -31,6 +31,12 @@ message ProvisionGceInstanceRequest {
|
||||
// backend will validate the other fields in the request and ensure
|
||||
// `owner_email` owns the previous instance as well.
|
||||
optional string existing_directory_id = 5;
|
||||
|
||||
// An instance identity token which includes GCP project and instance
|
||||
// information for a specific Compute Engine Instance.
|
||||
// More information about the contents of the token can be found at:
|
||||
// https://cloud.google.com/compute/docs/instances/verifying-instance-identity
|
||||
optional string instance_identity_token = 6;
|
||||
}
|
||||
|
||||
// Represents a service account created for a remote access host instance.
|
||||
|
Reference in New Issue
Block a user