diff --git a/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc b/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc index 1ac1aa43684..af78f6c5c2a 100644 --- a/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc +++ b/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc @@ -572,11 +572,11 @@ grpc_error_handle CdsLb::UpdateXdsCertificateProvider( } // Configure root cert. absl::string_view root_provider_instance_name = - cluster_data.common_tls_context.combined_validation_context - .validation_context_certificate_provider_instance.instance_name; + cluster_data.common_tls_context.certificate_validation_context + .ca_certificate_provider_instance.instance_name; absl::string_view root_provider_cert_name = - cluster_data.common_tls_context.combined_validation_context - .validation_context_certificate_provider_instance.certificate_name; + cluster_data.common_tls_context.certificate_validation_context + .ca_certificate_provider_instance.certificate_name; RefCountedPtr new_root_provider; if (!root_provider_instance_name.empty()) { new_root_provider = @@ -612,11 +612,11 @@ grpc_error_handle CdsLb::UpdateXdsCertificateProvider( : root_certificate_provider_->distributor()); // Configure identity cert. absl::string_view identity_provider_instance_name = - cluster_data.common_tls_context - .tls_certificate_certificate_provider_instance.instance_name; + cluster_data.common_tls_context.tls_certificate_provider_instance + .instance_name; absl::string_view identity_provider_cert_name = - cluster_data.common_tls_context - .tls_certificate_certificate_provider_instance.certificate_name; + cluster_data.common_tls_context.tls_certificate_provider_instance + .certificate_name; RefCountedPtr new_identity_provider; if (!identity_provider_instance_name.empty()) { new_identity_provider = @@ -653,8 +653,8 @@ grpc_error_handle CdsLb::UpdateXdsCertificateProvider( : identity_certificate_provider_->distributor()); // Configure SAN matchers. const std::vector& match_subject_alt_names = - cluster_data.common_tls_context.combined_validation_context - .default_validation_context.match_subject_alt_names; + cluster_data.common_tls_context.certificate_validation_context + .match_subject_alt_names; xds_certificate_provider_->UpdateSubjectAlternativeNameMatchers( cluster_name, match_subject_alt_names); return GRPC_ERROR_NONE; diff --git a/src/core/ext/xds/xds_api.cc b/src/core/ext/xds/xds_api.cc index b161c87bf3d..fddd32e50b1 100644 --- a/src/core/ext/xds/xds_api.cc +++ b/src/core/ext/xds/xds_api.cc @@ -438,11 +438,11 @@ bool XdsApi::CommonTlsContext::CertificateValidationContext::Empty() const { } // -// XdsApi::CommonTlsContext::CertificateValidationContext +// XdsApi::CommonTlsContext::CertificateProviderPluginInstance // -std::string XdsApi::CommonTlsContext::CertificateProviderInstance::ToString() - const { +std::string +XdsApi::CommonTlsContext::CertificateProviderPluginInstance::ToString() const { absl::InlinedVector contents; if (!instance_name.empty()) { contents.push_back(absl::StrFormat("instance_name=%s", instance_name)); @@ -454,34 +454,9 @@ std::string XdsApi::CommonTlsContext::CertificateProviderInstance::ToString() return absl::StrCat("{", absl::StrJoin(contents, ", "), "}"); } -bool XdsApi::CommonTlsContext::CertificateProviderInstance::Empty() const { - return instance_name.empty() && certificate_name.empty(); -} - -// -// XdsApi::CommonTlsContext::CombinedCertificateValidationContext -// - -std::string -XdsApi::CommonTlsContext::CombinedCertificateValidationContext::ToString() - const { - absl::InlinedVector contents; - if (!default_validation_context.Empty()) { - contents.push_back(absl::StrFormat("default_validation_context=%s", - default_validation_context.ToString())); - } - if (!validation_context_certificate_provider_instance.Empty()) { - contents.push_back(absl::StrFormat( - "validation_context_certificate_provider_instance=%s", - validation_context_certificate_provider_instance.ToString())); - } - return absl::StrCat("{", absl::StrJoin(contents, ", "), "}"); -} - -bool XdsApi::CommonTlsContext::CombinedCertificateValidationContext::Empty() +bool XdsApi::CommonTlsContext::CertificateProviderPluginInstance::Empty() const { - return default_validation_context.Empty() && - validation_context_certificate_provider_instance.Empty(); + return instance_name.empty() && certificate_name.empty(); } // @@ -490,21 +465,22 @@ bool XdsApi::CommonTlsContext::CombinedCertificateValidationContext::Empty() std::string XdsApi::CommonTlsContext::ToString() const { absl::InlinedVector contents; - if (!tls_certificate_certificate_provider_instance.Empty()) { - contents.push_back(absl::StrFormat( - "tls_certificate_certificate_provider_instance=%s", - tls_certificate_certificate_provider_instance.ToString())); + if (!tls_certificate_provider_instance.Empty()) { + contents.push_back( + absl::StrFormat("tls_certificate_provider_instance=%s", + tls_certificate_provider_instance.ToString())); } - if (!combined_validation_context.Empty()) { - contents.push_back(absl::StrFormat("combined_validation_context=%s", - combined_validation_context.ToString())); + if (!certificate_validation_context.Empty()) { + contents.push_back( + absl::StrFormat("certificate_validation_context=%s", + certificate_validation_context.ToString())); } return absl::StrCat("{", absl::StrJoin(contents, ", "), "}"); } bool XdsApi::CommonTlsContext::Empty() const { - return tls_certificate_certificate_provider_instance.Empty() && - combined_validation_context.Empty(); + return tls_certificate_provider_instance.Empty() && + certificate_validation_context.Empty(); } // @@ -1946,13 +1922,18 @@ grpc_error_handle RouteConfigParse( return GRPC_ERROR_NONE; } +// CertificateProviderInstance is deprecated but we are still supporting it for +// backward compatibility reasons. Note that we still parse the data into the +// same CertificateProviderPluginInstance struct since the fields are the same. +// TODO(yashykt): Remove this once we stop supporting the old way of fetching +// certificate provider instances. grpc_error_handle CertificateProviderInstanceParse( const EncodingContext& context, const envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_CertificateProviderInstance* certificate_provider_instance_proto, - XdsApi::CommonTlsContext::CertificateProviderInstance* - certificate_provider_instance) { - *certificate_provider_instance = { + XdsApi::CommonTlsContext::CertificateProviderPluginInstance* + certificate_provider_plugin_instance) { + *certificate_provider_plugin_instance = { UpbStringToStdString( envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_CertificateProviderInstance_instance_name( certificate_provider_instance_proto)), @@ -1960,22 +1941,160 @@ grpc_error_handle CertificateProviderInstanceParse( envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_CertificateProviderInstance_certificate_name( certificate_provider_instance_proto))}; if (context.certificate_provider_definition_map->find( - certificate_provider_instance->instance_name) == + certificate_provider_plugin_instance->instance_name) == context.certificate_provider_definition_map->end()) { return GRPC_ERROR_CREATE_FROM_COPIED_STRING( absl::StrCat("Unrecognized certificate provider instance name: ", - certificate_provider_instance->instance_name) + certificate_provider_plugin_instance->instance_name) .c_str()); } return GRPC_ERROR_NONE; } +grpc_error_handle CertificateProviderPluginInstanceParse( + const EncodingContext& context, + const envoy_extensions_transport_sockets_tls_v3_CertificateProviderPluginInstance* + certificate_provider_plugin_instance_proto, + XdsApi::CommonTlsContext::CertificateProviderPluginInstance* + certificate_provider_plugin_instance) { + *certificate_provider_plugin_instance = { + UpbStringToStdString( + envoy_extensions_transport_sockets_tls_v3_CertificateProviderPluginInstance_instance_name( + certificate_provider_plugin_instance_proto)), + UpbStringToStdString( + envoy_extensions_transport_sockets_tls_v3_CertificateProviderPluginInstance_certificate_name( + certificate_provider_plugin_instance_proto))}; + if (context.certificate_provider_definition_map->find( + certificate_provider_plugin_instance->instance_name) == + context.certificate_provider_definition_map->end()) { + return GRPC_ERROR_CREATE_FROM_COPIED_STRING( + absl::StrCat("Unrecognized certificate provider instance name: ", + certificate_provider_plugin_instance->instance_name) + .c_str()); + } + return GRPC_ERROR_NONE; +} + +grpc_error_handle CertificateValidationContextParse( + const EncodingContext& context, + const envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext* + certificate_validation_context_proto, + XdsApi::CommonTlsContext::CertificateValidationContext* + certificate_validation_context) { + std::vector errors; + size_t len = 0; + auto* subject_alt_names_matchers = + envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_match_subject_alt_names( + certificate_validation_context_proto, &len); + for (size_t i = 0; i < len; ++i) { + StringMatcher::Type type; + std::string matcher; + if (envoy_type_matcher_v3_StringMatcher_has_exact( + subject_alt_names_matchers[i])) { + type = StringMatcher::Type::kExact; + matcher = UpbStringToStdString(envoy_type_matcher_v3_StringMatcher_exact( + subject_alt_names_matchers[i])); + } else if (envoy_type_matcher_v3_StringMatcher_has_prefix( + subject_alt_names_matchers[i])) { + type = StringMatcher::Type::kPrefix; + matcher = UpbStringToStdString(envoy_type_matcher_v3_StringMatcher_prefix( + subject_alt_names_matchers[i])); + } else if (envoy_type_matcher_v3_StringMatcher_has_suffix( + subject_alt_names_matchers[i])) { + type = StringMatcher::Type::kSuffix; + matcher = UpbStringToStdString(envoy_type_matcher_v3_StringMatcher_suffix( + subject_alt_names_matchers[i])); + } else if (envoy_type_matcher_v3_StringMatcher_has_contains( + subject_alt_names_matchers[i])) { + type = StringMatcher::Type::kContains; + matcher = + UpbStringToStdString(envoy_type_matcher_v3_StringMatcher_contains( + subject_alt_names_matchers[i])); + } else if (envoy_type_matcher_v3_StringMatcher_has_safe_regex( + subject_alt_names_matchers[i])) { + type = StringMatcher::Type::kSafeRegex; + auto* regex_matcher = envoy_type_matcher_v3_StringMatcher_safe_regex( + subject_alt_names_matchers[i]); + matcher = UpbStringToStdString( + envoy_type_matcher_v3_RegexMatcher_regex(regex_matcher)); + } else { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Invalid StringMatcher specified")); + continue; + } + bool ignore_case = envoy_type_matcher_v3_StringMatcher_ignore_case( + subject_alt_names_matchers[i]); + absl::StatusOr string_matcher = + StringMatcher::Create(type, matcher, + /*case_sensitive=*/!ignore_case); + if (!string_matcher.ok()) { + errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( + absl::StrCat("string matcher: ", string_matcher.status().message()) + .c_str())); + continue; + } + if (type == StringMatcher::Type::kSafeRegex && ignore_case) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "StringMatcher: ignore_case has no effect for SAFE_REGEX.")); + continue; + } + certificate_validation_context->match_subject_alt_names.push_back( + std::move(string_matcher.value())); + } + auto* ca_certificate_provider_instance = + envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_ca_certificate_provider_instance( + certificate_validation_context_proto); + if (ca_certificate_provider_instance != nullptr) { + grpc_error_handle error = CertificateProviderPluginInstanceParse( + context, ca_certificate_provider_instance, + &certificate_validation_context->ca_certificate_provider_instance); + if (error != GRPC_ERROR_NONE) errors.push_back(error); + } + if (envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_verify_certificate_spki( + certificate_validation_context_proto, nullptr) != nullptr) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "CertificateValidationContext: verify_certificate_spki " + "unsupported")); + } + if (envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_verify_certificate_hash( + certificate_validation_context_proto, nullptr) != nullptr) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "CertificateValidationContext: verify_certificate_hash " + "unsupported")); + } + auto* require_signed_certificate_timestamp = + envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_require_signed_certificate_timestamp( + certificate_validation_context_proto); + if (require_signed_certificate_timestamp != nullptr && + google_protobuf_BoolValue_value(require_signed_certificate_timestamp)) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "CertificateValidationContext: " + "require_signed_certificate_timestamp unsupported")); + } + if (envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_has_crl( + certificate_validation_context_proto)) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "CertificateValidationContext: crl unsupported")); + } + if (envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_has_custom_validator_config( + certificate_validation_context_proto)) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "CertificateValidationContext: custom_validator_config " + "unsupported")); + } + return GRPC_ERROR_CREATE_FROM_VECTOR( + "Error parsing CertificateValidationContext", &errors); +} + grpc_error_handle CommonTlsContextParse( const EncodingContext& context, const envoy_extensions_transport_sockets_tls_v3_CommonTlsContext* common_tls_context_proto, XdsApi::CommonTlsContext* common_tls_context) { std::vector errors; + // The validation context is derived from the oneof in + // 'validation_context_type'. 'validation_context_sds_secret_config' is not + // supported. auto* combined_validation_context = envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_combined_validation_context( common_tls_context_proto); @@ -1984,123 +2103,89 @@ grpc_error_handle CommonTlsContextParse( envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_CombinedCertificateValidationContext_default_validation_context( combined_validation_context); if (default_validation_context != nullptr) { - size_t len = 0; - auto* subject_alt_names_matchers = - envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_match_subject_alt_names( - default_validation_context, &len); - for (size_t i = 0; i < len; ++i) { - StringMatcher::Type type; - std::string matcher; - if (envoy_type_matcher_v3_StringMatcher_has_exact( - subject_alt_names_matchers[i])) { - type = StringMatcher::Type::kExact; - matcher = - UpbStringToStdString(envoy_type_matcher_v3_StringMatcher_exact( - subject_alt_names_matchers[i])); - } else if (envoy_type_matcher_v3_StringMatcher_has_prefix( - subject_alt_names_matchers[i])) { - type = StringMatcher::Type::kPrefix; - matcher = - UpbStringToStdString(envoy_type_matcher_v3_StringMatcher_prefix( - subject_alt_names_matchers[i])); - } else if (envoy_type_matcher_v3_StringMatcher_has_suffix( - subject_alt_names_matchers[i])) { - type = StringMatcher::Type::kSuffix; - matcher = - UpbStringToStdString(envoy_type_matcher_v3_StringMatcher_suffix( - subject_alt_names_matchers[i])); - } else if (envoy_type_matcher_v3_StringMatcher_has_contains( - subject_alt_names_matchers[i])) { - type = StringMatcher::Type::kContains; - matcher = - UpbStringToStdString(envoy_type_matcher_v3_StringMatcher_contains( - subject_alt_names_matchers[i])); - } else if (envoy_type_matcher_v3_StringMatcher_has_safe_regex( - subject_alt_names_matchers[i])) { - type = StringMatcher::Type::kSafeRegex; - auto* regex_matcher = envoy_type_matcher_v3_StringMatcher_safe_regex( - subject_alt_names_matchers[i]); - matcher = UpbStringToStdString( - envoy_type_matcher_v3_RegexMatcher_regex(regex_matcher)); - } else { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Invalid StringMatcher specified")); - continue; - } - bool ignore_case = envoy_type_matcher_v3_StringMatcher_ignore_case( - subject_alt_names_matchers[i]); - absl::StatusOr string_matcher = - StringMatcher::Create(type, matcher, - /*case_sensitive=*/!ignore_case); - if (!string_matcher.ok()) { - errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( - absl::StrCat("string matcher: ", - string_matcher.status().message()) - .c_str())); - continue; - } - if (type == StringMatcher::Type::kSafeRegex && ignore_case) { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "StringMatcher: ignore_case has no effect for SAFE_REGEX.")); - continue; - } - common_tls_context->combined_validation_context - .default_validation_context.match_subject_alt_names.push_back( - std::move(string_matcher.value())); - } - if (envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_verify_certificate_spki( - default_validation_context, nullptr) != nullptr) { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "CertificateValidationContext: verify_certificate_spki " - "unsupported")); - } - if (envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_verify_certificate_hash( - default_validation_context, nullptr) != nullptr) { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "CertificateValidationContext: verify_certificate_hash " - "unsupported")); - } - auto* require_signed_certificate_timestamp = - envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_require_signed_certificate_timestamp( - default_validation_context); - if (require_signed_certificate_timestamp != nullptr && - google_protobuf_BoolValue_value( - require_signed_certificate_timestamp)) { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "CertificateValidationContext: " - "require_signed_certificate_timestamp unsupported")); - } - if (envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_has_crl( - default_validation_context)) { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "CertificateValidationContext: crl unsupported")); - } - if (envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_has_custom_validator_config( - default_validation_context)) { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "CertificateValidationContext: custom_validator_config " - "unsupported")); - } + grpc_error_handle error = CertificateValidationContextParse( + context, default_validation_context, + &common_tls_context->certificate_validation_context); + if (error != GRPC_ERROR_NONE) errors.push_back(error); } + // If after parsing default_validation_context, + // common_tls_context->certificate_validation_context.ca_certificate_provider_instance + // is empty, fall back onto + // 'validation_context_certificate_provider_instance' inside + // 'combined_validation_context'. Note that this way of fetching root + // certificates is deprecated and will be removed in the future. + // TODO(yashykt): Remove this once it's no longer needed. auto* validation_context_certificate_provider_instance = envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_CombinedCertificateValidationContext_validation_context_certificate_provider_instance( combined_validation_context); - if (validation_context_certificate_provider_instance != nullptr) { + if (common_tls_context->certificate_validation_context + .ca_certificate_provider_instance.Empty() && + validation_context_certificate_provider_instance != nullptr) { grpc_error_handle error = CertificateProviderInstanceParse( context, validation_context_certificate_provider_instance, - &common_tls_context->combined_validation_context - .validation_context_certificate_provider_instance); + &common_tls_context->certificate_validation_context + .ca_certificate_provider_instance); if (error != GRPC_ERROR_NONE) errors.push_back(error); } + } else { + auto* validation_context = + envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_validation_context( + common_tls_context_proto); + if (validation_context != nullptr) { + grpc_error_handle error = CertificateValidationContextParse( + context, validation_context, + &common_tls_context->certificate_validation_context); + if (error != GRPC_ERROR_NONE) errors.push_back(error); + } else if ( + envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_has_validation_context_sds_secret_config( + common_tls_context_proto)) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "validation_context_sds_secret_config unsupported")); + } } - auto* tls_certificate_certificate_provider_instance = - envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_tls_certificate_certificate_provider_instance( + auto* tls_certificate_provider_instance = + envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_tls_certificate_provider_instance( common_tls_context_proto); - if (tls_certificate_certificate_provider_instance != nullptr) { - grpc_error_handle error = CertificateProviderInstanceParse( - context, tls_certificate_certificate_provider_instance, - &common_tls_context->tls_certificate_certificate_provider_instance); + if (tls_certificate_provider_instance != nullptr) { + grpc_error_handle error = CertificateProviderPluginInstanceParse( + context, tls_certificate_provider_instance, + &common_tls_context->tls_certificate_provider_instance); if (error != GRPC_ERROR_NONE) errors.push_back(error); + } else { + // Fall back onto 'tls_certificate_certificate_provider_instance'. Note that + // this way of fetching identity certificates is deprecated and will be + // removed in the future. + // TODO(yashykt): Remove this once it's no longer needed. + auto* tls_certificate_certificate_provider_instance = + envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_tls_certificate_certificate_provider_instance( + common_tls_context_proto); + if (tls_certificate_certificate_provider_instance != nullptr) { + grpc_error_handle error = CertificateProviderInstanceParse( + context, tls_certificate_certificate_provider_instance, + &common_tls_context->tls_certificate_provider_instance); + if (error != GRPC_ERROR_NONE) errors.push_back(error); + } else { + if (envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_has_tls_certificates( + common_tls_context_proto)) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "tls_certificates unsupported")); + } + if (envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_has_tls_certificate_sds_secret_configs( + common_tls_context_proto)) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "tls_certificate_sds_secret_configs unsupported")); + } + } + } + if (envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_has_tls_params( + common_tls_context_proto)) { + errors.push_back( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("tls_params unsupported")); + } + if (envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_has_custom_handshaker( + common_tls_context_proto)) { + errors.push_back( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("custom_handshaker unsupported")); } return GRPC_ERROR_CREATE_FROM_VECTOR("Error parsing CommonTlsContext", &errors); @@ -2335,20 +2420,23 @@ grpc_error_handle DownstreamTlsContextParse( } } if (downstream_tls_context->common_tls_context - .tls_certificate_certificate_provider_instance.instance_name - .empty()) { + .tls_certificate_provider_instance.instance_name.empty()) { errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( "TLS configuration provided but no " - "tls_certificate_certificate_provider_instance found.")); + "tls_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()) { + downstream_tls_context->common_tls_context.certificate_validation_context + .ca_certificate_provider_instance.instance_name.empty()) { errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( "TLS configuration requires client certificates but no certificate " "provider instance specified for validation.")); } + if (!downstream_tls_context->common_tls_context.certificate_validation_context + .match_subject_alt_names.empty()) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "match_subject_alt_names not supported on servers")); + } return GRPC_ERROR_CREATE_FROM_VECTOR("Error parsing DownstreamTlsContext", &errors); } @@ -2840,13 +2928,11 @@ grpc_error_handle UpstreamTlsContextParse( } } } - if (common_tls_context->combined_validation_context - .validation_context_certificate_provider_instance.instance_name - .empty()) { + if (common_tls_context->certificate_validation_context + .ca_certificate_provider_instance.instance_name.empty()) { return GRPC_ERROR_CREATE_FROM_COPIED_STRING( "UpstreamTlsContext: TLS configuration provided but no " - "validation_context_certificate_provider_instance " - "found."); + "ca_certificate_provider_instance found."); } return GRPC_ERROR_NONE; } diff --git a/src/core/ext/xds/xds_api.h b/src/core/ext/xds/xds_api.h index 46aa42117ae..355f3a6fa57 100644 --- a/src/core/ext/xds/xds_api.h +++ b/src/core/ext/xds/xds_api.h @@ -193,22 +193,11 @@ class XdsApi { }; struct CommonTlsContext { - struct CertificateValidationContext { - std::vector match_subject_alt_names; - - bool operator==(const CertificateValidationContext& other) const { - return match_subject_alt_names == other.match_subject_alt_names; - } - - std::string ToString() const; - bool Empty() const; - }; - - struct CertificateProviderInstance { + struct CertificateProviderPluginInstance { std::string instance_name; std::string certificate_name; - bool operator==(const CertificateProviderInstance& other) const { + bool operator==(const CertificateProviderPluginInstance& other) const { return instance_name == other.instance_name && certificate_name == other.certificate_name; } @@ -217,28 +206,28 @@ class XdsApi { bool Empty() const; }; - struct CombinedCertificateValidationContext { - CertificateValidationContext default_validation_context; - CertificateProviderInstance - validation_context_certificate_provider_instance; + struct CertificateValidationContext { + CertificateProviderPluginInstance ca_certificate_provider_instance; + std::vector match_subject_alt_names; - bool operator==(const CombinedCertificateValidationContext& other) const { - return default_validation_context == other.default_validation_context && - validation_context_certificate_provider_instance == - other.validation_context_certificate_provider_instance; + bool operator==(const CertificateValidationContext& other) const { + return ca_certificate_provider_instance == + other.ca_certificate_provider_instance && + match_subject_alt_names == other.match_subject_alt_names; } std::string ToString() const; bool Empty() const; }; - CertificateProviderInstance tls_certificate_certificate_provider_instance; - CombinedCertificateValidationContext combined_validation_context; + CertificateValidationContext certificate_validation_context; + CertificateProviderPluginInstance tls_certificate_provider_instance; bool operator==(const CommonTlsContext& other) const { - return tls_certificate_certificate_provider_instance == - other.tls_certificate_certificate_provider_instance && - combined_validation_context == other.combined_validation_context; + return certificate_validation_context == + other.certificate_validation_context && + tls_certificate_provider_instance == + other.tls_certificate_provider_instance; } std::string ToString() const; diff --git a/src/core/ext/xds/xds_server_config_fetcher.cc b/src/core/ext/xds/xds_server_config_fetcher.cc index e9850f90b81..fe010cf2209 100644 --- a/src/core/ext/xds/xds_server_config_fetcher.cc +++ b/src/core/ext/xds/xds_server_config_fetcher.cc @@ -259,12 +259,12 @@ FilterChainMatchManager::CreateOrGetXdsCertificateProviderFromFilterChainData( // Configure root cert. absl::string_view root_provider_instance_name = filter_chain->downstream_tls_context.common_tls_context - .combined_validation_context - .validation_context_certificate_provider_instance.instance_name; + .certificate_validation_context.ca_certificate_provider_instance + .instance_name; absl::string_view root_provider_cert_name = filter_chain->downstream_tls_context.common_tls_context - .combined_validation_context - .validation_context_certificate_provider_instance.certificate_name; + .certificate_validation_context.ca_certificate_provider_instance + .certificate_name; if (!root_provider_instance_name.empty()) { certificate_providers.root = xds_client_->certificate_provider_store() @@ -278,10 +278,10 @@ FilterChainMatchManager::CreateOrGetXdsCertificateProviderFromFilterChainData( // Configure identity cert. absl::string_view identity_provider_instance_name = filter_chain->downstream_tls_context.common_tls_context - .tls_certificate_certificate_provider_instance.instance_name; + .tls_certificate_provider_instance.instance_name; absl::string_view identity_provider_cert_name = filter_chain->downstream_tls_context.common_tls_context - .tls_certificate_certificate_provider_instance.certificate_name; + .tls_certificate_provider_instance.certificate_name; if (!identity_provider_instance_name.empty()) { certificate_providers.instance = xds_client_->certificate_provider_store() diff --git a/src/proto/grpc/testing/xds/v3/tls.proto b/src/proto/grpc/testing/xds/v3/tls.proto index d0677cdd8ad..b2fc4532d8b 100644 --- a/src/proto/grpc/testing/xds/v3/tls.proto +++ b/src/proto/grpc/testing/xds/v3/tls.proto @@ -24,7 +24,33 @@ import "src/proto/grpc/testing/xds/v3/string.proto"; import "google/protobuf/wrappers.proto"; +// Indicates a certificate to be obtained from a named CertificateProvider plugin instance. +// The plugin instances are defined in the client's bootstrap file. +// The plugin allows certificates to be fetched/refreshed over the network asynchronously with +// respect to the TLS handshake. +// [#not-implemented-hide:] +message CertificateProviderPluginInstance { + // Provider instance name. If not present, defaults to "default". + // + // Instance names should generally be defined not in terms of the underlying provider + // implementation (e.g., "file_watcher") but rather in terms of the function of the + // certificates (e.g., "foo_deployment_identity"). + string instance_name = 1; + + // Opaque name used to specify certificate instances or types. For example, "ROOTCA" to specify + // a root-certificate (validation context) or "example.com" to specify a certificate for a + // particular domain. Not all provider instances will actually use this field, so the value + // defaults to the empty string. + string certificate_name = 2; +} + message CertificateValidationContext { + // Certificate provider instance for fetching TLS certificates. + // + // Only one of *trusted_ca* and *ca_certificate_provider_instance* may be specified. + // [#not-implemented-hide:] + CertificateProviderPluginInstance ca_certificate_provider_instance = 13; + // An optional list of base64-encoded SHA-256 hashes. If specified, Envoy will verify that the // SHA-256 of the DER-encoded Subject Public Key Information (SPKI) of the presented certificate // matches one of the specified values. @@ -212,10 +238,60 @@ message CommonTlsContext { CertificateProviderInstance validation_context_certificate_provider_instance = 4; } + message TlsParameters {} + + // TLS protocol versions, cipher suites etc. + TlsParameters tls_params = 1; + + message TlsCertificate {} + + // :ref:`Multiple TLS certificates ` can be associated with the + // same context to allow both RSA and ECDSA certificates. + // + // Only a single TLS certificate is supported in client contexts. In server contexts, the first + // RSA certificate is used for clients that only support RSA and the first ECDSA certificate is + // used for clients that support ECDSA. + // + // Only one of *tls_certificates*, *tls_certificate_sds_secret_configs*, + // and *tls_certificate_provider_instance* may be used. + // [#next-major-version: These mutually exclusive fields should ideally be in a oneof, but it's + // not legal to put a repeated field in a oneof. In the next major version, we should rework + // this to avoid this problem.] + repeated TlsCertificate tls_certificates = 2; + + message SdsSecretConfig {} + + // Configs for fetching TLS certificates via SDS API. Note SDS API allows certificates to be + // fetched/refreshed over the network asynchronously with respect to the TLS handshake. + // + // The same number and types of certificates as :ref:`tls_certificates ` + // are valid in the the certificates fetched through this setting. + // + // Only one of *tls_certificates*, *tls_certificate_sds_secret_configs*, + // and *tls_certificate_provider_instance* may be used. + // [#next-major-version: These mutually exclusive fields should ideally be in a oneof, but it's + // not legal to put a repeated field in a oneof. In the next major version, we should rework + // this to avoid this problem.] + repeated SdsSecretConfig tls_certificate_sds_secret_configs = 6; + + // Certificate provider instance for fetching TLS certs. + // + // Only one of *tls_certificates*, *tls_certificate_sds_secret_configs*, + // and *tls_certificate_provider_instance* may be used. + // [#not-implemented-hide:] + CertificateProviderPluginInstance tls_certificate_provider_instance = 14; + // Certificate provider instance for fetching TLS certificates. CertificateProviderInstance tls_certificate_certificate_provider_instance = 11; oneof validation_context_type { + // How to validate peer certificates. + CertificateValidationContext validation_context = 3; + + // Config for fetching validation context via SDS API. Note SDS API allows certificates to be + // fetched/refreshed over the network asynchronously with respect to the TLS handshake. + SdsSecretConfig validation_context_sds_secret_config = 7; + // Combined certificate validation context holds a default CertificateValidationContext // and SDS config. When SDS server returns dynamic CertificateValidationContext, both dynamic // and default CertificateValidationContext are merged into a new CertificateValidationContext @@ -225,4 +301,8 @@ message CommonTlsContext { // CertificateValidationContext, and logical OR is applied to boolean fields. CombinedCertificateValidationContext combined_validation_context = 8; } + + // Custom TLS handshaker. If empty, defaults to native TLS handshaking + // behavior. + config.core.v3.TypedExtensionConfig custom_handshaker = 13; } diff --git a/test/cpp/end2end/xds_end2end_test.cc b/test/cpp/end2end/xds_end2end_test.cc index 6fb6cda926d..b821e097d31 100644 --- a/test/cpp/end2end/xds_end2end_test.cc +++ b/test/cpp/end2end/xds_end2end_test.cc @@ -8257,27 +8257,26 @@ class XdsSecurityTest : public BasicTest { UpstreamTlsContext upstream_tls_context; if (!identity_instance_name.empty()) { upstream_tls_context.mutable_common_tls_context() - ->mutable_tls_certificate_certificate_provider_instance() + ->mutable_tls_certificate_provider_instance() ->set_instance_name(std::string(identity_instance_name)); upstream_tls_context.mutable_common_tls_context() - ->mutable_tls_certificate_certificate_provider_instance() + ->mutable_tls_certificate_provider_instance() ->set_certificate_name(std::string(identity_certificate_name)); } if (!root_instance_name.empty()) { upstream_tls_context.mutable_common_tls_context() - ->mutable_combined_validation_context() - ->mutable_validation_context_certificate_provider_instance() + ->mutable_validation_context() + ->mutable_ca_certificate_provider_instance() ->set_instance_name(std::string(root_instance_name)); upstream_tls_context.mutable_common_tls_context() - ->mutable_combined_validation_context() - ->mutable_validation_context_certificate_provider_instance() + ->mutable_validation_context() + ->mutable_ca_certificate_provider_instance() ->set_certificate_name(std::string(root_certificate_name)); } if (!san_matchers.empty()) { auto* validation_context = upstream_tls_context.mutable_common_tls_context() - ->mutable_combined_validation_context() - ->mutable_default_validation_context(); + ->mutable_validation_context(); for (const auto& san_matcher : san_matchers) { *validation_context->add_match_subject_alt_names() = san_matcher; } @@ -8367,9 +8366,8 @@ TEST_P(XdsSecurityTest, balancers_[0]->ads_service()->cds_response_state(); EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED); EXPECT_THAT(response_state.error_message, - ::testing::HasSubstr( - "TLS configuration provided but no " - "validation_context_certificate_provider_instance found.")); + ::testing::HasSubstr("TLS configuration provided but no " + "ca_certificate_provider_instance found.")); } TEST_P( @@ -8380,8 +8378,7 @@ TEST_P( transport_socket->set_name("envoy.transport_sockets.tls"); UpstreamTlsContext upstream_tls_context; auto* validation_context = upstream_tls_context.mutable_common_tls_context() - ->mutable_combined_validation_context() - ->mutable_default_validation_context(); + ->mutable_validation_context(); *validation_context->add_match_subject_alt_names() = server_san_exact_; transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context); balancers_[0]->ads_service()->SetCdsResource(cluster); @@ -8390,20 +8387,19 @@ TEST_P( balancers_[0]->ads_service()->cds_response_state(); EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED); EXPECT_THAT(response_state.error_message, - ::testing::HasSubstr( - "TLS configuration provided but no " - "validation_context_certificate_provider_instance found.")); + ::testing::HasSubstr("TLS configuration provided but no " + "ca_certificate_provider_instance found.")); } TEST_P( XdsSecurityTest, - TlsCertificateCertificateProviderInstanceWithoutValidationContextCertificateProviderInstance) { + TlsCertificateProviderInstanceWithoutValidationContextCertificateProviderInstance) { auto cluster = default_cluster_; auto* transport_socket = cluster.mutable_transport_socket(); transport_socket->set_name("envoy.transport_sockets.tls"); UpstreamTlsContext upstream_tls_context; upstream_tls_context.mutable_common_tls_context() - ->mutable_tls_certificate_certificate_provider_instance() + ->mutable_tls_certificate_provider_instance() ->set_instance_name(std::string("fake_plugin1")); transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context); balancers_[0]->ads_service()->SetCdsResource(cluster); @@ -8412,9 +8408,8 @@ TEST_P( balancers_[0]->ads_service()->cds_response_state(); EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED); EXPECT_THAT(response_state.error_message, - ::testing::HasSubstr( - "TLS configuration provided but no " - "validation_context_certificate_provider_instance found.")); + ::testing::HasSubstr("TLS configuration provided but no " + "ca_certificate_provider_instance found.")); } TEST_P(XdsSecurityTest, RegexSanMatcherDoesNotAllowIgnoreCase) { @@ -8423,12 +8418,11 @@ TEST_P(XdsSecurityTest, RegexSanMatcherDoesNotAllowIgnoreCase) { transport_socket->set_name("envoy.transport_sockets.tls"); UpstreamTlsContext upstream_tls_context; upstream_tls_context.mutable_common_tls_context() - ->mutable_combined_validation_context() - ->mutable_validation_context_certificate_provider_instance() + ->mutable_validation_context() + ->mutable_ca_certificate_provider_instance() ->set_instance_name(std::string("fake_plugin1")); auto* validation_context = upstream_tls_context.mutable_common_tls_context() - ->mutable_combined_validation_context() - ->mutable_default_validation_context(); + ->mutable_validation_context(); StringMatcher matcher; matcher.mutable_safe_regex()->mutable_google_re2(); matcher.mutable_safe_regex()->set_regex( @@ -8452,8 +8446,8 @@ TEST_P(XdsSecurityTest, UnknownRootCertificateProvider) { transport_socket->set_name("envoy.transport_sockets.tls"); UpstreamTlsContext upstream_tls_context; upstream_tls_context.mutable_common_tls_context() - ->mutable_combined_validation_context() - ->mutable_validation_context_certificate_provider_instance() + ->mutable_validation_context() + ->mutable_ca_certificate_provider_instance() ->set_instance_name("unknown"); transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context); balancers_[0]->ads_service()->SetCdsResource(cluster); @@ -8475,11 +8469,11 @@ TEST_P(XdsSecurityTest, UnknownIdentityCertificateProvider) { transport_socket->set_name("envoy.transport_sockets.tls"); UpstreamTlsContext upstream_tls_context; upstream_tls_context.mutable_common_tls_context() - ->mutable_tls_certificate_certificate_provider_instance() + ->mutable_tls_certificate_provider_instance() ->set_instance_name("unknown"); upstream_tls_context.mutable_common_tls_context() - ->mutable_combined_validation_context() - ->mutable_validation_context_certificate_provider_instance() + ->mutable_validation_context() + ->mutable_ca_certificate_provider_instance() ->set_instance_name("fake_plugin1"); transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context); balancers_[0]->ads_service()->SetCdsResource(cluster); @@ -8503,12 +8497,11 @@ TEST_P(XdsSecurityTest, transport_socket->set_name("envoy.transport_sockets.tls"); UpstreamTlsContext upstream_tls_context; upstream_tls_context.mutable_common_tls_context() - ->mutable_combined_validation_context() - ->mutable_validation_context_certificate_provider_instance() + ->mutable_validation_context() + ->mutable_ca_certificate_provider_instance() ->set_instance_name("fake_plugin1"); upstream_tls_context.mutable_common_tls_context() - ->mutable_combined_validation_context() - ->mutable_default_validation_context() + ->mutable_validation_context() ->add_verify_certificate_spki("spki"); transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context); balancers_[0]->ads_service()->SetCdsResource(cluster); @@ -8532,12 +8525,11 @@ TEST_P(XdsSecurityTest, transport_socket->set_name("envoy.transport_sockets.tls"); UpstreamTlsContext upstream_tls_context; upstream_tls_context.mutable_common_tls_context() - ->mutable_combined_validation_context() - ->mutable_validation_context_certificate_provider_instance() + ->mutable_validation_context() + ->mutable_ca_certificate_provider_instance() ->set_instance_name("fake_plugin1"); upstream_tls_context.mutable_common_tls_context() - ->mutable_combined_validation_context() - ->mutable_default_validation_context() + ->mutable_validation_context() ->add_verify_certificate_hash("hash"); transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context); balancers_[0]->ads_service()->SetCdsResource(cluster); @@ -8561,12 +8553,11 @@ TEST_P(XdsSecurityTest, transport_socket->set_name("envoy.transport_sockets.tls"); UpstreamTlsContext upstream_tls_context; upstream_tls_context.mutable_common_tls_context() - ->mutable_combined_validation_context() - ->mutable_validation_context_certificate_provider_instance() + ->mutable_validation_context() + ->mutable_ca_certificate_provider_instance() ->set_instance_name("fake_plugin1"); upstream_tls_context.mutable_common_tls_context() - ->mutable_combined_validation_context() - ->mutable_default_validation_context() + ->mutable_validation_context() ->mutable_require_signed_certificate_timestamp() ->set_value(true); transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context); @@ -8590,12 +8581,11 @@ TEST_P(XdsSecurityTest, NacksCertificateValidationContextWithCrl) { transport_socket->set_name("envoy.transport_sockets.tls"); UpstreamTlsContext upstream_tls_context; upstream_tls_context.mutable_common_tls_context() - ->mutable_combined_validation_context() - ->mutable_validation_context_certificate_provider_instance() + ->mutable_validation_context() + ->mutable_ca_certificate_provider_instance() ->set_instance_name("fake_plugin1"); upstream_tls_context.mutable_common_tls_context() - ->mutable_combined_validation_context() - ->mutable_default_validation_context() + ->mutable_validation_context() ->mutable_crl(); transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context); balancers_[0]->ads_service()->SetCdsResource(cluster); @@ -8618,12 +8608,11 @@ TEST_P(XdsSecurityTest, transport_socket->set_name("envoy.transport_sockets.tls"); UpstreamTlsContext upstream_tls_context; upstream_tls_context.mutable_common_tls_context() - ->mutable_combined_validation_context() - ->mutable_validation_context_certificate_provider_instance() + ->mutable_validation_context() + ->mutable_ca_certificate_provider_instance() ->set_instance_name("fake_plugin1"); upstream_tls_context.mutable_common_tls_context() - ->mutable_combined_validation_context() - ->mutable_default_validation_context() + ->mutable_validation_context() ->mutable_custom_validator_config(); transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context); balancers_[0]->ads_service()->SetCdsResource(cluster); @@ -8637,6 +8626,165 @@ TEST_P(XdsSecurityTest, "CertificateValidationContext: custom_validator_config unsupported")); } +TEST_P(XdsSecurityTest, NacksValidationContextSdsSecretConfig) { + FakeCertificateProvider::CertDataMap fake1_cert_map = { + {"", {root_cert_, identity_pair_}}}; + g_fake1_cert_data_map = &fake1_cert_map; + auto cluster = default_cluster_; + auto* transport_socket = cluster.mutable_transport_socket(); + transport_socket->set_name("envoy.transport_sockets.tls"); + UpstreamTlsContext upstream_tls_context; + upstream_tls_context.mutable_common_tls_context() + ->mutable_validation_context_sds_secret_config(); + transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context); + balancers_[0]->ads_service()->SetCdsResource(cluster); + ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK"; + 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("validation_context_sds_secret_config unsupported")); +} + +TEST_P(XdsSecurityTest, NacksTlsParams) { + FakeCertificateProvider::CertDataMap fake1_cert_map = { + {"", {root_cert_, identity_pair_}}}; + g_fake1_cert_data_map = &fake1_cert_map; + auto cluster = default_cluster_; + auto* transport_socket = cluster.mutable_transport_socket(); + transport_socket->set_name("envoy.transport_sockets.tls"); + UpstreamTlsContext upstream_tls_context; + upstream_tls_context.mutable_common_tls_context() + ->mutable_validation_context() + ->mutable_ca_certificate_provider_instance() + ->set_instance_name("fake_plugin1"); + upstream_tls_context.mutable_common_tls_context()->mutable_tls_params(); + transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context); + balancers_[0]->ads_service()->SetCdsResource(cluster); + ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK"; + 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("tls_params unsupported")); +} + +TEST_P(XdsSecurityTest, NacksCustomHandshaker) { + FakeCertificateProvider::CertDataMap fake1_cert_map = { + {"", {root_cert_, identity_pair_}}}; + g_fake1_cert_data_map = &fake1_cert_map; + auto cluster = default_cluster_; + auto* transport_socket = cluster.mutable_transport_socket(); + transport_socket->set_name("envoy.transport_sockets.tls"); + UpstreamTlsContext upstream_tls_context; + upstream_tls_context.mutable_common_tls_context() + ->mutable_validation_context() + ->mutable_ca_certificate_provider_instance() + ->set_instance_name("fake_plugin1"); + upstream_tls_context.mutable_common_tls_context() + ->mutable_custom_handshaker(); + transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context); + balancers_[0]->ads_service()->SetCdsResource(cluster); + ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK"; + 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("custom_handshaker unsupported")); +} + +TEST_P(XdsSecurityTest, NacksTlsCertificates) { + FakeCertificateProvider::CertDataMap fake1_cert_map = { + {"", {root_cert_, identity_pair_}}}; + g_fake1_cert_data_map = &fake1_cert_map; + auto cluster = default_cluster_; + auto* transport_socket = cluster.mutable_transport_socket(); + transport_socket->set_name("envoy.transport_sockets.tls"); + UpstreamTlsContext upstream_tls_context; + upstream_tls_context.mutable_common_tls_context() + ->mutable_validation_context() + ->mutable_ca_certificate_provider_instance() + ->set_instance_name("fake_plugin1"); + upstream_tls_context.mutable_common_tls_context()->add_tls_certificates(); + transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context); + balancers_[0]->ads_service()->SetCdsResource(cluster); + ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK"; + 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("tls_certificates unsupported")); +} + +TEST_P(XdsSecurityTest, NacksTlsCertificateSdsSecretConfigs) { + FakeCertificateProvider::CertDataMap fake1_cert_map = { + {"", {root_cert_, identity_pair_}}}; + g_fake1_cert_data_map = &fake1_cert_map; + auto cluster = default_cluster_; + auto* transport_socket = cluster.mutable_transport_socket(); + transport_socket->set_name("envoy.transport_sockets.tls"); + UpstreamTlsContext upstream_tls_context; + upstream_tls_context.mutable_common_tls_context() + ->mutable_validation_context() + ->mutable_ca_certificate_provider_instance() + ->set_instance_name("fake_plugin1"); + upstream_tls_context.mutable_common_tls_context() + ->add_tls_certificate_sds_secret_configs(); + transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context); + balancers_[0]->ads_service()->SetCdsResource(cluster); + ASSERT_TRUE(WaitForCdsNack()) << "timed out waiting for NACK"; + 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("tls_certificate_sds_secret_configs unsupported")); +} + +TEST_P(XdsSecurityTest, TestTlsConfigurationInCombinedValidationContext) { + FakeCertificateProvider::CertDataMap fake1_cert_map = { + {"", {root_cert_, identity_pair_}}}; + g_fake1_cert_data_map = &fake1_cert_map; + auto cluster = default_cluster_; + auto* transport_socket = cluster.mutable_transport_socket(); + transport_socket->set_name("envoy.transport_sockets.tls"); + UpstreamTlsContext upstream_tls_context; + upstream_tls_context.mutable_common_tls_context() + ->mutable_combined_validation_context() + ->mutable_default_validation_context() + ->mutable_ca_certificate_provider_instance() + ->set_instance_name("fake_plugin1"); + transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context); + balancers_[0]->ads_service()->SetCdsResource(cluster); + WaitForBackend(0, WaitForBackendOptions().set_allow_failures(true)); + Status status = SendRpc(); + EXPECT_TRUE(status.ok()) << "code=" << status.error_code() + << " message=" << status.error_message(); +} + +// TODO(yashykt): Remove this test once we stop supporting old fields +TEST_P(XdsSecurityTest, + TestTlsConfigurationInValidationContextCertificateProviderInstance) { + FakeCertificateProvider::CertDataMap fake1_cert_map = { + {"", {root_cert_, identity_pair_}}}; + g_fake1_cert_data_map = &fake1_cert_map; + auto cluster = default_cluster_; + auto* transport_socket = cluster.mutable_transport_socket(); + transport_socket->set_name("envoy.transport_sockets.tls"); + UpstreamTlsContext upstream_tls_context; + upstream_tls_context.mutable_common_tls_context() + ->mutable_combined_validation_context() + ->mutable_validation_context_certificate_provider_instance() + ->set_instance_name("fake_plugin1"); + transport_socket->mutable_typed_config()->PackFrom(upstream_tls_context); + balancers_[0]->ads_service()->SetCdsResource(cluster); + WaitForBackend(0, WaitForBackendOptions().set_allow_failures(true)); + Status status = SendRpc(); + EXPECT_TRUE(status.ok()) << "code=" << status.error_code() + << " message=" << status.error_message(); +} + TEST_P(XdsSecurityTest, TestMtlsConfigurationWithNoSanMatchers) { FakeCertificateProvider::CertDataMap fake1_cert_map = { {"", {root_cert_, identity_pair_}}}; @@ -9261,19 +9409,19 @@ class XdsServerSecurityTest : public XdsEnd2endTest { transport_socket->set_name("envoy.transport_sockets.tls"); DownstreamTlsContext downstream_tls_context; downstream_tls_context.mutable_common_tls_context() - ->mutable_tls_certificate_certificate_provider_instance() + ->mutable_tls_certificate_provider_instance() ->set_instance_name(std::string(identity_instance_name)); downstream_tls_context.mutable_common_tls_context() - ->mutable_tls_certificate_certificate_provider_instance() + ->mutable_tls_certificate_provider_instance() ->set_certificate_name(std::string(identity_certificate_name)); if (!root_instance_name.empty()) { downstream_tls_context.mutable_common_tls_context() - ->mutable_combined_validation_context() - ->mutable_validation_context_certificate_provider_instance() + ->mutable_validation_context() + ->mutable_ca_certificate_provider_instance() ->set_instance_name(std::string(root_instance_name)); downstream_tls_context.mutable_common_tls_context() - ->mutable_combined_validation_context() - ->mutable_validation_context_certificate_provider_instance() + ->mutable_validation_context() + ->mutable_ca_certificate_provider_instance() ->set_certificate_name(std::string(root_certificate_name)); downstream_tls_context.mutable_require_client_certificate()->set_value( require_client_certificates); @@ -9467,7 +9615,7 @@ TEST_P(XdsServerSecurityTest, NacksRequireSNI) { transport_socket->set_name("envoy.transport_sockets.tls"); DownstreamTlsContext downstream_tls_context; downstream_tls_context.mutable_common_tls_context() - ->mutable_tls_certificate_certificate_provider_instance() + ->mutable_tls_certificate_provider_instance() ->set_instance_name("fake_plugin1"); downstream_tls_context.mutable_require_sni()->set_value(true); transport_socket->mutable_typed_config()->PackFrom(downstream_tls_context); @@ -9496,7 +9644,7 @@ TEST_P(XdsServerSecurityTest, NacksOcspStaplePolicyOtherThanLenientStapling) { transport_socket->set_name("envoy.transport_sockets.tls"); DownstreamTlsContext downstream_tls_context; downstream_tls_context.mutable_common_tls_context() - ->mutable_tls_certificate_certificate_provider_instance() + ->mutable_tls_certificate_provider_instance() ->set_instance_name("fake_plugin1"); downstream_tls_context.set_ocsp_staple_policy( envoy::extensions::transport_sockets::tls::v3:: @@ -9530,7 +9678,7 @@ TEST_P( transport_socket->set_name("envoy.transport_sockets.tls"); DownstreamTlsContext downstream_tls_context; downstream_tls_context.mutable_common_tls_context() - ->mutable_tls_certificate_certificate_provider_instance() + ->mutable_tls_certificate_provider_instance() ->set_instance_name("fake_plugin1"); downstream_tls_context.mutable_require_client_certificate()->set_value(true); transport_socket->mutable_typed_config()->PackFrom(downstream_tls_context); @@ -9569,9 +9717,41 @@ TEST_P(XdsServerSecurityTest, balancers_[0]->ads_service()->lds_response_state(); EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED); EXPECT_THAT(response_state.error_message, - ::testing::HasSubstr( - "TLS configuration provided but no " - "tls_certificate_certificate_provider_instance found.")); + ::testing::HasSubstr("TLS configuration provided but no " + "tls_certificate_provider_instance found.")); +} + +TEST_P(XdsServerSecurityTest, NacksMatchSubjectAltNames) { + Listener listener; + listener.set_name( + absl::StrCat("grpc/server?xds.resource.listening_address=", + ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port())); + 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("envoy.transport_sockets.tls"); + DownstreamTlsContext downstream_tls_context; + downstream_tls_context.mutable_common_tls_context() + ->mutable_tls_certificate_provider_instance() + ->set_instance_name("fake_plugin1"); + downstream_tls_context.mutable_common_tls_context() + ->mutable_validation_context() + ->add_match_subject_alt_names() + ->set_exact("*.test.google.fr"); + transport_socket->mutable_typed_config()->PackFrom(downstream_tls_context); + balancers_[0]->ads_service()->SetLdsResource(listener); + ASSERT_TRUE(WaitForLdsNack(StatusCode::DEADLINE_EXCEEDED)) + << "timed out waiting for NACK"; + 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("match_subject_alt_names not supported on servers")); } TEST_P(XdsServerSecurityTest, UnknownIdentityCertificateProvider) { @@ -9602,6 +9782,35 @@ TEST_P(XdsServerSecurityTest, UnknownRootCertificateProvider) { "Unrecognized certificate provider instance name: unknown")); } +TEST_P(XdsServerSecurityTest, + TestDeprecateTlsCertificateCertificateProviderInstanceField) { + FakeCertificateProvider::CertDataMap fake1_cert_map = { + {"", {root_cert_, identity_pair_}}}; + g_fake1_cert_data_map = &fake1_cert_map; + Listener listener; + listener.set_name(absl::StrCat( + ipv6_only_ ? "grpc/server?xds.resource.listening_address=[::1]:" + : "grpc/server?xds.resource.listening_address=127.0.0.1:", + backends_[0]->port())); + listener.mutable_address()->mutable_socket_address()->set_address( + ipv6_only_ ? "[::1]" : "127.0.0.1"); + listener.mutable_address()->mutable_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("envoy.transport_sockets.tls"); + DownstreamTlsContext downstream_tls_context; + downstream_tls_context.mutable_common_tls_context() + ->mutable_tls_certificate_certificate_provider_instance() + ->set_instance_name("fake_plugin1"); + transport_socket->mutable_typed_config()->PackFrom(downstream_tls_context); + balancers_[0]->ads_service()->SetLdsResource(listener); + SendRpc([this]() { return CreateTlsChannel(); }, + server_authenticated_identity_, {}); +} + TEST_P(XdsServerSecurityTest, CertificatesNotAvailable) { FakeCertificateProvider::CertDataMap fake1_cert_map; g_fake1_cert_data_map = &fake1_cert_map; @@ -10340,7 +10549,7 @@ TEST_P(XdsServerFilterChainMatchTest, transport_socket->set_name("envoy.transport_sockets.tls"); DownstreamTlsContext downstream_tls_context; downstream_tls_context.mutable_common_tls_context() - ->mutable_tls_certificate_certificate_provider_instance() + ->mutable_tls_certificate_provider_instance() ->set_instance_name("fake_plugin1"); transport_socket->mutable_typed_config()->PackFrom(downstream_tls_context); balancers_[0]->ads_service()->SetLdsResource(listener);