diff --git a/src/envoy/BUILD b/src/envoy/BUILD index 43abb6b554f..c6eeb279f2e 100644 --- a/src/envoy/BUILD +++ b/src/envoy/BUILD @@ -29,7 +29,6 @@ envoy_cc_binary( "//src/envoy/http/jwt_auth:http_filter_factory", "//src/envoy/http/mixer:filter_lib", "//src/envoy/tcp/mixer:filter_lib", - "//src/envoy/alts:alts_socket_factory", "@envoy//source/exe:envoy_main_entry_lib", ], ) diff --git a/src/envoy/alts/BUILD b/src/envoy/alts/BUILD deleted file mode 100644 index 0076e57d8e6..00000000000 --- a/src/envoy/alts/BUILD +++ /dev/null @@ -1,111 +0,0 @@ -# Copyright 2018 Istio Authors. All Rights Reserved. -# -# 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. -# -################################################################################ -# -load( - "@envoy//bazel:envoy_build_system.bzl", - "envoy_cc_library", -) - -load( - "@envoy_api//bazel:api_build_system.bzl", - "api_proto_library", -) - -api_proto_library( - name = "alts_socket_proto", - srcs = [":alts_socket.proto"], - visibility = ["//visibility:public"], - require_py = 0, -) - -envoy_cc_library( - name = "grpc_tsi_wrapper", - repository = "@envoy", - visibility = ["//visibility:private"], - hdrs = [ - "transport_security_interface_wrapper.h", - ], - external_deps = [ - "grpc", - ], -) - -envoy_cc_library( - name = "tsi_handshaker", - repository = "@envoy", - visibility = ["//visibility:public"], - srcs = [ - "tsi_handshaker.cc", - ], - hdrs = [ - "tsi_handshaker.h", - ], - deps = [ - ":grpc_tsi_wrapper", - "@envoy//source/exe:envoy_common_lib", - ], -) - -envoy_cc_library( - name = "tsi_frame_protector", - repository = "@envoy", - visibility = ["//visibility:public"], - srcs = [ - "tsi_frame_protector.cc", - ], - hdrs = [ - "tsi_frame_protector.h", - ], - deps = [ - ":grpc_tsi_wrapper", - "@envoy//source/exe:envoy_common_lib", - ], -) - -envoy_cc_library( - name = "tsi_transport_socket", - repository = "@envoy", - visibility = ["//visibility:public"], - srcs = [ - "tsi_transport_socket.cc", - ], - hdrs = [ - "tsi_transport_socket.h", - ], - deps = [ - ":tsi_frame_protector", - ":tsi_handshaker", - "@envoy//source/exe:envoy_common_lib", - ], -) - -envoy_cc_library( - name = "alts_socket_factory", - repository = "@envoy", - visibility = ["//visibility:public"], - srcs = [ - "alts_socket_factory.cc", - ], - hdrs = [ - "alts_socket_factory.h", - ], - deps = [ - ":grpc_tsi_wrapper", - ":tsi_transport_socket", - ":alts_socket_proto_cc", - "@envoy//source/exe:envoy_common_lib", - ], -) diff --git a/src/envoy/alts/README.md b/src/envoy/alts/README.md deleted file mode 100644 index 5eeaa79bb60..00000000000 --- a/src/envoy/alts/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# ALTS support (experimental) - -*The code in this directory is experimental. Do not use in production* - -A prototype of -[ALTS](https://cloud.google.com/security/encryption-in-transit/application-layer-transport-security/) -support for Istio/Envoy. It depends on ALTS stack in gRPC library and implemented as Envoy's -[transport socket](https://www.envoyproxy.io/docs/envoy/latest/api-v2/api/v2/core/base.proto#core-transportsocket). - -An example config is in `example.yaml`. Note: If you want to enable the peer validation, please -uncomment and replace the content of `peer_service_accounts` with the actual service account in your -environment. Please make sure the service account is correct otherwise the ALTS connection will be -closed due to validation failure. diff --git a/src/envoy/alts/alts_socket.proto b/src/envoy/alts/alts_socket.proto deleted file mode 100644 index 7f7bf7a6c5e..00000000000 --- a/src/envoy/alts/alts_socket.proto +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2018 Istio 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 envoy.security.v2; - -import "google/protobuf/duration.proto"; -import "validate/validate.proto"; - -message AltsSocket { - // The location of a handshaker service, this is usually 169.254.169.254:8080 - // on GCE - string handshaker_service = 1 [(validate.rules).string.min_bytes = 1]; - - // The acceptable service accounts from peer, peers not in the list will be - // rejected in the handshake validation step. - // If empty, no validation will be performed. - repeated string peer_service_accounts = 2; -} diff --git a/src/envoy/alts/alts_socket_factory.cc b/src/envoy/alts/alts_socket_factory.cc deleted file mode 100644 index a4e24ab43d8..00000000000 --- a/src/envoy/alts/alts_socket_factory.cc +++ /dev/null @@ -1,158 +0,0 @@ -/* Copyright 2018 Istio Authors. All Rights Reserved. - * - * 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 "src/envoy/alts/alts_socket_factory.h" -#include "absl/strings/str_join.h" -#include "common/common/assert.h" -#include "common/protobuf/protobuf.h" -#include "common/protobuf/utility.h" -#include "envoy/registry/registry.h" -#include "envoy/server/transport_socket_config.h" -#include "src/envoy/alts/alts_socket.pb.h" -#include "src/envoy/alts/alts_socket.pb.validate.h" -#include "src/envoy/alts/transport_security_interface_wrapper.h" -#include "src/envoy/alts/tsi_handshaker.h" -#include "src/envoy/alts/tsi_transport_socket.h" - -namespace Envoy { -namespace Server { -namespace Configuration { - -using ::google::protobuf::RepeatedPtrField; - -// Returns true if the peer's service account is found in peers, otherwise -// returns false and fills out err with an error message. -static bool doValidate(const tsi_peer &peer, - const std::unordered_set &peers, - std::string &err) { - for (size_t i = 0; i < peer.property_count; ++i) { - std::string name = std::string(peer.properties[i].name); - std::string value = std::string(peer.properties[i].value.data, - peer.properties[i].value.length); - if (name.compare(TSI_ALTS_SERVICE_ACCOUNT_PEER_PROPERTY) == 0 && - peers.find(value) != peers.end()) { - return true; - } - } - - err = "Couldn't find peer's service account in peer_service_accounts: " + - absl::StrJoin(peers, ","); - return false; -} - -ProtobufTypes::MessagePtr -AltsTransportSocketConfigFactory::createEmptyConfigProto() { - return std::make_unique(); -} - -std::string -Envoy::Server::Configuration::AltsTransportSocketConfigFactory::name() const { - return "alts"; -} - -Network::TransportSocketFactoryPtr -UpstreamAltsTransportSocketConfigFactory::createTransportSocketFactory( - const Protobuf::Message &message, TransportSocketFactoryContext &) { - auto config = - MessageUtil::downcastAndValidate( - message); - - std::string handshaker_service = config.handshaker_service(); - const auto &peer_service_accounts = config.peer_service_accounts(); - std::unordered_set peers(peer_service_accounts.cbegin(), - peer_service_accounts.cend()); - - Security::HandshakeValidator validator; - // Skip validation if peers is empty. - if (!peers.empty()) { - validator = [peers](const tsi_peer &peer, std::string &err) { - return doValidate(peer, peers, err); - }; - } - - return std::make_unique( - [handshaker_service](Event::Dispatcher &dispatcher) { - grpc_alts_credentials_options *options = - grpc_alts_credentials_client_options_create(); - - tsi_handshaker *handshaker = nullptr; - - // Specifying target name as empty since TSI won't take care of - // validating peer identity in this use case. The validation will be - // implemented in TsiSocket later. - alts_tsi_handshaker_create(options, "", handshaker_service.c_str(), - true /* is_client */, &handshaker); - - ASSERT(handshaker != nullptr); - - grpc_alts_credentials_options_destroy(options); - - return std::make_unique(handshaker, - dispatcher); - }, - validator); -} - -Network::TransportSocketFactoryPtr -DownstreamAltsTransportSocketConfigFactory::createTransportSocketFactory( - const Protobuf::Message &message, TransportSocketFactoryContext &, - const std::vector &) { - auto config = - MessageUtil::downcastAndValidate( - message); - - std::string handshaker_service = config.handshaker_service(); - const auto &peer_service_accounts = config.peer_service_accounts(); - std::unordered_set peers(peer_service_accounts.cbegin(), - peer_service_accounts.cend()); - - Security::HandshakeValidator validator; - // Skip validation if peers is empty. - if (!peers.empty()) { - validator = [peers](const tsi_peer &peer, std::string &err) { - return doValidate(peer, peers, err); - }; - } - - return std::make_unique( - [handshaker_service](Event::Dispatcher &dispatcher) { - grpc_alts_credentials_options *options = - grpc_alts_credentials_server_options_create(); - - tsi_handshaker *handshaker = nullptr; - - alts_tsi_handshaker_create(options, nullptr, handshaker_service.c_str(), - false /* is_client */, &handshaker); - - ASSERT(handshaker != nullptr); - - grpc_alts_credentials_options_destroy(options); - - return std::make_unique(handshaker, - dispatcher); - }, - validator); -} - -static Registry::RegisterFactory - upstream_registered_; - -static Registry::RegisterFactory - downstream_registered_; -} // namespace Configuration -} // namespace Server -} // namespace Envoy diff --git a/src/envoy/alts/alts_socket_factory.h b/src/envoy/alts/alts_socket_factory.h deleted file mode 100644 index 797f5d87787..00000000000 --- a/src/envoy/alts/alts_socket_factory.h +++ /dev/null @@ -1,47 +0,0 @@ -/* Copyright 2018 Istio Authors. All Rights Reserved. - * - * 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 "envoy/server/transport_socket_config.h" - -namespace Envoy { -namespace Server { -namespace Configuration { - -// ALTS config registry -class AltsTransportSocketConfigFactory - : public virtual TransportSocketConfigFactory { - public: - ProtobufTypes::MessagePtr createEmptyConfigProto() override; - std::string name() const override; -}; - -class UpstreamAltsTransportSocketConfigFactory - : public AltsTransportSocketConfigFactory, - public UpstreamTransportSocketConfigFactory { - public: - Network::TransportSocketFactoryPtr createTransportSocketFactory( - const Protobuf::Message &, TransportSocketFactoryContext &) override; -}; - -class DownstreamAltsTransportSocketConfigFactory - : public AltsTransportSocketConfigFactory, - public DownstreamTransportSocketConfigFactory { - public: - Network::TransportSocketFactoryPtr createTransportSocketFactory( - const Protobuf::Message &, TransportSocketFactoryContext &, - const std::vector &) override; -}; -} // namespace Configuration -} // namespace Server -} // namespace Envoy diff --git a/src/envoy/alts/example.yaml b/src/envoy/alts/example.yaml deleted file mode 100644 index d157684969b..00000000000 --- a/src/envoy/alts/example.yaml +++ /dev/null @@ -1,59 +0,0 @@ -static_resources: - listeners: - - address: - socket_address: - address: 127.0.0.1 - port_value: 5000 - filter_chains: - - filters: - - name: envoy.tcp_proxy - config: - stat_prefix: client_tcp - cluster: server_envoy - - address: - socket_address: - address: 127.0.0.1 - port_value: 5005 - filter_chains: - - transport_socket: - name: alts - config: - handshaker_service: "169.254.169.254:8080" - # If you want to enable the peer validation, please uncomment peer_service_accounts and - # replace it with the actual service account used in your environment. - # peer_service_accounts: ["test-service-account"] - filters: - - name: envoy.tcp_proxy - config: - stat_prefix: server_tcp - cluster: tcp_backend - clusters: - - name: server_envoy - transport_socket: - name: alts - config: - handshaker_service: "169.254.169.254:8080" - # If you want to enable the peer validation, please uncomment peer_service_accounts and - # replace it with the actual service account used in your environment. - # peer_service_accounts: ["test-service-account"] - connect_timeout: 0.25s - type: strict_dns - lb_policy: round_robin - hosts: - - socket_address: - address: 127.0.0.1 - port_value: 5005 - - name: tcp_backend - connect_timeout: 0.25s - type: strict_dns - lb_policy: round_robin - hosts: - - socket_address: - address: 127.0.0.1 - port_value: 5050 -admin: - access_log_path: "/dev/null" - address: - socket_address: - address: 0.0.0.0 - port_value: 8001 diff --git a/src/envoy/alts/transport_security_interface_wrapper.h b/src/envoy/alts/transport_security_interface_wrapper.h deleted file mode 100644 index 9e6c60e60b2..00000000000 --- a/src/envoy/alts/transport_security_interface_wrapper.h +++ /dev/null @@ -1,26 +0,0 @@ -/* Copyright 2018 Istio Authors. All Rights Reserved. - * - * 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. - */ - -// Some gRPC headers contains old style cast and unused parameter which doesn't -// compile with -Werror, ignoring those compiler warning since we don't have -// control on those source codes. This works with GCC and Clang. - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#pragma GCC diagnostic ignored "-Wold-style-cast" -#include "grpc/grpc_security.h" -#include "src/core/tsi/alts/handshaker/alts_tsi_handshaker.h" -#include "src/core/tsi/transport_security_interface.h" -#pragma GCC diagnostic pop diff --git a/src/envoy/alts/tsi_frame_protector.cc b/src/envoy/alts/tsi_frame_protector.cc deleted file mode 100644 index a4454e5e614..00000000000 --- a/src/envoy/alts/tsi_frame_protector.cc +++ /dev/null @@ -1,94 +0,0 @@ -/* Copyright 2018 Istio Authors. All Rights Reserved. - * - * 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 "src/envoy/alts/tsi_frame_protector.h" - -#include "common/common/assert.h" - -namespace Envoy { -namespace Security { - -TsiFrameProtector::TsiFrameProtector(tsi_frame_protector *frame_protector) - : frame_protector_(frame_protector) {} - -tsi_result TsiFrameProtector::protect(Buffer::Instance &input, - Buffer::Instance &output) { - ASSERT(frame_protector_); - - // TODO(lizan): tune size later - unsigned char protected_buffer[4096]; - size_t protected_buffer_size = sizeof(protected_buffer); - while (input.length() > 0) { - auto *message_bytes = - reinterpret_cast(input.linearize(input.length())); - size_t protected_buffer_size_to_send = protected_buffer_size; - size_t processed_message_size = input.length(); - tsi_result result = tsi_frame_protector_protect( - frame_protector_.get(), message_bytes, &processed_message_size, - protected_buffer, &protected_buffer_size_to_send); - if (result != TSI_OK) { - ASSERT(result != TSI_INVALID_ARGUMENT && result != TSI_UNIMPLEMENTED); - return result; - } - output.add(protected_buffer, protected_buffer_size_to_send); - input.drain(processed_message_size); - } - - ASSERT(input.length() == 0); - size_t still_pending_size; - do { - size_t protected_buffer_size_to_send = protected_buffer_size; - tsi_result result = tsi_frame_protector_protect_flush( - frame_protector_.get(), protected_buffer, - &protected_buffer_size_to_send, &still_pending_size); - if (result != TSI_OK) { - ASSERT(result != TSI_INVALID_ARGUMENT && result != TSI_UNIMPLEMENTED); - return result; - } - output.add(protected_buffer, protected_buffer_size_to_send); - } while (still_pending_size > 0); - - return TSI_OK; -} - -tsi_result TsiFrameProtector::unprotect(Buffer::Instance &input, - Buffer::Instance &output) { - ASSERT(frame_protector_); - - // TODO(lizan): Tune the buffer size. - unsigned char unprotected_buffer[4096]; - size_t unprotected_buffer_size = sizeof(unprotected_buffer); - - while (input.length() > 0) { - auto *message_bytes = - reinterpret_cast(input.linearize(input.length())); - size_t unprotected_buffer_size_to_send = unprotected_buffer_size; - size_t processed_message_size = input.length(); - tsi_result result = tsi_frame_protector_unprotect( - frame_protector_.get(), message_bytes, &processed_message_size, - unprotected_buffer, &unprotected_buffer_size_to_send); - if (result != TSI_OK) { - ASSERT(result != TSI_INVALID_ARGUMENT && result != TSI_UNIMPLEMENTED); - return result; - } - output.add(unprotected_buffer, unprotected_buffer_size_to_send); - input.drain(processed_message_size); - } - - return TSI_OK; -} - -} // namespace Security -} // namespace Envoy diff --git a/src/envoy/alts/tsi_frame_protector.h b/src/envoy/alts/tsi_frame_protector.h deleted file mode 100644 index ccd36a6a9e5..00000000000 --- a/src/envoy/alts/tsi_frame_protector.h +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright 2018 Istio Authors. All Rights Reserved. - * - * 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. - */ -#pragma once - -#include "common/common/c_smart_ptr.h" -#include "envoy/buffer/buffer.h" -#include "envoy/event/dispatcher.h" - -#include "src/envoy/alts/transport_security_interface_wrapper.h" - -namespace Envoy { -namespace Security { - -typedef CSmartPtr - CFrameProtectorPtr; - -/** - * A C++ wrapper for tsi_frame_protector interface. - * For detail of tsi_frame_protector, see - * https://github.com/grpc/grpc/blob/v1.10.0/src/core/tsi/transport_security_interface.h#L70 - * - * TODO(lizan): migrate to tsi_zero_copy_grpc_protector for further optimization - */ -class TsiFrameProtector final { - public: - explicit TsiFrameProtector(tsi_frame_protector* frame_protector); - - /** - * Wrapper for tsi_frame_protector_protect - * @param input supplies the input buffer, the method will drain it when it is - * protected. - * @param output supplies the output buffer - * @return tsi_result the status. - */ - tsi_result protect(Buffer::Instance& input, Buffer::Instance& output); - - /** - * Wrapper for tsi_frame_protector_unprotect - * @param input supplies the input buffer, the method will drain it when it is - * protected. - * @param output supplies the output buffer - * @return tsi_result the status. - */ - tsi_result unprotect(Buffer::Instance& input, Buffer::Instance& output); - - private: - CFrameProtectorPtr frame_protector_; -}; - -typedef std::unique_ptr TsiFrameProtectorPtr; - -} // namespace Security -} // namespace Envoy diff --git a/src/envoy/alts/tsi_handshaker.cc b/src/envoy/alts/tsi_handshaker.cc deleted file mode 100644 index d5139470c39..00000000000 --- a/src/envoy/alts/tsi_handshaker.cc +++ /dev/null @@ -1,86 +0,0 @@ -/* Copyright 2018 Istio Authors. All Rights Reserved. - * - * 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 "src/envoy/alts/tsi_handshaker.h" -#include "common/buffer/buffer_impl.h" -#include "common/common/assert.h" - -namespace Envoy { -namespace Security { - -void TsiHandshaker::onNextDone(tsi_result status, void *user_data, - const unsigned char *bytes_to_send, - size_t bytes_to_send_size, - tsi_handshaker_result *handshaker_result) { - TsiHandshaker *handshaker = static_cast(user_data); - - Buffer::InstancePtr to_send = std::make_unique(); - if (bytes_to_send_size > 0) { - to_send->add(bytes_to_send, bytes_to_send_size); - } - - auto next_result = new TsiHandshakerCallbacks::NextResult{ - status, std::move(to_send), {handshaker_result}}; - - handshaker->dispatcher_.post([handshaker, next_result]() { - ASSERT(handshaker->calling_); - handshaker->calling_ = false; - - TsiHandshakerCallbacks::NextResultPtr next_result_ptr{next_result}; - - if (handshaker->delete_on_done_) { - handshaker->dispatcher_.deferredDelete( - Event::DeferredDeletablePtr{handshaker}); - return; - } - handshaker->callbacks_->onNextDone(std::move(next_result_ptr)); - }); -} - -TsiHandshaker::TsiHandshaker(tsi_handshaker *handshaker, - Event::Dispatcher &dispatcher) - : handshaker_(handshaker), dispatcher_(dispatcher) {} - -TsiHandshaker::~TsiHandshaker() { ASSERT(!calling_); } - -tsi_result TsiHandshaker::next(Envoy::Buffer::Instance &received) { - ASSERT(!calling_); - calling_ = true; - - uint64_t received_size = received.length(); - const unsigned char *bytes_to_send = nullptr; - size_t bytes_to_send_size = 0; - tsi_handshaker_result *result = nullptr; - tsi_result status = - tsi_handshaker_next(handshaker_.get(), - reinterpret_cast( - received.linearize(received_size)), - received_size, &bytes_to_send, &bytes_to_send_size, - &result, onNextDone, this); - - if (status != TSI_ASYNC) { - onNextDone(status, this, bytes_to_send, bytes_to_send_size, result); - } - return status; -} - -void TsiHandshaker::deferredDelete() { - if (calling_) { - delete_on_done_ = true; - } else { - dispatcher_.deferredDelete(Event::DeferredDeletablePtr{this}); - } -} -} // namespace Security -} // namespace Envoy diff --git a/src/envoy/alts/tsi_handshaker.h b/src/envoy/alts/tsi_handshaker.h deleted file mode 100644 index 01e8310aba8..00000000000 --- a/src/envoy/alts/tsi_handshaker.h +++ /dev/null @@ -1,112 +0,0 @@ -/* Copyright 2018 Istio Authors. All Rights Reserved. - * - * 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. - */ -#pragma once - -#include -#include - -#include "common/common/c_smart_ptr.h" -#include "envoy/buffer/buffer.h" -#include "envoy/event/dispatcher.h" - -#include "src/envoy/alts/transport_security_interface_wrapper.h" - -namespace Envoy { -namespace Security { - -typedef CSmartPtr - TsiHandshakerResultPtr; -typedef CSmartPtr CHandshakerPtr; - -/** - * An interface to get callback from TsiHandshaker. - * TsiHandshaker will call this callback in the thread which its dispatcher - * posts. - */ -class TsiHandshakerCallbacks { - public: - virtual ~TsiHandshakerCallbacks() {} - - struct NextResult { - // A enum of the result - tsi_result status_; - - // The buffer to be sent to the peer - Buffer::InstancePtr to_send_; - - // A pointer to tsi_handshaker_result struct. Owned by instance. - TsiHandshakerResultPtr result_; - }; - - typedef std::unique_ptr NextResultPtr; - - /** - * Called when `next` is done, this may be called in line in `next` if the - * handshaker is not - * asynchronous. - * @param result - */ - virtual void onNextDone(NextResultPtr&& result) PURE; -}; - -/** - * A C++ wrapper for tsi_handshaker interface. - * For detail of tsi_handshaker, see - * https://github.com/grpc/grpc/blob/v1.10.0/src/core/tsi/transport_security_interface.h#L236 - */ -class TsiHandshaker final : public Event::DeferredDeletable { - public: - explicit TsiHandshaker(tsi_handshaker* handshaker, - Event::Dispatcher& dispatcher); - ~TsiHandshaker(); - - /** - * Conduct next step of handshake, see - * https://github.com/grpc/grpc/blob/v1.10.0/src/core/tsi/transport_security_interface.h#L416 - * @param received the buffer received from peer. - */ - tsi_result next(Buffer::Instance& received); - - /** - * Set handshaker callbacks, this must be called before calling next. - * @param callbacks supplies the callback instance. - */ - void setHandshakerCallbacks(TsiHandshakerCallbacks& callbacks) { - callbacks_ = &callbacks; - } - - /** - * Delete the handshaker when it is ready. This must be called after releasing - * from a smart - * pointer. The actual delete happens after ongoing next call are processed. - */ - void deferredDelete(); - - private: - static void onNextDone(tsi_result status, void* user_data, - const unsigned char* bytes_to_send, - size_t bytes_to_send_size, - tsi_handshaker_result* handshaker_result); - - CHandshakerPtr handshaker_; - TsiHandshakerCallbacks* callbacks_{nullptr}; - bool calling_{false}; - bool delete_on_done_{false}; - Event::Dispatcher& dispatcher_; -}; - -typedef std::unique_ptr TsiHandshakerPtr; -} // namespace Security -} // namespace Envoy diff --git a/src/envoy/alts/tsi_transport_socket.cc b/src/envoy/alts/tsi_transport_socket.cc deleted file mode 100644 index 9e61ce1efd9..00000000000 --- a/src/envoy/alts/tsi_transport_socket.cc +++ /dev/null @@ -1,228 +0,0 @@ -/* Copyright 2018 Istio Authors. All Rights Reserved. - * - * 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 "src/envoy/alts/tsi_transport_socket.h" - -#include "common/common/assert.h" -#include "common/common/enum_to_int.h" - -namespace Envoy { -namespace Security { - -TsiSocket::TsiSocket(HandshakerFactory handshaker_factory, - HandshakeValidator handshake_validator) - : handshaker_factory_(handshaker_factory), - handshake_validator_(handshake_validator), - raw_buffer_callbacks_(*this) { - raw_buffer_socket_.setTransportSocketCallbacks(raw_buffer_callbacks_); -} - -TsiSocket::~TsiSocket() { ASSERT(!handshaker_); } - -void TsiSocket::setTransportSocketCallbacks( - Envoy::Network::TransportSocketCallbacks &callbacks) { - callbacks_ = &callbacks; - - handshaker_ = handshaker_factory_(callbacks.connection().dispatcher()); - handshaker_->setHandshakerCallbacks(*this); -} - -std::string TsiSocket::protocol() const { return ""; } - -Network::PostIoAction TsiSocket::doHandshake() { - ASSERT(!handshake_complete_); - ENVOY_CONN_LOG(debug, "TSI: doHandshake", callbacks_->connection()); - - if (!handshaker_next_calling_) { - doHandshakeNext(); - } - return Network::PostIoAction::KeepOpen; -} - -void TsiSocket::doHandshakeNext() { - ENVOY_CONN_LOG(debug, "TSI: doHandshake next: received: {}", - callbacks_->connection(), raw_read_buffer_.length()); - handshaker_next_calling_ = true; - Buffer::OwnedImpl handshaker_buffer; - handshaker_buffer.move(raw_read_buffer_); - handshaker_->next(handshaker_buffer); -} - -Network::PostIoAction TsiSocket::doHandshakeNextDone( - NextResultPtr &&next_result) { - ASSERT(next_result); - - ENVOY_CONN_LOG(debug, "TSI: doHandshake next done: status: {} to_send: {}", - callbacks_->connection(), next_result->status_, - next_result->to_send_->length()); - - tsi_result status = next_result->status_; - tsi_handshaker_result *handshaker_result = next_result->result_.get(); - - if (status != TSI_INCOMPLETE_DATA && status != TSI_OK) { - ENVOY_CONN_LOG(debug, "TSI: Handshake failed: status: {}", - callbacks_->connection(), status); - return Network::PostIoAction::Close; - } - - if (next_result->to_send_->length() > 0) { - raw_write_buffer_.move(*next_result->to_send_); - } - - if (status == TSI_OK && handshaker_result != nullptr) { - tsi_peer peer; - tsi_handshaker_result_extract_peer(handshaker_result, &peer); - ENVOY_CONN_LOG(debug, "TSI: Handshake successful: peer properties: {}", - callbacks_->connection(), peer.property_count); - for (size_t i = 0; i < peer.property_count; ++i) { - ENVOY_CONN_LOG(debug, " {}: {}", callbacks_->connection(), - peer.properties[i].name, - std::string(peer.properties[i].value.data, - peer.properties[i].value.length)); - } - if (handshake_validator_) { - std::string err; - bool peer_validated = handshake_validator_(peer, err); - if (peer_validated) { - ENVOY_CONN_LOG(info, "TSI: Handshake validation succeeded.", - callbacks_->connection()); - } else { - ENVOY_CONN_LOG(warn, "TSI: Handshake validation failed: {}", - callbacks_->connection(), err); - tsi_peer_destruct(&peer); - return Network::PostIoAction::Close; - } - } else { - ENVOY_CONN_LOG(info, "TSI: Handshake validation skipped.", - callbacks_->connection()); - } - tsi_peer_destruct(&peer); - - const unsigned char *unused_bytes; - size_t unused_byte_size; - - status = tsi_handshaker_result_get_unused_bytes( - handshaker_result, &unused_bytes, &unused_byte_size); - ASSERT(status == TSI_OK); - if (unused_byte_size > 0) { - raw_read_buffer_.add(unused_bytes, unused_byte_size); - } - ENVOY_CONN_LOG(debug, "TSI: Handshake successful: unused_bytes: {}", - callbacks_->connection(), unused_byte_size); - - tsi_frame_protector *frame_protector; - status = tsi_handshaker_result_create_frame_protector( - handshaker_result, NULL, &frame_protector); - ASSERT(status == TSI_OK); - frame_protector_ = std::make_unique(frame_protector); - - handshake_complete_ = true; - callbacks_->raiseEvent(Network::ConnectionEvent::Connected); - } - - if (raw_read_buffer_.length() > 0) { - callbacks_->setReadBufferReady(); - } - return Network::PostIoAction::KeepOpen; -} - -Network::IoResult TsiSocket::doRead(Buffer::Instance &buffer) { - Network::IoResult result = raw_buffer_socket_.doRead(raw_read_buffer_); - ENVOY_CONN_LOG(debug, "TSI: raw read result action {} bytes {} end_stream {}", - callbacks_->connection(), enumToInt(result.action_), - result.bytes_processed_, result.end_stream_read_); - if (result.action_ == Network::PostIoAction::Close && - result.bytes_processed_ == 0) { - return result; - } - - if (!handshake_complete_) { - Network::PostIoAction action = doHandshake(); - if (action == Network::PostIoAction::Close || !handshake_complete_) { - return {action, 0, false}; - } - } - - if (handshake_complete_) { - ASSERT(frame_protector_); - - uint64_t read_size = raw_read_buffer_.length(); - ENVOY_CONN_LOG(debug, "TSI: unprotecting buffer size: {}", - callbacks_->connection(), raw_read_buffer_.length()); - tsi_result status = frame_protector_->unprotect(raw_read_buffer_, buffer); - ENVOY_CONN_LOG(debug, "TSI: unprotected buffer left: {} result: {}", - callbacks_->connection(), raw_read_buffer_.length(), - tsi_result_to_string(status)); - result.bytes_processed_ = read_size - raw_read_buffer_.length(); - } - - ENVOY_CONN_LOG(debug, "TSI: do read result action {} bytes {} end_stream {}", - callbacks_->connection(), enumToInt(result.action_), - result.bytes_processed_, result.end_stream_read_); - return result; -} - -Network::IoResult TsiSocket::doWrite(Buffer::Instance &buffer, - bool end_stream) { - if (!handshake_complete_) { - Network::PostIoAction action = doHandshake(); - if (action == Network::PostIoAction::Close) { - return {action, 0, false}; - } - } - - if (handshake_complete_) { - ASSERT(frame_protector_); - ENVOY_CONN_LOG(debug, "TSI: protecting buffer size: {}", - callbacks_->connection(), buffer.length()); - tsi_result status = frame_protector_->protect(buffer, raw_write_buffer_); - ENVOY_CONN_LOG(debug, "TSI: protected buffer left: {} result: {}", - callbacks_->connection(), buffer.length(), - tsi_result_to_string(status)); - } - - ENVOY_CONN_LOG(debug, "TSI: raw_write length {} end_stream {}", - callbacks_->connection(), raw_write_buffer_.length(), - end_stream); - return raw_buffer_socket_.doWrite(raw_write_buffer_, - end_stream && (buffer.length() == 0)); -} - -void TsiSocket::closeSocket(Network::ConnectionEvent) { - handshaker_.release()->deferredDelete(); -} - -void TsiSocket::onConnected() { ASSERT(!handshake_complete_); } - -void TsiSocket::onNextDone(NextResultPtr &&result) { - handshaker_next_calling_ = false; - - Network::PostIoAction action = doHandshakeNextDone(std::move(result)); - if (action == Network::PostIoAction::Close) { - callbacks_->connection().close(Network::ConnectionCloseType::NoFlush); - } -} - -TsiSocketFactory::TsiSocketFactory(HandshakerFactory handshaker_factory, - HandshakeValidator handshake_validator) - : handshaker_factory_(std::move(handshaker_factory)), - handshake_validator_(std::move(handshake_validator)) {} - -bool TsiSocketFactory::implementsSecureTransport() const { return true; } - -Network::TransportSocketPtr TsiSocketFactory::createTransportSocket() const { - return std::make_unique(handshaker_factory_, handshake_validator_); -} -} // namespace Security -} // namespace Envoy diff --git a/src/envoy/alts/tsi_transport_socket.h b/src/envoy/alts/tsi_transport_socket.h deleted file mode 100644 index 629cb6f9e5b..00000000000 --- a/src/envoy/alts/tsi_transport_socket.h +++ /dev/null @@ -1,127 +0,0 @@ -/* Copyright 2018 Istio Authors. All Rights Reserved. - * - * 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. - */ -#pragma once - -#include "common/buffer/buffer_impl.h" -#include "common/network/raw_buffer_socket.h" -#include "envoy/network/transport_socket.h" -#include "src/envoy/alts/tsi_frame_protector.h" -#include "src/envoy/alts/tsi_handshaker.h" - -namespace Envoy { -namespace Security { - -typedef std::function HandshakerFactory; - -/** - * A function to validate the peer of the connection. - * @param peer the detail peer information of the connection. - * @param err an error message to indicate why the peer is invalid. This is an - * output param that should be populated by the function implementation. - * @return true if the peer is valid or false if the peer is invalid. - */ -typedef std::function - HandshakeValidator; - -/** - * A implementation of Network::TransportSocket based on gRPC TSI - */ -class TsiSocket : public Network::TransportSocket, - public TsiHandshakerCallbacks, - public Logger::Loggable { - public: - /** - * @param handshaker_factory a function to initiate a TsiHandshaker - * @param handshake_validator a function to validate the peer. Called right - * after the handshake completed with peer data to do the peer validation. - * The connection will be closed immediately if it returns false. - */ - TsiSocket(HandshakerFactory handshaker_factory, - HandshakeValidator handshake_validator); - virtual ~TsiSocket(); - - // Network::TransportSocket - void setTransportSocketCallbacks( - Envoy::Network::TransportSocketCallbacks& callbacks) override; - std::string protocol() const override; - bool canFlushClose() override { return handshake_complete_; } - const Envoy::Ssl::Connection* ssl() const override { return nullptr; } - Network::IoResult doWrite(Buffer::Instance& buffer, bool end_stream) override; - void closeSocket(Network::ConnectionEvent event) override; - Network::IoResult doRead(Buffer::Instance& buffer) override; - void onConnected() override; - - // TsiHandshakerCallbacks - void onNextDone(NextResultPtr&& result) override; - - private: - /** - * Callbacks for underlying RawBufferSocket, it proxies fd() and connection() - * but not raising event or flow control since they have to be handled in - * TsiSocket. - */ - class RawBufferCallbacks : public Network::TransportSocketCallbacks { - public: - explicit RawBufferCallbacks(TsiSocket& parent) : parent_(parent) {} - - int fd() const override { return parent_.callbacks_->fd(); } - Network::Connection& connection() override { - return parent_.callbacks_->connection(); - } - bool shouldDrainReadBuffer() override { return false; } - void setReadBufferReady() override {} - void raiseEvent(Network::ConnectionEvent) override {} - - private: - TsiSocket& parent_; - }; - - Network::PostIoAction doHandshake(); - void doHandshakeNext(); - Network::PostIoAction doHandshakeNextDone(NextResultPtr&& next_result); - - HandshakerFactory handshaker_factory_; - HandshakeValidator handshake_validator_; - TsiHandshakerPtr handshaker_{}; - bool handshaker_next_calling_{}; - // TODO(lizan): wrap frame protector in a C++ class - TsiFrameProtectorPtr frame_protector_; - - Envoy::Network::TransportSocketCallbacks* callbacks_{}; - RawBufferCallbacks raw_buffer_callbacks_; - Network::RawBufferSocket raw_buffer_socket_; - - Envoy::Buffer::OwnedImpl raw_read_buffer_; - Envoy::Buffer::OwnedImpl raw_write_buffer_; - bool handshake_complete_{}; -}; - -/** - * An implementation of Network::TransportSocketFactory for TsiSocket - */ -class TsiSocketFactory : public Network::TransportSocketFactory { - public: - TsiSocketFactory(HandshakerFactory handshaker_factory, - HandshakeValidator handshake_validator); - - bool implementsSecureTransport() const override; - Network::TransportSocketPtr createTransportSocket() const override; - - private: - HandshakerFactory handshaker_factory_; - HandshakeValidator handshake_validator_; -}; -} // namespace Security -} // namespace Envoy