Merge pull request #15150 from grpc/revert-15130-fake_handshaker

Revert "Add fake ALTS handshaker server (bazel only)"
pull/15157/head
Mark D. Roth 7 years ago committed by GitHub
commit 7ea45bebc7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 47
      test/core/tsi/alts/fake_handshaker/BUILD
  2. 268
      test/core/tsi/alts/fake_handshaker/fake_handshaker_server.cc
  3. 224
      test/core/tsi/alts/fake_handshaker/handshaker.proto
  4. 40
      test/core/tsi/alts/fake_handshaker/transport_security_common.proto

@ -1,47 +0,0 @@
# Copyright 2018 gRPC 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.
licenses(["notice"]) # Apache v2
load("//bazel:grpc_build_system.bzl", "grpc_proto_library", "grpc_cc_binary", "grpc_package")
grpc_package(name = "test/core/tsi/alts/fake_handshaker", visibility = "public")
grpc_proto_library(
name = "transport_security_common_proto",
srcs = ["transport_security_common.proto"],
has_services = False,
)
grpc_proto_library(
name = "handshaker_proto",
srcs = ["handshaker.proto"],
has_services = True,
deps = [
":transport_security_common_proto",
],
)
grpc_cc_binary(
name = "fake_handshaker_server",
testonly = True,
srcs = ["fake_handshaker_server.cc"],
language = "C++",
deps = [
":handshaker_proto",
":transport_security_common_proto",
"//:grpc++",
"//test/cpp/util:test_config",
],
)

@ -1,268 +0,0 @@
/*
*
* Copyright 2018 gRPC 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 <memory>
#include <sstream>
#include <string>
#include <gflags/gflags.h>
#include <grpc/grpc.h>
#include <grpc/support/log.h>
#include <grpcpp/impl/codegen/async_stream.h>
#include <grpcpp/security/server_credentials.h>
#include <grpcpp/server.h>
#include <grpcpp/server_builder.h>
#include <grpcpp/server_context.h>
#include "test/core/tsi/alts/fake_handshaker/handshaker.grpc.pb.h"
#include "test/core/tsi/alts/fake_handshaker/handshaker.pb.h"
#include "test/core/tsi/alts/fake_handshaker/transport_security_common.pb.h"
#include "test/cpp/util/test_config.h"
DEFINE_int32(handshaker_port, 55056,
"TCP port on which the fake handshaker server listens to.");
// Fake handshake messages.
constexpr char kClientInitFrame[] = "ClientInit";
constexpr char kServerFrame[] = "ServerInitAndFinished";
constexpr char kClientFinishFrame[] = "ClientFinished";
// Error messages.
constexpr char kInvalidFrameError[] = "Invalid input frame.";
constexpr char kWrongStateError[] = "Wrong handshake state.";
namespace grpc {
namespace gcp {
// FakeHandshakeService implements a fake handshaker service using a fake key
// exchange protocol. The fake key exchange protocol is a 3-message protocol:
// - Client first sends ClientInit message to Server.
// - Server then sends ServerInitAndFinished message back to Client.
// - Client finally sends ClientFinished message to Server.
// This fake handshaker service is intended for ALTS integration testing without
// relying on real ALTS handshaker service inside GCE.
// It is thread-safe.
class FakeHandshakerService : public HandshakerService::Service {
public:
Status DoHandshake(
ServerContext* server_context,
ServerReaderWriter<HandshakerResp, HandshakerReq>* stream) override {
Status status;
HandshakerContext context;
HandshakerReq request;
HandshakerResp response;
gpr_log(GPR_DEBUG, "Start a new handshake.");
while (stream->Read(&request)) {
status = ProcessRequest(&context, request, &response);
if (!status.ok()) return WriteErrorResponse(stream, status);
stream->Write(response);
if (context.state == COMPLETED) return Status::OK;
request.Clear();
}
return Status::OK;
}
private:
// HandshakeState is used by fake handshaker server to keep track of client's
// handshake status. In the beginning of a handshake, the state is INITIAL.
// If start_client or start_server request is called, the state becomes at
// least STARTED. When the handshaker server produces the first fame, the
// state becomes SENT. After the handshaker server processes the final frame
// from the peer, the state becomes COMPLETED.
enum HandshakeState { INITIAL, STARTED, SENT, COMPLETED };
struct HandshakerContext {
bool is_client = true;
HandshakeState state = INITIAL;
};
Status ProcessRequest(HandshakerContext* context,
const HandshakerReq& request,
HandshakerResp* response) {
GPR_ASSERT(context != nullptr && response != nullptr);
response->Clear();
if (request.has_client_start()) {
gpr_log(GPR_DEBUG, "Process client start request.");
return ProcessClientStart(context, request.client_start(), response);
} else if (request.has_server_start()) {
gpr_log(GPR_DEBUG, "Process server start request.");
return ProcessServerStart(context, request.server_start(), response);
} else if (request.has_next()) {
gpr_log(GPR_DEBUG, "Process next request.");
return ProcessNext(context, request.next(), response);
}
return Status(StatusCode::INVALID_ARGUMENT, "Request is empty.");
}
Status ProcessClientStart(HandshakerContext* context,
const StartClientHandshakeReq& request,
HandshakerResp* response) {
GPR_ASSERT(context != nullptr && response != nullptr);
// Checks request.
if (context->state != INITIAL) {
return Status(StatusCode::FAILED_PRECONDITION, kWrongStateError);
}
if (request.application_protocols_size() == 0) {
return Status(StatusCode::INVALID_ARGUMENT,
"At least one application protocol needed.");
}
if (request.record_protocols_size() == 0) {
return Status(StatusCode::INVALID_ARGUMENT,
"At least one record protocol needed.");
}
// Sets response.
response->set_out_frames(kClientInitFrame);
response->set_bytes_consumed(0);
response->mutable_status()->set_code(StatusCode::OK);
// Updates handshaker context.
context->is_client = true;
context->state = SENT;
return Status::OK;
}
Status ProcessServerStart(HandshakerContext* context,
const StartServerHandshakeReq& request,
HandshakerResp* response) {
GPR_ASSERT(context != nullptr && response != nullptr);
// Checks request.
if (context->state != INITIAL) {
return Status(StatusCode::FAILED_PRECONDITION, kWrongStateError);
}
if (request.application_protocols_size() == 0) {
return Status(StatusCode::INVALID_ARGUMENT,
"At least one application protocol needed.");
}
if (request.handshake_parameters().size() == 0) {
return Status(StatusCode::INVALID_ARGUMENT,
"At least one set of handshake parameters needed.");
}
// Sets response.
if (request.in_bytes().empty()) {
// start_server request does not have in_bytes.
response->set_bytes_consumed(0);
context->state = STARTED;
} else {
// start_server request has in_bytes.
if (request.in_bytes() == kClientInitFrame) {
response->set_out_frames(kServerFrame);
response->set_bytes_consumed(strlen(kClientInitFrame));
context->state = SENT;
} else {
return Status(StatusCode::UNKNOWN, kInvalidFrameError);
}
}
response->mutable_status()->set_code(StatusCode::OK);
context->is_client = false;
return Status::OK;
}
Status ProcessNext(HandshakerContext* context,
const NextHandshakeMessageReq& request,
HandshakerResp* response) {
GPR_ASSERT(context != nullptr && response != nullptr);
if (context->is_client) {
// Processes next request on client side.
if (context->state != SENT) {
return Status(StatusCode::FAILED_PRECONDITION, kWrongStateError);
}
if (request.in_bytes() != kServerFrame) {
return Status(StatusCode::UNKNOWN, kInvalidFrameError);
}
response->set_out_frames(kClientFinishFrame);
response->set_bytes_consumed(strlen(kServerFrame));
context->state = COMPLETED;
} else {
// Processes next request on server side.
HandshakeState current_state = context->state;
if (current_state == STARTED) {
if (request.in_bytes() != kClientInitFrame) {
return Status(StatusCode::UNKNOWN, kInvalidFrameError);
}
response->set_out_frames(kServerFrame);
response->set_bytes_consumed(strlen(kClientInitFrame));
context->state = SENT;
} else if (current_state == SENT) {
// Client finish frame may be sent along with the first payload from the
// client, handshaker only consumes the client finish frame.
if (request.in_bytes().substr(0, strlen(kClientFinishFrame)) !=
kClientFinishFrame) {
return Status(StatusCode::UNKNOWN, kInvalidFrameError);
}
response->set_bytes_consumed(strlen(kClientFinishFrame));
context->state = COMPLETED;
} else {
return Status(StatusCode::FAILED_PRECONDITION, kWrongStateError);
}
}
// At this point, processing next request succeeded.
response->mutable_status()->set_code(StatusCode::OK);
if (context->state == COMPLETED) {
*response->mutable_result() = GetHandshakerResult();
}
return Status::OK;
}
Status WriteErrorResponse(
ServerReaderWriter<HandshakerResp, HandshakerReq>* stream,
const Status& status) {
GPR_ASSERT(!status.ok());
HandshakerResp response;
response.mutable_status()->set_code(status.error_code());
response.mutable_status()->set_details(status.error_message());
stream->Write(response);
return status;
}
HandshakerResult GetHandshakerResult() {
HandshakerResult result;
result.set_application_protocol("grpc");
result.set_record_protocol("ALTSRP_GCM_AES128_REKEY");
result.mutable_peer_identity()->set_service_account("peer_identity");
result.mutable_local_identity()->set_service_account("local_identity");
string key(1024, '\0');
result.set_key_data(key);
result.mutable_peer_rpc_versions()->mutable_max_rpc_version()->set_major(2);
result.mutable_peer_rpc_versions()->mutable_max_rpc_version()->set_minor(1);
result.mutable_peer_rpc_versions()->mutable_min_rpc_version()->set_major(2);
result.mutable_peer_rpc_versions()->mutable_min_rpc_version()->set_minor(1);
return result;
}
};
} // namespace gcp
} // namespace grpc
void RunServer() {
GPR_ASSERT(FLAGS_handshaker_port != 0);
std::ostringstream server_address;
server_address << "[::1]:" << FLAGS_handshaker_port;
grpc::gcp::FakeHandshakerService service;
grpc::ServerBuilder builder;
builder.AddListeningPort(server_address.str(),
grpc::InsecureServerCredentials());
builder.RegisterService(&service);
std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
gpr_log(GPR_INFO, "Fake handshaker server listening on %s",
server_address.str().c_str());
server->Wait();
}
int main(int argc, char** argv) {
grpc::testing::InitTest(&argc, &argv, true);
RunServer();
return 0;
}

@ -1,224 +0,0 @@
// Copyright 2018 gRPC 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.
syntax = "proto3";
import "test/core/tsi/alts/fake_handshaker/transport_security_common.proto";
package grpc.gcp;
option java_package = "io.grpc.alts.internal";
enum HandshakeProtocol {
// Default value.
HANDSHAKE_PROTOCOL_UNSPECIFIED = 0;
// TLS handshake protocol.
TLS = 1;
// Application Layer Transport Security handshake protocol.
ALTS = 2;
}
enum NetworkProtocol {
NETWORK_PROTOCOL_UNSPECIFIED = 0;
TCP = 1;
UDP = 2;
}
message Endpoint {
// IP address. It should contain an IPv4 or IPv6 string literal, e.g.
// "192.168.0.1" or "2001:db8::1".
string ip_address = 1;
// Port number.
int32 port = 2;
// Network protocol (e.g., TCP, UDP) associated with this endpoint.
NetworkProtocol protocol = 3;
}
message Identity {
oneof identity_oneof {
// Service account of a connection endpoint.
string service_account = 1;
// Hostname of a connection endpoint.
string hostname = 2;
}
}
message StartClientHandshakeReq {
// Handshake security protocol requested by the client.
HandshakeProtocol handshake_security_protocol = 1;
// The application protocols supported by the client, e.g., "h2" (for http2),
// "grpc".
repeated string application_protocols = 2;
// The record protocols supported by the client, e.g.,
// "ALTSRP_GCM_AES128".
repeated string record_protocols = 3;
// (Optional) Describes which server identities are acceptable by the client.
// If target identities are provided and none of them matches the peer
// identity of the server, handshake will fail.
repeated Identity target_identities = 4;
// (Optional) Application may specify a local identity. Otherwise, the
// handshaker chooses a default local identity.
Identity local_identity = 5;
// (Optional) Local endpoint information of the connection to the server,
// such as local IP address, port number, and network protocol.
Endpoint local_endpoint = 6;
// (Optional) Endpoint information of the remote server, such as IP address,
// port number, and network protocol.
Endpoint remote_endpoint = 7;
// (Optional) If target name is provided, a secure naming check is performed
// to verify that the peer authenticated identity is indeed authorized to run
// the target name.
string target_name = 8;
// (Optional) RPC protocol versions supported by the client.
RpcProtocolVersions rpc_versions = 9;
}
message ServerHandshakeParameters {
// The record protocols supported by the server, e.g.,
// "ALTSRP_GCM_AES128".
repeated string record_protocols = 1;
// (Optional) A list of local identities supported by the server, if
// specified. Otherwise, the handshaker chooses a default local identity.
repeated Identity local_identities = 2;
}
message StartServerHandshakeReq {
// The application protocols supported by the server, e.g., "h2" (for http2),
// "grpc".
repeated string application_protocols = 1;
// Handshake parameters (record protocols and local identities supported by
// the server) mapped by the handshake protocol. Each handshake security
// protocol (e.g., TLS or ALTS) has its own set of record protocols and local
// identities. Since protobuf does not support enum as key to the map, the key
// to handshake_parameters is the integer value of HandshakeProtocol enum.
map<int32, ServerHandshakeParameters> handshake_parameters = 2;
// Bytes in out_frames returned from the peer's HandshakerResp. It is possible
// that the peer's out_frames are split into multiple HandshakReq messages.
bytes in_bytes = 3;
// (Optional) Local endpoint information of the connection to the client,
// such as local IP address, port number, and network protocol.
Endpoint local_endpoint = 4;
// (Optional) Endpoint information of the remote client, such as IP address,
// port number, and network protocol.
Endpoint remote_endpoint = 5;
// (Optional) RPC protocol versions supported by the server.
RpcProtocolVersions rpc_versions = 6;
}
message NextHandshakeMessageReq {
// Bytes in out_frames returned from the peer's HandshakerResp. It is possible
// that the peer's out_frames are split into multiple NextHandshakerMessageReq
// messages.
bytes in_bytes = 1;
}
message HandshakerReq {
oneof req_oneof {
// The start client handshake request message.
StartClientHandshakeReq client_start = 1;
// The start server handshake request message.
StartServerHandshakeReq server_start = 2;
// The next handshake request message.
NextHandshakeMessageReq next = 3;
}
}
message HandshakerResult {
// The application protocol negotiated for this connection.
string application_protocol = 1;
// The record protocol negotiated for this connection.
string record_protocol = 2;
// Cryptographic key data. The key data may be more than the key length
// required for the record protocol, thus the client of the handshaker
// service needs to truncate the key data into the right key length.
bytes key_data = 3;
// The authenticated identity of the peer.
Identity peer_identity = 4;
// The local identity used in the handshake.
Identity local_identity = 5;
// Indicate whether the handshaker service client should keep the channel
// between the handshaker service open, e.g., in order to handle
// post-handshake messages in the future.
bool keep_channel_open = 6;
// The RPC protocol versions supported by the peer.
RpcProtocolVersions peer_rpc_versions = 7;
}
message HandshakerStatus {
// The status code. This could be the gRPC status code.
uint32 code = 1;
// The status details.
string details = 2;
}
message HandshakerResp {
// Frames to be given to the peer for the NextHandshakeMessageReq. May be
// empty if no out_frames have to be sent to the peer or if in_bytes in the
// HandshakerReq are incomplete. All the non-empty out frames must be sent to
// the peer even if the handshaker status is not OK as these frames may
// contain the alert frames.
bytes out_frames = 1;
// Number of bytes in the in_bytes consumed by the handshaker. It is possible
// that part of in_bytes in HandshakerReq was unrelated to the handshake
// process.
uint32 bytes_consumed = 2;
// This is set iff the handshake was successful. out_frames may still be set
// to frames that needs to be forwarded to the peer.
HandshakerResult result = 3;
// Status of the handshaker.
HandshakerStatus status = 4;
}
service HandshakerService {
// Handshaker service accepts a stream of handshaker request, returning a
// stream of handshaker response. Client is expected to send exactly one
// message with either client_start or server_start followed by one or more
// messages with next. Each time client sends a request, the handshaker
// service expects to respond. Client does not have to wait for service's
// response before sending next request.
rpc DoHandshake(stream HandshakerReq)
returns (stream HandshakerResp) {
}
}

@ -1,40 +0,0 @@
// Copyright 2018 gRPC 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.
syntax = "proto3";
package grpc.gcp;
option java_package = "io.grpc.alts.internal";
// The security level of the created channel. The list is sorted in increasing
// level of security. This order must always be maintained.
enum SecurityLevel {
SECURITY_NONE = 0;
INTEGRITY_ONLY = 1;
INTEGRITY_AND_PRIVACY = 2;
}
// Max and min supported RPC protocol versions.
message RpcProtocolVersions {
// RPC version contains a major version and a minor version.
message Version {
uint32 major = 1;
uint32 minor = 2;
}
// Maximum supported RPC version.
Version max_rpc_version = 1;
// Minimum supported RPC version.
Version min_rpc_version = 2;
}
Loading…
Cancel
Save