Skip to content

Commit

Permalink
NACK xDS updates where transport_name is not recognized (grpc#26612)
Browse files Browse the repository at this point in the history
* NACK xDS updates where transport_name is not recognized

* Reviewer comments
  • Loading branch information
yashykt authored Jul 8, 2021
1 parent 933b10d commit 670a26c
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 85 deletions.
172 changes: 88 additions & 84 deletions src/core/ext/xds/xds_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2079,52 +2079,54 @@ grpc_error_handle DownstreamTlsContextParse(
XdsApi::DownstreamTlsContext* downstream_tls_context) {
absl::string_view name = UpbStringToAbsl(
envoy_config_core_v3_TransportSocket_name(transport_socket));
if (name == "envoy.transport_sockets.tls") {
auto* typed_config =
envoy_config_core_v3_TransportSocket_typed_config(transport_socket);
if (typed_config != nullptr) {
const upb_strview encoded_downstream_tls_context =
google_protobuf_Any_value(typed_config);
auto* downstream_tls_context_proto =
envoy_extensions_transport_sockets_tls_v3_DownstreamTlsContext_parse(
encoded_downstream_tls_context.data,
encoded_downstream_tls_context.size, context.arena);
if (downstream_tls_context_proto == nullptr) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Can't decode downstream tls context.");
}
auto* common_tls_context =
envoy_extensions_transport_sockets_tls_v3_DownstreamTlsContext_common_tls_context(
downstream_tls_context_proto);
if (common_tls_context != nullptr) {
grpc_error_handle error = CommonTlsContextParse(
common_tls_context, &downstream_tls_context->common_tls_context);
if (error != GRPC_ERROR_NONE) return error;
}
auto* require_client_certificate =
envoy_extensions_transport_sockets_tls_v3_DownstreamTlsContext_require_client_certificate(
downstream_tls_context_proto);
if (require_client_certificate != nullptr) {
downstream_tls_context->require_client_certificate =
google_protobuf_BoolValue_value(require_client_certificate);
}
}
if (downstream_tls_context->common_tls_context
.tls_certificate_certificate_provider_instance.instance_name
.empty()) {
if (name != "envoy.transport_sockets.tls") {
return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
absl::StrCat("Unrecognized transport socket: ", name).c_str());
}
auto* typed_config =
envoy_config_core_v3_TransportSocket_typed_config(transport_socket);
if (typed_config != nullptr) {
const upb_strview encoded_downstream_tls_context =
google_protobuf_Any_value(typed_config);
auto* downstream_tls_context_proto =
envoy_extensions_transport_sockets_tls_v3_DownstreamTlsContext_parse(
encoded_downstream_tls_context.data,
encoded_downstream_tls_context.size, context.arena);
if (downstream_tls_context_proto == nullptr) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"TLS configuration provided but no "
"tls_certificate_certificate_provider_instance found.");
"Can't decode downstream tls context.");
}
auto* common_tls_context =
envoy_extensions_transport_sockets_tls_v3_DownstreamTlsContext_common_tls_context(
downstream_tls_context_proto);
if (common_tls_context != nullptr) {
grpc_error_handle error = CommonTlsContextParse(
common_tls_context, &downstream_tls_context->common_tls_context);
if (error != GRPC_ERROR_NONE) return error;
}
if (downstream_tls_context->require_client_certificate &&
downstream_tls_context->common_tls_context.combined_validation_context
.validation_context_certificate_provider_instance.instance_name
.empty()) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"TLS configuration requires client certificates but no certificate "
"provider instance specified for validation.");
auto* require_client_certificate =
envoy_extensions_transport_sockets_tls_v3_DownstreamTlsContext_require_client_certificate(
downstream_tls_context_proto);
if (require_client_certificate != nullptr) {
downstream_tls_context->require_client_certificate =
google_protobuf_BoolValue_value(require_client_certificate);
}
}
if (downstream_tls_context->common_tls_context
.tls_certificate_certificate_provider_instance.instance_name
.empty()) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"TLS configuration provided but no "
"tls_certificate_certificate_provider_instance found.");
}
if (downstream_tls_context->require_client_certificate &&
downstream_tls_context->common_tls_context.combined_validation_context
.validation_context_certificate_provider_instance.instance_name
.empty()) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"TLS configuration requires client certificates but no certificate "
"provider instance specified for validation.");
}
return GRPC_ERROR_NONE;
}

Expand Down Expand Up @@ -3029,54 +3031,56 @@ grpc_error_handle CdsResponseParse(
if (transport_socket != nullptr) {
absl::string_view name = UpbStringToAbsl(
envoy_config_core_v3_TransportSocket_name(transport_socket));
if (name == "envoy.transport_sockets.tls") {
auto* typed_config =
envoy_config_core_v3_TransportSocket_typed_config(
transport_socket);
if (typed_config != nullptr) {
const upb_strview encoded_upstream_tls_context =
google_protobuf_Any_value(typed_config);
auto* upstream_tls_context =
envoy_extensions_transport_sockets_tls_v3_UpstreamTlsContext_parse(
encoded_upstream_tls_context.data,
encoded_upstream_tls_context.size, context.arena);
if (upstream_tls_context == nullptr) {
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
absl::StrCat(cluster_name,
": Can't decode upstream tls context.")
.c_str()));
resource_names_failed->insert(cluster_name);
continue;
}
auto* common_tls_context =
envoy_extensions_transport_sockets_tls_v3_UpstreamTlsContext_common_tls_context(
upstream_tls_context);
if (common_tls_context != nullptr) {
grpc_error_handle error = CommonTlsContextParse(
common_tls_context, &cds_update.common_tls_context);
if (error != GRPC_ERROR_NONE) {
errors.push_back(grpc_error_add_child(
GRPC_ERROR_CREATE_FROM_COPIED_STRING(
absl::StrCat(cluster_name, ": error in TLS context")
.c_str()),
error));
resource_names_failed->insert(cluster_name);
continue;
}
}
}
if (cds_update.common_tls_context.combined_validation_context
.validation_context_certificate_provider_instance
.instance_name.empty()) {
if (name != "envoy.transport_sockets.tls") {
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
absl::StrCat("Unrecognized transport socket: ", name).c_str()));
continue;
}
auto* typed_config =
envoy_config_core_v3_TransportSocket_typed_config(transport_socket);
if (typed_config != nullptr) {
const upb_strview encoded_upstream_tls_context =
google_protobuf_Any_value(typed_config);
auto* upstream_tls_context =
envoy_extensions_transport_sockets_tls_v3_UpstreamTlsContext_parse(
encoded_upstream_tls_context.data,
encoded_upstream_tls_context.size, context.arena);
if (upstream_tls_context == nullptr) {
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
absl::StrCat(cluster_name,
"TLS configuration provided but no "
"validation_context_certificate_provider_instance "
"found.")
": Can't decode upstream tls context.")
.c_str()));
resource_names_failed->insert(cluster_name);
continue;
}
auto* common_tls_context =
envoy_extensions_transport_sockets_tls_v3_UpstreamTlsContext_common_tls_context(
upstream_tls_context);
if (common_tls_context != nullptr) {
grpc_error_handle error = CommonTlsContextParse(
common_tls_context, &cds_update.common_tls_context);
if (error != GRPC_ERROR_NONE) {
errors.push_back(grpc_error_add_child(
GRPC_ERROR_CREATE_FROM_COPIED_STRING(
absl::StrCat(cluster_name, ": error in TLS context")
.c_str()),
error));
resource_names_failed->insert(cluster_name);
continue;
}
}
}
if (cds_update.common_tls_context.combined_validation_context
.validation_context_certificate_provider_instance.instance_name
.empty()) {
errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING(
absl::StrCat(cluster_name,
"TLS configuration provided but no "
"validation_context_certificate_provider_instance "
"found.")
.c_str()));
resource_names_failed->insert(cluster_name);
continue;
}
}
}
Expand Down
46 changes: 45 additions & 1 deletion test/cpp/end2end/xds_end2end_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7970,6 +7970,20 @@ class XdsSecurityTest : public BasicTest {
std::vector<std::string> fallback_authenticated_identity_;
};

TEST_P(XdsSecurityTest, UnknownTransportSocket) {
auto cluster = default_cluster_;
auto* transport_socket = cluster.mutable_transport_socket();
transport_socket->set_name("unknown_transport_socket");
balancers_[0]->ads_service()->SetCdsResource(cluster);
CheckRpcSendFailure();
const auto response_state =
balancers_[0]->ads_service()->cds_response_state();
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(response_state.error_message,
::testing::HasSubstr(
"Unrecognized transport socket: unknown_transport_socket"));
}

TEST_P(XdsSecurityTest,
TLSConfigurationWithoutValidationContextCertificateProviderInstance) {
auto cluster = default_cluster_;
Expand Down Expand Up @@ -8919,6 +8933,33 @@ class XdsServerSecurityTest : public XdsEnd2endTest {
std::vector<std::string> client_authenticated_identity_;
};

TEST_P(XdsServerSecurityTest, UnknownTransportSocket) {
Listener listener;
listener.set_name(
absl::StrCat("grpc/server?xds.resource.listening_address=",
ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()));
balancers_[0]->ads_service()->SetLdsResource(listener);
auto* socket_address = listener.mutable_address()->mutable_socket_address();
socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1");
socket_address->set_port_value(backends_[0]->port());
auto* filter_chain = listener.add_filter_chains();
filter_chain->add_filters()->mutable_typed_config()->PackFrom(
HttpConnectionManager());
auto* transport_socket = filter_chain->mutable_transport_socket();
transport_socket->set_name("unknown_transport_socket");
balancers_[0]->ads_service()->SetLdsResource(listener);
do {
CheckRpcSendFailure();
} while (balancers_[0]->ads_service()->lds_response_state().state ==
AdsServiceImpl::ResponseState::SENT);
const auto response_state =
balancers_[0]->ads_service()->lds_response_state();
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
EXPECT_THAT(response_state.error_message,
::testing::HasSubstr(
"Unrecognized transport socket: unknown_transport_socket"));
}

TEST_P(
XdsServerSecurityTest,
NacksRequiringClientCertificateWithoutValidationCertificateProviderInstance) {
Expand Down Expand Up @@ -8973,7 +9014,10 @@ TEST_P(XdsServerSecurityTest,
DownstreamTlsContext downstream_tls_context;
transport_socket->mutable_typed_config()->PackFrom(downstream_tls_context);
balancers_[0]->ads_service()->SetLdsResource(listener);
CheckRpcSendFailure(1, RpcOptions().set_wait_for_ready(true));
do {
CheckRpcSendFailure();
} while (balancers_[0]->ads_service()->lds_response_state().state ==
AdsServiceImpl::ResponseState::SENT);
const auto response_state =
balancers_[0]->ads_service()->lds_response_state();
EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED);
Expand Down

0 comments on commit 670a26c

Please sign in to comment.