Skip to content

Commit

Permalink
Unary gRPC transport template class (#4970)
Browse files Browse the repository at this point in the history
Implement unary transport class template for future Oak clients that use the unary interface.
  • Loading branch information
pmcgrath17 authored Apr 2, 2024
1 parent 65f6b46 commit fa50670
Show file tree
Hide file tree
Showing 7 changed files with 290 additions and 7 deletions.
46 changes: 46 additions & 0 deletions cc/transport/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ cc_library(
hdrs = ["grpc_streaming_transport.h"],
deps = [
":transport",
":util",
"//proto/crypto:crypto_cc_proto",
"//proto/session:messages_cc_proto",
"//proto/session:service_streaming_cc_grpc",
Expand All @@ -48,6 +49,34 @@ cc_library(
],
)

cc_library(
name = "grpc_unary_transport",
hdrs = ["grpc_unary_transport.h"],
deps = [
":transport",
":util",
"//proto/crypto:crypto_cc_proto",
"//proto/session:messages_cc_proto",
"//proto/session:service_unary_cc_grpc",
"//proto/session:service_unary_cc_proto",
"@com_github_grpc_grpc//:grpc++",
"@com_google_absl//absl/log",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
],
)

cc_library(
name = "util",
srcs = ["util.cc"],
hdrs = ["util.h"],
deps = [
"@com_github_grpc_grpc//:grpc++",
"@com_google_absl//absl/status",
],
)

cc_test(
name = "grpc_streaming_transport_test",
srcs = ["grpc_streaming_transport_test.cc"],
Expand All @@ -64,3 +93,20 @@ cc_test(
"@com_google_googletest//:gtest_main",
],
)

cc_test(
name = "grpc_unary_transport_test",
srcs = ["grpc_unary_transport_test.cc"],
deps = [
":grpc_unary_transport",
"//proto/crypto:crypto_cc_proto",
"//proto/session:messages_cc_proto",
"//proto/session:service_unary_cc_grpc",
"//proto/session:service_unary_cc_proto",
"@com_github_grpc_grpc//:grpc++",
"@com_google_absl//absl/log",
"@com_google_absl//absl/log:absl_check",
"@com_google_absl//absl/status",
"@com_google_googletest//:gtest_main",
],
)
8 changes: 1 addition & 7 deletions cc/transport/grpc_streaming_transport.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "cc/transport/util.h"
#include "grpcpp/channel.h"
#include "grpcpp/client_context.h"
#include "grpcpp/create_channel.h"
Expand All @@ -32,19 +33,12 @@

namespace oak::transport {

namespace {
using ::oak::crypto::v1::EncryptedRequest;
using ::oak::crypto::v1::EncryptedResponse;
using ::oak::session::v1::EndorsedEvidence;
using ::oak::session::v1::GetEndorsedEvidenceRequest;
using ::oak::session::v1::RequestWrapper;
using ::oak::session::v1::ResponseWrapper;
} // namespace

absl::Status to_absl_status(const grpc::Status& grpc_status) {
return absl::Status(static_cast<absl::StatusCode>(grpc_status.error_code()),
grpc_status.error_message());
}

absl::StatusOr<EndorsedEvidence> GrpcStreamingTransport::GetEndorsedEvidence() {
// Create request.
Expand Down
83 changes: 83 additions & 0 deletions cc/transport/grpc_unary_transport.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Copyright 2023 The Project Oak Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef CC_TRANSPORT_GRPC_UNARY_TRANSPORT_H_
#define CC_TRANSPORT_GRPC_UNARY_TRANSPORT_H_

#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "cc/transport/transport.h"
#include "cc/transport/util.h"
#include "grpcpp/client_context.h"
#include "proto/crypto/crypto.pb.h"
#include "proto/session/messages.pb.h"
#include "proto/session/service_unary.pb.h"

namespace oak::transport {

// Transport class for communication with unary gRPC Oak service. Evidence
// must be collected from the enclave and verified prior to issuing any data
// requests. This template class can be used to communicate with any unary
// stubby Oak service that use a gRPC interface consistent with
// oak/proto/session/service_unary.proto.
template <typename OakBackendStub>
class GrpcUnaryTransport : public ::oak::transport::TransportWrapper {
public:
explicit GrpcUnaryTransport(OakBackendStub* const client_stub) : client_stub_(client_stub) {}

// Collects the enclave's evidence that needs to be verified by the client.
absl::StatusOr<::oak::session::v1::EndorsedEvidence> GetEndorsedEvidence() override {
::grpc::ClientContext context;
::oak::session::v1::GetEndorsedEvidenceRequest request;
::oak::session::v1::GetEndorsedEvidenceResponse response;

grpc::Status status = client_stub_->GetEndorsedEvidence(&context, request, &response);
if (!status.ok()) {
absl::Status absl_status = to_absl_status(status);
LOG(ERROR) << "Failed to fetch evidence with status: " << absl_status;
return absl_status;
}

return response.endorsed_evidence();
}

// Takes an encrypted request and sends it to the enclave, returning the
// enclave's encrypted response.
absl::StatusOr<::oak::crypto::v1::EncryptedResponse> Invoke(
const ::oak::crypto::v1::EncryptedRequest& encrypted_request) override {
::grpc::ClientContext context;
::oak::session::v1::InvokeRequest request;
::oak::session::v1::InvokeResponse response;

*request.mutable_encrypted_request() = encrypted_request;
grpc::Status status = client_stub_->Invoke(&context, request, &response);
if (!status.ok()) {
absl::Status absl_status = to_absl_status(status);
LOG(ERROR) << "Failed to call invoke with status: " << absl_status;
return absl_status;
}

return response.encrypted_response();
}

private:
OakBackendStub* client_stub_;
};

} // namespace oak::transport

#endif // CC_TRANSPORT_GRPC_UNARY_TRANSPORT_H_
101 changes: 101 additions & 0 deletions cc/transport/grpc_unary_transport_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* Copyright 2023 The Project Oak Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "cc/transport/grpc_unary_transport.h"

#include <memory>
#include <string>

#include "absl/status/status.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "proto/crypto/crypto.pb.h"
#include "proto/session/messages.pb.h"
#include "proto/session/service_unary.pb.h"
#include "proto/session/service_unary_mock.grpc.pb.h"

namespace oak::transport {
namespace {

using ::oak::crypto::v1::AeadEncryptedMessage;
using ::oak::crypto::v1::EncryptedRequest;
using ::oak::crypto::v1::EncryptedResponse;
using ::oak::session::v1::EndorsedEvidence;
using ::oak::session::v1::GetEndorsedEvidenceRequest;
using ::oak::session::v1::GetEndorsedEvidenceResponse;
using ::oak::session::v1::InvokeRequest;
using ::oak::session::v1::InvokeResponse;
using ::oak::session::v1::MockUnarySessionStub;

using ::testing::_;
using ::testing::DoAll;
using ::testing::Return;
using ::testing::SetArgPointee;
using ::testing::StrEq;

TEST(StubbyUnaryTransportTest, KeyRetrievedAndInvokeCalledSuccess) {
auto mock_stub = std::make_unique<MockUnarySessionStub>();

// Test the get endorsed evidence method.
GetEndorsedEvidenceRequest empty_request;
GetEndorsedEvidenceResponse evidence_response;
std::string application_key = "001";
*evidence_response.mutable_endorsed_evidence()
->mutable_evidence()
->mutable_application_keys()
->mutable_encryption_public_key_certificate() = application_key;

EXPECT_CALL(*mock_stub, GetEndorsedEvidence(_, _, _))
.WillOnce(DoAll(SetArgPointee<2>(evidence_response), Return(grpc::Status::OK)));

GrpcUnaryTransport<MockUnarySessionStub> unary_transport(mock_stub.get());

auto actual_endorsed_evidence = unary_transport.GetEndorsedEvidence();
ASSERT_TRUE(actual_endorsed_evidence.ok());
EXPECT_THAT(
actual_endorsed_evidence->evidence().application_keys().encryption_public_key_certificate(),
StrEq(application_key));

// Now we test the invoke method.

const std::string request_ciphertext = "Some encrypted request.";
AeadEncryptedMessage request_aead_encrypted_message;
request_aead_encrypted_message.set_ciphertext(request_ciphertext);
EncryptedRequest encrypted_request;
*encrypted_request.mutable_encrypted_message() = request_aead_encrypted_message;
InvokeRequest invoke_request;
*invoke_request.mutable_encrypted_request() = encrypted_request;

const std::string response_ciphertext = "Some encrypted response.";
AeadEncryptedMessage response_aead_encrypted_message;
response_aead_encrypted_message.set_ciphertext(response_ciphertext);
EncryptedResponse encrypted_response;
*encrypted_response.mutable_encrypted_message() = response_aead_encrypted_message;
InvokeResponse invoke_response;
*invoke_response.mutable_encrypted_response() = encrypted_response;

EXPECT_CALL(*mock_stub, Invoke(_, _, _))
.WillOnce(DoAll(SetArgPointee<2>(invoke_response), Return(::grpc::Status::OK)));

auto actual_encrypted_response = unary_transport.Invoke(encrypted_request);
ASSERT_TRUE(actual_encrypted_response.ok());

EXPECT_THAT(actual_encrypted_response->encrypted_message().ciphertext(),
StrEq(response_ciphertext));
}

} // namespace
} // namespace oak::transport
27 changes: 27 additions & 0 deletions cc/transport/util.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright 2023 The Project Oak Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "absl/status/status.h"
#include "grpcpp/grpcpp.h"

namespace oak::transport {

absl::Status to_absl_status(const grpc::Status& grpc_status) {
return absl::Status(static_cast<absl::StatusCode>(grpc_status.error_code()),
grpc_status.error_message());
}

} // namespace oak::transport
31 changes: 31 additions & 0 deletions cc/transport/util.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright 2023 The Project Oak Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef CC_TRANSPORT_UTIL_H_
#define CC_TRANSPORT_UTIL_H_

#include "absl/status/status.h"
#include "grpcpp/grpcpp.h"

namespace oak::transport {

// Converts gRPC status to an absl status. The gRPC error status code is casted and the error
// message is copied.
absl::Status to_absl_status(const grpc::Status& grpc_status);

} // namespace oak::transport

#endif // CC_TRANSPORT_UTIL_H_
1 change: 1 addition & 0 deletions proto/session/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ cc_proto_library(
cc_grpc_library(
name = "service_unary_cc_grpc",
srcs = [":service_unary_proto"],
generate_mocks = True,
grpc_only = True,
deps = [":service_unary_cc_proto"],
)
Expand Down

0 comments on commit fa50670

Please sign in to comment.