finish metadata refactoring

pull/37550/head
Mark D. Roth 6 months ago
parent cb098e830f
commit 7af5c28449
  1. 112
      CMakeLists.txt
  2. 2
      Makefile
  3. 4
      Package.swift
  4. 41
      build_autogenerated.yaml
  5. 2
      config.m4
  6. 2
      config.w32
  7. 4
      gRPC-C++.podspec
  8. 6
      gRPC-Core.podspec
  9. 4
      grpc.gemspec
  10. 4
      package.xml
  11. 7
      src/core/xds/grpc/xds_cluster_parser.cc
  12. 1
      src/core/xds/grpc/xds_metadata.h
  13. 7
      src/core/xds/grpc/xds_metadata_parser.cc
  14. 2
      src/python/grpcio/grpc_core_dependencies.py
  15. 18
      test/core/xds/BUILD
  16. 159
      test/core/xds/xds_cluster_resource_type_test.cc
  17. 277
      test/core/xds/xds_metadata_test.cc
  18. 4
      tools/doxygen/Doxyfile.c++.internal
  19. 4
      tools/doxygen/Doxyfile.core.internal
  20. 48
      tools/run_tests/generated/tests.json

112
CMakeLists.txt generated

@ -1123,6 +1123,7 @@ if(gRPC_BUILD_TESTS)
add_dependencies(buildtests_cxx fuzzing_event_engine_test)
endif()
add_dependencies(buildtests_cxx fuzzing_event_engine_unittest)
add_dependencies(buildtests_cxx gcp_authentication_filter_test)
add_dependencies(buildtests_cxx generic_end2end_test)
add_dependencies(buildtests_cxx glob_test)
add_dependencies(buildtests_cxx goaway_server_test)
@ -1596,6 +1597,7 @@ if(gRPC_BUILD_TESTS)
add_dependencies(buildtests_cxx xds_http_filters_test)
add_dependencies(buildtests_cxx xds_lb_policy_registry_test)
add_dependencies(buildtests_cxx xds_listener_resource_type_test)
add_dependencies(buildtests_cxx xds_metadata_test)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
add_dependencies(buildtests_cxx xds_outlier_detection_end2end_test)
endif()
@ -2653,6 +2655,8 @@ add_library(grpc
src/core/xds/grpc/xds_lb_policy_registry.cc
src/core/xds/grpc/xds_listener.cc
src/core/xds/grpc/xds_listener_parser.cc
src/core/xds/grpc/xds_metadata.cc
src/core/xds/grpc/xds_metadata_parser.cc
src/core/xds/grpc/xds_route_config.cc
src/core/xds/grpc/xds_route_config_parser.cc
src/core/xds/grpc/xds_routing.cc
@ -15339,6 +15343,55 @@ target_link_libraries(fuzzing_event_engine_unittest
)
endif()
if(gRPC_BUILD_TESTS)
add_executable(gcp_authentication_filter_test
${_gRPC_PROTO_GENS_DIR}/test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.pb.cc
${_gRPC_PROTO_GENS_DIR}/test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.pb.h
${_gRPC_PROTO_GENS_DIR}/test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.grpc.pb.h
test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.cc
test/core/filters/filter_test.cc
test/core/filters/gcp_authentication_filter_test.cc
)
if(WIN32 AND MSVC)
if(BUILD_SHARED_LIBS)
target_compile_definitions(gcp_authentication_filter_test
PRIVATE
"GPR_DLL_IMPORTS"
"GRPC_DLL_IMPORTS"
)
endif()
endif()
target_compile_features(gcp_authentication_filter_test PUBLIC cxx_std_14)
target_include_directories(gcp_authentication_filter_test
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
${_gRPC_RE2_INCLUDE_DIR}
${_gRPC_SSL_INCLUDE_DIR}
${_gRPC_UPB_GENERATED_DIR}
${_gRPC_UPB_GRPC_GENERATED_DIR}
${_gRPC_UPB_INCLUDE_DIR}
${_gRPC_XXHASH_INCLUDE_DIR}
${_gRPC_ZLIB_INCLUDE_DIR}
third_party/googletest/googletest/include
third_party/googletest/googletest
third_party/googletest/googlemock/include
third_party/googletest/googlemock
${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(gcp_authentication_filter_test
${_gRPC_ALLTARGETS_LIBRARIES}
gtest
${_gRPC_PROTOBUF_LIBRARIES}
grpc_test_util
)
endif()
if(gRPC_BUILD_TESTS)
@ -36005,6 +36058,65 @@ target_link_libraries(xds_listener_resource_type_test
)
endif()
if(gRPC_BUILD_TESTS)
add_executable(xds_metadata_test
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/gcp_authn.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/gcp_authn.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/gcp_authn.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/gcp_authn.grpc.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.grpc.pb.cc
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.pb.h
${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.grpc.pb.h
src/cpp/client/global_callback_hook.cc
src/cpp/util/status.cc
test/core/xds/xds_metadata_test.cc
)
if(WIN32 AND MSVC)
if(BUILD_SHARED_LIBS)
target_compile_definitions(xds_metadata_test
PRIVATE
"GPR_DLL_IMPORTS"
"GRPC_DLL_IMPORTS"
)
endif()
endif()
target_compile_features(xds_metadata_test PUBLIC cxx_std_14)
target_include_directories(xds_metadata_test
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
${_gRPC_RE2_INCLUDE_DIR}
${_gRPC_SSL_INCLUDE_DIR}
${_gRPC_UPB_GENERATED_DIR}
${_gRPC_UPB_GRPC_GENERATED_DIR}
${_gRPC_UPB_INCLUDE_DIR}
${_gRPC_XXHASH_INCLUDE_DIR}
${_gRPC_ZLIB_INCLUDE_DIR}
third_party/googletest/googletest/include
third_party/googletest/googletest
third_party/googletest/googlemock/include
third_party/googletest/googlemock
${_gRPC_PROTO_GENS_DIR}
)
target_link_libraries(xds_metadata_test
${_gRPC_ALLTARGETS_LIBRARIES}
gtest
absl::absl_check
absl::absl_log
${_gRPC_PROTOBUF_LIBRARIES}
grpc_test_util
)
endif()
if(gRPC_BUILD_TESTS)
if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)

2
Makefile generated

@ -1512,6 +1512,8 @@ LIBGRPC_SRC = \
src/core/xds/grpc/xds_lb_policy_registry.cc \
src/core/xds/grpc/xds_listener.cc \
src/core/xds/grpc/xds_listener_parser.cc \
src/core/xds/grpc/xds_metadata.cc \
src/core/xds/grpc/xds_metadata_parser.cc \
src/core/xds/grpc/xds_route_config.cc \
src/core/xds/grpc/xds_route_config_parser.cc \
src/core/xds/grpc/xds_routing.cc \

4
Package.swift generated

@ -2021,6 +2021,10 @@ let package = Package(
"src/core/xds/grpc/xds_listener.h",
"src/core/xds/grpc/xds_listener_parser.cc",
"src/core/xds/grpc/xds_listener_parser.h",
"src/core/xds/grpc/xds_metadata.cc",
"src/core/xds/grpc/xds_metadata.h",
"src/core/xds/grpc/xds_metadata_parser.cc",
"src/core/xds/grpc/xds_metadata_parser.h",
"src/core/xds/grpc/xds_route_config.cc",
"src/core/xds/grpc/xds_route_config.h",
"src/core/xds/grpc/xds_route_config_parser.cc",

@ -1253,6 +1253,8 @@ libs:
- src/core/xds/grpc/xds_lb_policy_registry.h
- src/core/xds/grpc/xds_listener.h
- src/core/xds/grpc/xds_listener_parser.h
- src/core/xds/grpc/xds_metadata.h
- src/core/xds/grpc/xds_metadata_parser.h
- src/core/xds/grpc/xds_route_config.h
- src/core/xds/grpc/xds_route_config_parser.h
- src/core/xds/grpc/xds_routing.h
@ -2071,6 +2073,8 @@ libs:
- src/core/xds/grpc/xds_lb_policy_registry.cc
- src/core/xds/grpc/xds_listener.cc
- src/core/xds/grpc/xds_listener_parser.cc
- src/core/xds/grpc/xds_metadata.cc
- src/core/xds/grpc/xds_metadata_parser.cc
- src/core/xds/grpc/xds_route_config.cc
- src/core/xds/grpc/xds_route_config_parser.cc
- src/core/xds/grpc/xds_routing.cc
@ -10889,6 +10893,23 @@ targets:
- gtest
- protobuf
- grpc_test_util
- name: gcp_authentication_filter_test
gtest: true
build: test
language: c++
headers:
- test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.h
- test/core/filters/filter_test.h
src:
- test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.proto
- test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.cc
- test/core/filters/filter_test.cc
- test/core/filters/gcp_authentication_filter_test.cc
deps:
- gtest
- protobuf
- grpc_test_util
uses_polling: false
- name: generic_end2end_test
gtest: true
build: test
@ -21990,6 +22011,26 @@ targets:
- protoc
- grpc_test_util
uses_polling: false
- name: xds_metadata_test
gtest: true
build: test
language: c++
headers:
- test/core/test_util/scoped_env_var.h
src:
- src/proto/grpc/testing/xds/v3/base.proto
- src/proto/grpc/testing/xds/v3/gcp_authn.proto
- src/proto/grpc/testing/xds/v3/percent.proto
- src/cpp/client/global_callback_hook.cc
- src/cpp/util/status.cc
- test/core/xds/xds_metadata_test.cc
deps:
- gtest
- absl/log:absl_check
- absl/log:absl_log
- protobuf
- grpc_test_util
uses_polling: false
- name: xds_outlier_detection_end2end_test
gtest: true
build: test

2
config.m4 generated

@ -887,6 +887,8 @@ if test "$PHP_GRPC" != "no"; then
src/core/xds/grpc/xds_lb_policy_registry.cc \
src/core/xds/grpc/xds_listener.cc \
src/core/xds/grpc/xds_listener_parser.cc \
src/core/xds/grpc/xds_metadata.cc \
src/core/xds/grpc/xds_metadata_parser.cc \
src/core/xds/grpc/xds_route_config.cc \
src/core/xds/grpc/xds_route_config_parser.cc \
src/core/xds/grpc/xds_routing.cc \

2
config.w32 generated

@ -852,6 +852,8 @@ if (PHP_GRPC != "no") {
"src\\core\\xds\\grpc\\xds_lb_policy_registry.cc " +
"src\\core\\xds\\grpc\\xds_listener.cc " +
"src\\core\\xds\\grpc\\xds_listener_parser.cc " +
"src\\core\\xds\\grpc\\xds_metadata.cc " +
"src\\core\\xds\\grpc\\xds_metadata_parser.cc " +
"src\\core\\xds\\grpc\\xds_route_config.cc " +
"src\\core\\xds\\grpc\\xds_route_config_parser.cc " +
"src\\core\\xds\\grpc\\xds_routing.cc " +

4
gRPC-C++.podspec generated

@ -1363,6 +1363,8 @@ Pod::Spec.new do |s|
'src/core/xds/grpc/xds_lb_policy_registry.h',
'src/core/xds/grpc/xds_listener.h',
'src/core/xds/grpc/xds_listener_parser.h',
'src/core/xds/grpc/xds_metadata.h',
'src/core/xds/grpc/xds_metadata_parser.h',
'src/core/xds/grpc/xds_route_config.h',
'src/core/xds/grpc/xds_route_config_parser.h',
'src/core/xds/grpc/xds_routing.h',
@ -2658,6 +2660,8 @@ Pod::Spec.new do |s|
'src/core/xds/grpc/xds_lb_policy_registry.h',
'src/core/xds/grpc/xds_listener.h',
'src/core/xds/grpc/xds_listener_parser.h',
'src/core/xds/grpc/xds_metadata.h',
'src/core/xds/grpc/xds_metadata_parser.h',
'src/core/xds/grpc/xds_route_config.h',
'src/core/xds/grpc/xds_route_config_parser.h',
'src/core/xds/grpc/xds_routing.h',

6
gRPC-Core.podspec generated

@ -2137,6 +2137,10 @@ Pod::Spec.new do |s|
'src/core/xds/grpc/xds_listener.h',
'src/core/xds/grpc/xds_listener_parser.cc',
'src/core/xds/grpc/xds_listener_parser.h',
'src/core/xds/grpc/xds_metadata.cc',
'src/core/xds/grpc/xds_metadata.h',
'src/core/xds/grpc/xds_metadata_parser.cc',
'src/core/xds/grpc/xds_metadata_parser.h',
'src/core/xds/grpc/xds_route_config.cc',
'src/core/xds/grpc/xds_route_config.h',
'src/core/xds/grpc/xds_route_config_parser.cc',
@ -3443,6 +3447,8 @@ Pod::Spec.new do |s|
'src/core/xds/grpc/xds_lb_policy_registry.h',
'src/core/xds/grpc/xds_listener.h',
'src/core/xds/grpc/xds_listener_parser.h',
'src/core/xds/grpc/xds_metadata.h',
'src/core/xds/grpc/xds_metadata_parser.h',
'src/core/xds/grpc/xds_route_config.h',
'src/core/xds/grpc/xds_route_config_parser.h',
'src/core/xds/grpc/xds_routing.h',

4
grpc.gemspec generated

@ -2023,6 +2023,10 @@ Gem::Specification.new do |s|
s.files += %w( src/core/xds/grpc/xds_listener.h )
s.files += %w( src/core/xds/grpc/xds_listener_parser.cc )
s.files += %w( src/core/xds/grpc/xds_listener_parser.h )
s.files += %w( src/core/xds/grpc/xds_metadata.cc )
s.files += %w( src/core/xds/grpc/xds_metadata.h )
s.files += %w( src/core/xds/grpc/xds_metadata_parser.cc )
s.files += %w( src/core/xds/grpc/xds_metadata_parser.h )
s.files += %w( src/core/xds/grpc/xds_route_config.cc )
s.files += %w( src/core/xds/grpc/xds_route_config.h )
s.files += %w( src/core/xds/grpc/xds_route_config_parser.cc )

4
package.xml generated

@ -2005,6 +2005,10 @@
<file baseinstalldir="/" name="src/core/xds/grpc/xds_listener.h" role="src" />
<file baseinstalldir="/" name="src/core/xds/grpc/xds_listener_parser.cc" role="src" />
<file baseinstalldir="/" name="src/core/xds/grpc/xds_listener_parser.h" role="src" />
<file baseinstalldir="/" name="src/core/xds/grpc/xds_metadata.cc" role="src" />
<file baseinstalldir="/" name="src/core/xds/grpc/xds_metadata.h" role="src" />
<file baseinstalldir="/" name="src/core/xds/grpc/xds_metadata_parser.cc" role="src" />
<file baseinstalldir="/" name="src/core/xds/grpc/xds_metadata_parser.h" role="src" />
<file baseinstalldir="/" name="src/core/xds/grpc/xds_route_config.cc" role="src" />
<file baseinstalldir="/" name="src/core/xds/grpc/xds_route_config.h" role="src" />
<file baseinstalldir="/" name="src/core/xds/grpc/xds_route_config_parser.cc" role="src" />

@ -632,8 +632,11 @@ absl::StatusOr<std::shared_ptr<const XdsClusterResource>> CdsResourceParse(
XdsHealthStatus(XdsHealthStatus::kHealthy));
}
// Parse metadata.
cds_update->metadata = ParseXdsMetadataMap(
context, envoy_config_cluster_v3_Cluster_metadata(cluster), &errors);
{
ValidationErrors::ScopedField field(&errors, ".metadata");
cds_update->metadata = ParseXdsMetadataMap(
context, envoy_config_cluster_v3_Cluster_metadata(cluster), &errors);
}
// Return result.
if (!errors.ok()) {
return errors.status(absl::StatusCode::kInvalidArgument,

@ -62,6 +62,7 @@ class XdsMetadataMap {
const XdsMetadataValue* Find(absl::string_view key) const;
bool empty() const { return map_.empty(); }
size_t size() const { return map_.size(); }
bool operator==(const XdsMetadataMap& other) const;

@ -112,8 +112,11 @@ XdsMetadataMap ParseXdsMetadataMap(
// this into a separate registry.
if (XdsGcpAuthFilterEnabled() &&
extension->type == XdsGcpAuthnAudienceMetadataValue::Type()) {
metadata_map.Insert(
key, ParseGcpAuthnAudience(context, std::move(*extension), errors));
auto metadata_value =
ParseGcpAuthnAudience(context, std::move(*extension), errors);
if (metadata_value != nullptr) {
metadata_map.Insert(key, std::move(metadata_value));
}
}
}
// Then, try filter_metadata.

@ -861,6 +861,8 @@ CORE_SOURCE_FILES = [
'src/core/xds/grpc/xds_lb_policy_registry.cc',
'src/core/xds/grpc/xds_listener.cc',
'src/core/xds/grpc/xds_listener_parser.cc',
'src/core/xds/grpc/xds_metadata.cc',
'src/core/xds/grpc/xds_metadata_parser.cc',
'src/core/xds/grpc/xds_route_config.cc',
'src/core/xds/grpc/xds_route_config_parser.cc',
'src/core/xds/grpc/xds_routing.cc',

@ -230,6 +230,24 @@ grpc_cc_test(
],
)
grpc_cc_test(
name = "xds_metadata_test",
srcs = ["xds_metadata_test.cc"],
external_deps = ["gtest"],
language = "C++",
uses_event_engine = False,
uses_polling = False,
deps = [
"//:gpr",
"//:grpc",
"//src/core:grpc_xds_client",
"//src/proto/grpc/testing/xds/v3:base_proto",
"//src/proto/grpc/testing/xds/v3:gcp_authn_proto",
"//test/core/test_util:grpc_test_util",
"//test/core/test_util:scoped_env_var",
],
)
grpc_cc_test(
name = "xds_http_filters_test",
srcs = ["xds_http_filters_test.cc"],

@ -1654,13 +1654,6 @@ MATCHER_P(JsonEq, json_str, "") {
return ok;
}
MATCHER_P2(MetadataEntryEq, type, json_matcher, "") {
bool ok = ::testing::ExplainMatchResult(type, arg.type, result_listener);
ok &= ::testing::ExplainMatchResult(json_matcher, arg.json,
result_listener);
return ok;
}
TEST_F(MetadataTest, UntypedMetadata) {
Cluster cluster;
cluster.set_type(cluster.EDS);
@ -1668,78 +1661,6 @@ TEST_F(MetadataTest, UntypedMetadata) {
auto& filter_map = *cluster.mutable_metadata()->mutable_filter_metadata();
auto& label_map = *filter_map["filter_key"].mutable_fields();
*label_map["string_value"].mutable_string_value() = "abc";
label_map["bool_value"].set_bool_value(true);
label_map["number_value"].set_number_value(3.14);
label_map["null_value"].set_null_value(::google::protobuf::NULL_VALUE);
auto& list_value_values =
*label_map["list_value"].mutable_list_value()->mutable_values();
*list_value_values.Add()->mutable_string_value() = "efg";
list_value_values.Add()->set_number_value(3.14);
auto& struct_value_fields =
*label_map["struct_value"].mutable_struct_value()->mutable_fields();
struct_value_fields["bool_value"].set_bool_value(false);
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
auto& resource =
static_cast<const XdsClusterResource&>(**decode_result.resource);
EXPECT_THAT(resource.metadata,
::testing::ElementsAre(::testing::Pair(
"filter_key", MetadataEntryEq(
"google.protobuf.Struct",
JsonEq("{"
"\"bool_value\":true,"
"\"list_value\":[\"efg\",3.14],"
"\"null_value\":null,"
"\"number_value\":3.14,"
"\"string_value\":\"abc\","
"\"struct_value\":{\"bool_value\":false}"
"}")))));
}
TEST_F(MetadataTest, TypedMetadataTakesPrecendenceOverUntyped) {
ScopedExperimentalEnvVar env_var(
"GRPC_EXPERIMENTAL_XDS_GCP_AUTHENTICATION_FILTER");
Cluster cluster;
cluster.set_type(cluster.EDS);
cluster.mutable_eds_cluster_config()->mutable_eds_config()->mutable_self();
auto& filter_map = *cluster.mutable_metadata()->mutable_filter_metadata();
auto& label_map = *filter_map["filter_key"].mutable_fields();
*label_map["string_value"].mutable_string_value() = "abc";
Audience audience_proto;
audience_proto.set_url("foo");
auto& typed_filter_map =
*cluster.mutable_metadata()->mutable_typed_filter_metadata();
typed_filter_map["filter_key"].PackFrom(audience_proto);
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
auto& resource =
static_cast<const XdsClusterResource&>(**decode_result.resource);
EXPECT_THAT(resource.metadata,
::testing::ElementsAre(::testing::Pair(
"filter_key", MetadataEntryEq(
kXdsAudienceClusterMetadataType,
JsonEq("{\"url\":\"foo\"}")))));
}
TEST_F(MetadataTest, AudienceMetadata) {
ScopedExperimentalEnvVar env_var(
"GRPC_EXPERIMENTAL_XDS_GCP_AUTHENTICATION_FILTER");
Cluster cluster;
cluster.set_type(cluster.EDS);
cluster.mutable_eds_cluster_config()->mutable_eds_config()->mutable_self();
Audience audience_proto;
audience_proto.set_url("foo");
auto& filter_map =
*cluster.mutable_metadata()->mutable_typed_filter_metadata();
filter_map["filter_key"].PackFrom(audience_proto);
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
@ -1748,14 +1669,18 @@ TEST_F(MetadataTest, AudienceMetadata) {
ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
auto& resource =
static_cast<const XdsClusterResource&>(**decode_result.resource);
EXPECT_THAT(resource.metadata,
::testing::ElementsAre(::testing::Pair(
"filter_key", MetadataEntryEq(
kXdsAudienceClusterMetadataType,
JsonEq("{\"url\":\"foo\"}")))));
}
TEST_F(MetadataTest, AudienceMetadataUnparseable) {
ASSERT_EQ(resource.metadata.size(), 1);
auto* entry = resource.metadata.Find("filter_key");
ASSERT_NE(entry, nullptr);
ASSERT_EQ(entry->type(), XdsStructMetadataValue::Type());
EXPECT_THAT(DownCast<const XdsStructMetadataValue*>(entry)->json(),
JsonEq("{\"string_value\":\"abc\"}"));
}
// Test just one possible error from metadata validation, to make sure
// they're being passed through. A complete set of tests for metadata
// validation is in xds_metadata_test.cc.
TEST_F(MetadataTest, MetadataUnparseable) {
ScopedExperimentalEnvVar env_var(
"GRPC_EXPERIMENTAL_XDS_GCP_AUTHENTICATION_FILTER");
Cluster cluster;
@ -1781,66 +1706,6 @@ TEST_F(MetadataTest, AudienceMetadataUnparseable) {
<< decode_result.resource.status();
}
TEST_F(MetadataTest, AudienceMetadataMissingUrl) {
ScopedExperimentalEnvVar env_var(
"GRPC_EXPERIMENTAL_XDS_GCP_AUTHENTICATION_FILTER");
Cluster cluster;
cluster.set_type(cluster.EDS);
cluster.mutable_eds_cluster_config()->mutable_eds_config()->mutable_self();
Audience audience_proto;
auto& filter_map =
*cluster.mutable_metadata()->mutable_typed_filter_metadata();
filter_map["filter_key"].PackFrom(audience_proto);
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
EXPECT_EQ(decode_result.resource.status().code(),
absl::StatusCode::kInvalidArgument);
EXPECT_EQ(decode_result.resource.status().message(),
"errors validating Cluster resource: ["
"field:metadata.typed_filter_metadata[filter_key].value["
"envoy.extensions.filters.http.gcp_authn.v3.Audience].url "
"error:must be non-empty]")
<< decode_result.resource.status();
}
TEST_F(MetadataTest, AudienceIgnoredIfNotEnabled) {
Cluster cluster;
cluster.set_type(cluster.EDS);
cluster.mutable_eds_cluster_config()->mutable_eds_config()->mutable_self();
Audience audience_proto;
audience_proto.set_url("foo");
auto& filter_map =
*cluster.mutable_metadata()->mutable_typed_filter_metadata();
filter_map["filter_key"].PackFrom(audience_proto);
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
auto& resource =
static_cast<const XdsClusterResource&>(**decode_result.resource);
EXPECT_THAT(resource.metadata, ::testing::ElementsAre());
}
TEST_F(MetadataTest, MetadataUnset) {
Cluster cluster;
cluster.set_type(cluster.EDS);
cluster.mutable_eds_cluster_config()->mutable_eds_config()->mutable_self();
std::string serialized_resource;
ASSERT_TRUE(cluster.SerializeToString(&serialized_resource));
auto* resource_type = XdsClusterResourceType::Get();
auto decode_result =
resource_type->Decode(decode_context_, serialized_resource);
ASSERT_TRUE(decode_result.resource.ok()) << decode_result.resource.status();
auto& resource =
static_cast<const XdsClusterResource&>(**decode_result.resource);
EXPECT_THAT(resource.metadata, ::testing::ElementsAre());
}
} // namespace
} // namespace testing
} // namespace grpc_core

@ -0,0 +1,277 @@
//
// Copyright 2022 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include <string>
#include <utility>
#include <google/protobuf/any.pb.h>
#include <google/protobuf/struct.pb.h>
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_format.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/gprpp/crash.h"
#include "src/core/lib/gprpp/ref_counted_ptr.h"
#include "src/core/util/json/json.h"
#include "src/core/util/json/json_writer.h"
#include "src/core/xds/grpc/xds_bootstrap_grpc.h"
#include "src/core/xds/grpc/xds_metadata.h"
#include "src/core/xds/grpc/xds_metadata_parser.h"
#include "src/core/xds/xds_client/xds_bootstrap.h"
#include "src/core/xds/xds_client/xds_client.h"
#include "src/core/xds/xds_client/xds_resource_type.h"
#include "src/proto/grpc/testing/xds/v3/base.pb.h"
#include "src/proto/grpc/testing/xds/v3/gcp_authn.pb.h"
#include "test/core/test_util/scoped_env_var.h"
#include "test/core/test_util/test_config.h"
using envoy::config::core::v3::Metadata;
using envoy::extensions::filters::http::gcp_authn::v3::Audience;
namespace grpc_core {
namespace testing {
namespace {
class XdsMetadataTest : public ::testing::Test {
protected:
XdsMetadataTest()
: xds_client_(MakeXdsClient()),
decode_context_{xds_client_.get(),
*xds_client_->bootstrap().servers().front(),
// FIXME: why does each test need its own tracer?
&xds_cluster_resource_type_test_trace,
upb_def_pool_.ptr(), upb_arena_.ptr()} {}
static RefCountedPtr<XdsClient> MakeXdsClient() {
auto bootstrap = GrpcXdsBootstrap::Create(
"{\n"
" \"xds_servers\": [\n"
" {\n"
" \"server_uri\": \"xds.example.com\",\n"
" \"channel_creds\": [\n"
" {\"type\": \"google_default\"}\n"
" ]\n"
" }\n"
" ]\n"
"}");
if (!bootstrap.ok()) {
Crash(absl::StrFormat("Error parsing bootstrap: %s",
bootstrap.status().ToString().c_str()));
}
return MakeRefCounted<XdsClient>(std::move(*bootstrap),
/*transport_factory=*/nullptr,
/*event_engine=*/nullptr,
/*metrics_reporter=*/nullptr, "foo agent",
"foo version");
}
// For convenience, tests build protos using the protobuf API and then
// use this function to convert it to a upb object, which can be
// passed to ParseXdsMetadataMap() for validation.
const envoy_config_core_v3_Metadata* ConvertToUpb(Metadata proto) {
// Serialize the protobuf proto.
std::string serialized_proto;
if (!proto.SerializeToString(&serialized_proto)) {
EXPECT_TRUE(false) << "protobuf serialization failed";
return nullptr;
}
// Deserialize as upb proto.
const auto* upb_proto = envoy_config_core_v3_Metadata_parse(
serialized_proto.data(), serialized_proto.size(), upb_arena_.ptr());
if (upb_proto == nullptr) {
EXPECT_TRUE(false) << "upb parsing failed";
return nullptr;
}
return upb_proto;
}
absl::StatusOr<XdsMetadataMap> Parse(
const envoy_config_core_v3_Metadata* upb_proto) {
ValidationErrors errors;
XdsMetadataMap metadata_map =
ParseXdsMetadataMap(decode_context_, upb_proto, &errors);
if (!errors.ok()) {
return errors.status(absl::StatusCode::kInvalidArgument,
"validation failed");
}
return metadata_map;
}
absl::StatusOr<XdsMetadataMap> Decode(Metadata proto) {
const envoy_config_core_v3_Metadata* upb_proto =
ConvertToUpb(std::move(proto));
return Parse(upb_proto);
}
RefCountedPtr<XdsClient> xds_client_;
upb::DefPool upb_def_pool_;
upb::Arena upb_arena_;
XdsResourceType::DecodeContext decode_context_;
};
MATCHER_P(JsonEq, json_str, "") {
std::string actual = JsonDump(arg);
bool ok = ::testing::ExplainMatchResult(json_str, actual, result_listener);
if (!ok) *result_listener << "Actual: " << actual;
return ok;
}
TEST_F(XdsMetadataTest, UntypedMetadata) {
Metadata metadata_proto;
auto& filter_map = *metadata_proto.mutable_filter_metadata();
auto& label_map = *filter_map["filter_key"].mutable_fields();
*label_map["string_value"].mutable_string_value() = "abc";
label_map["bool_value"].set_bool_value(true);
label_map["number_value"].set_number_value(3.14);
label_map["null_value"].set_null_value(::google::protobuf::NULL_VALUE);
auto& list_value_values =
*label_map["list_value"].mutable_list_value()->mutable_values();
*list_value_values.Add()->mutable_string_value() = "efg";
list_value_values.Add()->set_number_value(3.14);
auto& struct_value_fields =
*label_map["struct_value"].mutable_struct_value()->mutable_fields();
struct_value_fields["bool_value"].set_bool_value(false);
// Decode.
auto metadata_map = Decode(std::move(metadata_proto));
ASSERT_TRUE(metadata_map.ok()) << metadata_map.status();
ASSERT_EQ(metadata_map->size(), 1);
auto* entry = metadata_map->Find("filter_key");
ASSERT_NE(entry, nullptr);
ASSERT_EQ(XdsStructMetadataValue::Type(), entry->type());
EXPECT_THAT(DownCast<const XdsStructMetadataValue*>(entry)->json(),
JsonEq("{"
"\"bool_value\":true,"
"\"list_value\":[\"efg\",3.14],"
"\"null_value\":null,"
"\"number_value\":3.14,"
"\"string_value\":\"abc\","
"\"struct_value\":{\"bool_value\":false}"
"}"));
}
TEST_F(XdsMetadataTest, TypedMetadataTakesPrecendenceOverUntyped) {
ScopedExperimentalEnvVar env_var(
"GRPC_EXPERIMENTAL_XDS_GCP_AUTHENTICATION_FILTER");
Metadata metadata_proto;
auto& filter_map = *metadata_proto.mutable_filter_metadata();
auto& label_map = *filter_map["filter_key"].mutable_fields();
*label_map["string_value"].mutable_string_value() = "abc";
Audience audience_proto;
audience_proto.set_url("foo");
auto& typed_filter_map = *metadata_proto.mutable_typed_filter_metadata();
typed_filter_map["filter_key"].PackFrom(audience_proto);
// Decode.
auto metadata_map = Decode(std::move(metadata_proto));
ASSERT_TRUE(metadata_map.ok()) << metadata_map.status();
ASSERT_EQ(metadata_map->size(), 1);
auto* entry = metadata_map->Find("filter_key");
ASSERT_NE(entry, nullptr);
ASSERT_EQ(XdsGcpAuthnAudienceMetadataValue::Type(), entry->type());
EXPECT_EQ(DownCast<const XdsGcpAuthnAudienceMetadataValue*>(entry)->url(),
"foo");
}
TEST_F(XdsMetadataTest, AudienceMetadata) {
ScopedExperimentalEnvVar env_var(
"GRPC_EXPERIMENTAL_XDS_GCP_AUTHENTICATION_FILTER");
Audience audience_proto;
audience_proto.set_url("foo");
Metadata metadata_proto;
auto& filter_map = *metadata_proto.mutable_typed_filter_metadata();
filter_map["filter_key"].PackFrom(audience_proto);
// Decode.
auto metadata_map = Decode(std::move(metadata_proto));
ASSERT_TRUE(metadata_map.ok()) << metadata_map.status();
ASSERT_EQ(metadata_map->size(), 1);
auto* entry = metadata_map->Find("filter_key");
ASSERT_NE(entry, nullptr);
ASSERT_EQ(XdsGcpAuthnAudienceMetadataValue::Type(), entry->type());
EXPECT_EQ(DownCast<const XdsGcpAuthnAudienceMetadataValue*>(entry)->url(),
"foo");
}
TEST_F(XdsMetadataTest, AudienceMetadataUnparseable) {
ScopedExperimentalEnvVar env_var(
"GRPC_EXPERIMENTAL_XDS_GCP_AUTHENTICATION_FILTER");
Metadata metadata_proto;
auto& filter_map = *metadata_proto.mutable_typed_filter_metadata();
auto& entry = filter_map["filter_key"];
entry.PackFrom(Audience());
entry.set_value(std::string("\0", 1));
// Decode.
auto metadata_map = Decode(std::move(metadata_proto));
EXPECT_EQ(metadata_map.status().code(),
absl::StatusCode::kInvalidArgument);
EXPECT_EQ(metadata_map.status().message(),
"validation failed: ["
"field:typed_filter_metadata[filter_key].value["
"envoy.extensions.filters.http.gcp_authn.v3.Audience] "
"error:could not parse audience metadata]")
<< metadata_map.status();
}
TEST_F(XdsMetadataTest, AudienceMetadataMissingUrl) {
ScopedExperimentalEnvVar env_var(
"GRPC_EXPERIMENTAL_XDS_GCP_AUTHENTICATION_FILTER");
Metadata metadata_proto;
auto& filter_map = *metadata_proto.mutable_typed_filter_metadata();
filter_map["filter_key"].PackFrom(Audience());
// Decode.
auto metadata_map = Decode(std::move(metadata_proto));
EXPECT_EQ(metadata_map.status().code(),
absl::StatusCode::kInvalidArgument);
EXPECT_EQ(metadata_map.status().message(),
"validation failed: ["
"field:typed_filter_metadata[filter_key].value["
"envoy.extensions.filters.http.gcp_authn.v3.Audience].url "
"error:must be non-empty]")
<< metadata_map.status();
}
TEST_F(XdsMetadataTest, AudienceIgnoredIfNotEnabled) {
Audience audience_proto;
audience_proto.set_url("foo");
Metadata metadata_proto;
auto& filter_map = *metadata_proto.mutable_typed_filter_metadata();
filter_map["filter_key"].PackFrom(audience_proto);
// Decode.
auto metadata_map = Decode(std::move(metadata_proto));
ASSERT_TRUE(metadata_map.ok()) << metadata_map.status();
EXPECT_EQ(metadata_map->size(), 0);
}
TEST_F(XdsMetadataTest, MetadataUnset) {
auto metadata_map = Parse(nullptr);
ASSERT_TRUE(metadata_map.ok()) << metadata_map.status();
EXPECT_EQ(metadata_map->size(), 0);
}
} // namespace
} // namespace testing
} // namespace grpc_core
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
grpc::testing::TestEnvironment env(&argc, argv);
grpc_init();
int ret = RUN_ALL_TESTS();
grpc_shutdown();
return ret;
}

@ -3029,6 +3029,10 @@ src/core/xds/grpc/xds_listener.cc \
src/core/xds/grpc/xds_listener.h \
src/core/xds/grpc/xds_listener_parser.cc \
src/core/xds/grpc/xds_listener_parser.h \
src/core/xds/grpc/xds_metadata.cc \
src/core/xds/grpc/xds_metadata.h \
src/core/xds/grpc/xds_metadata_parser.cc \
src/core/xds/grpc/xds_metadata_parser.h \
src/core/xds/grpc/xds_route_config.cc \
src/core/xds/grpc/xds_route_config.h \
src/core/xds/grpc/xds_route_config_parser.cc \

@ -2807,6 +2807,10 @@ src/core/xds/grpc/xds_listener.cc \
src/core/xds/grpc/xds_listener.h \
src/core/xds/grpc/xds_listener_parser.cc \
src/core/xds/grpc/xds_listener_parser.h \
src/core/xds/grpc/xds_metadata.cc \
src/core/xds/grpc/xds_metadata.h \
src/core/xds/grpc/xds_metadata_parser.cc \
src/core/xds/grpc/xds_metadata_parser.h \
src/core/xds/grpc/xds_route_config.cc \
src/core/xds/grpc/xds_route_config.h \
src/core/xds/grpc/xds_route_config_parser.cc \

@ -3975,6 +3975,30 @@
],
"uses_polling": true
},
{
"args": [],
"benchmark": false,
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": true,
"language": "c++",
"name": "gcp_authentication_filter_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
],
"uses_polling": false
},
{
"args": [],
"benchmark": false,
@ -12271,6 +12295,30 @@
],
"uses_polling": false
},
{
"args": [],
"benchmark": false,
"ci_platforms": [
"linux",
"mac",
"posix",
"windows"
],
"cpu_cost": 1.0,
"exclude_configs": [],
"exclude_iomgrs": [],
"flaky": false,
"gtest": true,
"language": "c++",
"name": "xds_metadata_test",
"platforms": [
"linux",
"mac",
"posix",
"windows"
],
"uses_polling": false
},
{
"args": [],
"benchmark": false,

Loading…
Cancel
Save