Authenticate runtime with CastCoreService.
This change integrates the runtime authentication flow with Cast Web Runtime that would allow using TCP/IP sockets on devices. Bug: b:389181125 Change-Id: I86877b3d0a1b0a1b7716b7663beb7451b5d379b9 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6219899 Commit-Queue: Vigen Issahhanjan <vigeni@google.com> Reviewed-by: Simeon Anfinrud <sanfin@chromium.org> Cr-Commit-Position: refs/heads/main@{#1418294}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
48b2ab99b1
commit
ee43a5ecbf
2
DEPS
2
DEPS
@ -1881,7 +1881,7 @@ deps = {
|
||||
Var('chromium_git') + '/breakpad/breakpad.git' + '@' + '0dfd77492fdb0dcd06027c5842095e2e908adc90',
|
||||
|
||||
'src/third_party/cast_core/public/src':
|
||||
Var('chromium_git') + '/cast_core/public' + '@' + 'fbc5e98031e1271a0a566fcd4d9092b2d3275d05',
|
||||
Var('chromium_git') + '/cast_core/public' + '@' + 'dcb3d2e87cebe20b6dda06d8b29abb9af27ca422',
|
||||
|
||||
'src/third_party/catapult':
|
||||
Var('chromium_git') + '/catapult.git' + '@' + Var('catapult_revision'),
|
||||
|
@ -39,10 +39,10 @@ void CastBrowserTest::SetUp() {
|
||||
void CastBrowserTest::SetUpCommandLine(base::CommandLine* command_line) {
|
||||
command_line->AppendSwitchASCII(switches::kTestType, "browser");
|
||||
command_line->AppendSwitchASCII(
|
||||
cast::core::kCastCoreRuntimeIdSwitch,
|
||||
cast::core::switches::kCastCoreRuntimeId,
|
||||
base::Uuid::GenerateRandomV4().AsLowercaseString());
|
||||
command_line->AppendSwitchASCII(
|
||||
cast::core::kRuntimeServicePathSwitch,
|
||||
cast::core::switches::kRuntimeServicePath,
|
||||
"unix:/tmp/runtime-service.sock." +
|
||||
base::Uuid::GenerateRandomV4().AsLowercaseString());
|
||||
}
|
||||
|
@ -5,17 +5,25 @@
|
||||
#ifndef CHROMECAST_CAST_CORE_CAST_CORE_SWITCHES_H_
|
||||
#define CHROMECAST_CAST_CORE_CAST_CORE_SWITCHES_H_
|
||||
|
||||
namespace cast {
|
||||
namespace core {
|
||||
namespace cast::core::switches {
|
||||
|
||||
// Specifies the Cast Core runtime ID, --cast-core-runtime-id=<runtime_id>.
|
||||
constexpr char kCastCoreRuntimeIdSwitch[] = "cast-core-runtime-id";
|
||||
inline constexpr char kCastCoreRuntimeId[] = "cast-core-runtime-id";
|
||||
|
||||
// Specifies the Cast Core runtime gRPC endpoint,
|
||||
// --runtime-service-path=<endpoint>.
|
||||
constexpr char kRuntimeServicePathSwitch[] = "runtime-service-path";
|
||||
inline constexpr char kRuntimeServicePath[] = "runtime-service-path";
|
||||
|
||||
} // namespace core
|
||||
} // namespace cast
|
||||
// Specifies the Cast Core service gRPC endpoint.
|
||||
inline constexpr char kCastCoreServiceEndpoint[] = "cast-core-service-endpoint";
|
||||
|
||||
// Specifies that TCP/IP should be used as the gRPC transport typeby Cast Core;
|
||||
// otherwise UDS is used.
|
||||
inline constexpr char kEnableGrpcOverTcpIp[] = "enable-grpc-over-tcpip";
|
||||
|
||||
// Authentication token securely sent to the runtime.
|
||||
inline constexpr char kRuntimeAuthToken[] = "runtime-auth-token";
|
||||
|
||||
} // namespace cast::core::switches
|
||||
|
||||
#endif // CHROMECAST_CAST_CORE_CAST_CORE_SWITCHES_H_
|
||||
|
@ -214,8 +214,12 @@ void RuntimeApplicationServiceImpl::Load(
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(INFO) << "Runtime application server started: endpoint="
|
||||
<< request.runtime_application_service_info().grpc_endpoint();
|
||||
LOG(INFO) << "Runtime application service started: app_id="
|
||||
<< request.application_config().app_id()
|
||||
#if DCHECK_IS_ON()
|
||||
<< ", endpoint=" << grpc_server_->endpoint()
|
||||
#endif // DCHECK_IS_ON()
|
||||
;
|
||||
|
||||
// TODO(vigeni): Consider extacting this into RuntimeApplicationBase as a
|
||||
// mojo.
|
||||
|
@ -60,7 +60,14 @@ class RuntimeApplicationServiceImpl : public cast_receiver::EmbedderApplication,
|
||||
void Stop(const cast::runtime::StopApplicationRequest& request,
|
||||
StatusCallback callback);
|
||||
|
||||
const std::string& app_id() { return runtime_application_->GetAppId(); }
|
||||
// Returns current application ID.
|
||||
const std::string& app_id() const { return runtime_application_->GetAppId(); }
|
||||
|
||||
// Returns RuntimeApplicationService gRPC server endpoint.
|
||||
const std::string& endpoint() const {
|
||||
CHECK(grpc_server_);
|
||||
return grpc_server_->endpoint();
|
||||
}
|
||||
|
||||
// EmbedderApplication implementation:
|
||||
void NotifyApplicationStarted() override;
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "base/check.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/functional/callback_helpers.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/task/bind_post_task.h"
|
||||
@ -53,30 +54,45 @@ RuntimeServiceImpl::~RuntimeServiceImpl() {
|
||||
cast_receiver::Status RuntimeServiceImpl::Start() {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
auto* command_line = base::CommandLine::ForCurrentProcess();
|
||||
std::string runtime_id =
|
||||
command_line->GetSwitchValueASCII(cast::core::kCastCoreRuntimeIdSwitch);
|
||||
std::string runtime_id = command_line->GetSwitchValueASCII(
|
||||
cast::core::switches::kCastCoreRuntimeId);
|
||||
if (runtime_id.empty()) {
|
||||
// This may happen during unfreeze of the browser process. Usually the cast
|
||||
// service process is dead, too, but a certain condition how this happens on
|
||||
// Android is not known. Most probable cause is OS reboot/update etc.
|
||||
LOG(ERROR) << "Runtime id must be specified in command line with: --"
|
||||
<< cast::core::kCastCoreRuntimeIdSwitch;
|
||||
<< cast::core::switches::kCastCoreRuntimeId;
|
||||
return cast_receiver::Status(
|
||||
cast_receiver::StatusCode::kFailedPrecondition);
|
||||
}
|
||||
|
||||
std::string runtime_service_path =
|
||||
command_line->GetSwitchValueASCII(cast::core::kRuntimeServicePathSwitch);
|
||||
std::string runtime_service_path = command_line->GetSwitchValueASCII(
|
||||
cast::core::switches::kRuntimeServicePath);
|
||||
if (runtime_service_path.empty()) {
|
||||
// This may happen during unfreeze of the browser process with cast service
|
||||
// process dead.
|
||||
LOG(ERROR)
|
||||
<< "Runtime service endpoint must be specified in command line with: --"
|
||||
<< cast::core::kRuntimeServicePathSwitch;
|
||||
<< cast::core::switches::kRuntimeServicePath;
|
||||
return cast_receiver::Status(
|
||||
cast_receiver::StatusCode::kFailedPrecondition);
|
||||
}
|
||||
return Start(runtime_id, runtime_service_path);
|
||||
|
||||
auto status = Start(runtime_id, runtime_service_path);
|
||||
if (!status.ok()) {
|
||||
return status;
|
||||
}
|
||||
|
||||
bool enable_grpc_over_tcpip =
|
||||
command_line->HasSwitch(cast::core::switches::kEnableGrpcOverTcpIp);
|
||||
std::string cast_core_service_endpoint = command_line->GetSwitchValueASCII(
|
||||
cast::core::switches::kCastCoreServiceEndpoint);
|
||||
std::string authentication_token = command_line->GetSwitchValueASCII(
|
||||
cast::core::switches::kRuntimeAuthToken);
|
||||
MaybeAuthenticateRuntime(enable_grpc_over_tcpip, runtime_id,
|
||||
cast_core_service_endpoint, authentication_token);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
cast_receiver::Status RuntimeServiceImpl::Start(
|
||||
@ -86,9 +102,6 @@ cast_receiver::Status RuntimeServiceImpl::Start(
|
||||
CHECK(!runtime_id.empty());
|
||||
CHECK(!runtime_service_endpoint.empty());
|
||||
|
||||
LOG(INFO) << "Starting runtime service: runtime_id=" << runtime_id
|
||||
<< ", endpoint=" << runtime_service_endpoint;
|
||||
|
||||
grpc_server_.emplace();
|
||||
grpc_server_
|
||||
->SetHandler<cast::runtime::RuntimeServiceHandler::LoadApplication>(
|
||||
@ -126,15 +139,21 @@ cast_receiver::Status RuntimeServiceImpl::Start(
|
||||
weak_factory_.GetWeakPtr())));
|
||||
|
||||
auto status = grpc_server_->Start(std::string(runtime_service_endpoint));
|
||||
// Browser runtime must crash if the runtime service failed to start to avoid
|
||||
// the process to dangle without any proper connection to the Cast Core.
|
||||
// Browser runtime must crash if the runtime service failed to start to
|
||||
// avoid the process to dangle without any proper connection to the Cast
|
||||
// Core.
|
||||
if (!status.ok()) {
|
||||
LOG(ERROR) << "Failed to start runtime service: status="
|
||||
<< status.error_message();
|
||||
return cast_receiver::Status(cast_receiver::StatusCode::kInvalidArgument);
|
||||
}
|
||||
|
||||
LOG(INFO) << "Runtime service started";
|
||||
LOG(INFO) << "Runtime service started: runtime_id=" << runtime_id
|
||||
#if DCHECK_IS_ON()
|
||||
<< ", endpoint=" << grpc_server_->endpoint()
|
||||
#endif // DCHECK_IS_ON()
|
||||
;
|
||||
|
||||
return cast_receiver::OkStatus();
|
||||
}
|
||||
|
||||
@ -143,8 +162,8 @@ void RuntimeServiceImpl::ResetGrpcServices() {
|
||||
|
||||
if (heartbeat_reactor_) {
|
||||
heartbeat_timer_.Stop();
|
||||
// Reset the writes callback as we're not expecting any more responses from
|
||||
// gRPC framework.
|
||||
// Reset the writes callback as we're not expecting any more responses
|
||||
// from gRPC framework.
|
||||
heartbeat_reactor_->SetWritesAvailableCallback(base::DoNothing());
|
||||
heartbeat_reactor_->Write(grpc::Status::OK);
|
||||
heartbeat_reactor_ = nullptr;
|
||||
@ -358,7 +377,8 @@ void RuntimeServiceImpl::HandleStartMetricsRecorder(
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(INFO) << "Started recording metrics";
|
||||
DLOG(INFO) << "Started recording metrics: endpoint="
|
||||
<< request.metrics_recorder_service_info().grpc_endpoint();
|
||||
metrics_recorder_stub_.emplace(
|
||||
request.metrics_recorder_service_info().grpc_endpoint());
|
||||
reactor->Write(cast::runtime::StartMetricsRecorderResponse());
|
||||
@ -414,6 +434,12 @@ void RuntimeServiceImpl::OnApplicationLoaded(
|
||||
|
||||
cast::runtime::LoadApplicationResponse response;
|
||||
response.mutable_message_port_info();
|
||||
response.mutable_runtime_application_service_info()->set_grpc_endpoint(
|
||||
platform_app->endpoint());
|
||||
|
||||
DLOG(INFO) << "Runtime application service loaded: endpoint="
|
||||
<< platform_app->endpoint();
|
||||
|
||||
reactor->Write(std::move(response));
|
||||
}
|
||||
|
||||
@ -502,6 +528,50 @@ void RuntimeServiceImpl::OnHeartbeatSent(
|
||||
weak_factory_.GetWeakPtr())));
|
||||
}
|
||||
|
||||
void RuntimeServiceImpl::MaybeAuthenticateRuntime(
|
||||
bool enable_grpc_over_tcpip,
|
||||
const std::string& runtime_id,
|
||||
const std::string& cast_core_service_endpoint,
|
||||
const std::string& authentication_token) {
|
||||
if (!enable_grpc_over_tcpip) {
|
||||
LOG(INFO) << "Skipping runtime authentication as not requested";
|
||||
return;
|
||||
}
|
||||
|
||||
CHECK(!cast_core_service_endpoint.empty())
|
||||
<< "Cast Core service endpoint must be specified for authentication";
|
||||
CHECK(!authentication_token.empty())
|
||||
<< "Auth token must be present for TCP/IP endpoints";
|
||||
|
||||
cast_core_service_stub_.emplace(cast_core_service_endpoint);
|
||||
auto call =
|
||||
cast_core_service_stub_
|
||||
->CreateCall<cast::core::CastCoreServiceStub::AuthenticateRuntime>();
|
||||
call.request().set_runtime_id(runtime_id);
|
||||
call.request().set_authentication_token(authentication_token);
|
||||
call.request().mutable_runtime_service_info()->set_grpc_endpoint(
|
||||
grpc_server_->endpoint());
|
||||
call.request().set_challenge("my challenge");
|
||||
std::move(call).InvokeAsync(base::BindPostTask(
|
||||
task_runner_, base::BindOnce(&RuntimeServiceImpl::OnRuntimeAuthenticated,
|
||||
weak_factory_.GetWeakPtr())));
|
||||
}
|
||||
|
||||
void RuntimeServiceImpl::OnRuntimeAuthenticated(
|
||||
cast::utils::GrpcStatusOr<cast::core::AuthenticateRuntimeResponse>
|
||||
response_or) {
|
||||
if (!response_or.ok()) {
|
||||
LOG(ERROR) << "Failed to authenticate runtime";
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(INFO) << "Runtime is authenticated: sig="
|
||||
<< response_or->challenge_signature()
|
||||
<< ", chain=" << response_or->certificate_chain_size();
|
||||
|
||||
// TODO(vigeni): Add signature verification.
|
||||
}
|
||||
|
||||
void RuntimeServiceImpl::RecordMetrics(
|
||||
cast::metrics::RecordRequest request,
|
||||
CastRuntimeMetricsRecorderService::RecordCompleteCallback
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "chromecast/cast_core/runtime/browser/runtime_application_service_impl.h"
|
||||
#include "components/cast_receiver/browser/public/runtime_application_dispatcher.h"
|
||||
#include "components/cast_receiver/common/public/status.h"
|
||||
#include "third_party/cast_core/public/src/proto/core/cast_core_service.castcore.pb.h"
|
||||
#include "third_party/cast_core/public/src/proto/metrics/metrics_recorder.castcore.pb.h"
|
||||
#include "third_party/cast_core/public/src/proto/runtime/runtime_service.castcore.pb.h"
|
||||
|
||||
@ -101,6 +102,13 @@ class RuntimeServiceImpl final
|
||||
void OnMetricsRecorderServiceStopped(
|
||||
cast::runtime::RuntimeServiceHandler::StopMetricsRecorder::Reactor*
|
||||
reactor);
|
||||
void MaybeAuthenticateRuntime(bool enable_grpc_over_tcpip,
|
||||
const std::string& runtime_id,
|
||||
const std::string& cast_core_service_endpoint,
|
||||
const std::string& runtime_auth_token);
|
||||
void OnRuntimeAuthenticated(
|
||||
cast::utils::GrpcStatusOr<cast::core::AuthenticateRuntimeResponse>
|
||||
response_or);
|
||||
|
||||
void ResetGrpcServices();
|
||||
|
||||
@ -120,6 +128,7 @@ class RuntimeServiceImpl final
|
||||
CastRuntimeMetricsRecorder metrics_recorder_;
|
||||
|
||||
std::optional<cast::utils::GrpcServer> grpc_server_;
|
||||
std::optional<cast::core::CastCoreServiceStub> cast_core_service_stub_;
|
||||
std::optional<cast::metrics::MetricsRecorderServiceStub>
|
||||
metrics_recorder_stub_;
|
||||
std::optional<CastRuntimeMetricsRecorderService> metrics_recorder_service_;
|
||||
|
2
third_party/cast_core/public/src
vendored
2
third_party/cast_core/public/src
vendored
Submodule third_party/cast_core/public/src updated: fbc5e98031...dcb3d2e87c
Reference in New Issue
Block a user