Line data Source code
1 : #include "source/extensions/transport_sockets/alts/alts_proxy.h" 2 : 3 : #include <memory> 4 : #include <utility> 5 : 6 : #include "absl/memory/memory.h" 7 : #include "absl/status/status.h" 8 : #include "absl/strings/string_view.h" 9 : #include "absl/time/time.h" 10 : #include "absl/types/span.h" 11 : #include "src/proto/grpc/gcp/handshaker.pb.h" 12 : #include "src/proto/grpc/gcp/transport_security_common.pb.h" 13 : 14 : namespace Envoy { 15 : namespace Extensions { 16 : namespace TransportSockets { 17 : namespace Alts { 18 : 19 : using ::grpc::gcp::HandshakeProtocol; 20 : using ::grpc::gcp::HandshakerReq; 21 : using ::grpc::gcp::HandshakerResp; 22 : using ::grpc::gcp::HandshakerService; 23 : using ::grpc::gcp::NextHandshakeMessageReq; 24 : using ::grpc::gcp::ServerHandshakeParameters; 25 : using ::grpc::gcp::StartClientHandshakeReq; 26 : using ::grpc::gcp::StartServerHandshakeReq; 27 : 28 : // TODO(matthewstevenson88): Make this deadline configurable. 29 : constexpr absl::Duration AltsClientContextDeadline = absl::Seconds(30); 30 : 31 0 : void AltsProxy::setRpcProtocolVersions(grpc::gcp::RpcProtocolVersions* rpc_protocol_versions) { 32 0 : rpc_protocol_versions->mutable_max_rpc_version()->set_major(MaxMajorRpcVersion); 33 0 : rpc_protocol_versions->mutable_max_rpc_version()->set_minor(MaxMinorRpcVersion); 34 0 : rpc_protocol_versions->mutable_min_rpc_version()->set_major(MinMajorRpcVersion); 35 0 : rpc_protocol_versions->mutable_min_rpc_version()->set_minor(MinMinorRpcVersion); 36 0 : } 37 : 38 : absl::StatusOr<std::unique_ptr<AltsProxy>> 39 0 : AltsProxy::create(std::shared_ptr<grpc::Channel> handshaker_service_channel) { 40 0 : if (handshaker_service_channel == nullptr) { 41 0 : return absl::InvalidArgumentError("Handshaker service channel is null."); 42 0 : } 43 0 : auto client_context = std::make_unique<grpc::ClientContext>(); 44 0 : client_context->set_deadline(absl::ToChronoTime(absl::Now() + AltsClientContextDeadline)); 45 : // TODO(matthewstevenson88): Investigate using Envoy's async gRPC client. 46 0 : auto stub = HandshakerService::NewStub(handshaker_service_channel); 47 0 : if (stub == nullptr) { 48 0 : return absl::InvalidArgumentError("Handshaker service stub is null."); 49 0 : } 50 0 : auto stream = stub->DoHandshake(client_context.get()); 51 0 : if (stream == nullptr) { 52 0 : return absl::InvalidArgumentError("Handshaker service stream is null."); 53 0 : } 54 0 : return absl::WrapUnique( 55 0 : new AltsProxy(std::move(client_context), std::move(stub), std::move(stream))); 56 0 : } 57 : 58 : AltsProxy::AltsProxy( 59 : std::unique_ptr<grpc::ClientContext> client_context, 60 : std::unique_ptr<HandshakerService::Stub> stub, 61 : std::unique_ptr<grpc::ClientReaderWriter<HandshakerReq, HandshakerResp>> stream) 62 : : client_context_(std::move(client_context)), stub_(std::move(stub)), 63 0 : stream_(std::move(stream)) {} 64 : 65 0 : AltsProxy::~AltsProxy() { 66 0 : if (stream_ != nullptr) { 67 0 : stream_->WritesDone(); 68 0 : } 69 0 : } 70 : 71 0 : absl::StatusOr<HandshakerResp> AltsProxy::sendStartClientHandshakeReq() { 72 : // Prepare the StartClientHandshakeReq message. Ignore the target name field, 73 : // it should never be populated for Envoy's use of ALTS. 74 0 : HandshakerReq request; 75 0 : StartClientHandshakeReq* client_start = request.mutable_client_start(); 76 0 : client_start->set_handshake_security_protocol(grpc::gcp::ALTS); 77 0 : client_start->add_application_protocols(ApplicationProtocol); 78 0 : client_start->add_record_protocols(RecordProtocol); 79 0 : setRpcProtocolVersions(client_start->mutable_rpc_versions()); 80 0 : client_start->set_max_frame_size(MaxFrameSize); 81 : 82 : // Send the StartClientHandshakeReq message to the handshaker service and wait 83 : // for the response. 84 0 : if (!stream_->Write(request)) { 85 0 : return absl::UnavailableError( 86 0 : "Failed to write client start to handshaker service. This is probably " 87 0 : "because the handshaker service is unreachable or unresponsive."); 88 0 : } 89 0 : HandshakerResp response; 90 0 : if (!stream_->Read(&response)) { 91 0 : return absl::InternalError("Failed to read client start response from handshaker service."); 92 0 : } 93 0 : if (response.has_status() && response.status().code() != 0) { 94 0 : return absl::Status(static_cast<absl::StatusCode>(response.status().code()), 95 0 : response.status().details()); 96 0 : } 97 0 : return response; 98 0 : } 99 : 100 : absl::StatusOr<HandshakerResp> 101 0 : AltsProxy::sendStartServerHandshakeReq(absl::Span<const uint8_t> in_bytes) { 102 : // Prepare the StartServerHandshakeReq message. 103 0 : ServerHandshakeParameters server_parameters; 104 0 : server_parameters.add_record_protocols(RecordProtocol); 105 0 : HandshakerReq request; 106 0 : StartServerHandshakeReq* server_start = request.mutable_server_start(); 107 0 : server_start->add_application_protocols(ApplicationProtocol); 108 0 : (*server_start->mutable_handshake_parameters())[HandshakeProtocol::ALTS] = server_parameters; 109 0 : setRpcProtocolVersions(server_start->mutable_rpc_versions()); 110 0 : server_start->set_in_bytes(in_bytes.data(), in_bytes.size()); 111 0 : server_start->set_max_frame_size(MaxFrameSize); 112 : 113 : // Send the StartServerHandshakeReq message to the handshaker service and wait 114 : // for the response. 115 0 : if (!stream_->Write(request)) { 116 0 : return absl::UnavailableError( 117 0 : "Failed to write server start to handshaker service. This is probably " 118 0 : "because the handshaker service is unreachable or unresponsive."); 119 0 : } 120 0 : HandshakerResp response; 121 0 : if (!stream_->Read(&response)) { 122 0 : return absl::InternalError("Failed to read server start response from handshaker service."); 123 0 : } 124 0 : if (response.has_status() && response.status().code() != 0) { 125 0 : return absl::Status(static_cast<absl::StatusCode>(response.status().code()), 126 0 : response.status().details()); 127 0 : } 128 0 : return response; 129 0 : } 130 : 131 : absl::StatusOr<grpc::gcp::HandshakerResp> 132 0 : AltsProxy::sendNextHandshakeReq(absl::Span<const uint8_t> in_bytes) { 133 : // Prepare the NextHandshakeMessageReq message. 134 0 : HandshakerReq request; 135 0 : NextHandshakeMessageReq* next = request.mutable_next(); 136 0 : next->set_in_bytes(in_bytes.data(), in_bytes.size()); 137 : 138 : // Send the NextHandshakeMessageReq message to the handshaker service and wait 139 : // for the response. 140 0 : if (!stream_->Write(request)) { 141 0 : return absl::UnavailableError( 142 0 : "Failed to write next message to handshaker service. This is probably " 143 0 : "because the handshaker service is unreachable or unresponsive."); 144 0 : } 145 0 : HandshakerResp response; 146 0 : if (!stream_->Read(&response)) { 147 0 : return absl::InternalError("Failed to read next response from handshaker service."); 148 0 : } 149 0 : if (response.has_status() && response.status().code() != 0) { 150 0 : return absl::Status(static_cast<absl::StatusCode>(response.status().code()), 151 0 : response.status().details()); 152 0 : } 153 0 : return response; 154 0 : } 155 : 156 : } // namespace Alts 157 : } // namespace TransportSockets 158 : } // namespace Extensions 159 : } // namespace Envoy