diff --git a/fog/api/proto/view.proto b/fog/api/proto/view.proto index 750ea43d93..7dbed6bfef 100644 --- a/fog/api/proto/view.proto +++ b/fog/api/proto/view.proto @@ -36,11 +36,40 @@ message FogViewRouterResponse { } } +message FogViewStoreDecryptionError { + /// The FogViewStoreUri for the specific Fog View Store that + /// tried to decrypt the MultiViewStoreQueryRequest and failed. + /// The client should subsequently authenticate with the machine + /// described by this URI. + string fog_view_store_uri = 1; + + /// An error message that describes the decryption error. + string error_message = 2; +} + +message MultiViewStoreQueryRequest { + /// A list of queries encrypted for Fog View Stores. + repeated attest.Message queries = 1; +} + +message MultiViewStoreQueryResponse { + /// Optional field that gets set when the Fog View Store is able to decrypt a query + /// included in the MultiViewStoreQueryRequest and create a query response for that + // query. + attest.Message query_response = 1; + + /// Optional error that gets returned when the Fog View Store + /// cannot decrypt the MultiViewStoreQuery. + FogViewStoreDecryptionError decryption_error = 2; +} + service FogViewAPI { /// This is called to perform IX key exchange with the enclave before calling GetOutputs. rpc Auth(attest.AuthMessage) returns (attest.AuthMessage) {} /// Input should be an encrypted QueryRequest, result is an encrypted QueryResponse rpc Query(attest.Message) returns (attest.Message) {} + /// Input should be an encrypted MultiViewStoreQueryRequest, result is an encrypted QueryResponse. + rpc MultiViewStoreQuery(MultiViewStoreQueryRequest) returns (MultiViewStoreQueryResponse) {} } /// There are several kinds of records returned by the fog view API diff --git a/fog/view/server/src/fog_view_service.rs b/fog/view/server/src/fog_view_service.rs index 685bc2d45a..ef544202d2 100644 --- a/fog/view/server/src/fog_view_service.rs +++ b/fog/view/server/src/fog_view_service.rs @@ -4,9 +4,13 @@ use crate::server::DbPollSharedState; use grpcio::{RpcContext, RpcStatus, RpcStatusCode, UnarySink}; use mc_attest_api::attest; use mc_common::logger::{log, Logger}; -use mc_fog_api::view_grpc::FogViewApi; +use mc_fog_api::{ + view::{MultiViewStoreQueryRequest, MultiViewStoreQueryResponse}, + view_grpc::FogViewApi, +}; use mc_fog_recovery_db_iface::RecoveryDb; use mc_fog_types::view::QueryRequestAAD; +use mc_fog_uri::{ConnectionUri, FogViewUri}; use mc_fog_view_enclave::{Error as ViewEnclaveError, ViewEnclaveProxy}; use mc_fog_view_enclave_api::UntrustedQueryResponse; use mc_util_grpc::{ @@ -31,6 +35,9 @@ pub struct FogViewService { /// GRPC request authenticator. authenticator: Arc, + /// The FogViewUri for this FogViewService. + fog_view_uri: FogViewUri, + /// Slog logger object logger: Logger, } @@ -43,6 +50,7 @@ impl FogViewService { db: Arc, db_poll_shared_state: Arc>, authenticator: Arc, + fog_view_uri: FogViewUri, logger: Logger, ) -> Self { Self { @@ -50,6 +58,7 @@ impl FogViewService { db, db_poll_shared_state, authenticator, + fog_view_uri, logger, } } @@ -188,4 +197,36 @@ impl FogViewApi for FogViewSe send_result(ctx, sink, self.query_impl(request), logger) }) } + + /// Fulfills the query if the MultiViewStoreQueryRequest contains an + /// encrypted Query for the store. If it doesn't, then it responds with + /// an grpc error that contains the store's hostname. + fn multi_view_store_query( + &mut self, + ctx: RpcContext, + request: MultiViewStoreQueryRequest, + sink: UnarySink, + ) { + mc_common::logger::scoped_global_logger(&rpc_logger(&ctx, &self.logger), |logger| { + if let Err(err) = self.authenticator.authenticate_rpc(&ctx) { + return send_result(ctx, sink, err.into(), logger); + } + let mut response = MultiViewStoreQueryResponse::new(); + for query in request.queries { + let result = self.query_impl(query); + if let Ok(attested_message) = result { + response.set_query_response(attested_message); + return send_result(ctx, sink, Ok(response), logger); + } + } + + let decryption_error = response.mut_decryption_error(); + decryption_error.set_fog_view_store_uri(self.fog_view_uri.url().to_string()); + decryption_error.set_error_message( + "Could not decrypt a query embedded in the MultiViewStoreQuery".to_string(), + ); + + send_result(ctx, sink, Ok(response), logger) + }); + } } diff --git a/fog/view/server/src/server.rs b/fog/view/server/src/server.rs index 0c658c5558..cf94c4e7a0 100644 --- a/fog/view/server/src/server.rs +++ b/fog/view/server/src/server.rs @@ -99,6 +99,7 @@ where Arc::new(recovery_db), db_poll_thread.get_shared_state(), client_authenticator, + config.client_listen_uri.clone(), logger.clone(), )); log::debug!(logger, "Constructed View GRPC Service");