From aeffe67ee147f94a82958dbf4a7488ad8093748c Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Wed, 12 Apr 2023 14:04:09 +0000 Subject: [PATCH 01/44] MaxMind Geolocation provider Signed-off-by: Kateryna Nezdolii --- CODEOWNERS | 2 + api/BUILD | 2 + .../filters/http/geoip/v3/geoip.proto | 55 +--- .../geoip_providers/common/v3/BUILD | 9 + .../geoip_providers/common/v3/common.proto | 63 ++++ .../geoip_providers/maxmind/v3/BUILD | 13 + .../geoip_providers/maxmind/v3/maxmind.proto | 32 ++ api/versioning/BUILD | 2 + bazel/foreign_cc/BUILD | 17 ++ bazel/repositories.bzl | 11 + bazel/repository_locations.bzl | 15 + .../http/http_filters/geoip_filter.rst | 1 + envoy/geoip/BUILD | 31 ++ .../geoip/geoip_provider_driver.h | 46 +-- source/common/common/logger.h | 1 + source/extensions/extensions_build_config.bzl | 8 +- source/extensions/extensions_metadata.yaml | 7 + source/extensions/filters/http/geoip/BUILD | 20 +- .../extensions/filters/http/geoip/config.cc | 12 +- source/extensions/filters/http/geoip/config.h | 5 +- .../filters/http/geoip/geoip_filter.cc | 47 +-- .../filters/http/geoip/geoip_filter.h | 26 +- .../http/geoip/geoip_provider_config_impl.h | 56 ---- .../extensions/geoip_providers/common/BUILD | 19 ++ .../geoip_providers/common/factory_base.h | 50 ++++ .../extensions/geoip_providers/maxmind/BUILD | 39 +++ .../geoip_providers/maxmind/config.cc | 34 +++ .../geoip_providers/maxmind/config.h | 35 +++ .../geoip_providers/maxmind/geoip_provider.cc | 279 ++++++++++++++++++ .../geoip_providers/maxmind/geoip_provider.h | 122 ++++++++ test/extensions/filters/http/geoip/BUILD | 34 ++- .../filters/http/geoip/config_test.cc | 112 ++----- .../geoip/geoip_filter_integration_test.cc | 200 +++++++++++++ .../filters/http/geoip/geoip_filter_test.cc | 126 +++----- test/extensions/filters/http/geoip/mocks.h | 15 +- test/extensions/filters/http/geoip/utils.h | 26 -- test/extensions/geoip_providers/maxmind/BUILD | 43 +++ .../geoip_providers/maxmind/config_test.cc | 258 ++++++++++++++++ .../maxmind/geoip_provider_test.cc | 249 ++++++++++++++++ .../geoip_providers/maxmind/mocks.h | 0 .../geoip_providers/maxmind/test_data/BUILD | 13 + .../test_data/GeoIP2-Anonymous-IP-Test.mmdb | Bin 0 -> 4382 bytes .../maxmind/test_data/GeoLite2-ASN-Test.mmdb | Bin 0 -> 12665 bytes .../maxmind/test_data/GeoLite2-City-Test.mmdb | Bin 0 -> 20809 bytes 44 files changed, 1672 insertions(+), 463 deletions(-) create mode 100644 api/envoy/extensions/geoip_providers/common/v3/BUILD create mode 100644 api/envoy/extensions/geoip_providers/common/v3/common.proto create mode 100644 api/envoy/extensions/geoip_providers/maxmind/v3/BUILD create mode 100644 api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto create mode 100644 envoy/geoip/BUILD rename source/extensions/filters/http/geoip/geoip_provider_config.h => envoy/geoip/geoip_provider_driver.h (57%) delete mode 100644 source/extensions/filters/http/geoip/geoip_provider_config_impl.h create mode 100644 source/extensions/geoip_providers/common/BUILD create mode 100644 source/extensions/geoip_providers/common/factory_base.h create mode 100644 source/extensions/geoip_providers/maxmind/BUILD create mode 100644 source/extensions/geoip_providers/maxmind/config.cc create mode 100644 source/extensions/geoip_providers/maxmind/config.h create mode 100644 source/extensions/geoip_providers/maxmind/geoip_provider.cc create mode 100644 source/extensions/geoip_providers/maxmind/geoip_provider.h create mode 100644 test/extensions/filters/http/geoip/geoip_filter_integration_test.cc delete mode 100644 test/extensions/filters/http/geoip/utils.h create mode 100644 test/extensions/geoip_providers/maxmind/BUILD create mode 100644 test/extensions/geoip_providers/maxmind/config_test.cc create mode 100644 test/extensions/geoip_providers/maxmind/geoip_provider_test.cc create mode 100644 test/extensions/geoip_providers/maxmind/mocks.h create mode 100644 test/extensions/geoip_providers/maxmind/test_data/BUILD create mode 100644 test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb create mode 100644 test/extensions/geoip_providers/maxmind/test_data/GeoLite2-ASN-Test.mmdb create mode 100644 test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test.mmdb diff --git a/CODEOWNERS b/CODEOWNERS index d169a56f97ad..ad22c67b3a5a 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -319,6 +319,8 @@ extensions/filters/http/oauth2 @derekargueta @mattklein123 /*/extensions/health_check/event_sinks/file @botengyao @yanavlasov # IP Geolocation /*/extensions/filters/http/geoip @nezdolik @ravenblackx +# Maxmind geolocation provider +/*/extensions/geoip_providers/maxmind @nezdolik @ravenblackx /*/extensions/health_checkers/common @zuercher @botengyao diff --git a/api/BUILD b/api/BUILD index 201c89aaed00..69f1ff01e81e 100644 --- a/api/BUILD +++ b/api/BUILD @@ -237,6 +237,8 @@ proto_library( "//envoy/extensions/formatter/cel/v3:pkg", "//envoy/extensions/formatter/metadata/v3:pkg", "//envoy/extensions/formatter/req_without_query/v3:pkg", + "//envoy/extensions/geoip_providers/common/v3:pkg", + "//envoy/extensions/geoip_providers/maxmind/v3:pkg", "//envoy/extensions/health_check/event_sinks/file/v3:pkg", "//envoy/extensions/health_checkers/redis/v3:pkg", "//envoy/extensions/health_checkers/thrift/v3:pkg", diff --git a/api/envoy/extensions/filters/http/geoip/v3/geoip.proto b/api/envoy/extensions/filters/http/geoip/v3/geoip.proto index a01356333524..5a11c09feb11 100644 --- a/api/envoy/extensions/filters/http/geoip/v3/geoip.proto +++ b/api/envoy/extensions/filters/http/geoip/v3/geoip.proto @@ -21,52 +21,6 @@ option (xds.annotations.v3.file_status).work_in_progress = true; // [#extension: envoy.filters.http.geoip] message Geoip { - // The set of geolocation headers to add to request. If any of the configured headers is present - // in the incoming request, it will be overridden by Geoip filter. - // [#next-free-field: 10] - message GeolocationHeadersToAdd { - // If set, the header will be used to populate the country ISO code associated with the IP address. - string country = 1 - [(validate.rules).string = {well_known_regex: HTTP_HEADER_NAME ignore_empty: true}]; - - // If set, the header will be used to populate the city associated with the IP address. - string city = 2 - [(validate.rules).string = {well_known_regex: HTTP_HEADER_NAME ignore_empty: true}]; - - // If set, the header will be used to populate the region ISO code associated with the IP address. - string region = 3 - [(validate.rules).string = {well_known_regex: HTTP_HEADER_NAME ignore_empty: true}]; - - // If set, the header will be used to populate the ASN associated with the IP address. - string asn = 4 - [(validate.rules).string = {well_known_regex: HTTP_HEADER_NAME ignore_empty: true}]; - - // If set, the IP address will be checked if it belongs to any type of anonymization network (e.g. VPN, public proxy etc) - // and header will be populated with the check result. Header value will be set to either "true" or "false" depending on the check result. - string is_anon = 5 - [(validate.rules).string = {well_known_regex: HTTP_HEADER_NAME ignore_empty: true}]; - - // If set, the IP address will be checked if it belongs to a VPN and header will be populated with the check result. - // Header value will be set to either "true" or "false" depending on the check result. - string anon_vpn = 6 - [(validate.rules).string = {well_known_regex: HTTP_HEADER_NAME ignore_empty: true}]; - - // If set, the IP address will be checked if it belongs to a hosting provider and header will be populated with the check result. - // Header value will be set to either "true" or "false" depending on the check result. - string anon_hosting = 7 - [(validate.rules).string = {well_known_regex: HTTP_HEADER_NAME ignore_empty: true}]; - - // If set, the IP address will be checked if it belongs to a TOR exit node and header will be populated with the check result. - // Header value will be set to either "true" or "false" depending on the check result. - string anon_tor = 8 - [(validate.rules).string = {well_known_regex: HTTP_HEADER_NAME ignore_empty: true}]; - - // If set, the IP address will be checked if it belongs to a public proxy and header will be populated with the check result. - // Header value will be set to either "true" or "false" depending on the check result. - string anon_proxy = 9 - [(validate.rules).string = {well_known_regex: HTTP_HEADER_NAME ignore_empty: true}]; - } - message XffConfig { // The number of additional ingress proxy hops from the right side of the // :ref:`config_http_conn_man_headers_x-forwarded-for` HTTP header to trust when @@ -82,9 +36,10 @@ message Geoip { // [#next-free-field: 2] XffConfig xff_config = 1; - // Configuration for geolocation headers to add to request. - GeolocationHeadersToAdd geo_headers_to_add = 2 [(validate.rules).message = {required: true}]; - - // Geolocation provider specific configuration. + // Geoip driver specific configuration which depends on the driver being instantiated. + // See the geoip drivers for examples: + // + // - :ref:`MaxMindConfig ` + // [#extension-category: envoy.geoip_providers] config.core.v3.TypedExtensionConfig provider = 3 [(validate.rules).message = {required: true}]; } diff --git a/api/envoy/extensions/geoip_providers/common/v3/BUILD b/api/envoy/extensions/geoip_providers/common/v3/BUILD new file mode 100644 index 000000000000..ee92fb652582 --- /dev/null +++ b/api/envoy/extensions/geoip_providers/common/v3/BUILD @@ -0,0 +1,9 @@ +# DO NOT EDIT. This file is generated by tools/proto_format/proto_sync.py. + +load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package") + +licenses(["notice"]) # Apache 2 + +api_proto_package( + deps = ["@com_github_cncf_udpa//udpa/annotations:pkg"], +) diff --git a/api/envoy/extensions/geoip_providers/common/v3/common.proto b/api/envoy/extensions/geoip_providers/common/v3/common.proto new file mode 100644 index 000000000000..369604c17bc1 --- /dev/null +++ b/api/envoy/extensions/geoip_providers/common/v3/common.proto @@ -0,0 +1,63 @@ +syntax = "proto3"; + +package envoy.extensions.geoip_providers.common.v3; + +import "udpa/annotations/status.proto"; +import "validate/validate.proto"; + +option java_package = "io.envoyproxy.envoy.extensions.geoip_providers.common.v3"; +option java_outer_classname = "CommonProto"; +option java_multiple_files = true; +option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/geoip_providers/common/v3;commonv3"; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +message CommonGeoipProviderConfig { + // The set of geolocation headers to add to request. If any of the configured headers is present + // in the incoming request, it will be overridden by Geoip filter. + // [#next-free-field: 10] + message GeolocationHeadersToAdd { + // If set, the header will be used to populate the country ISO code associated with the IP address. + string country = 1 + [(validate.rules).string = {well_known_regex: HTTP_HEADER_NAME ignore_empty: true}]; + + // If set, the header will be used to populate the city associated with the IP address. + string city = 2 + [(validate.rules).string = {well_known_regex: HTTP_HEADER_NAME ignore_empty: true}]; + + // If set, the header will be used to populate the region ISO code associated with the IP address. + string region = 3 + [(validate.rules).string = {well_known_regex: HTTP_HEADER_NAME ignore_empty: true}]; + + // If set, the header will be used to populate the ASN associated with the IP address. + string asn = 4 + [(validate.rules).string = {well_known_regex: HTTP_HEADER_NAME ignore_empty: true}]; + + // If set, the IP address will be checked if it belongs to any type of anonymization network (e.g. VPN, public proxy etc) + // and header will be populated with the check result. Header value will be set to either "true" or "false" depending on the check result. + string is_anon = 5 + [(validate.rules).string = {well_known_regex: HTTP_HEADER_NAME ignore_empty: true}]; + + // If set, the IP address will be checked if it belongs to a VPN and header will be populated with the check result. + // Header value will be set to either "true" or "false" depending on the check result. + string anon_vpn = 6 + [(validate.rules).string = {well_known_regex: HTTP_HEADER_NAME ignore_empty: true}]; + + // If set, the IP address will be checked if it belongs to a hosting provider and header will be populated with the check result. + // Header value will be set to either "true" or "false" depending on the check result. + string anon_hosting = 7 + [(validate.rules).string = {well_known_regex: HTTP_HEADER_NAME ignore_empty: true}]; + + // If set, the IP address will be checked if it belongs to a TOR exit node and header will be populated with the check result. + // Header value will be set to either "true" or "false" depending on the check result. + string anon_tor = 8 + [(validate.rules).string = {well_known_regex: HTTP_HEADER_NAME ignore_empty: true}]; + + // If set, the IP address will be checked if it belongs to a public proxy and header will be populated with the check result. + // Header value will be set to either "true" or "false" depending on the check result. + string anon_proxy = 9 + [(validate.rules).string = {well_known_regex: HTTP_HEADER_NAME ignore_empty: true}]; + } + + // Configuration for geolocation headers to add to request. + GeolocationHeadersToAdd geo_headers_to_add = 1 [(validate.rules).message = {required: true}]; +} diff --git a/api/envoy/extensions/geoip_providers/maxmind/v3/BUILD b/api/envoy/extensions/geoip_providers/maxmind/v3/BUILD new file mode 100644 index 000000000000..082f67d1e00a --- /dev/null +++ b/api/envoy/extensions/geoip_providers/maxmind/v3/BUILD @@ -0,0 +1,13 @@ +# DO NOT EDIT. This file is generated by tools/proto_format/proto_sync.py. + +load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package") + +licenses(["notice"]) # Apache 2 + +api_proto_package( + deps = [ + "//envoy/extensions/geoip_providers/common/v3:pkg", + "@com_github_cncf_udpa//udpa/annotations:pkg", + "@com_github_cncf_udpa//xds/annotations/v3:pkg", + ], +) diff --git a/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto b/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto new file mode 100644 index 000000000000..1cf417d6351d --- /dev/null +++ b/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto @@ -0,0 +1,32 @@ +syntax = "proto3"; + +package envoy.extensions.geoip_providers.maxmind.v3; + +import "envoy/extensions/geoip_providers/common/v3/common.proto"; + +import "xds/annotations/v3/status.proto"; + +import "udpa/annotations/status.proto"; +import "validate/validate.proto"; + +option java_package = "io.envoyproxy.envoy.extensions.geoip_providers.maxmind.v3"; +option java_outer_classname = "MaxmindProto"; +option java_multiple_files = true; +option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/geoip_providers/maxmind/v3;maxmindv3"; +option (udpa.annotations.file_status).package_version_status = ACTIVE; +option (xds.annotations.v3.file_status).work_in_progress = true; + +// [#protodoc-title: MaxMind geolocation provider] + +// Configuration for the MaxMind geolocation provider. +// [#extension: envoy.geoip_providers.maxmind] +message MaxMindConfig { + string city_db_path = 1; + + string isp_db_path = 2; + + string anon_db_path = 3; + + common.v3.CommonGeoipProviderConfig common_provider_config = 4 + [(validate.rules).message = {required: true}]; +} diff --git a/api/versioning/BUILD b/api/versioning/BUILD index 52f5060b54d3..3c7cd5723b59 100644 --- a/api/versioning/BUILD +++ b/api/versioning/BUILD @@ -175,6 +175,8 @@ proto_library( "//envoy/extensions/formatter/cel/v3:pkg", "//envoy/extensions/formatter/metadata/v3:pkg", "//envoy/extensions/formatter/req_without_query/v3:pkg", + "//envoy/extensions/geoip_providers/common/v3:pkg", + "//envoy/extensions/geoip_providers/maxmind/v3:pkg", "//envoy/extensions/health_check/event_sinks/file/v3:pkg", "//envoy/extensions/health_checkers/redis/v3:pkg", "//envoy/extensions/health_checkers/thrift/v3:pkg", diff --git a/bazel/foreign_cc/BUILD b/bazel/foreign_cc/BUILD index 67caf394a107..54c30b5826ca 100644 --- a/bazel/foreign_cc/BUILD +++ b/bazel/foreign_cc/BUILD @@ -570,3 +570,20 @@ envoy_cmake( }), working_directory = "build/cmake", ) + +envoy_cmake( + name = "maxmind", + cache_entries = { + "CMAKE_BUILD_TYPE": "Release", + "CMAKE_INSTALL_LIBDIR": "lib", + "CMAKE_CXX_COMPILER_FORCED": "on", + "BUILD_SHARED_LIBS": "no", + "BUILD_TESTING": "no", + }, + defines = ["MAXMIND_STATICLIB"], + lib_source = "@com_github_maxmind_libmaxminddb//:all", + out_static_libs = select({ + "//bazel:windows_x86_64": ["libmaxminddb.lib"], + "//conditions:default": ["libmaxminddb.a"], + }), +) diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index 647efda69d50..19e7bbdeb86e 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -317,6 +317,7 @@ def envoy_dependencies(skip_targets = []): external_http_archive("bazel_toolchains") external_http_archive("bazel_compdb") external_http_archive("envoy_build_tools") + _com_github_maxmind_libmaxminddb() # TODO(keith): Remove patch when we update rules_pkg external_http_archive( @@ -1373,3 +1374,13 @@ def _is_linux_s390x(ctxt): def _is_linux_x86_64(ctxt): return _is_linux(ctxt) and _is_arch(ctxt, "x86_64") + +def _com_github_maxmind_libmaxminddb(): + external_http_archive( + name = "com_github_maxmind_libmaxminddb", + build_file_content = BUILD_ALL_CONTENT, + ) + native.bind( + name = "maxmind", + actual = "@envoy//bazel/foreign_cc:maxmind", + ) diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 2ccda034d3c5..86b611410086 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -1448,6 +1448,21 @@ REPOSITORY_LOCATIONS_SPEC = dict( license = "MIT", license_url = "https://github.com/protocolbuffers/utf8_range/blob/{version}/LICENSE", ), + com_github_maxmind_libmaxminddb = dict( + project_name = "maxmind_libmaxminddb", + project_desc = "C library for reading MaxMind DB files", + project_url = "https://github.com/maxmind/libmaxminddb", + version = "1.7.1", + sha256 = "e8414f0dedcecbc1f6c31cb65cd81650952ab0677a4d8c49cab603b3b8fb083e", + strip_prefix = "libmaxminddb-{version}", + urls = ["https://github.com/maxmind/libmaxminddb/releases/download/{version}/libmaxminddb-{version}.tar.gz"], + use_category = ["dataplane_ext"], + extensions = ["envoy.geoip_providers.maxmind"], + release_date = "2022-09-30", + cpe = "N/A", + license = "Apache-2.0", + license_url = "https://github.com/maxmind/libmaxminddb/blob/{version}/LICENSE", + ), ) def _compiled_protoc_deps(locations, versions): diff --git a/docs/root/configuration/http/http_filters/geoip_filter.rst b/docs/root/configuration/http/http_filters/geoip_filter.rst index 84507290791e..cfa51ed0077d 100644 --- a/docs/root/configuration/http/http_filters/geoip_filter.rst +++ b/docs/root/configuration/http/http_filters/geoip_filter.rst @@ -7,6 +7,7 @@ Filter uses client address to lookup information (eg client's city, country) in Upon a successful lookup request will be enriched with the configured geolocation header and value from the database. In case the configured geolocation headers are present in the incoming request, they will be overriden by the filter. Geolocation filter emits stats for the number of successful lookups and the number of total lookups. +As for now, only `Maxmind ` geolocation provider is supported. Configuration ------------- diff --git a/envoy/geoip/BUILD b/envoy/geoip/BUILD new file mode 100644 index 000000000000..a1b967f66a4c --- /dev/null +++ b/envoy/geoip/BUILD @@ -0,0 +1,31 @@ +load( + "//bazel:envoy_build_system.bzl", + "envoy_cc_extension", + "envoy_extension_package", + "envoy_package", +) + +licenses(["notice"]) # Apache 2 + +envoy_package() + +# HTTP L7 filter that decorates request with geolocation data +# Public docs: https://envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/geoip_filter + +envoy_extension_package() + +#todo(nezdolik) may need to split into interface and impl +envoy_cc_extension( + name = "geoip_provider_driver_interface", + hdrs = [ + "geoip_provider_driver.h", + ], + deps = [ + "//envoy/config:typed_config_interface", + "//envoy/network:address_interface", + "//envoy/protobuf:message_validator_interface", + "//envoy/server:factory_context_interface", + "//source/common/common:hash_lib", + "//source/common/protobuf:utility_lib", + ], +) diff --git a/source/extensions/filters/http/geoip/geoip_provider_config.h b/envoy/geoip/geoip_provider_driver.h similarity index 57% rename from source/extensions/filters/http/geoip/geoip_provider_config.h rename to envoy/geoip/geoip_provider_driver.h index 5928b6b599c4..97d22d26af6e 100644 --- a/source/extensions/filters/http/geoip/geoip_provider_config.h +++ b/envoy/geoip/geoip_provider_driver.h @@ -1,43 +1,34 @@ #pragma once #include "envoy/config/typed_config.h" -#include "envoy/extensions/filters/http/geoip/v3/geoip.pb.h" -#include "envoy/extensions/filters/http/geoip/v3/geoip.pb.validate.h" #include "envoy/network/address.h" #include "envoy/protobuf/message_validator.h" +#include "envoy/server/factory_context.h" #include "absl/container/flat_hash_set.h" namespace Envoy { -namespace Extensions { -namespace HttpFilters { -namespace Geoip { +namespace Geolocation { // Actual result of the lookup. Each entry in the map represents the geolocation header (entry key) // for which the lookup was invoked mapped to a lookup result from the database. Entry value will be // set to absl::nullopt when database lookup yields an empty result. -using LookupResult = const absl::flat_hash_map>; +using LookupResult = const absl::flat_hash_map; // Async callbacks used for geolocation provider lookups. using LookupGeoHeadersCallback = std::function; +// todo remove headers class LookupRequest { public: LookupRequest() = default; - LookupRequest(Network::Address::InstanceConstSharedPtr&& remote_address, - absl::flat_hash_set&& geo_headers, - absl::flat_hash_set&& geo_anon_headers) - : remote_address_(std::move(remote_address)), geo_headers_(std::move(geo_headers)), - geo_anon_headers_(std::move(geo_anon_headers)){}; + LookupRequest(Network::Address::InstanceConstSharedPtr&& remote_address) + : remote_address_(std::move(remote_address)){}; - absl::flat_hash_set geoHeaders() const { return geo_headers_; } - absl::flat_hash_set geoAnonHeaders() const { return geo_anon_headers_; } const Network::Address::InstanceConstSharedPtr remoteAddress() const { return remote_address_; } private: Network::Address::InstanceConstSharedPtr remote_address_; - absl::flat_hash_set geo_headers_; - absl::flat_hash_set geo_anon_headers_; }; class Driver { @@ -55,22 +46,6 @@ class Driver { using DriverSharedPtr = std::shared_ptr; -/** - * Context passed to geolocation providers to access server resources. - */ -class GeoipProviderFactoryContext { -public: - virtual ~GeoipProviderFactoryContext() = default; - - /** - * @return ProtobufMessage::ValidationVisitor& validation visitor for geolocation provider - * configuration messages. - */ - virtual ProtobufMessage::ValidationVisitor& messageValidationVisitor() PURE; -}; - -using GeoipProviderFactoryContextPtr = std::unique_ptr; - /** * Implemented by each geolocation provider and registered via Registry::registerFactory() or the * convenience class RegisterFactory. @@ -89,13 +64,12 @@ class GeoipProviderFactory : public Config::TypedFactory { * @param config supplies the proto configuration for the geolocation provider * @param context supplies the factory context */ - virtual DriverSharedPtr createGeoipProviderDriver(const Protobuf::Message& config, - GeoipProviderFactoryContextPtr& context) PURE; + virtual DriverSharedPtr + createGeoipProviderDriver(const Protobuf::Message& config, const std::string& stat_prefix, + Server::Configuration::FactoryContext& context) PURE; std::string category() const override { return "envoy.geoip_providers"; } }; -} // namespace Geoip -} // namespace HttpFilters -} // namespace Extensions +} // namespace Geolocation } // namespace Envoy diff --git a/source/common/common/logger.h b/source/common/common/logger.h index 85e240221347..b3f81db04b1d 100644 --- a/source/common/common/logger.h +++ b/source/common/common/logger.h @@ -54,6 +54,7 @@ const static bool should_log = true; FUNCTION(file) \ FUNCTION(filter) \ FUNCTION(forward_proxy) \ + FUNCTION(geolocation) \ FUNCTION(grpc) \ FUNCTION(happy_eyeballs) \ FUNCTION(hc) \ diff --git a/source/extensions/extensions_build_config.bzl b/source/extensions/extensions_build_config.bzl index 1b777ecfb4c7..af2a26db0d4a 100644 --- a/source/extensions/extensions_build_config.bzl +++ b/source/extensions/extensions_build_config.bzl @@ -140,7 +140,7 @@ EXTENSIONS = { "envoy.filters.http.fault": "//source/extensions/filters/http/fault:config", "envoy.filters.http.file_system_buffer": "//source/extensions/filters/http/file_system_buffer:config", "envoy.filters.http.gcp_authn": "//source/extensions/filters/http/gcp_authn:config", - "envoy.filters.http.geoip": "//source/extensions/filters/http/geoip:config", + "envoy.filters.http.geoip": "//source/extensions/filters/http/geoip:config", "envoy.filters.http.grpc_http1_bridge": "//source/extensions/filters/http/grpc_http1_bridge:config", "envoy.filters.http.grpc_http1_reverse_bridge": "//source/extensions/filters/http/grpc_http1_reverse_bridge:config", "envoy.filters.http.grpc_json_transcoder": "//source/extensions/filters/http/grpc_json_transcoder:config", @@ -262,7 +262,6 @@ EXTENSIONS = { "envoy.transport_sockets.raw_buffer": "//source/extensions/transport_sockets/raw_buffer:config", "envoy.transport_sockets.tap": "//source/extensions/transport_sockets/tap:config", "envoy.transport_sockets.starttls": "//source/extensions/transport_sockets/starttls:config", - "envoy.transport_sockets.tcp_stats": "//source/extensions/transport_sockets/tcp_stats:config", "envoy.transport_sockets.internal_upstream": "//source/extensions/transport_sockets/internal_upstream:config", # @@ -462,6 +461,11 @@ EXTENSIONS = { "envoy.config_subscription.ads_collection": "//source/extensions/config_subscription/grpc:grpc_collection_subscription_lib", "envoy.config_mux.delta_grpc_mux_factory": "//source/extensions/config_subscription/grpc/xds_mux:grpc_mux_lib", "envoy.config_mux.sotw_grpc_mux_factory": "//source/extensions/config_subscription/grpc/xds_mux:grpc_mux_lib", + + # + # Geolocation Providers + # + "envoy.geoip_providers.maxmind": "//source/extensions/geoip_providers/maxmind:config", } # These can be changed to ["//visibility:public"], for downstream builds which diff --git a/source/extensions/extensions_metadata.yaml b/source/extensions/extensions_metadata.yaml index 92dd4929745b..29674e38003e 100644 --- a/source/extensions/extensions_metadata.yaml +++ b/source/extensions/extensions_metadata.yaml @@ -750,6 +750,13 @@ envoy.formatter.req_without_query: status: alpha type_urls: - envoy.extensions.formatter.req_without_query.v3.ReqWithoutQuery +envoy.geoip_providers.maxmind: + categories: + - envoy.geoip_providers + security_posture: unknown + status: wip + type_urls: + - envoy.extensions.geoip_providers.maxmind.v3.MaxMindConfig envoy.grpc_credentials.aws_iam: categories: - envoy.grpc_credentials diff --git a/source/extensions/filters/http/geoip/BUILD b/source/extensions/filters/http/geoip/BUILD index f12f88882178..c0e8965e08be 100644 --- a/source/extensions/filters/http/geoip/BUILD +++ b/source/extensions/filters/http/geoip/BUILD @@ -17,7 +17,7 @@ envoy_cc_library( srcs = ["geoip_filter.cc"], hdrs = ["geoip_filter.h"], deps = [ - ":provider_config", + "//envoy/geoip:geoip_provider_driver_interface", "//envoy/http:filter_interface", "//envoy/runtime:runtime_interface", "//source/common/common:assert_lib", @@ -29,28 +29,12 @@ envoy_cc_library( ], ) -#todo(nezdolik) may need to split into interface and impl -envoy_cc_extension( - name = "provider_config", - hdrs = [ - "geoip_provider_config.h", - "geoip_provider_config_impl.h", - ], - deps = [ - "//envoy/config:typed_config_interface", - "//envoy/network:address_interface", - "//envoy/protobuf:message_validator_interface", - "//source/common/common:hash_lib", - "@envoy_api//envoy/extensions/filters/http/geoip/v3:pkg_cc_proto", - ], -) - envoy_cc_extension( name = "config", srcs = ["config.cc"], hdrs = ["config.h"], deps = [ - ":provider_config", + "//envoy/geoip:geoip_provider_driver_interface", "//source/common/config:utility_lib", "//source/common/protobuf:utility_lib", "//source/extensions/filters/http/common:factory_base_lib", diff --git a/source/extensions/filters/http/geoip/config.cc b/source/extensions/filters/http/geoip/config.cc index b88138abbec2..86c83472dc91 100644 --- a/source/extensions/filters/http/geoip/config.cc +++ b/source/extensions/filters/http/geoip/config.cc @@ -5,7 +5,6 @@ #include "source/common/config/utility.h" #include "source/common/protobuf/utility.h" #include "source/extensions/filters/http/geoip/geoip_filter.h" -#include "source/extensions/filters/http/geoip/geoip_provider_config_impl.h" namespace Envoy { namespace Extensions { @@ -15,19 +14,16 @@ namespace Geoip { Http::FilterFactoryCb GeoipFilterFactory::createFilterFactoryFromProtoTyped( const envoy::extensions::filters::http::geoip::v3::Geoip& proto_config, const std::string& stat_prefix, Server::Configuration::FactoryContext& context) { - if (!provider_context_) { - provider_context_ = - std::make_unique(context.messageValidationVisitor()); - } GeoipFilterConfigSharedPtr filter_config( std::make_shared(proto_config, stat_prefix, context.scope())); const auto& provider_config = proto_config.provider(); auto& geo_provider_factory = - Envoy::Config::Utility::getAndCheckFactory(provider_config); + Envoy::Config::Utility::getAndCheckFactory( + provider_config); ProtobufTypes::MessagePtr message = Envoy::Config::Utility::translateToFactoryConfig( - provider_config, provider_context_->messageValidationVisitor(), geo_provider_factory); - auto driver = geo_provider_factory.createGeoipProviderDriver(*message, provider_context_); + provider_config, context.messageValidationVisitor(), geo_provider_factory); + auto driver = geo_provider_factory.createGeoipProviderDriver(*message, stat_prefix, context); return [filter_config, driver](Http::FilterChainFactoryCallbacks& callbacks) -> void { callbacks.addStreamDecoderFilter(std::make_shared(filter_config, driver)); }; diff --git a/source/extensions/filters/http/geoip/config.h b/source/extensions/filters/http/geoip/config.h index 8b6d782b8582..677cff6be55b 100644 --- a/source/extensions/filters/http/geoip/config.h +++ b/source/extensions/filters/http/geoip/config.h @@ -2,9 +2,9 @@ #include "envoy/extensions/filters/http/geoip/v3/geoip.pb.h" #include "envoy/extensions/filters/http/geoip/v3/geoip.pb.validate.h" +#include "envoy/geoip/geoip_provider_driver.h" #include "source/extensions/filters/http/common/factory_base.h" -#include "source/extensions/filters/http/geoip/geoip_provider_config.h" namespace Envoy { namespace Extensions { @@ -22,9 +22,6 @@ class GeoipFilterFactory Http::FilterFactoryCb createFilterFactoryFromProtoTyped( const envoy::extensions::filters::http::geoip::v3::Geoip& proto_config, const std::string& stats_prefix, Server::Configuration::FactoryContext& context) override; - -private: - GeoipProviderFactoryContextPtr provider_context_; }; } // namespace Geoip diff --git a/source/extensions/filters/http/geoip/geoip_filter.cc b/source/extensions/filters/http/geoip/geoip_filter.cc index cd3b2a423e35..2d197bb158fc 100644 --- a/source/extensions/filters/http/geoip/geoip_filter.cc +++ b/source/extensions/filters/http/geoip/geoip_filter.cc @@ -15,33 +15,10 @@ GeoipFilterConfig::GeoipFilterConfig( const envoy::extensions::filters::http::geoip::v3::Geoip& config, const std::string& stat_prefix, Stats::Scope& scope) : scope_(scope), stat_name_set_(scope.symbolTable().makeSet("Geoip")), - stats_prefix_(stat_name_set_->add(stat_prefix + "geoip")), - total_(stat_name_set_->add("total")), use_xff_(config.has_xff_config()), + stats_prefix_(stat_name_set_->add(stat_prefix + "geoip")), use_xff_(config.has_xff_config()), xff_num_trusted_hops_(config.has_xff_config() ? config.xff_config().xff_num_trusted_hops() : 0) { - const auto& geo_headers_to_add = config.geo_headers_to_add(); - geo_headers_ = processGeoHeaders({geo_headers_to_add.country(), geo_headers_to_add.city(), - geo_headers_to_add.region(), geo_headers_to_add.asn()}); - geo_anon_headers_ = - processGeoHeaders({geo_headers_to_add.is_anon(), geo_headers_to_add.anon_vpn(), - geo_headers_to_add.anon_hosting(), geo_headers_to_add.anon_tor(), - geo_headers_to_add.anon_proxy()}); - if (geo_headers_.empty() && geo_anon_headers_.empty()) { - throw EnvoyException("No geolocation headers configured"); - } -} - -absl::flat_hash_set -GeoipFilterConfig::processGeoHeaders(const absl::flat_hash_set& headers) const { - absl::flat_hash_set geo_headers; - for (auto header : headers) { - if (!header.empty()) { - stat_name_set_->rememberBuiltin(absl::StrCat(header, ".hit")); - stat_name_set_->rememberBuiltin(absl::StrCat(header, ".total")); - geo_headers.insert(std::string(header)); - } - } - return geo_headers; + stat_name_set_->rememberBuiltin("total"); } void GeoipFilterConfig::incCounter(Stats::StatName name) { @@ -49,7 +26,7 @@ void GeoipFilterConfig::incCounter(Stats::StatName name) { scope_.counterFromStatName(Stats::StatName(storage.get())).inc(); } -GeoipFilter::GeoipFilter(GeoipFilterConfigSharedPtr config, DriverSharedPtr driver) +GeoipFilter::GeoipFilter(GeoipFilterConfigSharedPtr config, Geolocation::DriverSharedPtr driver) : config_(config), driver_(std::move(driver)) {} GeoipFilter::~GeoipFilter() = default; @@ -76,13 +53,9 @@ Http::FilterHeadersStatus GeoipFilter::decodeHeaders(Http::RequestHeaderMap& hea // This is a safe measure to protect against the case when filter gets deleted before the callback // is run. GeoipFilterWeakPtr self = weak_from_this(); - // Copy header values to pass to the driver lookup function (in case filter gets destroyed before - // lookup completes). - absl::flat_hash_set geo_headers = config_->geoHeaders(); - absl::flat_hash_set geo_anon_headers = config_->geoAnonHeaders(); driver_->lookup( - LookupRequest{std::move(remote_address), std::move(geo_headers), std::move(geo_anon_headers)}, - [self, &dispatcher = decoder_callbacks_->dispatcher()](LookupResult&& result) { + Geolocation::LookupRequest{std::move(remote_address)}, + [self, &dispatcher = decoder_callbacks_->dispatcher()](Geolocation::LookupResult&& result) { dispatcher.post([self, result]() { if (GeoipFilterSharedPtr filter = self.lock()) { filter->onLookupComplete(std::move(result)); @@ -106,18 +79,16 @@ void GeoipFilter::setDecoderFilterCallbacks(Http::StreamDecoderFilterCallbacks& decoder_callbacks_ = &callbacks; } -void GeoipFilter::onLookupComplete(LookupResult&& result) { +void GeoipFilter::onLookupComplete(Geolocation::LookupResult&& result) { ASSERT(request_headers_); for (auto it = result.cbegin(); it != result.cend();) { const auto& geo_header = it->first; const auto& lookup_result = it++->second; - if (lookup_result) { - request_headers_->setCopy(Http::LowerCaseString(geo_header), lookup_result.value()); - config_->incHit(geo_header); + if (!lookup_result.empty()) { + request_headers_->setCopy(Http::LowerCaseString(geo_header), lookup_result); } - config_->incTotal(geo_header); } - + config_->incTotal(); ENVOY_LOG(debug, "Geoip filter: finished decoding geolocation headers"); decoder_callbacks_->continueDecoding(); } diff --git a/source/extensions/filters/http/geoip/geoip_filter.h b/source/extensions/filters/http/geoip/geoip_filter.h index 254ab7c9a3d1..bbc2345b311e 100644 --- a/source/extensions/filters/http/geoip/geoip_filter.h +++ b/source/extensions/filters/http/geoip/geoip_filter.h @@ -3,19 +3,15 @@ #include "envoy/common/exception.h" #include "envoy/common/optref.h" #include "envoy/extensions/filters/http/geoip/v3/geoip.pb.h" +#include "envoy/geoip/geoip_provider_driver.h" #include "envoy/http/filter.h" #include "envoy/stats/scope.h" -#include "source/extensions/filters/http/geoip/geoip_provider_config.h" - namespace Envoy { namespace Extensions { namespace HttpFilters { namespace Geoip { -using GeolocationHeadersToAdd = - envoy::extensions::filters::http::geoip::v3::Geoip_GeolocationHeadersToAdd; - /** * Configuration for the Geoip filter. */ @@ -24,32 +20,20 @@ class GeoipFilterConfig { GeoipFilterConfig(const envoy::extensions::filters::http::geoip::v3::Geoip& config, const std::string& stat_prefix, Stats::Scope& scope); - void incHit(absl::string_view geo_header) { - incCounter(stat_name_set_->getBuiltin(absl::StrCat(geo_header, ".hit"), unknown_hit_)); - } - void incTotal(absl::string_view geo_header) { - incCounter(stat_name_set_->getBuiltin(absl::StrCat(geo_header, ".total"), unknown_hit_)); - } + void incTotal() { incCounter(stat_name_set_->getBuiltin("total", unknown_hit_)); } bool useXff() const { return use_xff_; } uint32_t xffNumTrustedHops() const { return xff_num_trusted_hops_; } - const absl::flat_hash_set& geoHeaders() const { return geo_headers_; } - const absl::flat_hash_set& geoAnonHeaders() const { return geo_anon_headers_; } private: void incCounter(Stats::StatName name); - absl::flat_hash_set - processGeoHeaders(const absl::flat_hash_set& headers) const; Stats::Scope& scope_; Stats::StatNameSetPtr stat_name_set_; const Stats::StatName stats_prefix_; - const Stats::StatName total_; const Stats::StatName unknown_hit_; bool use_xff_; const uint32_t xff_num_trusted_hops_; - absl::flat_hash_set geo_headers_; - absl::flat_hash_set geo_anon_headers_; }; using GeoipFilterConfigSharedPtr = std::shared_ptr; @@ -58,7 +42,7 @@ class GeoipFilter : public Http::StreamDecoderFilter, public Logger::Loggable, public std::enable_shared_from_this { public: - GeoipFilter(GeoipFilterConfigSharedPtr config, DriverSharedPtr driver); + GeoipFilter(GeoipFilterConfigSharedPtr config, Geolocation::DriverSharedPtr driver); ~GeoipFilter() override; // Http::StreamFilterBase @@ -71,14 +55,14 @@ class GeoipFilter : public Http::StreamDecoderFilter, Http::FilterTrailersStatus decodeTrailers(Http::RequestTrailerMap& trailers) override; void setDecoderFilterCallbacks(Http::StreamDecoderFilterCallbacks& callbacks) override; // Callbacks for geolocation filter when lookup is complete. - void onLookupComplete(LookupResult&& result); + void onLookupComplete(Geolocation::LookupResult&& result); private: // Allow the unit test to have access to private members. friend class GeoipFilterPeer; GeoipFilterConfigSharedPtr config_; Http::StreamDecoderFilterCallbacks* decoder_callbacks_{}; - DriverSharedPtr driver_; + Geolocation::DriverSharedPtr driver_; OptRef request_headers_; }; diff --git a/source/extensions/filters/http/geoip/geoip_provider_config_impl.h b/source/extensions/filters/http/geoip/geoip_provider_config_impl.h deleted file mode 100644 index 4b67084b0a13..000000000000 --- a/source/extensions/filters/http/geoip/geoip_provider_config_impl.h +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once - -#include "source/common/protobuf/utility.h" -#include "source/extensions/filters/http/geoip/geoip_provider_config.h" - -namespace Envoy { -namespace Extensions { -namespace HttpFilters { -namespace Geoip { - -class GeoipProviderFactoryContextImpl : public GeoipProviderFactoryContext { -public: - GeoipProviderFactoryContextImpl(ProtobufMessage::ValidationVisitor& validation_visitor) - : validation_visitor_(validation_visitor) {} - ProtobufMessage::ValidationVisitor& messageValidationVisitor() override { - return validation_visitor_; - } - -private: - ProtobufMessage::ValidationVisitor& validation_visitor_; -}; - -/** - * Common base class for geolocation provider registrations. - */ -template class GeoipProviderFactoryBase : public GeoipProviderFactory { -public: - // Server::Configuration::GeoipProviderFactory - DriverSharedPtr createGeoipProviderDriver(const Protobuf::Message& config, - GeoipProviderFactoryContextPtr& context) override { - return createGeoipProviderDriverTyped(MessageUtil::downcastAndValidate( - config, context->messageValidationVisitor()), - context); - } - - ProtobufTypes::MessagePtr createEmptyConfigProto() override { - return std::make_unique(); - } - - std::string name() const override { return name_; } - -protected: - GeoipProviderFactoryBase(const std::string& name) : name_(name) {} - -private: - virtual DriverSharedPtr - createGeoipProviderDriverTyped(const ConfigProto& proto_config, - GeoipProviderFactoryContextPtr& context) PURE; - - const std::string name_; -}; - -} // namespace Geoip -} // namespace HttpFilters -} // namespace Extensions -} // namespace Envoy diff --git a/source/extensions/geoip_providers/common/BUILD b/source/extensions/geoip_providers/common/BUILD new file mode 100644 index 000000000000..2817c1847a76 --- /dev/null +++ b/source/extensions/geoip_providers/common/BUILD @@ -0,0 +1,19 @@ +load( + "//bazel:envoy_build_system.bzl", + "envoy_cc_library", + "envoy_extension_package", +) + +licenses(["notice"]) # Apache 2 + +envoy_extension_package() + +envoy_cc_library( + name = "factory_base_lib", + hdrs = ["factory_base.h"], + deps = [ + "//envoy/geoip:geoip_provider_driver_interface", + "//source/common/config:utility_lib", + "//source/common/protobuf:utility_lib", + ], +) diff --git a/source/extensions/geoip_providers/common/factory_base.h b/source/extensions/geoip_providers/common/factory_base.h new file mode 100644 index 000000000000..d91686275093 --- /dev/null +++ b/source/extensions/geoip_providers/common/factory_base.h @@ -0,0 +1,50 @@ +#pragma once + +#include "envoy/geoip/geoip_provider_driver.h" + +#include "source/common/protobuf/protobuf.h" +#include "source/common/protobuf/utility.h" + +namespace Envoy { +namespace Extensions { +namespace GeoipProviders { +namespace Common { + +/** + * Common base class for geoip provider factory registrations. Removes a substantial amount of + * boilerplate. + */ +template class FactoryBase : public Geolocation::GeoipProviderFactory { +public: + // GeoipProviderFactory + Geolocation::DriverSharedPtr + createGeoipProviderDriver(const Protobuf::Message& config, const std::string& stat_prefix, + Server::Configuration::FactoryContext& context) override { + return createGeoipProviderDriverTyped(MessageUtil::downcastAndValidate( + config, context.messageValidationVisitor()), + stat_prefix, context); + } + + ProtobufTypes::MessagePtr createEmptyConfigProto() override { + return std::make_unique(); + } + + std::string name() const override { return name_; } + + std::string category() const override { return "envoy.geoip_providers"; } + +protected: + FactoryBase(const std::string& name) : name_(name) {} + +private: + virtual Geolocation::DriverSharedPtr + createGeoipProviderDriverTyped(const ConfigProto& proto_config, const std::string& stat_prefix, + Server::Configuration::FactoryContext& context) PURE; + + const std::string name_; +}; + +} // namespace Common +} // namespace GeoipProviders +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/geoip_providers/maxmind/BUILD b/source/extensions/geoip_providers/maxmind/BUILD new file mode 100644 index 000000000000..690f121d7689 --- /dev/null +++ b/source/extensions/geoip_providers/maxmind/BUILD @@ -0,0 +1,39 @@ +load( + "//bazel:envoy_build_system.bzl", + "envoy_cc_extension", + "envoy_cc_library", + "envoy_extension_package", +) + +licenses(["notice"]) # Apache 2 + +# HTTP L7 filter that decorates request with geolocation data +# Public docs: https://envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/geoip_filter + +envoy_extension_package() + +envoy_cc_extension( + name = "config", + srcs = ["config.cc"], + hdrs = ["config.h"], + deps = [ + ":provider_impl", + "//envoy/geoip:geoip_provider_driver_interface", + "//source/common/config:utility_lib", + "//source/common/protobuf:utility_lib", + "//source/extensions/geoip_providers/common:factory_base_lib", + "@envoy_api//envoy/extensions/geoip_providers/maxmind/v3:pkg_cc_proto", + ], +) + +envoy_cc_library( + name = "provider_impl", + srcs = ["geoip_provider.cc"], + hdrs = ["geoip_provider.h"], + external_deps = ["maxmind"], + deps = [ + "//envoy/geoip:geoip_provider_driver_interface", + "@envoy_api//envoy/extensions/filters/http/geoip/v3:pkg_cc_proto", + "@envoy_api//envoy/extensions/geoip_providers/maxmind/v3:pkg_cc_proto", + ], +) diff --git a/source/extensions/geoip_providers/maxmind/config.cc b/source/extensions/geoip_providers/maxmind/config.cc new file mode 100644 index 000000000000..c47beff080ed --- /dev/null +++ b/source/extensions/geoip_providers/maxmind/config.cc @@ -0,0 +1,34 @@ +#include "source/extensions/geoip_providers/maxmind/config.h" + +#include "envoy/extensions/geoip_providers/maxmind/v3/maxmind.pb.h" +#include "envoy/registry/registry.h" + +#include "source/common/common/utility.h" + +#include "geoip_provider.h" + +namespace Envoy { +namespace Extensions { +namespace GeoipProviders { +namespace Maxmind { + +MaxmindProviderFactory::MaxmindProviderFactory() : FactoryBase("envoy.geoip_providers.maxmind") {} + +DriverSharedPtr MaxmindProviderFactory::createGeoipProviderDriverTyped( + const envoy::extensions::geoip_providers::maxmind::v3::MaxMindConfig& proto_config, + const std::string& stat_prefix, Server::Configuration::FactoryContext& context) { + const auto& provider_config = + std::make_shared(proto_config, stat_prefix, context.scope()); + return std::make_shared(provider_config); +} + +/** + * Static registration for the Maxmind provider. @see RegisterFactory. + */ +REGISTER_FACTORY(MaxmindProviderFactory, + Geolocation::GeoipProviderFactory){"envoy.geoip_providers"}; + +} // namespace Maxmind +} // namespace GeoipProviders +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/geoip_providers/maxmind/config.h b/source/extensions/geoip_providers/maxmind/config.h new file mode 100644 index 000000000000..d46f7efcc07b --- /dev/null +++ b/source/extensions/geoip_providers/maxmind/config.h @@ -0,0 +1,35 @@ +#pragma once + +#include "envoy/extensions/geoip_providers/maxmind/v3/maxmind.pb.h" +#include "envoy/extensions/geoip_providers/maxmind/v3/maxmind.pb.validate.h" + +#include "source/common/protobuf/protobuf.h" +#include "source/extensions/geoip_providers/common/factory_base.h" + +namespace Envoy { +namespace Extensions { +namespace GeoipProviders { +namespace Maxmind { + +using DriverSharedPtr = Envoy::Geolocation::DriverSharedPtr; + +class MaxmindProviderFactory + : public Common::FactoryBase { +public: + MaxmindProviderFactory(); + + ProtobufTypes::MessagePtr createEmptyConfigProto() override { + return std::make_unique(); + } + +private: + // FactoryBase + DriverSharedPtr createGeoipProviderDriverTyped( + const envoy::extensions::geoip_providers::maxmind::v3::MaxMindConfig& proto_config, + const std::string& stat_prefix, Server::Configuration::FactoryContext& context) override; +}; + +} // namespace Maxmind +} // namespace GeoipProviders +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/geoip_providers/maxmind/geoip_provider.cc b/source/extensions/geoip_providers/maxmind/geoip_provider.cc new file mode 100644 index 000000000000..1bc626a605bc --- /dev/null +++ b/source/extensions/geoip_providers/maxmind/geoip_provider.cc @@ -0,0 +1,279 @@ +#include "source/extensions/geoip_providers/maxmind/geoip_provider.h" + +#include "source/common/common/assert.h" +#include "source/common/protobuf/protobuf.h" + +namespace Envoy { +namespace Extensions { +namespace GeoipProviders { +namespace Maxmind { + +namespace { +static constexpr const char* MMDB_CITY_LOOKUP_ARGS[] = {"city", "names", "en"}; +static constexpr const char* MMDB_REGION_LOOKUP_ARGS[] = {"subdivisions", "0", "names", "en"}; +static constexpr const char* MMDB_COUNTRY_LOOKUP_ARGS[] = {"country", "names", "en"}; +static constexpr const char* MMDB_ASN_LOOKUP_ARGS[] = {"autonomous_system_number"}; +static constexpr const char* MMDB_ANON_LOOKUP_ARGS[] = {"is_anonymous", "is_anonymous_vpn", + "is_hosting_provider", "is_tor_exit_node", + "is_public_proxy"}; +} // namespace + +GeoipProviderConfig::GeoipProviderConfig( + const envoy::extensions::geoip_providers::maxmind::v3::MaxMindConfig& config, + const std::string& stat_prefix, Stats::Scope& scope) + : city_db_path_(!config.city_db_path().empty() ? absl::make_optional(config.city_db_path()) + : absl::nullopt), + isp_db_path_(!config.isp_db_path().empty() ? absl::make_optional(config.isp_db_path()) + : absl::nullopt), + anon_db_path_(!config.anon_db_path().empty() ? absl::make_optional(config.anon_db_path()) + : absl::nullopt), + scope_(scope), stat_name_set_(scope.symbolTable().makeSet("Maxmind")), + stats_prefix_(stat_name_set_->add(stat_prefix + "maxmind")) { + auto geo_headers_to_add = config.common_provider_config().geo_headers_to_add(); + country_header_ = !geo_headers_to_add.country().empty() + ? absl::make_optional(geo_headers_to_add.country()) + : absl::nullopt; + city_header_ = !geo_headers_to_add.city().empty() ? absl::make_optional(geo_headers_to_add.city()) + : absl::nullopt; + region_header_ = !geo_headers_to_add.region().empty() + ? absl::make_optional(geo_headers_to_add.region()) + : absl::nullopt; + asn_header_ = !geo_headers_to_add.asn().empty() ? absl::make_optional(geo_headers_to_add.asn()) + : absl::nullopt; + anon_header_ = !geo_headers_to_add.is_anon().empty() + ? absl::make_optional(geo_headers_to_add.is_anon()) + : absl::nullopt; + anon_vpn_header_ = !geo_headers_to_add.anon_vpn().empty() + ? absl::make_optional(geo_headers_to_add.anon_vpn()) + : absl::nullopt; + anon_hosting_header_ = !geo_headers_to_add.anon_hosting().empty() + ? absl::make_optional(geo_headers_to_add.anon_hosting()) + : absl::nullopt; + anon_tor_header_ = !geo_headers_to_add.anon_tor().empty() + ? absl::make_optional(geo_headers_to_add.anon_tor()) + : absl::nullopt; + anon_proxy_header_ = !geo_headers_to_add.anon_proxy().empty() + ? absl::make_optional(geo_headers_to_add.anon_proxy()) + : absl::nullopt; + if (!city_db_path_ && !isp_db_path_ && !anon_db_path_) { + throw EnvoyException("At least one geolocation database path needs to be configured: " + "city_db_path, isp_db_path or anon_db_path"); + } + if (city_db_path_) { + registerGeoDbStats("city_db"); + } + if (isp_db_path_) { + registerGeoDbStats("isp_db"); + } + if (anon_db_path_) { + registerGeoDbStats("anon_db"); + } +}; + +void GeoipProviderConfig::registerGeoDbStats(const std::string& db_type) { + stat_name_set_->rememberBuiltin(absl::StrCat(db_type, ".total")); + stat_name_set_->rememberBuiltin(absl::StrCat(db_type, ".hit")); + stat_name_set_->rememberBuiltin(absl::StrCat(db_type, ".lookup_error")); +} + +bool GeoipProviderConfig::isLookupEnabledForHeader(const absl::optional& header) { + return (header && !header.value().empty()); +} + +void GeoipProviderConfig::incCounter(Stats::StatName name) { + Stats::SymbolTable::StoragePtr storage = scope_.symbolTable().join({stats_prefix_, name}); + scope_.counterFromStatName(Stats::StatName(storage.get())).inc(); +} + +GeoipProvider::~GeoipProvider() { + ENVOY_LOG(debug, "Shutting down Maxmind geolocation provider"); + // todo(nezdolik) consider switching to atomic singleton for db objects + if (city_db_) { + MMDB_close(city_db_.get()); + } + if (isp_db_) { + MMDB_close(isp_db_.get()); + } + if (anon_db_) { + MMDB_close(anon_db_.get()); + } +} + +MaxmindDbPtr GeoipProvider::initMaxMindDb(const absl::optional& db_path) { + if (db_path) { + MMDB_s maxmind_db; + int result_code = MMDB_open(db_path.value().c_str(), MMDB_MODE_MMAP, &maxmind_db); + RELEASE_ASSERT(MMDB_SUCCESS == result_code, + fmt::format("Unable to open Maxmind database file {}. Error {}", db_path.value(), + std::string(MMDB_strerror(result_code)))); + return std::make_unique(maxmind_db); + } else { + ENVOY_LOG(debug, "Geolocation database path is empty, skipping database creation"); + return nullptr; + } +} + +void GeoipProvider::lookup(Geolocation::LookupRequest&& request, + Geolocation::LookupGeoHeadersCallback&& cb) const { + auto& remote_address = request.remoteAddress(); + auto lookup_result = absl::flat_hash_map{}; + std::cerr << "***Lookup for ip: " << remote_address->ip()->addressAsString() << std::endl; + lookupInCityDb(remote_address, lookup_result); + lookupInAsnDb(remote_address, lookup_result); + lookupInAnonDb(remote_address, lookup_result); + cb(std::move(lookup_result)); +} + +// todo: document En as default and only language used for lookups. Document that region is selcted +// as least specific subdivision +void GeoipProvider::lookupInCityDb( + const Network::Address::InstanceConstSharedPtr& remote_address, + absl::flat_hash_map& lookup_result) const { + if (config_->isLookupEnabledForHeader(config_->cityHeader()) || + config_->isLookupEnabledForHeader(config_->regionHeader()) || + config_->isLookupEnabledForHeader(config_->countryHeader())) { + ASSERT(city_db_, "Maxmind city database is not initialised for performing lookups"); + int mmdb_error; + const uint32_t n_prev_hits = lookup_result.size(); + MMDB_lookup_result_s mmdb_lookup_result = MMDB_lookup_sockaddr( + city_db_.get(), reinterpret_cast(remote_address->sockAddr()), &mmdb_error); + if (!mmdb_error) { + MMDB_entry_data_list_s* entry_data_list; + int status = MMDB_get_entry_data_list(&mmdb_lookup_result.entry, &entry_data_list); + if (status == MMDB_SUCCESS) { + if (config_->isLookupEnabledForHeader(config_->cityHeader())) { + populateGeoLookupResult(mmdb_lookup_result, lookup_result, config_->cityHeader().value(), + MMDB_CITY_LOOKUP_ARGS[0], MMDB_CITY_LOOKUP_ARGS[1], + MMDB_CITY_LOOKUP_ARGS[2]); + } + if (config_->isLookupEnabledForHeader(config_->regionHeader())) { + populateGeoLookupResult(mmdb_lookup_result, lookup_result, + config_->regionHeader().value(), MMDB_REGION_LOOKUP_ARGS[0], + MMDB_REGION_LOOKUP_ARGS[1], MMDB_REGION_LOOKUP_ARGS[2], + MMDB_REGION_LOOKUP_ARGS[3]); + } + if (config_->isLookupEnabledForHeader(config_->countryHeader())) { + populateGeoLookupResult(mmdb_lookup_result, lookup_result, + config_->countryHeader().value(), MMDB_COUNTRY_LOOKUP_ARGS[0], + MMDB_COUNTRY_LOOKUP_ARGS[1], MMDB_COUNTRY_LOOKUP_ARGS[2]); + } + // todo remove this in final version, this is only for testing + MMDB_dump_entry_data_list(stdout, entry_data_list, 2); + if (lookup_result.size() > n_prev_hits) { + config_->incHit("city_db"); + } + MMDB_free_entry_data_list(entry_data_list); + } + + } else { + config_->incLookupError("city_db"); + } + config_->incTotal("city_db"); + } +} + +void GeoipProvider::lookupInAsnDb( + const Network::Address::InstanceConstSharedPtr& remote_address, + absl::flat_hash_map& lookup_result) const { + if (config_->isLookupEnabledForHeader(config_->asnHeader())) { + ASSERT(isp_db_, "Maxmind asn database is not initialised for performing lookups"); + int mmdb_error; + const uint32_t n_prev_hits = lookup_result.size(); + MMDB_lookup_result_s mmdb_lookup_result = MMDB_lookup_sockaddr( + isp_db_.get(), reinterpret_cast(remote_address->sockAddr()), &mmdb_error); + if (!mmdb_error) { + MMDB_entry_data_list_s* entry_data_list; + int status = MMDB_get_entry_data_list(&mmdb_lookup_result.entry, &entry_data_list); + if (status == MMDB_SUCCESS && entry_data_list) { + populateGeoLookupResult(mmdb_lookup_result, lookup_result, config_->asnHeader().value(), + MMDB_ASN_LOOKUP_ARGS[0]); + // todo remove this in final version, this is only for testing + MMDB_dump_entry_data_list(stdout, entry_data_list, 2); + MMDB_free_entry_data_list(entry_data_list); + if (lookup_result.size() > n_prev_hits) { + config_->incHit("isp_db"); + } + } else { + config_->incLookupError("isp_db"); + } + } + config_->incTotal("isp_db"); + } +} + +// todo: document En as default and only language used for lookups. Document that region is selcted +// as least specific subdivision +void GeoipProvider::lookupInAnonDb( + const Network::Address::InstanceConstSharedPtr& remote_address, + absl::flat_hash_map& lookup_result) const { + if (config_->isLookupEnabledForHeader(config_->anonHeader()) || config_->anonVpnHeader()) { + ASSERT(anon_db_, "Maxmind city database is not initialised for performing lookups"); + int mmdb_error; + const uint32_t n_prev_hits = lookup_result.size(); + MMDB_lookup_result_s mmdb_lookup_result = MMDB_lookup_sockaddr( + anon_db_.get(), reinterpret_cast(remote_address->sockAddr()), &mmdb_error); + if (!mmdb_error) { + MMDB_entry_data_list_s* entry_data_list; + int status = MMDB_get_entry_data_list(&mmdb_lookup_result.entry, &entry_data_list); + if (status == MMDB_SUCCESS) { + if (config_->isLookupEnabledForHeader(config_->anonHeader())) { + populateGeoLookupResult(mmdb_lookup_result, lookup_result, config_->anonHeader().value(), + MMDB_ANON_LOOKUP_ARGS[0]); + } + if (config_->isLookupEnabledForHeader(config_->anonVpnHeader())) { + populateGeoLookupResult(mmdb_lookup_result, lookup_result, + config_->anonVpnHeader().value(), MMDB_ANON_LOOKUP_ARGS[1]); + } + if (config_->isLookupEnabledForHeader(config_->anonHostingHeader())) { + populateGeoLookupResult(mmdb_lookup_result, lookup_result, + config_->anonHostingHeader().value(), MMDB_ANON_LOOKUP_ARGS[2]); + } + if (config_->isLookupEnabledForHeader(config_->anonTorHeader())) { + populateGeoLookupResult(mmdb_lookup_result, lookup_result, + config_->anonTorHeader().value(), MMDB_ANON_LOOKUP_ARGS[3]); + } + if (config_->isLookupEnabledForHeader(config_->anonProxyHeader())) { + populateGeoLookupResult(mmdb_lookup_result, lookup_result, + config_->anonProxyHeader().value(), MMDB_ANON_LOOKUP_ARGS[4]); + } + // todo remove this in final version, this is only for testing + MMDB_dump_entry_data_list(stdout, entry_data_list, 2); + if (lookup_result.size() > n_prev_hits) { + config_->incHit("anon_db"); + } + MMDB_free_entry_data_list(entry_data_list); + } else { + config_->incLookupError("anon_db"); + } + } + config_->incTotal("anon_db"); + } +} + +template +void GeoipProvider::populateGeoLookupResult( + MMDB_lookup_result_s& mmdb_lookup_result, + absl::flat_hash_map& lookup_result, const std::string& result_key, + Params... lookup_params) const { + MMDB_entry_data_s entry_data; + if ((MMDB_get_value(&mmdb_lookup_result.entry, &entry_data, lookup_params..., NULL)) == + MMDB_SUCCESS) { + std::string result_value; + if (entry_data.has_data && entry_data.type == MMDB_DATA_TYPE_UTF8_STRING) { + result_value = std::string(entry_data.utf8_string, entry_data.data_size); + } else if (entry_data.has_data && entry_data.type == MMDB_DATA_TYPE_UINT32 && + entry_data.uint32 > 0) { + result_value = std::to_string(entry_data.uint32); + } else if (entry_data.has_data && entry_data.type == MMDB_DATA_TYPE_BOOLEAN) { + result_value = entry_data.boolean ? "true" : "false"; + } + if (!result_value.empty()) { + lookup_result.insert(std::make_pair(result_key, result_value)); + } + } +} + +} // namespace Maxmind +} // namespace GeoipProviders +} // namespace Extensions +} // namespace Envoy diff --git a/source/extensions/geoip_providers/maxmind/geoip_provider.h b/source/extensions/geoip_providers/maxmind/geoip_provider.h new file mode 100644 index 000000000000..3183265f6c64 --- /dev/null +++ b/source/extensions/geoip_providers/maxmind/geoip_provider.h @@ -0,0 +1,122 @@ +#pragma once + +#include "envoy/geoip/geoip_provider_driver.h" + +// todo (nezdolik) do we need this? +#include "envoy/extensions/filters/http/geoip/v3/geoip.pb.h" +#include "envoy/extensions/filters/http/geoip/v3/geoip.pb.validate.h" +#include "envoy/extensions/geoip_providers/maxmind/v3/maxmind.pb.h" +#include "source/common/common/logger.h" +#include "maxminddb.h" + +namespace Envoy { +namespace Extensions { +namespace GeoipProviders { +namespace Maxmind { + +// todo(nezdolik) add validation of config values +class GeoipProviderConfig { +public: + GeoipProviderConfig(const envoy::extensions::geoip_providers::maxmind::v3::MaxMindConfig& config, + const std::string& stat_prefix, Stats::Scope& scope); + + const absl::optional& cityDbPath() const { return city_db_path_; } + const absl::optional& ispDbPath() const { return isp_db_path_; } + const absl::optional& anonDbPath() const { return anon_db_path_; } + + bool isLookupEnabledForHeader(const absl::optional& header); + + const absl::optional& countryHeader() const { return country_header_; } + const absl::optional& cityHeader() const { return city_header_; } + const absl::optional& regionHeader() const { return region_header_; } + const absl::optional& asnHeader() const { return asn_header_; } + + const absl::optional& anonHeader() const { return anon_header_; } + const absl::optional& anonVpnHeader() const { return anon_vpn_header_; } + const absl::optional& anonHostingHeader() const { return anon_hosting_header_; } + const absl::optional& anonTorHeader() const { return anon_tor_header_; } + const absl::optional& anonProxyHeader() const { return anon_proxy_header_; } + + void incLookupError(absl::string_view maxmind_db_type) { + incCounter( + stat_name_set_->getBuiltin(absl::StrCat(maxmind_db_type, ".lookup_error"), unknown_hit_)); + } + + void incTotal(absl::string_view maxmind_db_type) { + incCounter(stat_name_set_->getBuiltin(absl::StrCat(maxmind_db_type, ".total"), unknown_hit_)); + } + + void incHit(absl::string_view maxmind_db_type) { + incCounter(stat_name_set_->getBuiltin(absl::StrCat(maxmind_db_type, ".hit"), unknown_hit_)); + } + + void registerGeoDbStats(const std::string& db_type); + +private: + absl::optional city_db_path_; + absl::optional isp_db_path_; + absl::optional anon_db_path_; + + absl::optional country_header_; + absl::optional city_header_; + absl::optional region_header_; + absl::optional asn_header_; + + absl::optional anon_header_; + absl::optional anon_vpn_header_; + absl::optional anon_hosting_header_; + absl::optional anon_tor_header_; + absl::optional anon_proxy_header_; + + Stats::Scope& scope_; + Stats::StatNameSetPtr stat_name_set_; + const Stats::StatName stats_prefix_; + const Stats::StatName unknown_hit_; + void incCounter(Stats::StatName name); +}; + +using GeoipProviderConfigSharedPtr = std::shared_ptr; + +// todo (nezdolik) should this be std::atomic>> instead? +using MaxmindDbPtr = std::unique_ptr; +class GeoipProvider : public Envoy::Geolocation::Driver, + public Logger::Loggable { + +public: + GeoipProvider(GeoipProviderConfigSharedPtr config) : config_(config) { + city_db_ = initMaxMindDb(config_->cityDbPath()); + isp_db_ = initMaxMindDb(config_->ispDbPath()); + anon_db_ = initMaxMindDb(config_->anonDbPath()); + }; + + ~GeoipProvider(); + + // Envoy::Geolocation::Driver + void lookup(Geolocation::LookupRequest&&, Geolocation::LookupGeoHeadersCallback&&) const override; + +private: + // Allow the unit test to have access to private members. + friend class GeoipProviderPeer; + GeoipProviderConfigSharedPtr config_; + MaxmindDbPtr city_db_; + MaxmindDbPtr isp_db_; + MaxmindDbPtr anon_db_; + MaxmindDbPtr initMaxMindDb(const absl::optional& db_path); + void lookupInCityDb(const Network::Address::InstanceConstSharedPtr& remote_address, + absl::flat_hash_map& lookup_result) const; + void lookupInAsnDb(const Network::Address::InstanceConstSharedPtr& remote_address, + absl::flat_hash_map& lookup_result) const; + void lookupInAnonDb(const Network::Address::InstanceConstSharedPtr& remote_address, + absl::flat_hash_map& lookup_result) const; + template + void populateGeoLookupResult(MMDB_lookup_result_s& mmdb_lookup_result, + absl::flat_hash_map& lookup_result, + const std::string& result_key, Params... lookup_params) const; +}; + +using GeoipProviderSharedPtr = std::shared_ptr; + +} // namespace Maxmind +} // namespace GeoipProviders +} // namespace Extensions +} // namespace Envoy diff --git a/test/extensions/filters/http/geoip/BUILD b/test/extensions/filters/http/geoip/BUILD index 03ce9172a8ff..3c90737e8272 100644 --- a/test/extensions/filters/http/geoip/BUILD +++ b/test/extensions/filters/http/geoip/BUILD @@ -7,7 +7,6 @@ load( "//test/extensions:extensions_build_system.bzl", "envoy_extension_cc_mock", "envoy_extension_cc_test", - "envoy_extension_cc_test_library", ) licenses(["notice"]) # Apache 2 @@ -26,7 +25,6 @@ envoy_extension_cc_test( extension_names = ["envoy.filters.http.geoip"], deps = [ ":geoip_mocks", - ":utils_lib", "//source/common/http:message_lib", "//source/extensions/filters/http/geoip:config", "//test/mocks/server:factory_context_mocks", @@ -53,19 +51,31 @@ envoy_extension_cc_test( ], ) -envoy_extension_cc_mock( - name = "geoip_mocks", - hdrs = ["mocks.h"], - extension_names = ["envoy.filters.http.geoip"], +envoy_extension_cc_test( + name = "geoip_filter_integration_test", + size = "large", + srcs = ["geoip_filter_integration_test.cc"], + data = [ + "//test/extensions/geoip_providers/maxmind/test_data:geolocation_databases", + ], + extension_names = [ + "envoy.filters.http.geoip", + "envoy.geoip_providers.maxmind", + ], deps = [ - ":dummy_cc_proto", - "//source/extensions/filters/http/geoip:provider_config", + "//source/extensions/filters/http/geoip:config", + "//source/extensions/filters/http/geoip:geoip_filter_lib", + "//source/extensions/geoip_providers/maxmind:config", + "//source/extensions/geoip_providers/maxmind:provider_impl", + "//test/integration:http_integration_lib", + "//test/test_common:utility_lib", + "@envoy_api//envoy/extensions/filters/http/geoip/v3:pkg_cc_proto", ], ) -envoy_extension_cc_test_library( - name = "utils_lib", - hdrs = ["utils.h"], +envoy_extension_cc_mock( + name = "geoip_mocks", + hdrs = ["mocks.h"], extension_names = ["envoy.filters.http.geoip"], - deps = ["//source/extensions/filters/http/geoip:geoip_filter_lib"], + deps = ["//envoy/geoip:geoip_provider_driver_interface"], ) diff --git a/test/extensions/filters/http/geoip/config_test.cc b/test/extensions/filters/http/geoip/config_test.cc index 7c27734d1b91..da6c6db167cd 100644 --- a/test/extensions/filters/http/geoip/config_test.cc +++ b/test/extensions/filters/http/geoip/config_test.cc @@ -1,12 +1,11 @@ #include "envoy/extensions/filters/http/geoip/v3/geoip.pb.h" #include "envoy/extensions/filters/http/geoip/v3/geoip.pb.validate.h" +#include "envoy/geoip/geoip_provider_driver.h" #include "source/extensions/filters/http/geoip/config.h" #include "source/extensions/filters/http/geoip/geoip_filter.h" -#include "source/extensions/filters/http/geoip/geoip_provider_config.h" #include "test/extensions/filters/http/geoip/mocks.h" -#include "test/extensions/filters/http/geoip/utils.h" #include "test/mocks/server/factory_context.h" #include "test/test_common/registry.h" #include "test/test_common/test_runtime.h" @@ -20,6 +19,14 @@ namespace Envoy { namespace Extensions { namespace HttpFilters { namespace Geoip { + +class GeoipFilterPeer { +public: + static bool useXff(const GeoipFilter& filter) { return filter.config_->useXff(); } + static uint32_t xffNumTrustedHops(const GeoipFilter& filter) { + return filter.config_->xffNumTrustedHops(); + } +}; namespace { using GeoipFilterConfig = envoy::extensions::filters::http::geoip::v3::Geoip; @@ -44,61 +51,11 @@ MATCHER_P(HasXffNumTrustedHops, expected, "") { return false; } -MATCHER_P(HasGeoHeader, expected_header, "") { - auto filter = std::static_pointer_cast(arg); - auto geo_headers = GeoipFilterPeer::geoHeaders(*filter); - for (const auto& header : geo_headers) { - if (testing::Matches(expected_header)(header)) { - return true; - } - } - *result_listener << "expected header=" << expected_header - << " but header was not found in header map"; - return false; -} - -MATCHER_P(HasGeoHeadersSize, expected_size, "") { - auto filter = std::static_pointer_cast(arg); - auto geo_headers = GeoipFilterPeer::geoHeaders(*filter); - if (expected_size == static_cast(geo_headers.size())) { - return true; - } - *result_listener << "expected geo headers size=" << expected_size << " but was " - << geo_headers.size(); - return false; -} - -MATCHER_P(HasGeoAnonHeader, expected_header, "") { - auto filter = std::static_pointer_cast(arg); - auto geo_anon_headers = GeoipFilterPeer::geoAnonHeaders(*filter); - for (const auto& header : geo_anon_headers) { - if (testing::Matches(expected_header)(header)) { - return true; - } - } - *result_listener << "expected anon header=" << expected_header - << " but header was not found in header map"; - return false; -} - -MATCHER_P(HasAnonGeoHeadersSize, expected_size, "") { - auto filter = std::static_pointer_cast(arg); - auto geo_headers = GeoipFilterPeer::geoAnonHeaders(*filter); - if (expected_size == static_cast(geo_headers.size())) { - return true; - } - *result_listener << "expected geo anon headers size=" << expected_size << " but was " - << geo_headers.size(); - return false; -} - TEST(GeoipFilterConfigTest, GeoipFilterDefaultValues) { TestScopedRuntime scoped_runtime; DummyGeoipProviderFactory dummy_factory; - Registry::InjectFactory registered(dummy_factory); + Registry::InjectFactory registered(dummy_factory); std::string filter_config_yaml = R"EOF( - geo_headers_to_add: - city: "x-geo-city" provider: name: "envoy.geoip_providers.dummy" typed_config: @@ -112,23 +69,17 @@ TEST(GeoipFilterConfigTest, GeoipFilterDefaultValues) { Http::FilterFactoryCb cb = factory.createFilterFactoryFromProto(filter_config, "geoip", context); Http::MockFilterChainFactoryCallbacks filter_callback; EXPECT_CALL(filter_callback, - addStreamDecoderFilter(AllOf(HasUseXff(false), HasXffNumTrustedHops(0), - HasGeoHeader("x-geo-city"), HasGeoHeadersSize(1), - HasAnonGeoHeadersSize(0)))); + addStreamDecoderFilter(AllOf(HasUseXff(false), HasXffNumTrustedHops(0)))); cb(filter_callback); } TEST(GeoipFilterConfigTest, GeoipFilterConfigWithCorrectProto) { TestScopedRuntime scoped_runtime; DummyGeoipProviderFactory dummy_factory; - Registry::InjectFactory registered(dummy_factory); + Registry::InjectFactory registered(dummy_factory); std::string filter_config_yaml = R"EOF( xff_config: xff_num_trusted_hops: 1 - geo_headers_to_add: - country: "x-geo-country" - region: "x-geo-region" - anon_vpn: "x-anon-vpn" provider: name: "envoy.geoip_providers.dummy" typed_config: @@ -142,43 +93,17 @@ TEST(GeoipFilterConfigTest, GeoipFilterConfigWithCorrectProto) { Http::FilterFactoryCb cb = factory.createFilterFactoryFromProto(filter_config, "geoip", context); Http::MockFilterChainFactoryCallbacks filter_callback; EXPECT_CALL(filter_callback, - addStreamDecoderFilter( - AllOf(HasUseXff(true), HasXffNumTrustedHops(1), HasGeoHeader("x-geo-country"), - HasGeoHeader("x-geo-region"), HasGeoHeadersSize(2), - HasAnonGeoHeadersSize(1), HasGeoAnonHeader("x-anon-vpn")))); + addStreamDecoderFilter(AllOf(HasUseXff(true), HasXffNumTrustedHops(1)))); cb(filter_callback); } -TEST(GeoipFilterConfigTest, GeoipFilterConfigMissingGeoHeaders) { +TEST(GeoipFilterConfigTest, GeoipFilterConfigMissingProvider) { TestScopedRuntime scoped_runtime; DummyGeoipProviderFactory dummy_factory; - Registry::InjectFactory registered(dummy_factory); + Registry::InjectFactory registered(dummy_factory); std::string filter_config_yaml = R"EOF( xff_config: xff_num_trusted_hops: 0 - provider: - typed_config: - "@type": type.googleapis.com/test.extensions.filters.http.geoip.DummyProvider - )EOF"; - GeoipFilterConfig filter_config; - - TestUtility::loadFromYaml(filter_config_yaml, filter_config); - NiceMock context; - EXPECT_CALL(context, messageValidationVisitor()); - GeoipFilterFactory factory; - EXPECT_THROW_WITH_REGEX(factory.createFilterFactoryFromProto(filter_config, "geoip", context), - ProtoValidationException, - "Proto constraint validation failed.*value is required.*"); -} - -TEST(GeoipFilterConfigTest, GeoipFilterConfigMissingProvider) { - TestScopedRuntime scoped_runtime; - DummyGeoipProviderFactory dummy_factory; - Registry::InjectFactory registered(dummy_factory); - std::string filter_config_yaml = R"EOF( - geo_headers_to_add: - country: "x-geo-country" - region: "x-geo-region" )EOF"; GeoipFilterConfig filter_config; @@ -194,11 +119,8 @@ TEST(GeoipFilterConfigTest, GeoipFilterConfigMissingProvider) { TEST(GeoipFilterConfigTest, GeoipFilterConfigUnknownProvider) { TestScopedRuntime scoped_runtime; DummyGeoipProviderFactory dummy_factory; - Registry::InjectFactory registered(dummy_factory); + Registry::InjectFactory registered(dummy_factory); std::string filter_config_yaml = R"EOF( - geo_headers_to_add: - country: "x-geo-country" - region: "x-geo-region" provider: name: "envoy.geoip_providers.unknown" )EOF"; @@ -206,7 +128,7 @@ TEST(GeoipFilterConfigTest, GeoipFilterConfigUnknownProvider) { TestUtility::loadFromYaml(filter_config_yaml, filter_config); NiceMock context; - EXPECT_CALL(context, messageValidationVisitor()); + // EXPECT_CALL(context, messageValidationVisitor()); GeoipFilterFactory factory; EXPECT_THROW_WITH_MESSAGE( factory.createFilterFactoryFromProtoTyped(filter_config, "geoip", context), diff --git a/test/extensions/filters/http/geoip/geoip_filter_integration_test.cc b/test/extensions/filters/http/geoip/geoip_filter_integration_test.cc new file mode 100644 index 000000000000..66b3823403e7 --- /dev/null +++ b/test/extensions/filters/http/geoip/geoip_filter_integration_test.cc @@ -0,0 +1,200 @@ +#include "envoy/extensions/filters/http/geoip/v3/geoip.pb.h" + +#include "test/integration/http_integration.h" +#include "test/test_common/registry.h" +#include "test/test_common/utility.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using testing::DoAll; +using testing::SaveArg; + +namespace Envoy { +namespace Extensions { +namespace HttpFilters { +namespace Geoip { +namespace { + +const std::string DefaultConfig = R"EOF( +name: envoy.filters.http.geoip +typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.geoip.v3.Geoip + provider: + name: envoy.geoip_providers.maxmind + typed_config: + "@type": type.googleapis.com/envoy.extensions.geoip_providers.maxmind.v3.MaxMindConfig + common_provider_config: + geo_headers_to_add: + country: "x-geo-country" + region: "x-geo-region" + city: "x-geo-city" + asn: "x-geo-asn" + city_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test.mmdb" + isp_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-ASN-Test.mmdb" +)EOF"; + +const std::string ConfigWithXff = R"EOF( +name: envoy.filters.http.geoip +typed_config: + "@type": type.googleapis.com/envoy.extensions.filters.http.geoip.v3.Geoip + xff_config: + xff_num_trusted_hops: 1 + provider: + name: envoy.geoip_providers.maxmind + typed_config: + "@type": type.googleapis.com/envoy.extensions.geoip_providers.maxmind.v3.MaxMindConfig + common_provider_config: + geo_headers_to_add: + country: "x-geo-country" + region: "x-geo-region" + city: "x-geo-city" + asn: "x-geo-asn" + is_anon: "x-geo-anon" + anon_vpn: "x-geo-anon-vpn" + city_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test.mmdb" + isp_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-ASN-Test.mmdb" + anon_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" +)EOF"; + +class GeoipFilterIntegrationTest : public testing::TestWithParam, + public HttpIntegrationTest { +public: + GeoipFilterIntegrationTest() : HttpIntegrationTest(Http::CodecType::HTTP1, GetParam()) {} +}; + +INSTANTIATE_TEST_SUITE_P(IpVersions, GeoipFilterIntegrationTest, + testing::ValuesIn(TestEnvironment::getIpVersionsForTest()), + TestUtility::ipTestParamsToString); + +TEST_P(GeoipFilterIntegrationTest, GeoDataPopulatedNoXff) { + config_helper_.prependFilter(TestEnvironment::substitute(DefaultConfig)); + initialize(); + codec_client_ = makeHttpConnection(makeClientConnection(lookupPort("http"))); + Http::TestRequestHeaderMapImpl request_headers{ + {":method", "GET"}, {":path", "/"}, {":scheme", "http"}, {":authority", "host"}}; + auto response = sendRequestAndWaitForResponse(request_headers, 0, default_response_headers_, 0); + EXPECT_EQ("Boxford", upstream_request_->headers() + .get(Http::LowerCaseString("x-geo-city"))[0] + ->value() + .getStringView()); + EXPECT_EQ("England", upstream_request_->headers() + .get(Http::LowerCaseString("x-geo-region"))[0] + ->value() + .getStringView()); + EXPECT_EQ("United Kingdom", upstream_request_->headers() + .get(Http::LowerCaseString("x-geo-country"))[0] + ->value() + .getStringView()); + EXPECT_EQ("15169", upstream_request_->headers() + .get(Http::LowerCaseString("x-geo-asn"))[0] + ->value() + .getStringView()); + ASSERT_TRUE(response->complete()); + EXPECT_EQ("200", response->headers().getStatusValue()); + test_server_->waitForCounterEq("http.config_test.geoip.total", 1); + EXPECT_EQ(1, test_server_->counter("http.config_test.maxmind.city_db.total")->value()); + EXPECT_EQ(1, test_server_->counter("http.config_test.maxmind.isp_db.total")->value()); + EXPECT_EQ(1, test_server_->counter("http.config_test.maxmind.city_db.hit")->value()); + EXPECT_EQ(1, test_server_->counter("http.config_test.maxmind.isp_db.hit")->value()); +} + +TEST_P(GeoipFilterIntegrationTest, GeoDataPopulatedUseXff) { + config_helper_.prependFilter(TestEnvironment::substitute(ConfigWithXff)); + initialize(); + codec_client_ = makeHttpConnection(makeClientConnection(lookupPort("http"))); + Http::TestRequestHeaderMapImpl request_headers{{":method", "GET"}, + {":path", "/"}, + {":scheme", "http"}, + {":authority", "host"}, + {"x-forwarded-for", "1.2.0.0,9.10.11.12"}}; + auto response = sendRequestAndWaitForResponse(request_headers, 0, default_response_headers_, 0); + EXPECT_EQ("Boxford", upstream_request_->headers() + .get(Http::LowerCaseString("x-geo-city"))[0] + ->value() + .getStringView()); + EXPECT_EQ("England", upstream_request_->headers() + .get(Http::LowerCaseString("x-geo-region"))[0] + ->value() + .getStringView()); + EXPECT_EQ("United Kingdom", upstream_request_->headers() + .get(Http::LowerCaseString("x-geo-country"))[0] + ->value() + .getStringView()); + EXPECT_EQ("15169", upstream_request_->headers() + .get(Http::LowerCaseString("x-geo-asn"))[0] + ->value() + .getStringView()); + EXPECT_EQ("true", upstream_request_->headers() + .get(Http::LowerCaseString("x-geo-anon"))[0] + ->value() + .getStringView()); + EXPECT_EQ("true", upstream_request_->headers() + .get(Http::LowerCaseString("x-geo-anon-vpn"))[0] + ->value() + .getStringView()); + ASSERT_TRUE(response->complete()); + EXPECT_EQ("200", response->headers().getStatusValue()); + test_server_->waitForCounterEq("http.config_test.geoip.total", 1); + EXPECT_EQ(1, test_server_->counter("http.config_test.maxmind.anon_db.total")->value()); + EXPECT_EQ(1, test_server_->counter("http.config_test.maxmind.anon_db.hit")->value()); + EXPECT_EQ(1, test_server_->counter("http.config_test.maxmind.city_db.total")->value()); + EXPECT_EQ(1, test_server_->counter("http.config_test.maxmind.city_db.hit")->value()); + EXPECT_EQ(1, test_server_->counter("http.config_test.maxmind.isp_db.total")->value()); + EXPECT_EQ(1, test_server_->counter("http.config_test.maxmind.isp_db.hit")->value()); +} + +TEST_P(GeoipFilterIntegrationTest, GeoHeadersOverridenInRequest) { + config_helper_.prependFilter(TestEnvironment::substitute(ConfigWithXff)); + initialize(); + codec_client_ = makeHttpConnection(makeClientConnection(lookupPort("http"))); + Http::TestRequestHeaderMapImpl request_headers{{":method", "GET"}, + {":path", "/"}, + {":scheme", "http"}, + {":authority", "host"}, + {"x-forwarded-for", "81.2.69.142,9.10.11.12"}, + {"x-geo-city", "Berlin"}, + {"x-geo-country", "Germany"}}; + auto response = sendRequestAndWaitForResponse(request_headers, 0, default_response_headers_, 0); + EXPECT_EQ("London", upstream_request_->headers() + .get(Http::LowerCaseString("x-geo-city"))[0] + ->value() + .getStringView()); + EXPECT_EQ("United Kingdom", upstream_request_->headers() + .get(Http::LowerCaseString("x-geo-country"))[0] + ->value() + .getStringView()); + ASSERT_TRUE(response->complete()); + EXPECT_EQ("200", response->headers().getStatusValue()); + test_server_->waitForCounterEq("http.config_test.geoip.total", 1); + EXPECT_EQ(1, test_server_->counter("http.config_test.maxmind.anon_db.total")->value()); + EXPECT_EQ(1, test_server_->counter("http.config_test.maxmind.anon_db.hit")->value()); + EXPECT_EQ(1, test_server_->counter("http.config_test.maxmind.city_db.total")->value()); + EXPECT_EQ(1, test_server_->counter("http.config_test.maxmind.city_db.hit")->value()); + EXPECT_EQ(1, test_server_->counter("http.config_test.maxmind.isp_db.total")->value()); + EXPECT_EQ(1, test_server_->counter("http.config_test.maxmind.isp_db.hit")->value()); +} + +TEST_P(GeoipFilterIntegrationTest, GeoDataNotPopulatedOnEmptyLookupResult) { + config_helper_.prependFilter(TestEnvironment::substitute(ConfigWithXff)); + initialize(); + codec_client_ = makeHttpConnection(makeClientConnection(lookupPort("http"))); + Http::TestRequestHeaderMapImpl request_headers{{":method", "GET"}, + {":path", "/"}, + {":scheme", "http"}, + {":authority", "host"}, + {"x-forwarded-for", "10.10.10.10,9.10.11.12"}}; + auto response = sendRequestAndWaitForResponse(request_headers, 0, default_response_headers_, 0); + // 10.10.10.10 is a private IP and is absent in test_data/GeoIP2-Anonymous-IP-Test.mmdb database. + ASSERT_TRUE(response->headers().get(Http::LowerCaseString("x-geo-anon")).empty()); + ASSERT_TRUE(response->headers().get(Http::LowerCaseString("x-geo-anon-vpn")).empty()); + test_server_->waitForCounterEq("http.config_test.geoip.total", 1); + EXPECT_EQ(1, test_server_->counter("http.config_test.maxmind.anon_db.total")->value()); + EXPECT_EQ(nullptr, test_server_->counter("http.config_test.maxmind.anon_db.hit")); +} + +} // namespace +} // namespace Geoip +} // namespace HttpFilters +} // namespace Extensions +} // namespace Envoy diff --git a/test/extensions/filters/http/geoip/geoip_filter_test.cc b/test/extensions/filters/http/geoip/geoip_filter_test.cc index 035827901bc6..2a0aa027ffbd 100644 --- a/test/extensions/filters/http/geoip/geoip_filter_test.cc +++ b/test/extensions/filters/http/geoip/geoip_filter_test.cc @@ -45,8 +45,8 @@ MATCHER_P2(HasExpectedHeader, expected_header, expected_value, "") { class GeoipFilterTest : public testing::Test { public: GeoipFilterTest() - : dummy_factory_(new DummyGeoipProviderFactory()), dummy_driver_(dummy_factory_->getDriver()), - empty_response_(absl::nullopt) {} + : dummy_factory_(new DummyGeoipProviderFactory()), + dummy_driver_(dummy_factory_->getDriver()) {} void initializeFilter(const std::string& yaml) { ON_CALL(filter_callbacks_, dispatcher()).WillByDefault(::testing::ReturnRef(*dispatcher_)); @@ -59,12 +59,13 @@ class GeoipFilterTest : public testing::Test { void initializeProviderFactory() { TestScopedRuntime scoped_runtime; - Registry::InjectFactory registered(*dummy_factory_); + scoped_runtime.mergeValues( + {{"envoy.reloadable_features.no_extension_lookup_by_name", "false"}}); + Registry::InjectFactory registered(*dummy_factory_); } - void expectStats(const std::string& geo_header) { - EXPECT_CALL(stats_, counter(absl::StrCat("prefix.geoip.", geo_header, ".total"))); - EXPECT_CALL(stats_, counter(absl::StrCat("prefix.geoip.", geo_header, ".hit"))); + void expectStats(const uint32_t n_total = 1) { + EXPECT_CALL(stats_, counter("prefix.geoip.total")).Times(n_total); } NiceMock stats_; @@ -75,17 +76,14 @@ class GeoipFilterTest : public testing::Test { NiceMock filter_callbacks_; Api::ApiPtr api_ = Api::createApiForTest(); Event::DispatcherPtr dispatcher_ = api_->allocateDispatcher("test_thread"); - absl::optional empty_response_; - LookupRequest captured_rq_; - LookupGeoHeadersCallback captured_cb_; + Geolocation::LookupRequest captured_rq_; + Geolocation::LookupGeoHeadersCallback captured_cb_; Buffer::OwnedImpl data_; }; TEST_F(GeoipFilterTest, NoXffSuccessfulLookup) { initializeProviderFactory(); const std::string external_request_yaml = R"EOF( - geo_headers_to_add: - city: "x-geo-city" provider: name: "envoy.geoip_providers.dummy" typed_config: @@ -93,7 +91,7 @@ TEST_F(GeoipFilterTest, NoXffSuccessfulLookup) { )EOF"; initializeFilter(external_request_yaml); Http::TestRequestHeaderMapImpl request_headers; - expectStats("x-geo-city"); + expectStats(); Network::Address::InstanceConstSharedPtr remote_address = Network::Utility::parseInternetAddress("1.2.3.4"); filter_callbacks_.stream_info_.downstream_connection_info_provider_->setRemoteAddress( @@ -105,15 +103,12 @@ TEST_F(GeoipFilterTest, NoXffSuccessfulLookup) { EXPECT_EQ(Http::FilterTrailersStatus::Continue, filter_->decodeTrailers(request_trailers)); EXPECT_EQ(Http::FilterHeadersStatus::StopIteration, filter_->decodeHeaders(request_headers, false)); - captured_cb_(LookupResult{{"x-geo-city", absl::make_optional("dummy-city")}}); + captured_cb_(Geolocation::LookupResult{{"x-geo-city", "dummy-city"}}); EXPECT_CALL(filter_callbacks_, continueDecoding()); dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_EQ(1, request_headers.size()); EXPECT_THAT(request_headers, HasExpectedHeader("x-geo-city", "dummy-city")); EXPECT_EQ("1.2.3.4:0", captured_rq_.remoteAddress()->asString()); - EXPECT_EQ(0, captured_rq_.geoAnonHeaders().size()); - EXPECT_EQ(1, captured_rq_.geoHeaders().size()); - EXPECT_THAT(captured_rq_.geoHeaders(), testing::UnorderedElementsAre("x-geo-city")); ::testing::Mock::VerifyAndClearExpectations(&filter_callbacks_); filter_->onDestroy(); } @@ -123,15 +118,13 @@ TEST_F(GeoipFilterTest, UseXffSuccessfulLookup) { const std::string external_request_yaml = R"EOF( xff_config: xff_num_trusted_hops: 1 - geo_headers_to_add: - region: "x-geo-region" provider: name: "envoy.geoip_providers.dummy" )EOF"; initializeFilter(external_request_yaml); Http::TestRequestHeaderMapImpl request_headers; request_headers.addCopy("x-forwarded-for", "10.0.0.1,10.0.0.2"); - expectStats("x-geo-region"); + expectStats(); Network::Address::InstanceConstSharedPtr remote_address = Network::Utility::parseInternetAddress("1.2.3.4"); filter_callbacks_.stream_info_.downstream_connection_info_provider_->setRemoteAddress( @@ -139,7 +132,7 @@ TEST_F(GeoipFilterTest, UseXffSuccessfulLookup) { EXPECT_CALL(*dummy_driver_, lookup(_, _)) .WillRepeatedly( DoAll(SaveArg<0>(&captured_rq_), SaveArg<1>(&captured_cb_), Invoke([this]() { - captured_cb_(LookupResult{{"x-geo-region", absl::make_optional("dummy-region")}}); + captured_cb_(Geolocation::LookupResult{{"x-geo-region", "dummy-region"}}); }))); EXPECT_EQ(Http::FilterHeadersStatus::StopIteration, filter_->decodeHeaders(request_headers, false)); @@ -148,9 +141,6 @@ TEST_F(GeoipFilterTest, UseXffSuccessfulLookup) { EXPECT_EQ(2, request_headers.size()); EXPECT_THAT(request_headers, HasExpectedHeader("x-geo-region", "dummy-region")); EXPECT_EQ("10.0.0.1:0", captured_rq_.remoteAddress()->asString()); - EXPECT_EQ(0, captured_rq_.geoAnonHeaders().size()); - EXPECT_EQ(1, captured_rq_.geoHeaders().size()); - EXPECT_THAT(captured_rq_.geoHeaders(), testing::UnorderedElementsAre("x-geo-region")); ::testing::Mock::VerifyAndClearExpectations(&filter_callbacks_); filter_->onDestroy(); } @@ -158,9 +148,6 @@ TEST_F(GeoipFilterTest, UseXffSuccessfulLookup) { TEST_F(GeoipFilterTest, GeoHeadersOverridenForIncomingRequest) { initializeProviderFactory(); const std::string external_request_yaml = R"EOF( - geo_headers_to_add: - region: "x-geo-region" - city: "x-geo-city" provider: name: "envoy.geoip_providers.dummy" )EOF"; @@ -170,20 +157,16 @@ TEST_F(GeoipFilterTest, GeoHeadersOverridenForIncomingRequest) { request_headers.addCopy("x-geo-city", "ngnix_city"); std::map geo_headers = {{"x-geo-region", "dummy_region"}, {"x-geo-city", "dummy_city"}}; - for (auto& geo_header : geo_headers) { - auto& header = geo_header.first; - expectStats(header); - } + expectStats(); Network::Address::InstanceConstSharedPtr remote_address = Network::Utility::parseInternetAddress("1.2.3.4"); filter_callbacks_.stream_info_.downstream_connection_info_provider_->setRemoteAddress( remote_address); EXPECT_CALL(*dummy_driver_, lookup(_, _)) - .WillRepeatedly( - DoAll(SaveArg<0>(&captured_rq_), SaveArg<1>(&captured_cb_), Invoke([this]() { - captured_cb_(LookupResult{{"x-geo-city", absl::make_optional("dummy-city")}, - {"x-geo-region", absl::make_optional("dummy-region")}}); - }))); + .WillRepeatedly(DoAll(SaveArg<0>(&captured_rq_), SaveArg<1>(&captured_cb_), Invoke([this]() { + captured_cb_(Geolocation::LookupResult{ + {"x-geo-city", "dummy-city"}, {"x-geo-region", "dummy-region"}}); + }))); EXPECT_EQ(Http::FilterHeadersStatus::StopIteration, filter_->decodeHeaders(request_headers, false)); EXPECT_CALL(filter_callbacks_, continueDecoding()); @@ -192,10 +175,6 @@ TEST_F(GeoipFilterTest, GeoHeadersOverridenForIncomingRequest) { EXPECT_THAT(request_headers, HasExpectedHeader("x-geo-city", "dummy-city")); EXPECT_THAT(request_headers, HasExpectedHeader("x-geo-region", "dummy-region")); EXPECT_EQ("1.2.3.4:0", captured_rq_.remoteAddress()->asString()); - EXPECT_EQ(0, captured_rq_.geoAnonHeaders().size()); - EXPECT_EQ(2, captured_rq_.geoHeaders().size()); - EXPECT_THAT(captured_rq_.geoHeaders(), - testing::UnorderedElementsAre("x-geo-region", "x-geo-city")); ::testing::Mock::VerifyAndClearExpectations(&filter_callbacks_); filter_->onDestroy(); } @@ -203,16 +182,6 @@ TEST_F(GeoipFilterTest, GeoHeadersOverridenForIncomingRequest) { TEST_F(GeoipFilterTest, AllHeadersPropagatedCorrectly) { initializeProviderFactory(); const std::string external_request_yaml = R"EOF( - geo_headers_to_add: - region: "x-geo-region" - country: "x-geo-country" - city: "x-geo-city" - asn: "x-geo-asn" - is_anon: "x-geo-anon" - anon_vpn: "x-geo-anon-vpn" - anon_hosting: "x-geo-anon-hosting" - anon_tor: "x-geo-anon-tor" - anon_proxy: "x-geo-anon-proxy" provider: name: "envoy.geoip_providers.dummy" )EOF"; @@ -227,29 +196,23 @@ TEST_F(GeoipFilterTest, AllHeadersPropagatedCorrectly) { {"x-geo-anon-hosting", "true"}, {"x-geo-anon-tor", "true"}, {"x-geo-anon-proxy", "true"}}; - for (auto& geo_header : geo_headers) { - auto& header = geo_header.first; - expectStats(header); - } - for (auto& geo_anon_header : geo_anon_headers) { - auto& header = geo_anon_header.first; - expectStats(header); - } + expectStats(); Network::Address::InstanceConstSharedPtr remote_address = Network::Utility::parseInternetAddress("1.2.3.4"); filter_callbacks_.stream_info_.downstream_connection_info_provider_->setRemoteAddress( remote_address); EXPECT_CALL(*dummy_driver_, lookup(_, _)) .WillRepeatedly(DoAll(SaveArg<0>(&captured_rq_), SaveArg<1>(&captured_cb_), Invoke([this]() { - captured_cb_(LookupResult{{"x-geo-city", "dummy-city"}, - {"x-geo-region", "dummy-region"}, - {"x-geo-country", "dummy-country"}, - {"x-geo-asn", "dummy-asn"}, - {"x-geo-anon", "true"}, - {"x-geo-anon-vpn", "false"}, - {"x-geo-anon-hosting", "true"}, - {"x-geo-anon-tor", "true"}, - {"x-geo-anon-proxy", "true"}}); + captured_cb_( + Geolocation::LookupResult{{"x-geo-city", "dummy-city"}, + {"x-geo-region", "dummy-region"}, + {"x-geo-country", "dummy-country"}, + {"x-geo-asn", "dummy-asn"}, + {"x-geo-anon", "true"}, + {"x-geo-anon-vpn", "false"}, + {"x-geo-anon-hosting", "true"}, + {"x-geo-anon-tor", "true"}, + {"x-geo-anon-proxy", "true"}}); }))); EXPECT_EQ(Http::FilterHeadersStatus::StopIteration, filter_->decodeHeaders(request_headers, false)); @@ -257,14 +220,6 @@ TEST_F(GeoipFilterTest, AllHeadersPropagatedCorrectly) { dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_EQ("1.2.3.4:0", captured_rq_.remoteAddress()->asString()); EXPECT_EQ(9, request_headers.size()); - EXPECT_EQ(5, captured_rq_.geoAnonHeaders().size()); - EXPECT_EQ(4, captured_rq_.geoHeaders().size()); - EXPECT_THAT( - captured_rq_.geoHeaders(), - testing::UnorderedElementsAre("x-geo-region", "x-geo-city", "x-geo-country", "x-geo-asn")); - EXPECT_THAT(captured_rq_.geoAnonHeaders(), - testing::UnorderedElementsAre("x-geo-anon", "x-geo-anon-vpn", "x-geo-anon-hosting", - "x-geo-anon-tor", "x-geo-anon-proxy")); for (auto& geo_header : geo_headers) { auto& header = geo_header.first; auto& value = geo_header.second; @@ -282,26 +237,20 @@ TEST_F(GeoipFilterTest, AllHeadersPropagatedCorrectly) { TEST_F(GeoipFilterTest, GeoHeaderNotAppendedOnEmptyLookup) { initializeProviderFactory(); const std::string external_request_yaml = R"EOF( - geo_headers_to_add: - region: "x-geo-region" - city: "x-geo-city" provider: name: "envoy.geoip_providers.dummy" )EOF"; initializeFilter(external_request_yaml); Http::TestRequestHeaderMapImpl request_headers; - EXPECT_CALL(stats_, counter("prefix.geoip.x-geo-city.total")); - EXPECT_CALL(stats_, counter("prefix.geoip.x-geo-city.hit")).Times(0); - EXPECT_CALL(stats_, counter("prefix.geoip.x-geo-region.total")); - EXPECT_CALL(stats_, counter("prefix.geoip.x-geo-region.hit")); + expectStats(); Network::Address::InstanceConstSharedPtr remote_address = Network::Utility::parseInternetAddress("1.2.3.4"); filter_callbacks_.stream_info_.downstream_connection_info_provider_->setRemoteAddress( remote_address); EXPECT_CALL(*dummy_driver_, lookup(_, _)) .WillRepeatedly(DoAll(SaveArg<0>(&captured_rq_), SaveArg<1>(&captured_cb_), Invoke([this]() { - captured_cb_(LookupResult{{"x-geo-city", empty_response_}, - {"x-geo-region", "dummy-region"}}); + captured_cb_(Geolocation::LookupResult{ + {"x-geo-city", ""}, {"x-geo-region", "dummy-region"}}); }))); EXPECT_EQ(Http::FilterHeadersStatus::StopIteration, filter_->decodeHeaders(request_headers, false)); @@ -309,8 +258,6 @@ TEST_F(GeoipFilterTest, GeoHeaderNotAppendedOnEmptyLookup) { dispatcher_->run(Event::Dispatcher::RunType::Block); EXPECT_EQ("1.2.3.4:0", captured_rq_.remoteAddress()->asString()); EXPECT_EQ(1, request_headers.size()); - EXPECT_EQ(0, captured_rq_.geoAnonHeaders().size()); - EXPECT_EQ(2, captured_rq_.geoHeaders().size()); EXPECT_THAT(request_headers, HasExpectedHeader("x-geo-region", "dummy-region")); ::testing::Mock::VerifyAndClearExpectations(&filter_callbacks_); filter_->onDestroy(); @@ -319,8 +266,6 @@ TEST_F(GeoipFilterTest, GeoHeaderNotAppendedOnEmptyLookup) { TEST_F(GeoipFilterTest, NoCrashIfFilterDestroyedBeforeCallbackCalled) { initializeProviderFactory(); const std::string external_request_yaml = R"EOF( - geo_headers_to_add: - city: "x-geo-city" provider: name: "envoy.geoip_providers.dummy" )EOF"; @@ -331,10 +276,9 @@ TEST_F(GeoipFilterTest, NoCrashIfFilterDestroyedBeforeCallbackCalled) { filter_callbacks_.stream_info_.downstream_connection_info_provider_->setRemoteAddress( remote_address); EXPECT_CALL(*dummy_driver_, lookup(_, _)) - .WillRepeatedly( - DoAll(SaveArg<0>(&captured_rq_), SaveArg<1>(&captured_cb_), Invoke([this]() { - captured_cb_(LookupResult{{"x-geo-city", absl::make_optional("dummy-city")}}); - }))); + .WillRepeatedly(DoAll(SaveArg<0>(&captured_rq_), SaveArg<1>(&captured_cb_), Invoke([this]() { + captured_cb_(Geolocation::LookupResult{{"x-geo-city", "dummy-city"}}); + }))); EXPECT_EQ(Http::FilterHeadersStatus::StopIteration, filter_->decodeHeaders(request_headers, false)); filter_.reset(); diff --git a/test/extensions/filters/http/geoip/mocks.h b/test/extensions/filters/http/geoip/mocks.h index ffc2c361d9ec..7b7fc15c1678 100644 --- a/test/extensions/filters/http/geoip/mocks.h +++ b/test/extensions/filters/http/geoip/mocks.h @@ -1,4 +1,4 @@ -#include "source/extensions/filters/http/geoip/geoip_provider_config.h" +#include "envoy/geoip/geoip_provider_driver.h" #include "test/extensions/filters/http/geoip/dummy.pb.h" #include "test/extensions/filters/http/geoip/dummy.pb.validate.h" @@ -10,18 +10,21 @@ namespace Extensions { namespace HttpFilters { namespace Geoip { -class MockDriver : public Driver { +class MockDriver : public Geolocation::Driver { public: - MOCK_METHOD(void, lookup, (LookupRequest && request, LookupGeoHeadersCallback&&), (const)); + MOCK_METHOD(void, lookup, + (Geolocation::LookupRequest && request, Geolocation::LookupGeoHeadersCallback&&), + (const)); }; using MockDriverSharedPtr = std::shared_ptr; -class DummyGeoipProviderFactory : public GeoipProviderFactory { +class DummyGeoipProviderFactory : public Geolocation::GeoipProviderFactory { public: DummyGeoipProviderFactory() : driver_(new MockDriver()) {} - DriverSharedPtr createGeoipProviderDriver(const Protobuf::Message&, - GeoipProviderFactoryContextPtr&) override { + Geolocation::DriverSharedPtr + createGeoipProviderDriver(const Protobuf::Message&, const std::string&, + Server::Configuration::FactoryContext&) override { return driver_; } diff --git a/test/extensions/filters/http/geoip/utils.h b/test/extensions/filters/http/geoip/utils.h deleted file mode 100644 index a80c09e24d04..000000000000 --- a/test/extensions/filters/http/geoip/utils.h +++ /dev/null @@ -1,26 +0,0 @@ -#include "source/extensions/filters/http/geoip/geoip_filter.h" - -namespace Envoy { -namespace Extensions { -namespace HttpFilters { -namespace Geoip { - -class GeoipFilterPeer { -public: - static bool useXff(const GeoipFilter& filter) { return filter.config_->useXff(); } - static uint32_t xffNumTrustedHops(const GeoipFilter& filter) { - return filter.config_->xffNumTrustedHops(); - } - - static const absl::flat_hash_set& geoHeaders(const GeoipFilter& filter) { - return filter.config_->geoHeaders(); - } - static const absl::flat_hash_set& geoAnonHeaders(const GeoipFilter& filter) { - return filter.config_->geoAnonHeaders(); - } -}; - -} // namespace Geoip -} // namespace HttpFilters -} // namespace Extensions -} // namespace Envoy diff --git a/test/extensions/geoip_providers/maxmind/BUILD b/test/extensions/geoip_providers/maxmind/BUILD new file mode 100644 index 000000000000..972a66c308ef --- /dev/null +++ b/test/extensions/geoip_providers/maxmind/BUILD @@ -0,0 +1,43 @@ +load( + "//bazel:envoy_build_system.bzl", + "envoy_package", +) +load( + "//test/extensions:extensions_build_system.bzl", + "envoy_extension_cc_test", +) + +licenses(["notice"]) # Apache 2 + +envoy_package() + +envoy_extension_cc_test( + name = "config_test", + size = "small", + srcs = ["config_test.cc"], + data = [ + "//test/extensions/geoip_providers/maxmind/test_data:geolocation_databases", + ], + extension_names = ["envoy.geoip_providers.maxmind"], + deps = [ + "//source/extensions/geoip_providers/maxmind:config", + "//source/extensions/geoip_providers/maxmind:provider_impl", + "//test/mocks/server:factory_context_mocks", + "@envoy_api//envoy/extensions/geoip_providers/maxmind/v3:pkg_cc_proto", + ], +) + +envoy_extension_cc_test( + name = "geoip_provider_test", + size = "small", + srcs = ["geoip_provider_test.cc"], + data = [ + "//test/extensions/geoip_providers/maxmind/test_data:geolocation_databases", + ], + extension_names = ["envoy.geoip_providers.maxmind"], + deps = [ + "//source/extensions/geoip_providers/maxmind:config", + "//source/extensions/geoip_providers/maxmind:provider_impl", + "@envoy_api//envoy/extensions/geoip_providers/maxmind/v3:pkg_cc_proto", + ], +) diff --git a/test/extensions/geoip_providers/maxmind/config_test.cc b/test/extensions/geoip_providers/maxmind/config_test.cc new file mode 100644 index 000000000000..a2b7f9bbcfc7 --- /dev/null +++ b/test/extensions/geoip_providers/maxmind/config_test.cc @@ -0,0 +1,258 @@ +#include "envoy/extensions/geoip_providers/maxmind/v3/maxmind.pb.h" +#include "envoy/extensions/geoip_providers/maxmind/v3/maxmind.pb.validate.h" + +#include "source/extensions/geoip_providers/maxmind/config.h" +#include "source/extensions/geoip_providers/maxmind/geoip_provider.h" + +#include "test/mocks/server/factory_context.h" +#include "test/test_common/environment.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using ::testing::AllOf; + +namespace Envoy { +namespace Extensions { +namespace GeoipProviders { +namespace Maxmind { + +using MaxmindProviderConfig = envoy::extensions::geoip_providers::maxmind::v3::MaxMindConfig; + +class GeoipProviderPeer { +public: + static const absl::optional& cityDbPath(const GeoipProvider& provider) { + return provider.config_->cityDbPath(); + } + static const absl::optional& ispDbPath(const GeoipProvider& provider) { + return provider.config_->ispDbPath(); + } + static const absl::optional& anonDbPath(const GeoipProvider& provider) { + return provider.config_->anonDbPath(); + } + static const absl::optional& countryHeader(const GeoipProvider& provider) { + return provider.config_->countryHeader(); + } + static const absl::optional& cityHeader(const GeoipProvider& provider) { + return provider.config_->cityHeader(); + } + static const absl::optional& regionHeader(const GeoipProvider& provider) { + return provider.config_->regionHeader(); + } + static const absl::optional& asnHeader(const GeoipProvider& provider) { + return provider.config_->asnHeader(); + } + static const absl::optional& anonVpnHeader(const GeoipProvider& provider) { + return provider.config_->anonVpnHeader(); + } + static const absl::optional& anonTorHeader(const GeoipProvider& provider) { + return provider.config_->anonTorHeader(); + } + static const absl::optional& anonProxyHeader(const GeoipProvider& provider) { + return provider.config_->anonProxyHeader(); + } + static const absl::optional& anonHostingHeader(const GeoipProvider& provider) { + return provider.config_->anonHostingHeader(); + } +}; + +MATCHER_P(HasCityDbPath, expected_db_path, "") { + auto provider = std::static_pointer_cast(arg); + auto city_db_path = GeoipProviderPeer::cityDbPath(*provider); + if (city_db_path && testing::Matches(expected_db_path)(city_db_path.value())) { + return true; + } + *result_listener << "expected city_db_path=" << expected_db_path + << " but city_db_path was not found in provider config"; + return false; +} + +MATCHER_P(HasIspDbPath, expected_db_path, "") { + auto provider = std::static_pointer_cast(arg); + auto isp_db_path = GeoipProviderPeer::ispDbPath(*provider); + if (isp_db_path && testing::Matches(expected_db_path)(isp_db_path.value())) { + return true; + } + *result_listener << "expected isp_db_path=" << expected_db_path + << " but isp_db_path was not found in provider config"; + return false; +} + +MATCHER_P(HasAnonDbPath, expected_db_path, "") { + auto provider = std::static_pointer_cast(arg); + auto anon_db_path = GeoipProviderPeer::anonDbPath(*provider); + if (anon_db_path && testing::Matches(expected_db_path)(anon_db_path.value())) { + return true; + } + *result_listener << "expected anon_db_path=" << expected_db_path + << " but anon_db_path was not found in provider config"; + return false; +} + +MATCHER_P(HasCountryHeader, expected_header, "") { + auto provider = std::static_pointer_cast(arg); + auto country_header = GeoipProviderPeer::countryHeader(*provider); + if (country_header && testing::Matches(expected_header)(country_header.value())) { + return true; + } + *result_listener << "expected country header=" << expected_header + << " but header was not found in provider config with expected value"; + return false; +} + +MATCHER_P(HasCityHeader, expected_header, "") { + auto provider = std::static_pointer_cast(arg); + auto city_header = GeoipProviderPeer::cityHeader(*provider); + if (city_header && testing::Matches(expected_header)(city_header.value())) { + return true; + } + *result_listener << "expected city header=" << expected_header + << " but header was not found in provider config with expected value"; + return false; +} + +MATCHER_P(HasRegionHeader, expected_header, "") { + auto provider = std::static_pointer_cast(arg); + auto region_header = GeoipProviderPeer::regionHeader(*provider); + if (region_header && testing::Matches(expected_header)(region_header.value())) { + return true; + } + *result_listener << "expected region header=" << expected_header + << " but header was not found in provider config with expected value"; + return false; +} + +MATCHER_P(HasAsnHeader, expected_header, "") { + auto provider = std::static_pointer_cast(arg); + auto asn_header = GeoipProviderPeer::asnHeader(*provider); + if (asn_header && testing::Matches(expected_header)(asn_header.value())) { + return true; + } + *result_listener << "expected asn header=" << expected_header + << " but header was not found in provider config with expected value"; + return false; +} + +MATCHER_P(HasAnonVpnHeader, expected_header, "") { + auto provider = std::static_pointer_cast(arg); + auto anon_vpn_header = GeoipProviderPeer::anonVpnHeader(*provider); + if (anon_vpn_header && testing::Matches(expected_header)(anon_vpn_header.value())) { + return true; + } + *result_listener << "expected anon_vpn header=" << expected_header + << " but header was not found in provider config with expected value"; + return false; +} + +MATCHER_P(HasAnonTorHeader, expected_header, "") { + auto provider = std::static_pointer_cast(arg); + auto anon_tor_header = GeoipProviderPeer::anonTorHeader(*provider); + if (anon_tor_header && testing::Matches(expected_header)(anon_tor_header.value())) { + return true; + } + *result_listener << "expected anon_tor header=" << expected_header + << " but header was not found in provider config with expected value"; + return false; +} + +MATCHER_P(HasAnonProxyHeader, expected_header, "") { + auto provider = std::static_pointer_cast(arg); + auto anon_proxy_header = GeoipProviderPeer::anonProxyHeader(*provider); + if (anon_proxy_header && testing::Matches(expected_header)(anon_proxy_header.value())) { + return true; + } + *result_listener << "expected anon_proxy header=" << expected_header + << " but header was not found in provider config with expected value"; + return false; +} + +MATCHER_P(HasAnonHostingHeader, expected_header, "") { + auto provider = std::static_pointer_cast(arg); + auto anon_hosting_header = GeoipProviderPeer::anonHostingHeader(*provider); + if (anon_hosting_header && testing::Matches(expected_header)(anon_hosting_header.value())) { + return true; + } + *result_listener << "expected anon_hosting_header header=" << expected_header + << " but header was not found in provider config with expected value"; + return false; +} + +std::string genGeoDbFilePath(std::string db_name) { + return TestEnvironment::substitute( + "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/" + db_name); +} + +TEST(MaxmindProviderConfigTest, ProviderConfigWithCorrectProto) { + const auto provider_config_yaml = R"EOF( + common_provider_config: + geo_headers_to_add: + country: "x-geo-country" + region: "x-geo-region" + city: "x-geo-city" + anon_vpn: "x-anon-vpn" + asn: "x-geo-asn" + is_anon: "x-geo-anon" + anon_vpn: "x-anon-vpn" + anon_tor: "x-anon-tor" + anon_proxy: "x-anon-proxy" + anon_hosting: "x-anon-hosting" + city_db_path: %s + isp_db_path: %s + anon_db_path: %s + )EOF"; + MaxmindProviderConfig provider_config; + auto city_db_path = genGeoDbFilePath("GeoLite2-City-Test.mmdb"); + auto asn_db_path = genGeoDbFilePath("GeoLite2-ASN-Test.mmdb"); + auto anon_db_path = genGeoDbFilePath("GeoIP2-Anonymous-IP-Test.mmdb"); + auto processed_provider_config_yaml = + absl::StrFormat(provider_config_yaml, city_db_path, asn_db_path, anon_db_path); + TestUtility::loadFromYaml(processed_provider_config_yaml, provider_config); + NiceMock context; + EXPECT_CALL(context, messageValidationVisitor()); + MaxmindProviderFactory factory; + Geolocation::DriverSharedPtr driver = + factory.createGeoipProviderDriver(provider_config, "maxmind", context); + EXPECT_THAT(driver, AllOf(HasCityDbPath(city_db_path), HasIspDbPath(asn_db_path), + HasAnonDbPath(anon_db_path), HasCountryHeader("x-geo-country"), + HasCityHeader("x-geo-city"), HasRegionHeader("x-geo-region"), + HasAsnHeader("x-geo-asn"), HasAnonVpnHeader("x-anon-vpn"), + HasAnonTorHeader("x-anon-tor"), HasAnonProxyHeader("x-anon-proxy"), + HasAnonHostingHeader("x-anon-hosting"))); +} + +TEST(MaxmindProviderConfigTest, ProviderConfigWithNoDbPaths) { + std::string provider_config_yaml = R"EOF( + common_provider_config: + geo_headers_to_add: + country: "x-geo-country" + region: "x-geo-region" + )EOF"; + MaxmindProviderConfig provider_config; + TestUtility::loadFromYaml(provider_config_yaml, provider_config); + NiceMock context; + EXPECT_CALL(context, messageValidationVisitor()); + MaxmindProviderFactory factory; + EXPECT_THROW_WITH_MESSAGE(factory.createGeoipProviderDriver(provider_config, "maxmind", context), + Envoy::EnvoyException, + "At least one geolocation database path needs to be configured: " + "city_db_path, isp_db_path or anon_db_path"); +} + +TEST(MaxmindProviderConfigTest, ProviderConfigWithNoGeoHeaders) { + std::string provider_config_yaml = R"EOF( + isp_db_path: "/geoip2/Isp.mmdb" + )EOF"; + MaxmindProviderConfig provider_config; + TestUtility::loadFromYaml(provider_config_yaml, provider_config); + NiceMock context; + EXPECT_CALL(context, messageValidationVisitor()); + MaxmindProviderFactory factory; + EXPECT_THROW_WITH_REGEX(factory.createGeoipProviderDriver(provider_config, "maxmind", context), + ProtoValidationException, + "Proto constraint validation failed.*value is required.*"); +} + +} // namespace Maxmind +} // namespace GeoipProviders +} // namespace Extensions +} // namespace Envoy diff --git a/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc b/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc new file mode 100644 index 000000000000..691d44f7f97f --- /dev/null +++ b/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc @@ -0,0 +1,249 @@ +#include "envoy/extensions/geoip_providers/maxmind/v3/maxmind.pb.h" + +#include "source/common/network/address_impl.h" +#include "source/common/network/utility.h" +#include "source/extensions/geoip_providers/maxmind/geoip_provider.h" + +#include "test/mocks/stats/mocks.h" +#include "test/test_common/environment.h" +#include "test/test_common/utility.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using testing::_; +using testing::NiceMock; +using testing::SaveArg; + +namespace Envoy { +namespace Extensions { +namespace GeoipProviders { +namespace Maxmind { + +class GeoipProviderTest : public testing::Test { +public: + void initializeProvider(const std::string& yaml) { + envoy::extensions::geoip_providers::maxmind::v3::MaxMindConfig config; + TestUtility::loadFromYaml(TestEnvironment::substitute(yaml), config); + config_ = std::make_shared(config, "prefix.", stats_.mockScope()); + provider_ = std::make_shared(config_); + } + + void expectStats(const std::string& db_type, const uint32_t total_times = 1, + const uint32_t hit_times = 1, const uint32_t error_times = 0) { + EXPECT_CALL(stats_, counter(absl::StrCat("prefix.maxmind.", db_type, ".total"))) + .Times(total_times); + EXPECT_CALL(stats_, counter(absl::StrCat("prefix.maxmind.", db_type, ".hit"))).Times(hit_times); + EXPECT_CALL(stats_, counter(absl::StrCat("prefix.maxmind.", db_type, ".lookup_error"))) + .Times(error_times); + } + + NiceMock stats_; + GeoipProviderConfigSharedPtr config_; + GeoipProviderSharedPtr provider_; + absl::flat_hash_map captured_lookup_response_; +}; + +TEST_F(GeoipProviderTest, ValidConfigCityAndIspDbsSuccessfulLookup) { + const std::string config_yaml = R"EOF( + common_provider_config: + geo_headers_to_add: + country: "x-geo-country" + region: "x-geo-region" + city: "x-geo-city" + asn: "x-geo-asn" + city_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test.mmdb" + isp_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-ASN-Test.mmdb" + )EOF"; + initializeProvider(config_yaml); + Network::Address::InstanceConstSharedPtr remote_address = + Network::Utility::parseInternetAddress("78.26.243.166"); + Geolocation::LookupRequest lookup_rq{std::move(remote_address)}; + testing::MockFunction lookup_cb; + auto lookup_cb_std = lookup_cb.AsStdFunction(); + EXPECT_CALL(lookup_cb, Call(_)).WillRepeatedly(SaveArg<0>(&captured_lookup_response_)); + expectStats("city_db"); + expectStats("isp_db"); + provider_->lookup(std::move(lookup_rq), std::move(lookup_cb_std)); + EXPECT_EQ(4, captured_lookup_response_.size()); + const auto& city_it = captured_lookup_response_.find("x-geo-city"); + EXPECT_EQ("Boxford", city_it->second); + const auto& region_it = captured_lookup_response_.find("x-geo-region"); + EXPECT_EQ("England", region_it->second); + const auto& country_it = captured_lookup_response_.find("x-geo-country"); + EXPECT_EQ("United Kingdom", country_it->second); + const auto& asn_it = captured_lookup_response_.find("x-geo-asn"); + EXPECT_EQ("15169", asn_it->second); +} + +// Tests for anonymous database replicate expectations from corresponding Maxmind tests: +// https://github.com/maxmind/GeoIP2-perl/blob/main/t/GeoIP2/Database/Reader-Anonymous-IP.t +TEST_F(GeoipProviderTest, ValidConfigAnonVpnSuccessfulLookup) { + const std::string config_yaml = R"EOF( + common_provider_config: + geo_headers_to_add: + is_anon: "x-geo-anon" + anon_vpn: "x-geo-anon-vpn" + anon_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" + )EOF"; + initializeProvider(config_yaml); + Network::Address::InstanceConstSharedPtr remote_address = + Network::Utility::parseInternetAddress("1.2.0.0"); + Geolocation::LookupRequest lookup_rq{std::move(remote_address)}; + testing::MockFunction lookup_cb; + auto lookup_cb_std = lookup_cb.AsStdFunction(); + EXPECT_CALL(lookup_cb, Call(_)).WillRepeatedly(SaveArg<0>(&captured_lookup_response_)); + expectStats("anon_db"); + provider_->lookup(std::move(lookup_rq), std::move(lookup_cb_std)); + EXPECT_EQ(2, captured_lookup_response_.size()); + const auto& anon_it = captured_lookup_response_.find("x-geo-anon"); + EXPECT_EQ("true", anon_it->second); + const auto& anon_vpn_it = captured_lookup_response_.find("x-geo-anon-vpn"); + EXPECT_EQ("true", anon_vpn_it->second); +} + +TEST_F(GeoipProviderTest, ValidConfigAnonHostingSuccessfulLookup) { + const std::string config_yaml = R"EOF( + common_provider_config: + geo_headers_to_add: + is_anon: "x-geo-anon" + anon_hosting: "x-geo-anon-hosting" + anon_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" + )EOF"; + initializeProvider(config_yaml); + Network::Address::InstanceConstSharedPtr remote_address = + Network::Utility::parseInternetAddress("71.160.223.45"); + Geolocation::LookupRequest lookup_rq{std::move(remote_address)}; + testing::MockFunction lookup_cb; + auto lookup_cb_std = lookup_cb.AsStdFunction(); + EXPECT_CALL(lookup_cb, Call(_)).WillRepeatedly(SaveArg<0>(&captured_lookup_response_)); + expectStats("anon_db"); + provider_->lookup(std::move(lookup_rq), std::move(lookup_cb_std)); + EXPECT_EQ(2, captured_lookup_response_.size()); + const auto& anon_it = captured_lookup_response_.find("x-geo-anon"); + EXPECT_EQ("true", anon_it->second); + const auto& anon_hosting_it = captured_lookup_response_.find("x-geo-anon-hosting"); + EXPECT_EQ("true", anon_hosting_it->second); +} + +TEST_F(GeoipProviderTest, ValidConfigAnonTorNodeSuccessfulLookup) { + const std::string config_yaml = R"EOF( + common_provider_config: + geo_headers_to_add: + is_anon: "x-geo-anon" + anon_tor: "x-geo-anon-tor" + anon_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" + )EOF"; + initializeProvider(config_yaml); + Network::Address::InstanceConstSharedPtr remote_address = + Network::Utility::parseInternetAddress("65.4.3.2"); + Geolocation::LookupRequest lookup_rq{std::move(remote_address)}; + testing::MockFunction lookup_cb; + auto lookup_cb_std = lookup_cb.AsStdFunction(); + EXPECT_CALL(lookup_cb, Call(_)).WillRepeatedly(SaveArg<0>(&captured_lookup_response_)); + expectStats("anon_db"); + provider_->lookup(std::move(lookup_rq), std::move(lookup_cb_std)); + EXPECT_EQ(2, captured_lookup_response_.size()); + const auto& anon_it = captured_lookup_response_.find("x-geo-anon"); + EXPECT_EQ("true", anon_it->second); + const auto& anon_tor_it = captured_lookup_response_.find("x-geo-anon-tor"); + EXPECT_EQ("true", anon_tor_it->second); +} + +TEST_F(GeoipProviderTest, ValidConfigAnonProxySuccessfulLookup) { + const std::string config_yaml = R"EOF( + common_provider_config: + geo_headers_to_add: + is_anon: "x-geo-anon" + anon_proxy: "x-geo-anon-proxy" + anon_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" + )EOF"; + initializeProvider(config_yaml); + Network::Address::InstanceConstSharedPtr remote_address = + Network::Utility::parseInternetAddress("abcd:1000::1"); + Geolocation::LookupRequest lookup_rq{std::move(remote_address)}; + testing::MockFunction lookup_cb; + auto lookup_cb_std = lookup_cb.AsStdFunction(); + EXPECT_CALL(lookup_cb, Call(_)).WillRepeatedly(SaveArg<0>(&captured_lookup_response_)); + expectStats("anon_db"); + provider_->lookup(std::move(lookup_rq), std::move(lookup_cb_std)); + EXPECT_EQ(2, captured_lookup_response_.size()); + const auto& anon_it = captured_lookup_response_.find("x-geo-anon"); + EXPECT_EQ("true", anon_it->second); + const auto& anon_tor_it = captured_lookup_response_.find("x-geo-anon-proxy"); + EXPECT_EQ("true", anon_tor_it->second); +} + +TEST_F(GeoipProviderTest, ValidConfigEmptyLookupResult) { + const std::string config_yaml = R"EOF( + common_provider_config: + geo_headers_to_add: + is_anon: "x-geo-anon" + anon_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" + )EOF"; + initializeProvider(config_yaml); + Network::Address::InstanceConstSharedPtr remote_address = + Network::Utility::parseInternetAddress("10.10.10.10"); + Geolocation::LookupRequest lookup_rq{std::move(remote_address)}; + testing::MockFunction lookup_cb; + auto lookup_cb_std = lookup_cb.AsStdFunction(); + EXPECT_CALL(lookup_cb, Call(_)).WillRepeatedly(SaveArg<0>(&captured_lookup_response_)); + expectStats("anon_db", 1, 0); + provider_->lookup(std::move(lookup_rq), std::move(lookup_cb_std)); + EXPECT_EQ(0, captured_lookup_response_.size()); +} + +TEST_F(GeoipProviderTest, GeoDbNotSetForConfiguredHeader) { + const std::string config_yaml = R"EOF( + common_provider_config: + geo_headers_to_add: + city: "x-geo-city" + asn: "x-geo-asn" + city_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test.mmdb" + )EOF"; + initializeProvider(config_yaml); + Network::Address::InstanceConstSharedPtr remote_address = + Network::Utility::parseInternetAddress("78.26.243.166"); + Geolocation::LookupRequest lookup_rq{std::move(remote_address)}; + testing::MockFunction lookup_cb; + auto lookup_cb_std = lookup_cb.AsStdFunction(); + EXPECT_CALL(lookup_cb, Call(_)).WillRepeatedly(SaveArg<0>(&captured_lookup_response_)); + EXPECT_DEATH(provider_->lookup(std::move(lookup_rq), std::move(lookup_cb_std)), + "assert failure: isp_db_. Details: Maxmind asn database is not initialised for " + "performing lookups"); +} + +TEST_F(GeoipProviderTest, ValidConfigCityMultipleLookups) { + const std::string config_yaml = R"EOF( + common_provider_config: + geo_headers_to_add: + country: "x-geo-country" + region: "x-geo-region" + city: "x-geo-city" + city_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test.mmdb" + )EOF"; + initializeProvider(config_yaml); + Network::Address::InstanceConstSharedPtr remote_address1 = + Network::Utility::parseInternetAddress("78.26.243.166"); + Geolocation::LookupRequest lookup_rq1{std::move(remote_address1)}; + testing::MockFunction lookup_cb; + auto lookup_cb_std = lookup_cb.AsStdFunction(); + EXPECT_CALL(lookup_cb, Call(_)).WillRepeatedly(SaveArg<0>(&captured_lookup_response_)); + expectStats("city_db", 2, 2); + provider_->lookup(std::move(lookup_rq1), std::move(lookup_cb_std)); + EXPECT_EQ(3, captured_lookup_response_.size()); + // Another lookup request. + Network::Address::InstanceConstSharedPtr remote_address2 = + Network::Utility::parseInternetAddress("63.25.243.11"); + Geolocation::LookupRequest lookup_rq2{std::move(remote_address2)}; + testing::MockFunction lookup_cb2; + auto lookup_cb_std2 = lookup_cb2.AsStdFunction(); + EXPECT_CALL(lookup_cb2, Call(_)).WillRepeatedly(SaveArg<0>(&captured_lookup_response_)); + provider_->lookup(std::move(lookup_rq2), std::move(lookup_cb_std2)); + EXPECT_EQ(3, captured_lookup_response_.size()); +} + +} // namespace Maxmind +} // namespace GeoipProviders +} // namespace Extensions +} // namespace Envoy diff --git a/test/extensions/geoip_providers/maxmind/mocks.h b/test/extensions/geoip_providers/maxmind/mocks.h new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/test/extensions/geoip_providers/maxmind/test_data/BUILD b/test/extensions/geoip_providers/maxmind/test_data/BUILD new file mode 100644 index 000000000000..610f5d5f2272 --- /dev/null +++ b/test/extensions/geoip_providers/maxmind/test_data/BUILD @@ -0,0 +1,13 @@ +load( + "//bazel:envoy_build_system.bzl", + "envoy_package", +) + +licenses(["notice"]) # Apache 2 + +envoy_package() + +filegroup( + name = "geolocation_databases", + srcs = glob(["*"]), + diff --git a/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb b/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb new file mode 100644 index 0000000000000000000000000000000000000000..ad9895c20de94cdfb1fbc53358c013c06474df4c GIT binary patch literal 4382 zcmZA22XqwG9>?+D9YQZl?`7yUsM!00D25P-g8CG3*=&ZeknAkGo0wq3-rlqK3W$|w z?_IGM?228AqS#QM<=MS6-(<%lC!A0I?as~4%wEYz=6=bsKXIv*jn0uuh+0D%XbbIZ z%fF=dL>-_bbb`*%1!B+@x<#vAIrjf#m;(F2 zRM;2xgK4lol)-c;hZ#@-Ghr4~!U6X7+t~w&X2Tpf2o8orz&2x>FNY5@jFu=Q z2YDz+^~^Oyb4OBZl$xUCQt7BDI$Am=ijI|z3nMLq7&jBb}z; z&kPD@NP0jz({i2kZ<7D9(FM|3(ZJc#In>UD^Wc11mOr1$_;R1Gq zJ4oIcCGV2%CV3Cs8`bWU?k`5pD(OMH%Hz^Q#iSmV9%1fLc&u2n_ri%wS_4nOlOe%< zdfL{$Ci#r?tc~6!dQN)YMsG+j6c^Kr)YigF@G`stufl8adhua+lbyW<>)>s8C&Y=hNxvD*V_ai!za?_sO3|VpTQRC^QiU($uFg^NH$+@tNli? zUrOJENquXh9i{IqL!|$a{2qR=$-dH$mJZTSB>xXT!!PhF{06_nAMj_05m=qLj03Ig z((PqRh+0D%XbbH^n%}=>Oh=M&JKiZ+Po}d>7Y1U`6}m;8-RbNh)00{+=pD8630v${ zOus1EUuHlQ4U`$g++dRSiF4vC?aBk@h0EY_xI!}b1=o_fQsyd>SHp5x0V{3G%`(>zt%7SU z_LaE~u7?}oMz{%9Lva4t2X}r*c-dQIZnaT7_>s8{ZkM?uO5REGF1TCfp0H-_rG=L= zTr)27fK4`kGdw8sP_)X!GLJ;jqb&9qJPvDQo(NmalTqhW)Si}kCQ3dl^BkSe!wXUE zMVYlEUxJt66?he1gV*5=coW`&b?`R41Mk9n@IHJ1AHqkl9yY*6*aRQLC$Jelh0kCM zd=6iLJ^LK{A#?tjuZgz8H}EZd2b_QAd!irUNB9Xi|IE)szre5X8~hG`z@H(Gz<>?y z&YV_I0o?9w=M%|{pJ}S| z>+_~<<=?|ZLpI~aHo1-)bGx~*pjPm639m6-NM!tK&y8&iYo*P<%(e{+{d^&vsYzsW zenYz2%ek@5E%WY7H#W<*Wb3PH)2X1NvB{0iv6-Bgx4oG{I$7J2c3T#8m$WL}8Zp+-NbS9Z=N-Xemb;&}aF1g6=s=>?U(|%@!^UrEJ6IGX&SJkI$s}o+< zPc1BQQY(9}tEf&El2ysPmnbx4z1h<|zpQdn>ExD=q_nKEyxPmBa_MZrF27-lmzg(- zCb!t+mQ}iQynMl(+Ps!KW^T$w literal 0 HcmV?d00001 diff --git a/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-ASN-Test.mmdb b/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-ASN-Test.mmdb new file mode 100644 index 0000000000000000000000000000000000000000..bc31924dc15183886762c9fba8e630aa53165bc2 GIT binary patch literal 12665 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 literal 0 HcmV?d00001 diff --git a/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test.mmdb b/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test.mmdb new file mode 100644 index 0000000000000000000000000000000000000000..f391123b82e1dd06416cfbfc7f758428799a5d68 GIT binary patch literal 20809 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 jLx`fF&A?+aeE5))KPP Date: Tue, 15 Aug 2023 14:18:35 +0000 Subject: [PATCH 02/44] Apply most of review comments Signed-off-by: Kateryna Nezdolii --- .../geoip_providers/maxmind/v3/maxmind.proto | 7 ++++ bazel/repository_locations.bzl | 2 +- envoy/geoip/BUILD | 1 - envoy/geoip/geoip_provider_driver.h | 4 +- source/extensions/extensions_build_config.bzl | 10 ++--- .../geoip_providers/maxmind/geoip_provider.cc | 7 +--- .../maxmind/geoip_provider_test.cc | 42 ++++++++++--------- .../geoip_providers/maxmind/mocks.h | 0 .../geoip_providers/maxmind/test_data/BUILD | 4 +- 9 files changed, 39 insertions(+), 38 deletions(-) delete mode 100644 test/extensions/geoip_providers/maxmind/mocks.h diff --git a/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto b/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto index 1cf417d6351d..3831be7f9d1a 100644 --- a/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto +++ b/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto @@ -19,14 +19,21 @@ option (xds.annotations.v3.file_status).work_in_progress = true; // [#protodoc-title: MaxMind geolocation provider] // Configuration for the MaxMind geolocation provider. +// At least one geolocation database path :ref:`city_db_path `, +// :ref:`isp_db_path ` or +// :ref:`anon_db_path ` must be configured. // [#extension: envoy.geoip_providers.maxmind] message MaxMindConfig { + // Full file path to the Maxmind city database, e.g. `/etc/GeoLite2-City.mmdb`. string city_db_path = 1; + // Full file path to the Maxmind ASN database, e.g. `/etc/GeoLite2-ASN.mmdb`. string isp_db_path = 2; + // Full file path to the Maxmind anonymous IP database, e.g. `/etc/GeoIP2-Anonymous-IP.mmdb`. string anon_db_path = 3; + // Common provider configuration that specifies which geolocation headers will be populated with geolocation data. common.v3.CommonGeoipProviderConfig common_provider_config = 4 [(validate.rules).message = {required: true}]; } diff --git a/bazel/repository_locations.bzl b/bazel/repository_locations.bzl index 86b611410086..250408bbca4f 100644 --- a/bazel/repository_locations.bzl +++ b/bazel/repository_locations.bzl @@ -1459,7 +1459,7 @@ REPOSITORY_LOCATIONS_SPEC = dict( use_category = ["dataplane_ext"], extensions = ["envoy.geoip_providers.maxmind"], release_date = "2022-09-30", - cpe = "N/A", + cpe = "cpe:2.3:a:maxmind:libmaxminddb:*", license = "Apache-2.0", license_url = "https://github.com/maxmind/libmaxminddb/blob/{version}/LICENSE", ), diff --git a/envoy/geoip/BUILD b/envoy/geoip/BUILD index a1b967f66a4c..296c9e55c9fc 100644 --- a/envoy/geoip/BUILD +++ b/envoy/geoip/BUILD @@ -14,7 +14,6 @@ envoy_package() envoy_extension_package() -#todo(nezdolik) may need to split into interface and impl envoy_cc_extension( name = "geoip_provider_driver_interface", hdrs = [ diff --git a/envoy/geoip/geoip_provider_driver.h b/envoy/geoip/geoip_provider_driver.h index 97d22d26af6e..fe038c0ffe16 100644 --- a/envoy/geoip/geoip_provider_driver.h +++ b/envoy/geoip/geoip_provider_driver.h @@ -11,14 +11,12 @@ namespace Envoy { namespace Geolocation { // Actual result of the lookup. Each entry in the map represents the geolocation header (entry key) -// for which the lookup was invoked mapped to a lookup result from the database. Entry value will be -// set to absl::nullopt when database lookup yields an empty result. +// for which the lookup was invoked mapped to a lookup result from the database. using LookupResult = const absl::flat_hash_map; // Async callbacks used for geolocation provider lookups. using LookupGeoHeadersCallback = std::function; -// todo remove headers class LookupRequest { public: LookupRequest() = default; diff --git a/source/extensions/extensions_build_config.bzl b/source/extensions/extensions_build_config.bzl index af2a26db0d4a..d6164dacef35 100644 --- a/source/extensions/extensions_build_config.bzl +++ b/source/extensions/extensions_build_config.bzl @@ -140,7 +140,8 @@ EXTENSIONS = { "envoy.filters.http.fault": "//source/extensions/filters/http/fault:config", "envoy.filters.http.file_system_buffer": "//source/extensions/filters/http/file_system_buffer:config", "envoy.filters.http.gcp_authn": "//source/extensions/filters/http/gcp_authn:config", - "envoy.filters.http.geoip": "//source/extensions/filters/http/geoip:config", + "envoy.filters.http.geoip": "//source/extensions/filters/http/geoip:config", + "envoy.filters.http.grpc_field_extraction": "//source/extensions/filters/http/grpc_field_extraction:config", "envoy.filters.http.grpc_http1_bridge": "//source/extensions/filters/http/grpc_http1_bridge:config", "envoy.filters.http.grpc_http1_reverse_bridge": "//source/extensions/filters/http/grpc_http1_reverse_bridge:config", "envoy.filters.http.grpc_json_transcoder": "//source/extensions/filters/http/grpc_json_transcoder:config", @@ -149,6 +150,7 @@ EXTENSIONS = { "envoy.filters.http.header_to_metadata": "//source/extensions/filters/http/header_to_metadata:config", "envoy.filters.http.health_check": "//source/extensions/filters/http/health_check:config", "envoy.filters.http.ip_tagging": "//source/extensions/filters/http/ip_tagging:config", + "envoy.filters.http.json_to_metadata": "//source/extensions/filters/http/json_to_metadata:config", "envoy.filters.http.jwt_authn": "//source/extensions/filters/http/jwt_authn:config", "envoy.filters.http.rate_limit_quota": "//source/extensions/filters/http/rate_limit_quota:config", # Disabled by default @@ -262,6 +264,7 @@ EXTENSIONS = { "envoy.transport_sockets.raw_buffer": "//source/extensions/transport_sockets/raw_buffer:config", "envoy.transport_sockets.tap": "//source/extensions/transport_sockets/tap:config", "envoy.transport_sockets.starttls": "//source/extensions/transport_sockets/starttls:config", + "envoy.transport_sockets.tcp_stats": "//source/extensions/transport_sockets/tcp_stats:config", "envoy.transport_sockets.internal_upstream": "//source/extensions/transport_sockets/internal_upstream:config", # @@ -461,11 +464,6 @@ EXTENSIONS = { "envoy.config_subscription.ads_collection": "//source/extensions/config_subscription/grpc:grpc_collection_subscription_lib", "envoy.config_mux.delta_grpc_mux_factory": "//source/extensions/config_subscription/grpc/xds_mux:grpc_mux_lib", "envoy.config_mux.sotw_grpc_mux_factory": "//source/extensions/config_subscription/grpc/xds_mux:grpc_mux_lib", - - # - # Geolocation Providers - # - "envoy.geoip_providers.maxmind": "//source/extensions/geoip_providers/maxmind:config", } # These can be changed to ["//visibility:public"], for downstream builds which diff --git a/source/extensions/geoip_providers/maxmind/geoip_provider.cc b/source/extensions/geoip_providers/maxmind/geoip_provider.cc index 1bc626a605bc..e43f8c50da59 100644 --- a/source/extensions/geoip_providers/maxmind/geoip_provider.cc +++ b/source/extensions/geoip_providers/maxmind/geoip_provider.cc @@ -117,14 +117,13 @@ void GeoipProvider::lookup(Geolocation::LookupRequest&& request, Geolocation::LookupGeoHeadersCallback&& cb) const { auto& remote_address = request.remoteAddress(); auto lookup_result = absl::flat_hash_map{}; - std::cerr << "***Lookup for ip: " << remote_address->ip()->addressAsString() << std::endl; lookupInCityDb(remote_address, lookup_result); lookupInAsnDb(remote_address, lookup_result); lookupInAnonDb(remote_address, lookup_result); cb(std::move(lookup_result)); } -// todo: document En as default and only language used for lookups. Document that region is selcted +// todo: document En as default and only language used for lookups. Document that region is selected // as least specific subdivision void GeoipProvider::lookupInCityDb( const Network::Address::InstanceConstSharedPtr& remote_address, @@ -157,8 +156,6 @@ void GeoipProvider::lookupInCityDb( config_->countryHeader().value(), MMDB_COUNTRY_LOOKUP_ARGS[0], MMDB_COUNTRY_LOOKUP_ARGS[1], MMDB_COUNTRY_LOOKUP_ARGS[2]); } - // todo remove this in final version, this is only for testing - MMDB_dump_entry_data_list(stdout, entry_data_list, 2); if (lookup_result.size() > n_prev_hits) { config_->incHit("city_db"); } @@ -176,7 +173,7 @@ void GeoipProvider::lookupInAsnDb( const Network::Address::InstanceConstSharedPtr& remote_address, absl::flat_hash_map& lookup_result) const { if (config_->isLookupEnabledForHeader(config_->asnHeader())) { - ASSERT(isp_db_, "Maxmind asn database is not initialised for performing lookups"); + RELEASE_ASSERT(isp_db_, "Maxmind asn database is not initialised for performing lookups"); int mmdb_error; const uint32_t n_prev_hits = lookup_result.size(); MMDB_lookup_result_s mmdb_lookup_result = MMDB_lookup_sockaddr( diff --git a/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc b/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc index 691d44f7f97f..f38eb38ba3fb 100644 --- a/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc +++ b/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc @@ -193,26 +193,6 @@ TEST_F(GeoipProviderTest, ValidConfigEmptyLookupResult) { EXPECT_EQ(0, captured_lookup_response_.size()); } -TEST_F(GeoipProviderTest, GeoDbNotSetForConfiguredHeader) { - const std::string config_yaml = R"EOF( - common_provider_config: - geo_headers_to_add: - city: "x-geo-city" - asn: "x-geo-asn" - city_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test.mmdb" - )EOF"; - initializeProvider(config_yaml); - Network::Address::InstanceConstSharedPtr remote_address = - Network::Utility::parseInternetAddress("78.26.243.166"); - Geolocation::LookupRequest lookup_rq{std::move(remote_address)}; - testing::MockFunction lookup_cb; - auto lookup_cb_std = lookup_cb.AsStdFunction(); - EXPECT_CALL(lookup_cb, Call(_)).WillRepeatedly(SaveArg<0>(&captured_lookup_response_)); - EXPECT_DEATH(provider_->lookup(std::move(lookup_rq), std::move(lookup_cb_std)), - "assert failure: isp_db_. Details: Maxmind asn database is not initialised for " - "performing lookups"); -} - TEST_F(GeoipProviderTest, ValidConfigCityMultipleLookups) { const std::string config_yaml = R"EOF( common_provider_config: @@ -243,6 +223,28 @@ TEST_F(GeoipProviderTest, ValidConfigCityMultipleLookups) { EXPECT_EQ(3, captured_lookup_response_.size()); } +using GeoipProviderDeathTest = GeoipProviderTest; + +TEST_F(GeoipProviderDeathTest, GeoDbNotSetForConfiguredHeader) { + const std::string config_yaml = R"EOF( + common_provider_config: + geo_headers_to_add: + city: "x-geo-city" + asn: "x-geo-asn" + city_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test.mmdb" + )EOF"; + initializeProvider(config_yaml); + Network::Address::InstanceConstSharedPtr remote_address = + Network::Utility::parseInternetAddress("78.26.243.166"); + Geolocation::LookupRequest lookup_rq{std::move(remote_address)}; + testing::MockFunction lookup_cb; + auto lookup_cb_std = lookup_cb.AsStdFunction(); + EXPECT_CALL(lookup_cb, Call(_)).WillRepeatedly(SaveArg<0>(&captured_lookup_response_)); + EXPECT_DEATH(provider_->lookup(std::move(lookup_rq), std::move(lookup_cb_std)), + "assert failure: isp_db_. Details: Maxmind asn database is not initialised for " + "performing lookups"); +} + } // namespace Maxmind } // namespace GeoipProviders } // namespace Extensions diff --git a/test/extensions/geoip_providers/maxmind/mocks.h b/test/extensions/geoip_providers/maxmind/mocks.h deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/test/extensions/geoip_providers/maxmind/test_data/BUILD b/test/extensions/geoip_providers/maxmind/test_data/BUILD index 610f5d5f2272..847abf30c889 100644 --- a/test/extensions/geoip_providers/maxmind/test_data/BUILD +++ b/test/extensions/geoip_providers/maxmind/test_data/BUILD @@ -9,5 +9,5 @@ envoy_package() filegroup( name = "geolocation_databases", - srcs = glob(["*"]), - + srcs = glob(["*.mmdb"]), +) From 569a9875d511ca30f4b1ad3e8efb2a8977b3345d Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Tue, 15 Aug 2023 14:32:32 +0000 Subject: [PATCH 03/44] Cleanup & fix format Signed-off-by: Kateryna Nezdolii --- source/extensions/geoip_providers/maxmind/geoip_provider.cc | 6 +----- source/extensions/geoip_providers/maxmind/geoip_provider.h | 5 ++--- tools/spelling/spelling_dictionary.txt | 2 ++ 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/source/extensions/geoip_providers/maxmind/geoip_provider.cc b/source/extensions/geoip_providers/maxmind/geoip_provider.cc index e43f8c50da59..fc18316b3297 100644 --- a/source/extensions/geoip_providers/maxmind/geoip_provider.cc +++ b/source/extensions/geoip_providers/maxmind/geoip_provider.cc @@ -87,7 +87,7 @@ void GeoipProviderConfig::incCounter(Stats::StatName name) { GeoipProvider::~GeoipProvider() { ENVOY_LOG(debug, "Shutting down Maxmind geolocation provider"); - // todo(nezdolik) consider switching to atomic singleton for db objects + // TODO(nezdolik) consider switching to atomic singleton for db objects if (city_db_) { MMDB_close(city_db_.get()); } @@ -184,8 +184,6 @@ void GeoipProvider::lookupInAsnDb( if (status == MMDB_SUCCESS && entry_data_list) { populateGeoLookupResult(mmdb_lookup_result, lookup_result, config_->asnHeader().value(), MMDB_ASN_LOOKUP_ARGS[0]); - // todo remove this in final version, this is only for testing - MMDB_dump_entry_data_list(stdout, entry_data_list, 2); MMDB_free_entry_data_list(entry_data_list); if (lookup_result.size() > n_prev_hits) { config_->incHit("isp_db"); @@ -233,8 +231,6 @@ void GeoipProvider::lookupInAnonDb( populateGeoLookupResult(mmdb_lookup_result, lookup_result, config_->anonProxyHeader().value(), MMDB_ANON_LOOKUP_ARGS[4]); } - // todo remove this in final version, this is only for testing - MMDB_dump_entry_data_list(stdout, entry_data_list, 2); if (lookup_result.size() > n_prev_hits) { config_->incHit("anon_db"); } diff --git a/source/extensions/geoip_providers/maxmind/geoip_provider.h b/source/extensions/geoip_providers/maxmind/geoip_provider.h index 3183265f6c64..6d55c6739f77 100644 --- a/source/extensions/geoip_providers/maxmind/geoip_provider.h +++ b/source/extensions/geoip_providers/maxmind/geoip_provider.h @@ -2,7 +2,7 @@ #include "envoy/geoip/geoip_provider_driver.h" -// todo (nezdolik) do we need this? +// TODO(nezdolik) do we need this? #include "envoy/extensions/filters/http/geoip/v3/geoip.pb.h" #include "envoy/extensions/filters/http/geoip/v3/geoip.pb.validate.h" #include "envoy/extensions/geoip_providers/maxmind/v3/maxmind.pb.h" @@ -14,7 +14,6 @@ namespace Extensions { namespace GeoipProviders { namespace Maxmind { -// todo(nezdolik) add validation of config values class GeoipProviderConfig { public: GeoipProviderConfig(const envoy::extensions::geoip_providers::maxmind::v3::MaxMindConfig& config, @@ -77,7 +76,7 @@ class GeoipProviderConfig { using GeoipProviderConfigSharedPtr = std::shared_ptr; -// todo (nezdolik) should this be std::atomic>> instead? +// TODO(nezdolik) should this be std::atomic>> instead? using MaxmindDbPtr = std::unique_ptr; class GeoipProvider : public Envoy::Geolocation::Driver, public Logger::Loggable { diff --git a/tools/spelling/spelling_dictionary.txt b/tools/spelling/spelling_dictionary.txt index a7a578de18d2..9efeeab89b5b 100644 --- a/tools/spelling/spelling_dictionary.txt +++ b/tools/spelling/spelling_dictionary.txt @@ -910,6 +910,7 @@ matcher matchers maxage maxbuffer +Maxmind megamiss mem memcmp @@ -931,6 +932,7 @@ misconfigured mixin mkdir mmap +mmdb mmsg mmsghdr mongo From 6e3287c77a6b6f06c65586a442c2256c37cb20a0 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Mon, 4 Sep 2023 22:00:16 +0000 Subject: [PATCH 04/44] Singleton maxmind config Signed-off-by: Kateryna Nezdolii --- envoy/geoip/BUILD | 2 - .../geoip_providers/maxmind/config.cc | 48 +++++++++++++++++-- .../geoip_providers/maxmind/geoip_provider.h | 5 +- 3 files changed, 48 insertions(+), 7 deletions(-) diff --git a/envoy/geoip/BUILD b/envoy/geoip/BUILD index 296c9e55c9fc..a00bcc33c02b 100644 --- a/envoy/geoip/BUILD +++ b/envoy/geoip/BUILD @@ -7,8 +7,6 @@ load( licenses(["notice"]) # Apache 2 -envoy_package() - # HTTP L7 filter that decorates request with geolocation data # Public docs: https://envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/geoip_filter diff --git a/source/extensions/geoip_providers/maxmind/config.cc b/source/extensions/geoip_providers/maxmind/config.cc index c47beff080ed..22ee81dcb8f2 100644 --- a/source/extensions/geoip_providers/maxmind/config.cc +++ b/source/extensions/geoip_providers/maxmind/config.cc @@ -4,6 +4,7 @@ #include "envoy/registry/registry.h" #include "source/common/common/utility.h" +#include "source/common/protobuf/utility.h" #include "geoip_provider.h" @@ -12,14 +13,53 @@ namespace Extensions { namespace GeoipProviders { namespace Maxmind { +using ConfigProto = envoy::extensions::geoip_providers::maxmind::v3::MaxMindConfig; + +/** + * A singleton that acts as a factory for generating and looking up GeoipProviders. + * When given equivalent provider configs, the singleton returns pointers to the same driver/provider. + * When given different configs, the singleton returns different provider instances. + */ +class DriverSingleton : public Envoy::Singleton::Instance { + public: + std::shared_ptr get(std::shared_ptr singleton, + const ConfigProto& proto_config, + const std::string& stat_prefix, Server::Configuration::FactoryContext& context) { + std::shared_ptr driver; + const uint64_t key = MessageUtil::hash(proto_config); + absl::MutexLock lock(&mu_); + auto it = drivers_.find(key); + if (it != drivers_.end()) { + driver = it->second.lock(); + } else { + const auto& provider_config = + std::make_shared(proto_config, stat_prefix, context.scope()); + driver = std::make_shared(singleton, provider_config); + drivers_[key] = driver; + } + return driver; + } + private: + absl::Mutex mu_; + // We keep weak_ptr here so the providers can be destroyed if the config is updated to stop using + // that config of the provider. Each provider stores shared_ptrs to this singleton, which keeps the + // singleton from being destroyed unless it's no longer keeping track of any providers. + // (The singleton shared_ptr is *only* held by cache instances.) + absl::flat_hash_map> drivers_ ABSL_GUARDED_BY(mu_); +}; + +SINGLETON_MANAGER_REGISTRATION(maxmind_geolocation_provider_singleton); + MaxmindProviderFactory::MaxmindProviderFactory() : FactoryBase("envoy.geoip_providers.maxmind") {} DriverSharedPtr MaxmindProviderFactory::createGeoipProviderDriverTyped( - const envoy::extensions::geoip_providers::maxmind::v3::MaxMindConfig& proto_config, + const ConfigProto& proto_config, const std::string& stat_prefix, Server::Configuration::FactoryContext& context) { - const auto& provider_config = - std::make_shared(proto_config, stat_prefix, context.scope()); - return std::make_shared(provider_config); + std::shared_ptr drivers = context.singletonManager().getTyped( + SINGLETON_MANAGER_REGISTERED_NAME(maxmind_geolocation_provider_singleton), [] { + return std::make_shared(); + }); + return drivers->get(drivers, proto_config, stat_prefix, context); } /** diff --git a/source/extensions/geoip_providers/maxmind/geoip_provider.h b/source/extensions/geoip_providers/maxmind/geoip_provider.h index 6d55c6739f77..fceac502aa63 100644 --- a/source/extensions/geoip_providers/maxmind/geoip_provider.h +++ b/source/extensions/geoip_providers/maxmind/geoip_provider.h @@ -82,7 +82,8 @@ class GeoipProvider : public Envoy::Geolocation::Driver, public Logger::Loggable { public: - GeoipProvider(GeoipProviderConfigSharedPtr config) : config_(config) { + GeoipProvider(Singleton::InstanceSharedPtr owner, GeoipProviderConfigSharedPtr config) : config_(config), + owner_(owner) { city_db_ = initMaxMindDb(config_->cityDbPath()); isp_db_ = initMaxMindDb(config_->ispDbPath()); anon_db_ = initMaxMindDb(config_->anonDbPath()); @@ -111,6 +112,8 @@ class GeoipProvider : public Envoy::Geolocation::Driver, void populateGeoLookupResult(MMDB_lookup_result_s& mmdb_lookup_result, absl::flat_hash_map& lookup_result, const std::string& result_key, Params... lookup_params) const; + // A shared_ptr to keep the provider singleton alive as long as any of its providers are in use. + const Singleton::InstanceSharedPtr owner_; }; using GeoipProviderSharedPtr = std::shared_ptr; From 04368f17a9f39fe49fd38f50c28d82baaa02883c Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Wed, 6 Sep 2023 09:12:39 +0000 Subject: [PATCH 05/44] Address review comments Signed-off-by: Kateryna Nezdolii --- .../geoip_providers/common/v3/common.proto | 1 + .../geoip_providers/maxmind/v3/maxmind.proto | 6 +- .../http/http_filters/geoip_filter.rst | 56 ++++++++----- source/extensions/extensions_build_config.bzl | 16 ++-- .../geoip_providers/maxmind/config.cc | 68 ++++++++-------- .../geoip_providers/maxmind/config.h | 2 + .../geoip_providers/maxmind/geoip_provider.cc | 2 - .../geoip_providers/maxmind/geoip_provider.h | 6 +- test/extensions/filters/http/geoip/BUILD | 7 +- test/extensions/geoip_providers/maxmind/BUILD | 3 +- .../geoip_providers/maxmind/config_test.cc | 80 +++++++++++++++++++ .../maxmind/geoip_provider_test.cc | 16 +++- 12 files changed, 187 insertions(+), 76 deletions(-) diff --git a/api/envoy/extensions/geoip_providers/common/v3/common.proto b/api/envoy/extensions/geoip_providers/common/v3/common.proto index 369604c17bc1..4a934f1af89b 100644 --- a/api/envoy/extensions/geoip_providers/common/v3/common.proto +++ b/api/envoy/extensions/geoip_providers/common/v3/common.proto @@ -25,6 +25,7 @@ message CommonGeoipProviderConfig { [(validate.rules).string = {well_known_regex: HTTP_HEADER_NAME ignore_empty: true}]; // If set, the header will be used to populate the region ISO code associated with the IP address. + // The least specific subdivision will be selected as region value. string region = 3 [(validate.rules).string = {well_known_regex: HTTP_HEADER_NAME ignore_empty: true}]; diff --git a/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto b/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto index 3831be7f9d1a..68ce7d0d9454 100644 --- a/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto +++ b/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto @@ -25,13 +25,13 @@ option (xds.annotations.v3.file_status).work_in_progress = true; // [#extension: envoy.geoip_providers.maxmind] message MaxMindConfig { // Full file path to the Maxmind city database, e.g. `/etc/GeoLite2-City.mmdb`. - string city_db_path = 1; + string city_db_path = 1 [(validate.rules).string = {pattern: "^$|*\.mmdb"}];; // Full file path to the Maxmind ASN database, e.g. `/etc/GeoLite2-ASN.mmdb`. - string isp_db_path = 2; + string isp_db_path = 2 [(validate.rules).string = {pattern: "^$|*\.mmdb"}];; // Full file path to the Maxmind anonymous IP database, e.g. `/etc/GeoIP2-Anonymous-IP.mmdb`. - string anon_db_path = 3; + string anon_db_path = 3 [(validate.rules).string = {pattern: "^$|*\.mmdb"}];; // Common provider configuration that specifies which geolocation headers will be populated with geolocation data. common.v3.CommonGeoipProviderConfig common_provider_config = 4 diff --git a/docs/root/configuration/http/http_filters/geoip_filter.rst b/docs/root/configuration/http/http_filters/geoip_filter.rst index aa60ca263a40..b2d3547e5fe0 100644 --- a/docs/root/configuration/http/http_filters/geoip_filter.rst +++ b/docs/root/configuration/http/http_filters/geoip_filter.rst @@ -4,10 +4,36 @@ IP Geolocation Filter ========================= This filter decorates HTTP requests with the geolocation data. Filter uses client address to lookup information (e.g., client's city, country) in the geolocation provider database. -Upon a successful lookup request will be enriched with the configured geolocation header and value from the database. +Upon a successful lookup request will be enriched with the configured geolocation header and the value from the database. In case the configured geolocation headers are present in the incoming request, they will be overriden by the filter. -Geolocation filter emits stats for the number of successful lookups and the number of total lookups. +Geolocation filter emits stats for the number of the successful lookups and the number of total lookups. As for now, only `Maxmind ` geolocation provider is supported. +English language is used for the geolocation lookups, the result of the lookup will be UTF-8 encoded. + +Statistics +------------- + +Geolocation HTTP filter has a statistics tree rooted at ``http..``. The :ref:`stat prefix +` +comes from the owning HTTP connection manager. + +.. csv-table:: + :header: Name, Type, Description + :widths: 1, 1, 2 + + ``rq_total``, Counter, Total number of requests for which geolocation filter was invoked. + +Besides Geolocation filter level statisctics, there is statistics emitted by the :ref:`Maxmind geolocation provider ` +per geolocation database type (rooted at ``.maxmind.``). Database type can be one of `city_db `, +`isp_db `, `anon_db `. + +.. csv-table:: + :header: Name, Type, Description + :widths: 1, 1, 2 + + ``.total``, Counter, Total number of lookups performed for a given geolocation database file. + ``.hit``, Counter, Total number of successful lookups (with non empty lookup result) performed for a given geolocation database file. + ``.lookup_error``, Counter, Total number of errors that occured during lookups for a given geolocation database file. Configuration ------------- @@ -25,23 +51,17 @@ Configuration example "@type": type.googleapis.com/envoy.extensions.filters.http.geoip.v3.Geoip use_xff: true xff_num_trusted_hops: 1 - geo_headers_to_add: - country: "x-geo-country" - region: "x-geo-region" provider: name: "envoy.geoip_providers.maxmind" + typed_config: + "@type": type.googleapis.com/envoy.extensions.geoip_providers.maxmind.v3.MaxMindConfig + common_provider_config: + geo_headers_to_add: + country: "x-geo-country" + region: "x-geo-region" + city: "x-geo-city" + asn: "x-geo-asn" + city_db_path: "geoip/GeoLite2-City-Test.mmdb" + isp_db_path: "geoip/GeoLite2-ASN-Test.mmdb" -Statistics ----------- -Geolocation filter outputs statistics in the -``http..geoip..`` namespace. The :ref:`stat prefix -` -comes from the owning HTTP connection manager. - -.. csv-table:: - :header: Name, Type, Description - :widths: auto - - .hit, Counter, Number of successful lookups within geolocation database for a configured geolocation header. - .total, Counter, Number of total lookups within geolocation database for a configured geolocation header. diff --git a/source/extensions/extensions_build_config.bzl b/source/extensions/extensions_build_config.bzl index d6164dacef35..6a5e4e1c0b04 100644 --- a/source/extensions/extensions_build_config.bzl +++ b/source/extensions/extensions_build_config.bzl @@ -140,7 +140,7 @@ EXTENSIONS = { "envoy.filters.http.fault": "//source/extensions/filters/http/fault:config", "envoy.filters.http.file_system_buffer": "//source/extensions/filters/http/file_system_buffer:config", "envoy.filters.http.gcp_authn": "//source/extensions/filters/http/gcp_authn:config", - "envoy.filters.http.geoip": "//source/extensions/filters/http/geoip:config", + "envoy.filters.http.geoip": "//source/extensions/filters/http/geoip:config", "envoy.filters.http.grpc_field_extraction": "//source/extensions/filters/http/grpc_field_extraction:config", "envoy.filters.http.grpc_http1_bridge": "//source/extensions/filters/http/grpc_http1_bridge:config", "envoy.filters.http.grpc_http1_reverse_bridge": "//source/extensions/filters/http/grpc_http1_reverse_bridge:config", @@ -258,15 +258,6 @@ EXTENSIONS = { # Transport sockets # - "envoy.transport_sockets.alts": "//source/extensions/transport_sockets/alts:config", - "envoy.transport_sockets.http_11_proxy": "//source/extensions/transport_sockets/http_11_proxy:upstream_config", - "envoy.transport_sockets.upstream_proxy_protocol": "//source/extensions/transport_sockets/proxy_protocol:upstream_config", - "envoy.transport_sockets.raw_buffer": "//source/extensions/transport_sockets/raw_buffer:config", - "envoy.transport_sockets.tap": "//source/extensions/transport_sockets/tap:config", - "envoy.transport_sockets.starttls": "//source/extensions/transport_sockets/starttls:config", - "envoy.transport_sockets.tcp_stats": "//source/extensions/transport_sockets/tcp_stats:config", - "envoy.transport_sockets.internal_upstream": "//source/extensions/transport_sockets/internal_upstream:config", - # # Retry host predicates # @@ -464,6 +455,11 @@ EXTENSIONS = { "envoy.config_subscription.ads_collection": "//source/extensions/config_subscription/grpc:grpc_collection_subscription_lib", "envoy.config_mux.delta_grpc_mux_factory": "//source/extensions/config_subscription/grpc/xds_mux:grpc_mux_lib", "envoy.config_mux.sotw_grpc_mux_factory": "//source/extensions/config_subscription/grpc/xds_mux:grpc_mux_lib", + + # + # Geolocation Provider + # + "envoy.geoip_providers.maxmind": "//source/extensions/geoip_providers/maxmind:config", } # These can be changed to ["//visibility:public"], for downstream builds which diff --git a/source/extensions/geoip_providers/maxmind/config.cc b/source/extensions/geoip_providers/maxmind/config.cc index 22ee81dcb8f2..e44d44ad5c76 100644 --- a/source/extensions/geoip_providers/maxmind/config.cc +++ b/source/extensions/geoip_providers/maxmind/config.cc @@ -17,35 +17,38 @@ using ConfigProto = envoy::extensions::geoip_providers::maxmind::v3::MaxMindConf /** * A singleton that acts as a factory for generating and looking up GeoipProviders. - * When given equivalent provider configs, the singleton returns pointers to the same driver/provider. - * When given different configs, the singleton returns different provider instances. + * When given equivalent provider configs, the singleton returns pointers to the same + * driver/provider. When given different configs, the singleton returns different provider + * instances. */ class DriverSingleton : public Envoy::Singleton::Instance { - public: - std::shared_ptr get(std::shared_ptr singleton, - const ConfigProto& proto_config, - const std::string& stat_prefix, Server::Configuration::FactoryContext& context) { - std::shared_ptr driver; - const uint64_t key = MessageUtil::hash(proto_config); - absl::MutexLock lock(&mu_); - auto it = drivers_.find(key); - if (it != drivers_.end()) { - driver = it->second.lock(); - } else { - const auto& provider_config = - std::make_shared(proto_config, stat_prefix, context.scope()); - driver = std::make_shared(singleton, provider_config); - drivers_[key] = driver; - } - return driver; +public: + std::shared_ptr get(std::shared_ptr singleton, + const ConfigProto& proto_config, + const std::string& stat_prefix, + Server::Configuration::FactoryContext& context) { + std::shared_ptr driver; + const uint64_t key = MessageUtil::hash(proto_config); + absl::MutexLock lock(&mu_); + auto it = drivers_.find(key); + if (it != drivers_.end()) { + driver = it->second.lock(); + } else { + const auto& provider_config = + std::make_shared(proto_config, stat_prefix, context.scope()); + driver = std::make_shared(singleton, provider_config); + drivers_[key] = driver; + } + return driver; } - private: - absl::Mutex mu_; - // We keep weak_ptr here so the providers can be destroyed if the config is updated to stop using - // that config of the provider. Each provider stores shared_ptrs to this singleton, which keeps the - // singleton from being destroyed unless it's no longer keeping track of any providers. - // (The singleton shared_ptr is *only* held by cache instances.) - absl::flat_hash_map> drivers_ ABSL_GUARDED_BY(mu_); + +private: + absl::Mutex mu_; + // We keep weak_ptr here so the providers can be destroyed if the config is updated to stop using + // that config of the provider. Each provider stores shared_ptrs to this singleton, which keeps + // the singleton from being destroyed unless it's no longer keeping track of any providers. (The + // singleton shared_ptr is *only* held by cache instances.) + absl::flat_hash_map> drivers_ ABSL_GUARDED_BY(mu_); }; SINGLETON_MANAGER_REGISTRATION(maxmind_geolocation_provider_singleton); @@ -53,20 +56,19 @@ SINGLETON_MANAGER_REGISTRATION(maxmind_geolocation_provider_singleton); MaxmindProviderFactory::MaxmindProviderFactory() : FactoryBase("envoy.geoip_providers.maxmind") {} DriverSharedPtr MaxmindProviderFactory::createGeoipProviderDriverTyped( - const ConfigProto& proto_config, - const std::string& stat_prefix, Server::Configuration::FactoryContext& context) { + const ConfigProto& proto_config, const std::string& stat_prefix, + Server::Configuration::FactoryContext& context) { std::shared_ptr drivers = context.singletonManager().getTyped( - SINGLETON_MANAGER_REGISTERED_NAME(maxmind_geolocation_provider_singleton), [] { - return std::make_shared(); - }); + SINGLETON_MANAGER_REGISTERED_NAME(maxmind_geolocation_provider_singleton), + [] { return std::make_shared(); }); return drivers->get(drivers, proto_config, stat_prefix, context); } /** * Static registration for the Maxmind provider. @see RegisterFactory. */ -REGISTER_FACTORY(MaxmindProviderFactory, - Geolocation::GeoipProviderFactory){"envoy.geoip_providers"}; +static Registry::RegisterFactory + register_; } // namespace Maxmind } // namespace GeoipProviders diff --git a/source/extensions/geoip_providers/maxmind/config.h b/source/extensions/geoip_providers/maxmind/config.h index d46f7efcc07b..007bc90936ee 100644 --- a/source/extensions/geoip_providers/maxmind/config.h +++ b/source/extensions/geoip_providers/maxmind/config.h @@ -29,6 +29,8 @@ class MaxmindProviderFactory const std::string& stat_prefix, Server::Configuration::FactoryContext& context) override; }; +DECLARE_FACTORY(MaxmindProviderFactory); + } // namespace Maxmind } // namespace GeoipProviders } // namespace Extensions diff --git a/source/extensions/geoip_providers/maxmind/geoip_provider.cc b/source/extensions/geoip_providers/maxmind/geoip_provider.cc index fc18316b3297..acc26e4552e0 100644 --- a/source/extensions/geoip_providers/maxmind/geoip_provider.cc +++ b/source/extensions/geoip_providers/maxmind/geoip_provider.cc @@ -196,8 +196,6 @@ void GeoipProvider::lookupInAsnDb( } } -// todo: document En as default and only language used for lookups. Document that region is selcted -// as least specific subdivision void GeoipProvider::lookupInAnonDb( const Network::Address::InstanceConstSharedPtr& remote_address, absl::flat_hash_map& lookup_result) const { diff --git a/source/extensions/geoip_providers/maxmind/geoip_provider.h b/source/extensions/geoip_providers/maxmind/geoip_provider.h index fceac502aa63..d3a9aac14059 100644 --- a/source/extensions/geoip_providers/maxmind/geoip_provider.h +++ b/source/extensions/geoip_providers/maxmind/geoip_provider.h @@ -82,8 +82,8 @@ class GeoipProvider : public Envoy::Geolocation::Driver, public Logger::Loggable { public: - GeoipProvider(Singleton::InstanceSharedPtr owner, GeoipProviderConfigSharedPtr config) : config_(config), - owner_(owner) { + GeoipProvider(Singleton::InstanceSharedPtr owner, GeoipProviderConfigSharedPtr config) + : config_(config), owner_(owner) { city_db_ = initMaxMindDb(config_->cityDbPath()); isp_db_ = initMaxMindDb(config_->ispDbPath()); anon_db_ = initMaxMindDb(config_->anonDbPath()); @@ -112,7 +112,7 @@ class GeoipProvider : public Envoy::Geolocation::Driver, void populateGeoLookupResult(MMDB_lookup_result_s& mmdb_lookup_result, absl::flat_hash_map& lookup_result, const std::string& result_key, Params... lookup_params) const; - // A shared_ptr to keep the provider singleton alive as long as any of its providers are in use. + // A shared_ptr to keep the provider singleton alive as long as any of its providers are in use. const Singleton::InstanceSharedPtr owner_; }; diff --git a/test/extensions/filters/http/geoip/BUILD b/test/extensions/filters/http/geoip/BUILD index 3c90737e8272..30a05b991c1d 100644 --- a/test/extensions/filters/http/geoip/BUILD +++ b/test/extensions/filters/http/geoip/BUILD @@ -40,6 +40,7 @@ envoy_extension_cc_test( srcs = ["geoip_filter_test.cc"], extension_names = ["envoy.filters.http.geoip"], deps = [ + ":dummy_cc_proto", ":geoip_mocks", "//source/extensions/filters/http/geoip:config", "//source/extensions/filters/http/geoip:geoip_filter_lib", @@ -60,7 +61,6 @@ envoy_extension_cc_test( ], extension_names = [ "envoy.filters.http.geoip", - "envoy.geoip_providers.maxmind", ], deps = [ "//source/extensions/filters/http/geoip:config", @@ -77,5 +77,8 @@ envoy_extension_cc_mock( name = "geoip_mocks", hdrs = ["mocks.h"], extension_names = ["envoy.filters.http.geoip"], - deps = ["//envoy/geoip:geoip_provider_driver_interface"], + deps = [ + ":dummy_cc_proto", + "//envoy/geoip:geoip_provider_driver_interface", + ], ) diff --git a/test/extensions/geoip_providers/maxmind/BUILD b/test/extensions/geoip_providers/maxmind/BUILD index 972a66c308ef..405f2702acdb 100644 --- a/test/extensions/geoip_providers/maxmind/BUILD +++ b/test/extensions/geoip_providers/maxmind/BUILD @@ -38,6 +38,7 @@ envoy_extension_cc_test( deps = [ "//source/extensions/geoip_providers/maxmind:config", "//source/extensions/geoip_providers/maxmind:provider_impl", + "//test/mocks/server:factory_context_mocks", "@envoy_api//envoy/extensions/geoip_providers/maxmind/v3:pkg_cc_proto", ], -) + diff --git a/test/extensions/geoip_providers/maxmind/config_test.cc b/test/extensions/geoip_providers/maxmind/config_test.cc index a2b7f9bbcfc7..a7329df7bf8b 100644 --- a/test/extensions/geoip_providers/maxmind/config_test.cc +++ b/test/extensions/geoip_providers/maxmind/config_test.cc @@ -252,6 +252,86 @@ TEST(MaxmindProviderConfigTest, ProviderConfigWithNoGeoHeaders) { "Proto constraint validation failed.*value is required.*"); } +TEST(MaxmindProviderConfigTest, ReusesProviderInstanceForSameProtoConfig) { + const auto provider_config_yaml = R"EOF( + common_provider_config: + geo_headers_to_add: + country: "x-geo-country" + city: "x-geo-city" + anon_vpn: "x-anon-vpn" + asn: "x-geo-asn" + anon_tor: "x-anon-tor" + anon_proxy: "x-anon-proxy" + anon_hosting: "x-anon-hosting" + city_db_path: %s + isp_db_path: %s + anon_db_path: %s + )EOF"; + MaxmindProviderConfig provider_config; + auto city_db_path = genGeoDbFilePath("GeoLite2-City-Test.mmdb"); + auto asn_db_path = genGeoDbFilePath("GeoLite2-ASN-Test.mmdb"); + auto anon_db_path = genGeoDbFilePath("GeoIP2-Anonymous-IP-Test.mmdb"); + auto processed_provider_config_yaml = + absl::StrFormat(provider_config_yaml, city_db_path, asn_db_path, anon_db_path); + TestUtility::loadFromYaml(processed_provider_config_yaml, provider_config); + NiceMock context; + EXPECT_CALL(context, messageValidationVisitor()).Times(2); + MaxmindProviderFactory factory; + Geolocation::DriverSharedPtr driver1 = + factory.createGeoipProviderDriver(provider_config, "maxmind", context); + Geolocation::DriverSharedPtr driver2 = + factory.createGeoipProviderDriver(provider_config, "maxmind", context); + EXPECT_EQ(driver1.get(), driver2.get()); +} + +TEST(MaxmindProviderConfigTest, DifferentProviderInstancesForDifferentProtoConfig) { + const auto provider_config_yaml1 = R"EOF( + common_provider_config: + geo_headers_to_add: + country: "x-geo-country" + city: "x-geo-city" + anon_vpn: "x-anon-vpn" + asn: "x-geo-asn" + anon_tor: "x-anon-tor" + anon_proxy: "x-anon-proxy" + anon_hosting: "x-anon-hosting" + city_db_path: %s + isp_db_path: %s + anon_db_path: %s + )EOF"; + const auto provider_config_yaml2 = R"EOF( + common_provider_config: + geo_headers_to_add: + country: "x-geo-country" + city: "x-geo-city" + anon_vpn: "x-anon-vpn" + anon_tor: "x-anon-tor" + anon_proxy: "x-anon-proxy" + anon_hosting: "x-anon-hosting" + city_db_path: %s + anon_db_path: %s + )EOF"; + MaxmindProviderConfig provider_config1; + MaxmindProviderConfig provider_config2; + auto city_db_path = genGeoDbFilePath("GeoLite2-City-Test.mmdb"); + auto asn_db_path = genGeoDbFilePath("GeoLite2-ASN-Test.mmdb"); + auto anon_db_path = genGeoDbFilePath("GeoIP2-Anonymous-IP-Test.mmdb"); + auto processed_provider_config_yaml1 = + absl::StrFormat(provider_config_yaml1, city_db_path, asn_db_path, anon_db_path); + auto processed_provider_config_yaml2 = + absl::StrFormat(provider_config_yaml2, city_db_path, anon_db_path); + TestUtility::loadFromYaml(processed_provider_config_yaml1, provider_config1); + TestUtility::loadFromYaml(processed_provider_config_yaml2, provider_config2); + NiceMock context; + EXPECT_CALL(context, messageValidationVisitor()).Times(2); + MaxmindProviderFactory factory; + Geolocation::DriverSharedPtr driver1 = + factory.createGeoipProviderDriver(provider_config1, "maxmind", context); + Geolocation::DriverSharedPtr driver2 = + factory.createGeoipProviderDriver(provider_config2, "maxmind", context); + EXPECT_NE(driver1.get(), driver2.get()); +} + } // namespace Maxmind } // namespace GeoipProviders } // namespace Extensions diff --git a/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc b/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc index f38eb38ba3fb..2aa0762ec702 100644 --- a/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc +++ b/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc @@ -2,8 +2,10 @@ #include "source/common/network/address_impl.h" #include "source/common/network/utility.h" +#include "source/extensions/geoip_providers/maxmind/config.h" #include "source/extensions/geoip_providers/maxmind/geoip_provider.h" +#include "test/mocks/server/factory_context.h" #include "test/mocks/stats/mocks.h" #include "test/test_common/environment.h" #include "test/test_common/utility.h" @@ -25,8 +27,13 @@ class GeoipProviderTest : public testing::Test { void initializeProvider(const std::string& yaml) { envoy::extensions::geoip_providers::maxmind::v3::MaxMindConfig config; TestUtility::loadFromYaml(TestEnvironment::substitute(yaml), config); - config_ = std::make_shared(config, "prefix.", stats_.mockScope()); - provider_ = std::make_shared(config_); + provider_factory_ = Registry::FactoryRegistry::getFactoryByType( + "envoy.extensions.geoip_providers.maxmind.v3.MaxMindConfig"); + if (provider_factory_ == nullptr) { + throw EnvoyException("Didn't find a registered implementation for type " + "envoy.extensions.geoip_providers.maxmind.v3.MaxMindConfig"); + } + provider_ = provider_factory_->createGeoipProviderDriver(config, "prefix.", context_); } void expectStats(const std::string& db_type, const uint32_t total_times = 1, @@ -39,8 +46,9 @@ class GeoipProviderTest : public testing::Test { } NiceMock stats_; - GeoipProviderConfigSharedPtr config_; - GeoipProviderSharedPtr provider_; + NiceMock context_; + DriverSharedPtr provider_; + MaxmindProviderFactory* provider_factory_; absl::flat_hash_map captured_lookup_response_; }; From 8784a985e148f695ff1a1895808ed6febb7cad57 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Wed, 6 Sep 2023 09:21:11 +0000 Subject: [PATCH 06/44] Revert unrelated change Signed-off-by: Kateryna Nezdolii --- source/extensions/extensions_build_config.bzl | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/source/extensions/extensions_build_config.bzl b/source/extensions/extensions_build_config.bzl index 6a5e4e1c0b04..a6f9a727b346 100644 --- a/source/extensions/extensions_build_config.bzl +++ b/source/extensions/extensions_build_config.bzl @@ -258,6 +258,15 @@ EXTENSIONS = { # Transport sockets # + "envoy.transport_sockets.alts": "//source/extensions/transport_sockets/alts:config", + "envoy.transport_sockets.http_11_proxy": "//source/extensions/transport_sockets/http_11_proxy:upstream_config", + "envoy.transport_sockets.upstream_proxy_protocol": "//source/extensions/transport_sockets/proxy_protocol:upstream_config", + "envoy.transport_sockets.raw_buffer": "//source/extensions/transport_sockets/raw_buffer:config", + "envoy.transport_sockets.tap": "//source/extensions/transport_sockets/tap:config", + "envoy.transport_sockets.starttls": "//source/extensions/transport_sockets/starttls:config", + "envoy.transport_sockets.tcp_stats": "//source/extensions/transport_sockets/tcp_stats:config", + "envoy.transport_sockets.internal_upstream": "//source/extensions/transport_sockets/internal_upstream:config", + # # Retry host predicates # From 8df0173f0f9f86943798397d55dca7a662f91307 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Wed, 6 Sep 2023 09:22:44 +0000 Subject: [PATCH 07/44] Fix BUILD file Signed-off-by: Kateryna Nezdolii --- envoy/geoip/BUILD | 2 ++ 1 file changed, 2 insertions(+) diff --git a/envoy/geoip/BUILD b/envoy/geoip/BUILD index a00bcc33c02b..296c9e55c9fc 100644 --- a/envoy/geoip/BUILD +++ b/envoy/geoip/BUILD @@ -7,6 +7,8 @@ load( licenses(["notice"]) # Apache 2 +envoy_package() + # HTTP L7 filter that decorates request with geolocation data # Public docs: https://envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/geoip_filter From 52efec39cb49df48bb525683342dd33d0ee91084 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Wed, 6 Sep 2023 10:01:30 +0000 Subject: [PATCH 08/44] More fixes Signed-off-by: Kateryna Nezdolii --- .../extensions/geoip_providers/maxmind/v3/maxmind.proto | 6 +++--- envoy/geoip/BUILD | 3 --- test/extensions/geoip_providers/maxmind/BUILD | 2 ++ 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto b/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto index 68ce7d0d9454..b98756f0be06 100644 --- a/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto +++ b/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto @@ -25,13 +25,13 @@ option (xds.annotations.v3.file_status).work_in_progress = true; // [#extension: envoy.geoip_providers.maxmind] message MaxMindConfig { // Full file path to the Maxmind city database, e.g. `/etc/GeoLite2-City.mmdb`. - string city_db_path = 1 [(validate.rules).string = {pattern: "^$|*\.mmdb"}];; + string city_db_path = 1 [(validate.rules).string = {pattern: "^$|^.*\\.mmdb$"}];; // Full file path to the Maxmind ASN database, e.g. `/etc/GeoLite2-ASN.mmdb`. - string isp_db_path = 2 [(validate.rules).string = {pattern: "^$|*\.mmdb"}];; + string isp_db_path = 2 [(validate.rules).string = {pattern: "^$|^.*\\.mmdb$"}];; // Full file path to the Maxmind anonymous IP database, e.g. `/etc/GeoIP2-Anonymous-IP.mmdb`. - string anon_db_path = 3 [(validate.rules).string = {pattern: "^$|*\.mmdb"}];; + string anon_db_path = 3 [(validate.rules).string = {pattern: "^$|^.*\\.mmdb$"}];; // Common provider configuration that specifies which geolocation headers will be populated with geolocation data. common.v3.CommonGeoipProviderConfig common_provider_config = 4 diff --git a/envoy/geoip/BUILD b/envoy/geoip/BUILD index 296c9e55c9fc..ae7016558550 100644 --- a/envoy/geoip/BUILD +++ b/envoy/geoip/BUILD @@ -1,7 +1,6 @@ load( "//bazel:envoy_build_system.bzl", "envoy_cc_extension", - "envoy_extension_package", "envoy_package", ) @@ -12,8 +11,6 @@ envoy_package() # HTTP L7 filter that decorates request with geolocation data # Public docs: https://envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/geoip_filter -envoy_extension_package() - envoy_cc_extension( name = "geoip_provider_driver_interface", hdrs = [ diff --git a/test/extensions/geoip_providers/maxmind/BUILD b/test/extensions/geoip_providers/maxmind/BUILD index 405f2702acdb..0f5b069d869b 100644 --- a/test/extensions/geoip_providers/maxmind/BUILD +++ b/test/extensions/geoip_providers/maxmind/BUILD @@ -36,9 +36,11 @@ envoy_extension_cc_test( ], extension_names = ["envoy.geoip_providers.maxmind"], deps = [ + "//envoy/registry", "//source/extensions/geoip_providers/maxmind:config", "//source/extensions/geoip_providers/maxmind:provider_impl", "//test/mocks/server:factory_context_mocks", "@envoy_api//envoy/extensions/geoip_providers/maxmind/v3:pkg_cc_proto", ], +) From 1237ed780a04cbf45c799d9778f0a1b9797497e6 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Wed, 6 Sep 2023 17:21:20 +0000 Subject: [PATCH 09/44] Try to fix factory Signed-off-by: Kateryna Nezdolii --- .../geoip_providers/maxmind/config.cc | 67 +++++++++---------- .../maxmind/geoip_provider_test.cc | 18 +++-- 2 files changed, 43 insertions(+), 42 deletions(-) diff --git a/source/extensions/geoip_providers/maxmind/config.cc b/source/extensions/geoip_providers/maxmind/config.cc index e44d44ad5c76..669a136aadd8 100644 --- a/source/extensions/geoip_providers/maxmind/config.cc +++ b/source/extensions/geoip_providers/maxmind/config.cc @@ -17,38 +17,35 @@ using ConfigProto = envoy::extensions::geoip_providers::maxmind::v3::MaxMindConf /** * A singleton that acts as a factory for generating and looking up GeoipProviders. - * When given equivalent provider configs, the singleton returns pointers to the same - * driver/provider. When given different configs, the singleton returns different provider - * instances. + * When given equivalent provider configs, the singleton returns pointers to the same driver/provider. + * When given different configs, the singleton returns different provider instances. */ class DriverSingleton : public Envoy::Singleton::Instance { -public: - std::shared_ptr get(std::shared_ptr singleton, - const ConfigProto& proto_config, - const std::string& stat_prefix, - Server::Configuration::FactoryContext& context) { - std::shared_ptr driver; - const uint64_t key = MessageUtil::hash(proto_config); - absl::MutexLock lock(&mu_); - auto it = drivers_.find(key); - if (it != drivers_.end()) { - driver = it->second.lock(); - } else { - const auto& provider_config = - std::make_shared(proto_config, stat_prefix, context.scope()); - driver = std::make_shared(singleton, provider_config); - drivers_[key] = driver; - } - return driver; + public: + std::shared_ptr get(std::shared_ptr singleton, + const ConfigProto& proto_config, + const std::string& stat_prefix, Server::Configuration::FactoryContext& context) { + std::shared_ptr driver; + const uint64_t key = MessageUtil::hash(proto_config); + absl::MutexLock lock(&mu_); + auto it = drivers_.find(key); + if (it != drivers_.end()) { + driver = it->second.lock(); + } else { + const auto& provider_config = + std::make_shared(proto_config, stat_prefix, context.scope()); + driver = std::make_shared(singleton, provider_config); + drivers_[key] = driver; + } + return driver; } - -private: - absl::Mutex mu_; - // We keep weak_ptr here so the providers can be destroyed if the config is updated to stop using - // that config of the provider. Each provider stores shared_ptrs to this singleton, which keeps - // the singleton from being destroyed unless it's no longer keeping track of any providers. (The - // singleton shared_ptr is *only* held by cache instances.) - absl::flat_hash_map> drivers_ ABSL_GUARDED_BY(mu_); + private: + absl::Mutex mu_; + // We keep weak_ptr here so the providers can be destroyed if the config is updated to stop using + // that config of the provider. Each provider stores shared_ptrs to this singleton, which keeps the + // singleton from being destroyed unless it's no longer keeping track of any providers. + // (The singleton shared_ptr is *only* held by cache instances.) + absl::flat_hash_map> drivers_ ABSL_GUARDED_BY(mu_); }; SINGLETON_MANAGER_REGISTRATION(maxmind_geolocation_provider_singleton); @@ -56,19 +53,19 @@ SINGLETON_MANAGER_REGISTRATION(maxmind_geolocation_provider_singleton); MaxmindProviderFactory::MaxmindProviderFactory() : FactoryBase("envoy.geoip_providers.maxmind") {} DriverSharedPtr MaxmindProviderFactory::createGeoipProviderDriverTyped( - const ConfigProto& proto_config, const std::string& stat_prefix, - Server::Configuration::FactoryContext& context) { + const ConfigProto& proto_config, + const std::string& stat_prefix, Server::Configuration::FactoryContext& context) { std::shared_ptr drivers = context.singletonManager().getTyped( - SINGLETON_MANAGER_REGISTERED_NAME(maxmind_geolocation_provider_singleton), - [] { return std::make_shared(); }); + SINGLETON_MANAGER_REGISTERED_NAME(maxmind_geolocation_provider_singleton), [] { + return std::make_shared(); + }); return drivers->get(drivers, proto_config, stat_prefix, context); } /** * Static registration for the Maxmind provider. @see RegisterFactory. */ -static Registry::RegisterFactory - register_; +REGISTER_FACTORY(MaxmindProviderFactory, Geolocation::GeoipProviderFactory); } // namespace Maxmind } // namespace GeoipProviders diff --git a/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc b/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc index 2aa0762ec702..8f4f6ece36ca 100644 --- a/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc +++ b/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc @@ -1,5 +1,6 @@ #include "envoy/extensions/geoip_providers/maxmind/v3/maxmind.pb.h" +#include "envoy/registry/registry.h" #include "source/common/network/address_impl.h" #include "source/common/network/utility.h" #include "source/extensions/geoip_providers/maxmind/config.h" @@ -24,15 +25,18 @@ namespace Maxmind { class GeoipProviderTest : public testing::Test { public: + GeoipProviderTest() { + ExtensionRegistry::registerFactories(); + provider_factory_ = Registry::FactoryRegistry::getFactory( + "envoy.geoip_providers.maxmind"); + if (provider_factory_ == nullptr) { + throw EnvoyException("Didn't find a registered implementation for type envoy.geoip_providers.maxmind"); + } + } + void initializeProvider(const std::string& yaml) { envoy::extensions::geoip_providers::maxmind::v3::MaxMindConfig config; TestUtility::loadFromYaml(TestEnvironment::substitute(yaml), config); - provider_factory_ = Registry::FactoryRegistry::getFactoryByType( - "envoy.extensions.geoip_providers.maxmind.v3.MaxMindConfig"); - if (provider_factory_ == nullptr) { - throw EnvoyException("Didn't find a registered implementation for type " - "envoy.extensions.geoip_providers.maxmind.v3.MaxMindConfig"); - } provider_ = provider_factory_->createGeoipProviderDriver(config, "prefix.", context_); } @@ -84,7 +88,7 @@ TEST_F(GeoipProviderTest, ValidConfigCityAndIspDbsSuccessfulLookup) { EXPECT_EQ("15169", asn_it->second); } -// Tests for anonymous database replicate expectations from corresponding Maxmind tests: + // Tests for anonymous database replicate expectations from corresponding Maxmind tests: // https://github.com/maxmind/GeoIP2-perl/blob/main/t/GeoIP2/Database/Reader-Anonymous-IP.t TEST_F(GeoipProviderTest, ValidConfigAnonVpnSuccessfulLookup) { const std::string config_yaml = R"EOF( From bea685bfe77fb3a5c9d8d662dbd4c08a222a78e9 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Wed, 6 Sep 2023 17:28:05 +0000 Subject: [PATCH 10/44] Remove not needed ocde Signed-off-by: Kateryna Nezdolii --- test/extensions/geoip_providers/maxmind/geoip_provider_test.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc b/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc index 8f4f6ece36ca..d03036f7f2db 100644 --- a/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc +++ b/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc @@ -26,7 +26,6 @@ namespace Maxmind { class GeoipProviderTest : public testing::Test { public: GeoipProviderTest() { - ExtensionRegistry::registerFactories(); provider_factory_ = Registry::FactoryRegistry::getFactory( "envoy.geoip_providers.maxmind"); if (provider_factory_ == nullptr) { From aa124faa2d665e5a38d9e9ecbf990c98c9492452 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Wed, 6 Sep 2023 20:28:09 +0000 Subject: [PATCH 11/44] Fix more things Signed-off-by: Kateryna Nezdolii --- .../geoip_providers/maxmind/v3/maxmind.proto | 3 + .../geoip_providers/maxmind/config.cc | 68 ++++++++++--------- .../geoip_providers/maxmind/geoip_provider.cc | 2 +- test/extensions/geoip_providers/maxmind/BUILD | 3 +- .../geoip_providers/maxmind/config_test.cc | 15 ++++ .../maxmind/geoip_provider_test.cc | 39 +++++++---- tools/spelling/spelling_dictionary.txt | 3 + 7 files changed, 83 insertions(+), 50 deletions(-) diff --git a/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto b/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto index b98756f0be06..092b912792f2 100644 --- a/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto +++ b/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto @@ -25,12 +25,15 @@ option (xds.annotations.v3.file_status).work_in_progress = true; // [#extension: envoy.geoip_providers.maxmind] message MaxMindConfig { // Full file path to the Maxmind city database, e.g. `/etc/GeoLite2-City.mmdb`. + // Database file is expected to have `.mmdb` extension. string city_db_path = 1 [(validate.rules).string = {pattern: "^$|^.*\\.mmdb$"}];; // Full file path to the Maxmind ASN database, e.g. `/etc/GeoLite2-ASN.mmdb`. + // Database file is expected to have `.mmdb` extension. string isp_db_path = 2 [(validate.rules).string = {pattern: "^$|^.*\\.mmdb$"}];; // Full file path to the Maxmind anonymous IP database, e.g. `/etc/GeoIP2-Anonymous-IP.mmdb`. + // Database file is expected to have `.mmdb` extension. string anon_db_path = 3 [(validate.rules).string = {pattern: "^$|^.*\\.mmdb$"}];; // Common provider configuration that specifies which geolocation headers will be populated with geolocation data. diff --git a/source/extensions/geoip_providers/maxmind/config.cc b/source/extensions/geoip_providers/maxmind/config.cc index 669a136aadd8..c754405a3cb2 100644 --- a/source/extensions/geoip_providers/maxmind/config.cc +++ b/source/extensions/geoip_providers/maxmind/config.cc @@ -17,48 +17,52 @@ using ConfigProto = envoy::extensions::geoip_providers::maxmind::v3::MaxMindConf /** * A singleton that acts as a factory for generating and looking up GeoipProviders. - * When given equivalent provider configs, the singleton returns pointers to the same driver/provider. - * When given different configs, the singleton returns different provider instances. + * When given equivalent provider configs, the singleton returns pointers to the same + * driver/provider. When given different configs, the singleton returns different provider + * instances. */ class DriverSingleton : public Envoy::Singleton::Instance { - public: - std::shared_ptr get(std::shared_ptr singleton, - const ConfigProto& proto_config, - const std::string& stat_prefix, Server::Configuration::FactoryContext& context) { - std::shared_ptr driver; - const uint64_t key = MessageUtil::hash(proto_config); - absl::MutexLock lock(&mu_); - auto it = drivers_.find(key); - if (it != drivers_.end()) { - driver = it->second.lock(); - } else { - const auto& provider_config = - std::make_shared(proto_config, stat_prefix, context.scope()); - driver = std::make_shared(singleton, provider_config); - drivers_[key] = driver; - } - return driver; +public: + std::shared_ptr get(std::shared_ptr singleton, + const ConfigProto& proto_config, + const std::string& stat_prefix, + Server::Configuration::FactoryContext& context) { + std::shared_ptr driver; + const uint64_t key = MessageUtil::hash(proto_config); + absl::MutexLock lock(&mu_); + auto it = drivers_.find(key); + if (it != drivers_.end()) { + driver = it->second.lock(); + } else { + const auto& provider_config = + std::make_shared(proto_config, stat_prefix, context.scope()); + driver = std::make_shared(singleton, provider_config); + drivers_[key] = driver; + } + return driver; } - private: - absl::Mutex mu_; - // We keep weak_ptr here so the providers can be destroyed if the config is updated to stop using - // that config of the provider. Each provider stores shared_ptrs to this singleton, which keeps the - // singleton from being destroyed unless it's no longer keeping track of any providers. - // (The singleton shared_ptr is *only* held by cache instances.) - absl::flat_hash_map> drivers_ ABSL_GUARDED_BY(mu_); + +private: + absl::Mutex mu_; + // We keep weak_ptr here so the providers can be destroyed if the config is updated to stop using + // that config of the provider. Each provider stores shared_ptrs to this singleton, which keeps + // the singleton from being destroyed unless it's no longer keeping track of any providers. (The + // singleton shared_ptr is *only* held by cache instances.) + absl::flat_hash_map> drivers_ ABSL_GUARDED_BY(mu_); }; SINGLETON_MANAGER_REGISTRATION(maxmind_geolocation_provider_singleton); -MaxmindProviderFactory::MaxmindProviderFactory() : FactoryBase("envoy.geoip_providers.maxmind") {} +MaxmindProviderFactory::MaxmindProviderFactory() : FactoryBase("envoy.geoip_providers.maxmind") { + std::cerr << "****Created instance of MaxmindProviderFactory" << std::endl; +} DriverSharedPtr MaxmindProviderFactory::createGeoipProviderDriverTyped( - const ConfigProto& proto_config, - const std::string& stat_prefix, Server::Configuration::FactoryContext& context) { + const ConfigProto& proto_config, const std::string& stat_prefix, + Server::Configuration::FactoryContext& context) { std::shared_ptr drivers = context.singletonManager().getTyped( - SINGLETON_MANAGER_REGISTERED_NAME(maxmind_geolocation_provider_singleton), [] { - return std::make_shared(); - }); + SINGLETON_MANAGER_REGISTERED_NAME(maxmind_geolocation_provider_singleton), + [] { return std::make_shared(); }); return drivers->get(drivers, proto_config, stat_prefix, context); } diff --git a/source/extensions/geoip_providers/maxmind/geoip_provider.cc b/source/extensions/geoip_providers/maxmind/geoip_provider.cc index acc26e4552e0..6e63632f7842 100644 --- a/source/extensions/geoip_providers/maxmind/geoip_provider.cc +++ b/source/extensions/geoip_providers/maxmind/geoip_provider.cc @@ -173,7 +173,7 @@ void GeoipProvider::lookupInAsnDb( const Network::Address::InstanceConstSharedPtr& remote_address, absl::flat_hash_map& lookup_result) const { if (config_->isLookupEnabledForHeader(config_->asnHeader())) { - RELEASE_ASSERT(isp_db_, "Maxmind asn database is not initialised for performing lookups"); + RELEASE_ASSERT(isp_db_, "Maxmind asn database is not initialized for performing lookups"); int mmdb_error; const uint32_t n_prev_hits = lookup_result.size(); MMDB_lookup_result_s mmdb_lookup_result = MMDB_lookup_sockaddr( diff --git a/test/extensions/geoip_providers/maxmind/BUILD b/test/extensions/geoip_providers/maxmind/BUILD index 0f5b069d869b..3c018d0a945e 100644 --- a/test/extensions/geoip_providers/maxmind/BUILD +++ b/test/extensions/geoip_providers/maxmind/BUILD @@ -39,8 +39,7 @@ envoy_extension_cc_test( "//envoy/registry", "//source/extensions/geoip_providers/maxmind:config", "//source/extensions/geoip_providers/maxmind:provider_impl", - "//test/mocks/server:factory_context_mocks", + "//test/mocks/server:factory_context_mocks", "@envoy_api//envoy/extensions/geoip_providers/maxmind/v3:pkg_cc_proto", ], ) - diff --git a/test/extensions/geoip_providers/maxmind/config_test.cc b/test/extensions/geoip_providers/maxmind/config_test.cc index a7329df7bf8b..5d2c29c9e1b0 100644 --- a/test/extensions/geoip_providers/maxmind/config_test.cc +++ b/test/extensions/geoip_providers/maxmind/config_test.cc @@ -252,6 +252,21 @@ TEST(MaxmindProviderConfigTest, ProviderConfigWithNoGeoHeaders) { "Proto constraint validation failed.*value is required.*"); } +TEST(MaxmindProviderConfigTest, DbPathFormatValidatedWhenNonEmptyValue) { + std::string provider_config_yaml = R"EOF( + isp_db_path: "/geoip2/Isp.exe" + )EOF"; + MaxmindProviderConfig provider_config; + TestUtility::loadFromYaml(provider_config_yaml, provider_config); + NiceMock context; + EXPECT_CALL(context, messageValidationVisitor()); + MaxmindProviderFactory factory; + EXPECT_THROW_WITH_REGEX( + factory.createGeoipProviderDriver(provider_config, "maxmind", context), + ProtoValidationException, + "Proto constraint validation failed.*value does not match regex pattern.*"); +} + TEST(MaxmindProviderConfigTest, ReusesProviderInstanceForSameProtoConfig) { const auto provider_config_yaml = R"EOF( common_provider_config: diff --git a/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc b/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc index d03036f7f2db..883957238b75 100644 --- a/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc +++ b/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc @@ -1,6 +1,6 @@ #include "envoy/extensions/geoip_providers/maxmind/v3/maxmind.pb.h" - #include "envoy/registry/registry.h" + #include "source/common/network/address_impl.h" #include "source/common/network/utility.h" #include "source/extensions/geoip_providers/maxmind/config.h" @@ -16,6 +16,7 @@ using testing::_; using testing::NiceMock; +using testing::ReturnRef; using testing::SaveArg; namespace Envoy { @@ -26,17 +27,17 @@ namespace Maxmind { class GeoipProviderTest : public testing::Test { public: GeoipProviderTest() { - provider_factory_ = Registry::FactoryRegistry::getFactory( - "envoy.geoip_providers.maxmind"); - if (provider_factory_ == nullptr) { - throw EnvoyException("Didn't find a registered implementation for type envoy.geoip_providers.maxmind"); - } + provider_factory_ = dynamic_cast( + Registry::FactoryRegistry::getFactory( + "envoy.geoip_providers.maxmind")); + ASSERT(provider_factory_); } void initializeProvider(const std::string& yaml) { envoy::extensions::geoip_providers::maxmind::v3::MaxMindConfig config; TestUtility::loadFromYaml(TestEnvironment::substitute(yaml), config); provider_ = provider_factory_->createGeoipProviderDriver(config, "prefix.", context_); + EXPECT_CALL(context_, scope()).WillRepeatedly(ReturnRef(scope_)); } void expectStats(const std::string& db_type, const uint32_t total_times = 1, @@ -49,6 +50,7 @@ class GeoipProviderTest : public testing::Test { } NiceMock stats_; + Stats::MockScope& scope_{stats_.mockScope()}; NiceMock context_; DriverSharedPtr provider_; MaxmindProviderFactory* provider_factory_; @@ -87,7 +89,7 @@ TEST_F(GeoipProviderTest, ValidConfigCityAndIspDbsSuccessfulLookup) { EXPECT_EQ("15169", asn_it->second); } - // Tests for anonymous database replicate expectations from corresponding Maxmind tests: +// Tests for anonymous database replicate expectations from corresponding Maxmind tests: // https://github.com/maxmind/GeoIP2-perl/blob/main/t/GeoIP2/Database/Reader-Anonymous-IP.t TEST_F(GeoipProviderTest, ValidConfigAnonVpnSuccessfulLookup) { const std::string config_yaml = R"EOF( @@ -95,7 +97,8 @@ TEST_F(GeoipProviderTest, ValidConfigAnonVpnSuccessfulLookup) { geo_headers_to_add: is_anon: "x-geo-anon" anon_vpn: "x-geo-anon-vpn" - anon_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" + anon_db_path: "{{ test_rundir + }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" )EOF"; initializeProvider(config_yaml); Network::Address::InstanceConstSharedPtr remote_address = @@ -119,7 +122,8 @@ TEST_F(GeoipProviderTest, ValidConfigAnonHostingSuccessfulLookup) { geo_headers_to_add: is_anon: "x-geo-anon" anon_hosting: "x-geo-anon-hosting" - anon_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" + anon_db_path: "{{ test_rundir + }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" )EOF"; initializeProvider(config_yaml); Network::Address::InstanceConstSharedPtr remote_address = @@ -143,7 +147,8 @@ TEST_F(GeoipProviderTest, ValidConfigAnonTorNodeSuccessfulLookup) { geo_headers_to_add: is_anon: "x-geo-anon" anon_tor: "x-geo-anon-tor" - anon_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" + anon_db_path: "{{ test_rundir + }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" )EOF"; initializeProvider(config_yaml); Network::Address::InstanceConstSharedPtr remote_address = @@ -167,7 +172,8 @@ TEST_F(GeoipProviderTest, ValidConfigAnonProxySuccessfulLookup) { geo_headers_to_add: is_anon: "x-geo-anon" anon_proxy: "x-geo-anon-proxy" - anon_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" + anon_db_path: "{{ test_rundir + }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" )EOF"; initializeProvider(config_yaml); Network::Address::InstanceConstSharedPtr remote_address = @@ -190,7 +196,8 @@ TEST_F(GeoipProviderTest, ValidConfigEmptyLookupResult) { common_provider_config: geo_headers_to_add: is_anon: "x-geo-anon" - anon_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" + anon_db_path: "{{ test_rundir + }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" )EOF"; initializeProvider(config_yaml); Network::Address::InstanceConstSharedPtr remote_address = @@ -211,7 +218,8 @@ TEST_F(GeoipProviderTest, ValidConfigCityMultipleLookups) { country: "x-geo-country" region: "x-geo-region" city: "x-geo-city" - city_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test.mmdb" + city_db_path: "{{ test_rundir + }}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test.mmdb" )EOF"; initializeProvider(config_yaml); Network::Address::InstanceConstSharedPtr remote_address1 = @@ -242,7 +250,8 @@ TEST_F(GeoipProviderDeathTest, GeoDbNotSetForConfiguredHeader) { geo_headers_to_add: city: "x-geo-city" asn: "x-geo-asn" - city_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test.mmdb" + city_db_path: "{{ test_rundir + }}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test.mmdb" )EOF"; initializeProvider(config_yaml); Network::Address::InstanceConstSharedPtr remote_address = @@ -252,7 +261,7 @@ TEST_F(GeoipProviderDeathTest, GeoDbNotSetForConfiguredHeader) { auto lookup_cb_std = lookup_cb.AsStdFunction(); EXPECT_CALL(lookup_cb, Call(_)).WillRepeatedly(SaveArg<0>(&captured_lookup_response_)); EXPECT_DEATH(provider_->lookup(std::move(lookup_rq), std::move(lookup_cb_std)), - "assert failure: isp_db_. Details: Maxmind asn database is not initialised for " + "assert failure: isp_db_. Details: Maxmind asn database is not initialized for " "performing lookups"); } diff --git a/tools/spelling/spelling_dictionary.txt b/tools/spelling/spelling_dictionary.txt index b9acd242d8ce..acc1c56a5320 100644 --- a/tools/spelling/spelling_dictionary.txt +++ b/tools/spelling/spelling_dictionary.txt @@ -767,6 +767,7 @@ gateway gcov genrule geolocation +geo geoip Geoip getaddrinfo @@ -851,6 +852,7 @@ iovecs ips iptables ish +isp istio istream istringstream @@ -914,6 +916,7 @@ matchers maxage maxbuffer Maxmind +maxmind megamiss mem memcmp From 87d06bba53a5eb265cb26db32661307da0d1b2b2 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Fri, 8 Sep 2023 20:07:14 +0000 Subject: [PATCH 12/44] Address TODOs Signed-off-by: Kateryna Nezdolii --- .../geoip_providers/common/v3/common.proto | 2 +- .../geoip_providers/maxmind/v3/maxmind.proto | 6 ++-- .../geoip_providers/maxmind/config.cc | 4 +-- .../geoip_providers/maxmind/geoip_provider.cc | 3 -- .../geoip_providers/maxmind/geoip_provider.h | 4 --- test/extensions/filters/http/geoip/mocks.h | 1 - .../maxmind/geoip_provider_test.cc | 33 ++++++++++--------- 7 files changed, 23 insertions(+), 30 deletions(-) diff --git a/api/envoy/extensions/geoip_providers/common/v3/common.proto b/api/envoy/extensions/geoip_providers/common/v3/common.proto index 4a934f1af89b..0b11189e89e1 100644 --- a/api/envoy/extensions/geoip_providers/common/v3/common.proto +++ b/api/envoy/extensions/geoip_providers/common/v3/common.proto @@ -13,7 +13,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; message CommonGeoipProviderConfig { // The set of geolocation headers to add to request. If any of the configured headers is present - // in the incoming request, it will be overridden by Geoip filter. + // in the incoming request, it will be overridden by the :ref:`Geoip filter `. // [#next-free-field: 10] message GeolocationHeadersToAdd { // If set, the header will be used to populate the country ISO code associated with the IP address. diff --git a/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto b/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto index 092b912792f2..d9908a55b878 100644 --- a/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto +++ b/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto @@ -26,15 +26,15 @@ option (xds.annotations.v3.file_status).work_in_progress = true; message MaxMindConfig { // Full file path to the Maxmind city database, e.g. `/etc/GeoLite2-City.mmdb`. // Database file is expected to have `.mmdb` extension. - string city_db_path = 1 [(validate.rules).string = {pattern: "^$|^.*\\.mmdb$"}];; + string city_db_path = 1 [(validate.rules).string = {pattern: "^$|^.*\\.mmdb$"}]; // Full file path to the Maxmind ASN database, e.g. `/etc/GeoLite2-ASN.mmdb`. // Database file is expected to have `.mmdb` extension. - string isp_db_path = 2 [(validate.rules).string = {pattern: "^$|^.*\\.mmdb$"}];; + string isp_db_path = 2 [(validate.rules).string = {pattern: "^$|^.*\\.mmdb$"}]; // Full file path to the Maxmind anonymous IP database, e.g. `/etc/GeoIP2-Anonymous-IP.mmdb`. // Database file is expected to have `.mmdb` extension. - string anon_db_path = 3 [(validate.rules).string = {pattern: "^$|^.*\\.mmdb$"}];; + string anon_db_path = 3 [(validate.rules).string = {pattern: "^$|^.*\\.mmdb$"}]; // Common provider configuration that specifies which geolocation headers will be populated with geolocation data. common.v3.CommonGeoipProviderConfig common_provider_config = 4 diff --git a/source/extensions/geoip_providers/maxmind/config.cc b/source/extensions/geoip_providers/maxmind/config.cc index c754405a3cb2..4df7ba250b5e 100644 --- a/source/extensions/geoip_providers/maxmind/config.cc +++ b/source/extensions/geoip_providers/maxmind/config.cc @@ -53,9 +53,7 @@ class DriverSingleton : public Envoy::Singleton::Instance { SINGLETON_MANAGER_REGISTRATION(maxmind_geolocation_provider_singleton); -MaxmindProviderFactory::MaxmindProviderFactory() : FactoryBase("envoy.geoip_providers.maxmind") { - std::cerr << "****Created instance of MaxmindProviderFactory" << std::endl; -} +MaxmindProviderFactory::MaxmindProviderFactory() : FactoryBase("envoy.geoip_providers.maxmind") {} DriverSharedPtr MaxmindProviderFactory::createGeoipProviderDriverTyped( const ConfigProto& proto_config, const std::string& stat_prefix, diff --git a/source/extensions/geoip_providers/maxmind/geoip_provider.cc b/source/extensions/geoip_providers/maxmind/geoip_provider.cc index 6e63632f7842..8b10ecefdda0 100644 --- a/source/extensions/geoip_providers/maxmind/geoip_provider.cc +++ b/source/extensions/geoip_providers/maxmind/geoip_provider.cc @@ -87,7 +87,6 @@ void GeoipProviderConfig::incCounter(Stats::StatName name) { GeoipProvider::~GeoipProvider() { ENVOY_LOG(debug, "Shutting down Maxmind geolocation provider"); - // TODO(nezdolik) consider switching to atomic singleton for db objects if (city_db_) { MMDB_close(city_db_.get()); } @@ -123,8 +122,6 @@ void GeoipProvider::lookup(Geolocation::LookupRequest&& request, cb(std::move(lookup_result)); } -// todo: document En as default and only language used for lookups. Document that region is selected -// as least specific subdivision void GeoipProvider::lookupInCityDb( const Network::Address::InstanceConstSharedPtr& remote_address, absl::flat_hash_map& lookup_result) const { diff --git a/source/extensions/geoip_providers/maxmind/geoip_provider.h b/source/extensions/geoip_providers/maxmind/geoip_provider.h index d3a9aac14059..b7da97af5335 100644 --- a/source/extensions/geoip_providers/maxmind/geoip_provider.h +++ b/source/extensions/geoip_providers/maxmind/geoip_provider.h @@ -2,9 +2,6 @@ #include "envoy/geoip/geoip_provider_driver.h" -// TODO(nezdolik) do we need this? -#include "envoy/extensions/filters/http/geoip/v3/geoip.pb.h" -#include "envoy/extensions/filters/http/geoip/v3/geoip.pb.validate.h" #include "envoy/extensions/geoip_providers/maxmind/v3/maxmind.pb.h" #include "source/common/common/logger.h" #include "maxminddb.h" @@ -76,7 +73,6 @@ class GeoipProviderConfig { using GeoipProviderConfigSharedPtr = std::shared_ptr; -// TODO(nezdolik) should this be std::atomic>> instead? using MaxmindDbPtr = std::unique_ptr; class GeoipProvider : public Envoy::Geolocation::Driver, public Logger::Loggable { diff --git a/test/extensions/filters/http/geoip/mocks.h b/test/extensions/filters/http/geoip/mocks.h index 8a2533c4eb26..6f89272740b8 100644 --- a/test/extensions/filters/http/geoip/mocks.h +++ b/test/extensions/filters/http/geoip/mocks.h @@ -2,7 +2,6 @@ #include "envoy/geoip/geoip_provider_driver.h" - #include "test/extensions/filters/http/geoip/dummy.pb.h" #include "test/extensions/filters/http/geoip/dummy.pb.validate.h" diff --git a/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc b/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc index 883957238b75..6b06bf170524 100644 --- a/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc +++ b/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc @@ -34,10 +34,10 @@ class GeoipProviderTest : public testing::Test { } void initializeProvider(const std::string& yaml) { + EXPECT_CALL(context_, scope()).WillRepeatedly(ReturnRef(scope_)); envoy::extensions::geoip_providers::maxmind::v3::MaxMindConfig config; TestUtility::loadFromYaml(TestEnvironment::substitute(yaml), config); provider_ = provider_factory_->createGeoipProviderDriver(config, "prefix.", context_); - EXPECT_CALL(context_, scope()).WillRepeatedly(ReturnRef(scope_)); } void expectStats(const std::string& db_type, const uint32_t total_times = 1, @@ -97,8 +97,7 @@ TEST_F(GeoipProviderTest, ValidConfigAnonVpnSuccessfulLookup) { geo_headers_to_add: is_anon: "x-geo-anon" anon_vpn: "x-geo-anon-vpn" - anon_db_path: "{{ test_rundir - }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" + anon_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" )EOF"; initializeProvider(config_yaml); Network::Address::InstanceConstSharedPtr remote_address = @@ -122,8 +121,7 @@ TEST_F(GeoipProviderTest, ValidConfigAnonHostingSuccessfulLookup) { geo_headers_to_add: is_anon: "x-geo-anon" anon_hosting: "x-geo-anon-hosting" - anon_db_path: "{{ test_rundir - }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" + anon_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" )EOF"; initializeProvider(config_yaml); Network::Address::InstanceConstSharedPtr remote_address = @@ -147,8 +145,7 @@ TEST_F(GeoipProviderTest, ValidConfigAnonTorNodeSuccessfulLookup) { geo_headers_to_add: is_anon: "x-geo-anon" anon_tor: "x-geo-anon-tor" - anon_db_path: "{{ test_rundir - }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" + anon_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" )EOF"; initializeProvider(config_yaml); Network::Address::InstanceConstSharedPtr remote_address = @@ -172,8 +169,7 @@ TEST_F(GeoipProviderTest, ValidConfigAnonProxySuccessfulLookup) { geo_headers_to_add: is_anon: "x-geo-anon" anon_proxy: "x-geo-anon-proxy" - anon_db_path: "{{ test_rundir - }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" + anon_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" )EOF"; initializeProvider(config_yaml); Network::Address::InstanceConstSharedPtr remote_address = @@ -196,8 +192,7 @@ TEST_F(GeoipProviderTest, ValidConfigEmptyLookupResult) { common_provider_config: geo_headers_to_add: is_anon: "x-geo-anon" - anon_db_path: "{{ test_rundir - }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" + anon_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoIP2-Anonymous-IP-Test.mmdb" )EOF"; initializeProvider(config_yaml); Network::Address::InstanceConstSharedPtr remote_address = @@ -218,8 +213,7 @@ TEST_F(GeoipProviderTest, ValidConfigCityMultipleLookups) { country: "x-geo-country" region: "x-geo-region" city: "x-geo-city" - city_db_path: "{{ test_rundir - }}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test.mmdb" + city_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test.mmdb" )EOF"; initializeProvider(config_yaml); Network::Address::InstanceConstSharedPtr remote_address1 = @@ -250,8 +244,7 @@ TEST_F(GeoipProviderDeathTest, GeoDbNotSetForConfiguredHeader) { geo_headers_to_add: city: "x-geo-city" asn: "x-geo-asn" - city_db_path: "{{ test_rundir - }}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test.mmdb" + city_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/GeoLite2-City-Test.mmdb" )EOF"; initializeProvider(config_yaml); Network::Address::InstanceConstSharedPtr remote_address = @@ -265,6 +258,16 @@ TEST_F(GeoipProviderDeathTest, GeoDbNotSetForConfiguredHeader) { "performing lookups"); } +TEST_F(GeoipProviderDeathTest, GeoDbPathDoesNotExist) { + const std::string config_yaml = R"EOF( + common_provider_config: + geo_headers_to_add: + city: "x-geo-city" + city_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data_atc/GeoLite2-City-Test.mmdb" + )EOF"; + EXPECT_DEATH(initializeProvider(config_yaml), ".*Unable to open Maxmind database file.*"); +} + } // namespace Maxmind } // namespace GeoipProviders } // namespace Extensions From 5fdf71b803527f436482128a2daea9f2bf2c5110 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Fri, 8 Sep 2023 20:38:37 +0000 Subject: [PATCH 13/44] Fix some format Signed-off-by: Kateryna Nezdolii --- source/extensions/geoip_providers/maxmind/BUILD | 1 - source/extensions/geoip_providers/maxmind/geoip_provider.h | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/extensions/geoip_providers/maxmind/BUILD b/source/extensions/geoip_providers/maxmind/BUILD index 690f121d7689..26e0b2d435f9 100644 --- a/source/extensions/geoip_providers/maxmind/BUILD +++ b/source/extensions/geoip_providers/maxmind/BUILD @@ -33,7 +33,6 @@ envoy_cc_library( external_deps = ["maxmind"], deps = [ "//envoy/geoip:geoip_provider_driver_interface", - "@envoy_api//envoy/extensions/filters/http/geoip/v3:pkg_cc_proto", "@envoy_api//envoy/extensions/geoip_providers/maxmind/v3:pkg_cc_proto", ], ) diff --git a/source/extensions/geoip_providers/maxmind/geoip_provider.h b/source/extensions/geoip_providers/maxmind/geoip_provider.h index b7da97af5335..8cf394a591fe 100644 --- a/source/extensions/geoip_providers/maxmind/geoip_provider.h +++ b/source/extensions/geoip_providers/maxmind/geoip_provider.h @@ -1,9 +1,10 @@ #pragma once +#include "envoy/extensions/geoip_providers/maxmind/v3/maxmind.pb.h" #include "envoy/geoip/geoip_provider_driver.h" -#include "envoy/extensions/geoip_providers/maxmind/v3/maxmind.pb.h" #include "source/common/common/logger.h" + #include "maxminddb.h" namespace Envoy { From ac7d26d988d1d1986b390e105a69d569b6c4a867 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Fri, 8 Sep 2023 21:18:01 +0000 Subject: [PATCH 14/44] Add owners for geoip_providers/common Signed-off-by: Kateryna Nezdolii --- CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/CODEOWNERS b/CODEOWNERS index d90ea880334c..681447317069 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -321,6 +321,7 @@ extensions/filters/http/oauth2 @derekargueta @mattklein123 /*/extensions/health_check/event_sinks/file @botengyao @yanavlasov # IP Geolocation /*/extensions/filters/http/geoip @nezdolik @ravenblackx +/*/extensions/geoip_providers/common @nezdolik @ravenblackx # Maxmind geolocation provider /*/extensions/geoip_providers/maxmind @nezdolik @ravenblackx From 728e6684d9145f5f4e845056cfc35707fb7978e3 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Fri, 8 Sep 2023 21:40:40 +0000 Subject: [PATCH 15/44] Add title to proto file Signed-off-by: Kateryna Nezdolii --- api/envoy/extensions/geoip_providers/common/v3/common.proto | 1 + 1 file changed, 1 insertion(+) diff --git a/api/envoy/extensions/geoip_providers/common/v3/common.proto b/api/envoy/extensions/geoip_providers/common/v3/common.proto index 0b11189e89e1..68fa135d8ef3 100644 --- a/api/envoy/extensions/geoip_providers/common/v3/common.proto +++ b/api/envoy/extensions/geoip_providers/common/v3/common.proto @@ -11,6 +11,7 @@ option java_multiple_files = true; option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/geoip_providers/common/v3;commonv3"; option (udpa.annotations.file_status).package_version_status = ACTIVE; +// [#protodoc-title: Common Geolocation Provider Configuration] message CommonGeoipProviderConfig { // The set of geolocation headers to add to request. If any of the configured headers is present // in the incoming request, it will be overridden by the :ref:`Geoip filter `. From b72dd2950c97fb756ba998441c6082ecc8530016 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Mon, 11 Sep 2023 12:55:31 +0200 Subject: [PATCH 16/44] Update api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto Co-authored-by: phlax Signed-off-by: Kateryna Nezdolii --- api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto b/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto index d9908a55b878..f27f3ff8c46e 100644 --- a/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto +++ b/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto @@ -17,7 +17,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; option (xds.annotations.v3.file_status).work_in_progress = true; // [#protodoc-title: MaxMind geolocation provider] - +// // Configuration for the MaxMind geolocation provider. // At least one geolocation database path :ref:`city_db_path `, // :ref:`isp_db_path ` or From 9eba89e042c79a3d5fc8a1d69fa3bb2608400e81 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Mon, 11 Sep 2023 11:10:57 +0000 Subject: [PATCH 17/44] Fix proto format Signed-off-by: Kateryna Nezdolii --- api/envoy/extensions/geoip_providers/common/v3/common.proto | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api/envoy/extensions/geoip_providers/common/v3/common.proto b/api/envoy/extensions/geoip_providers/common/v3/common.proto index 68fa135d8ef3..6a4c7993fd47 100644 --- a/api/envoy/extensions/geoip_providers/common/v3/common.proto +++ b/api/envoy/extensions/geoip_providers/common/v3/common.proto @@ -12,6 +12,8 @@ option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/geo option (udpa.annotations.file_status).package_version_status = ACTIVE; // [#protodoc-title: Common Geolocation Provider Configuration] +// +// Common configuration shared across geolocation providers. message CommonGeoipProviderConfig { // The set of geolocation headers to add to request. If any of the configured headers is present // in the incoming request, it will be overridden by the :ref:`Geoip filter `. From 6cd975703a05cef72259c2ab1efafa8d24be24b7 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Mon, 11 Sep 2023 13:37:48 +0200 Subject: [PATCH 18/44] Update maxmind.proto Update common.proto Signed-off-by: Kateryna Nezdolii --- api/envoy/extensions/geoip_providers/common/v3/common.proto | 3 ++- .../extensions/geoip_providers/maxmind/v3/maxmind.proto | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/api/envoy/extensions/geoip_providers/common/v3/common.proto b/api/envoy/extensions/geoip_providers/common/v3/common.proto index 6a4c7993fd47..e47a943d2623 100644 --- a/api/envoy/extensions/geoip_providers/common/v3/common.proto +++ b/api/envoy/extensions/geoip_providers/common/v3/common.proto @@ -12,8 +12,9 @@ option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/geo option (udpa.annotations.file_status).package_version_status = ACTIVE; // [#protodoc-title: Common Geolocation Provider Configuration] -// // Common configuration shared across geolocation providers. + +// [#next-free-field: 2] message CommonGeoipProviderConfig { // The set of geolocation headers to add to request. If any of the configured headers is present // in the incoming request, it will be overridden by the :ref:`Geoip filter `. diff --git a/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto b/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto index f27f3ff8c46e..019e1b2f99ba 100644 --- a/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto +++ b/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto @@ -16,13 +16,14 @@ option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/geo option (udpa.annotations.file_status).package_version_status = ACTIVE; option (xds.annotations.v3.file_status).work_in_progress = true; -// [#protodoc-title: MaxMind geolocation provider] -// +// [#protodoc-title: MaxMind Geolocation Provider] // Configuration for the MaxMind geolocation provider. // At least one geolocation database path :ref:`city_db_path `, // :ref:`isp_db_path ` or // :ref:`anon_db_path ` must be configured. // [#extension: envoy.geoip_providers.maxmind] + +// [#next-free-field: 5] message MaxMindConfig { // Full file path to the Maxmind city database, e.g. `/etc/GeoLite2-City.mmdb`. // Database file is expected to have `.mmdb` extension. From ef2c242242d476d368a827e909e32e7488f7d03c Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Mon, 11 Sep 2023 12:54:50 +0000 Subject: [PATCH 19/44] Try to fix again... Signed-off-by: Kateryna Nezdolii --- api/envoy/extensions/geoip_providers/common/v3/common.proto | 1 - api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto | 1 - 2 files changed, 2 deletions(-) diff --git a/api/envoy/extensions/geoip_providers/common/v3/common.proto b/api/envoy/extensions/geoip_providers/common/v3/common.proto index e47a943d2623..37c85dd0ad9e 100644 --- a/api/envoy/extensions/geoip_providers/common/v3/common.proto +++ b/api/envoy/extensions/geoip_providers/common/v3/common.proto @@ -14,7 +14,6 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // [#protodoc-title: Common Geolocation Provider Configuration] // Common configuration shared across geolocation providers. -// [#next-free-field: 2] message CommonGeoipProviderConfig { // The set of geolocation headers to add to request. If any of the configured headers is present // in the incoming request, it will be overridden by the :ref:`Geoip filter `. diff --git a/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto b/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto index 019e1b2f99ba..8cbcbc946ba1 100644 --- a/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto +++ b/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto @@ -23,7 +23,6 @@ option (xds.annotations.v3.file_status).work_in_progress = true; // :ref:`anon_db_path ` must be configured. // [#extension: envoy.geoip_providers.maxmind] -// [#next-free-field: 5] message MaxMindConfig { // Full file path to the Maxmind city database, e.g. `/etc/GeoLite2-City.mmdb`. // Database file is expected to have `.mmdb` extension. From 3f20397530707e7f4aabe09564a91920a7d06aa9 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Mon, 11 Sep 2023 19:36:03 +0000 Subject: [PATCH 20/44] Fix CI+review comment Signed-off-by: Kateryna Nezdolii --- .../filters/http/geoip/v3/geoip.proto | 2 +- .../http/http_filters/geoip_filter.rst | 59 +++++++++++-------- .../geoip_providers/maxmind/config.cc | 2 +- 3 files changed, 35 insertions(+), 28 deletions(-) diff --git a/api/envoy/extensions/filters/http/geoip/v3/geoip.proto b/api/envoy/extensions/filters/http/geoip/v3/geoip.proto index 5a11c09feb11..cd520077f08e 100644 --- a/api/envoy/extensions/filters/http/geoip/v3/geoip.proto +++ b/api/envoy/extensions/filters/http/geoip/v3/geoip.proto @@ -39,7 +39,7 @@ message Geoip { // Geoip driver specific configuration which depends on the driver being instantiated. // See the geoip drivers for examples: // - // - :ref:`MaxMindConfig ` + // - :ref:`MaxMindConfig ` // [#extension-category: envoy.geoip_providers] config.core.v3.TypedExtensionConfig provider = 3 [(validate.rules).message = {required: true}]; } diff --git a/docs/root/configuration/http/http_filters/geoip_filter.rst b/docs/root/configuration/http/http_filters/geoip_filter.rst index b2d3547e5fe0..6d1d39cda7ff 100644 --- a/docs/root/configuration/http/http_filters/geoip_filter.rst +++ b/docs/root/configuration/http/http_filters/geoip_filter.rst @@ -7,39 +7,20 @@ Filter uses client address to lookup information (e.g., client's city, country) Upon a successful lookup request will be enriched with the configured geolocation header and the value from the database. In case the configured geolocation headers are present in the incoming request, they will be overriden by the filter. Geolocation filter emits stats for the number of the successful lookups and the number of total lookups. -As for now, only `Maxmind ` geolocation provider is supported. English language is used for the geolocation lookups, the result of the lookup will be UTF-8 encoded. -Statistics -------------- - -Geolocation HTTP filter has a statistics tree rooted at ``http..``. The :ref:`stat prefix -` -comes from the owning HTTP connection manager. - -.. csv-table:: - :header: Name, Type, Description - :widths: 1, 1, 2 - - ``rq_total``, Counter, Total number of requests for which geolocation filter was invoked. - -Besides Geolocation filter level statisctics, there is statistics emitted by the :ref:`Maxmind geolocation provider ` -per geolocation database type (rooted at ``.maxmind.``). Database type can be one of `city_db `, -`isp_db `, `anon_db `. - -.. csv-table:: - :header: Name, Type, Description - :widths: 1, 1, 2 - - ``.total``, Counter, Total number of lookups performed for a given geolocation database file. - ``.hit``, Counter, Total number of successful lookups (with non empty lookup result) performed for a given geolocation database file. - ``.lookup_error``, Counter, Total number of errors that occured during lookups for a given geolocation database file. - Configuration ------------- * This filter should be configured with the type URL ``type.googleapis.com/envoy.extensions.filters.http.geoip.v3.Geoip``. * :ref:`v3 API reference ` +Geolocation Providers +--------------------- +Currently only `Maxmind ` geolocation provider is supported. +This provider should be configured with the type URL ``type.googleapis.com/envoy.extensions.geoip_providers.maxmind.v3.MaxMindConfig``. + +* :ref:`v3 API reference ` +* :ref:`Common provider configuration ` Configuration example --------------------- @@ -65,3 +46,29 @@ Configuration example isp_db_path: "geoip/GeoLite2-ASN-Test.mmdb" +Statistics +------------- + +Geolocation HTTP filter has a statistics tree rooted at ``http..``. The :ref:`stat prefix +` +comes from the owning HTTP connection manager. + +.. csv-table:: + :header: Name, Type, Description + :widths: 1, 1, 2 + + ``rq_total``, Counter, Total number of requests for which geolocation filter was invoked. + +Besides Geolocation filter level statisctics, there is statistics emitted by the :ref:`Maxmind geolocation provider ` +per geolocation database type (rooted at ``.maxmind.``). Database type can be one of `city_db `, +`isp_db `, `anon_db `. + +.. csv-table:: + :header: Name, Type, Description + :widths: 1, 1, 2 + + ``.total``, Counter, Total number of lookups performed for a given geolocation database file. + ``.hit``, Counter, Total number of successful lookups (with non empty lookup result) performed for a given geolocation database file. + ``.lookup_error``, Counter, Total number of errors that occured during lookups for a given geolocation database file. + + diff --git a/source/extensions/geoip_providers/maxmind/config.cc b/source/extensions/geoip_providers/maxmind/config.cc index 4df7ba250b5e..df7575436b9f 100644 --- a/source/extensions/geoip_providers/maxmind/config.cc +++ b/source/extensions/geoip_providers/maxmind/config.cc @@ -47,7 +47,7 @@ class DriverSingleton : public Envoy::Singleton::Instance { // We keep weak_ptr here so the providers can be destroyed if the config is updated to stop using // that config of the provider. Each provider stores shared_ptrs to this singleton, which keeps // the singleton from being destroyed unless it's no longer keeping track of any providers. (The - // singleton shared_ptr is *only* held by cache instances.) + // singleton shared_ptr is *only* held by driver instances.) absl::flat_hash_map> drivers_ ABSL_GUARDED_BY(mu_); }; From 480d6a22fd00ca033810b516fda2c347d9c35894 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Mon, 11 Sep 2023 20:12:36 +0000 Subject: [PATCH 21/44] Here i try again Signed-off-by: Kateryna Nezdolii --- api/envoy/extensions/filters/http/geoip/v3/geoip.proto | 2 +- api/envoy/extensions/geoip_providers/common/v3/common.proto | 1 + docs/root/configuration/http/http_filters/geoip_filter.rst | 5 +++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/api/envoy/extensions/filters/http/geoip/v3/geoip.proto b/api/envoy/extensions/filters/http/geoip/v3/geoip.proto index cd520077f08e..965b743d11f2 100644 --- a/api/envoy/extensions/filters/http/geoip/v3/geoip.proto +++ b/api/envoy/extensions/filters/http/geoip/v3/geoip.proto @@ -39,7 +39,7 @@ message Geoip { // Geoip driver specific configuration which depends on the driver being instantiated. // See the geoip drivers for examples: // - // - :ref:`MaxMindConfig ` + // - :ref:`MaxMindConfig ` // [#extension-category: envoy.geoip_providers] config.core.v3.TypedExtensionConfig provider = 3 [(validate.rules).message = {required: true}]; } diff --git a/api/envoy/extensions/geoip_providers/common/v3/common.proto b/api/envoy/extensions/geoip_providers/common/v3/common.proto index 37c85dd0ad9e..91a9126cfef8 100644 --- a/api/envoy/extensions/geoip_providers/common/v3/common.proto +++ b/api/envoy/extensions/geoip_providers/common/v3/common.proto @@ -12,6 +12,7 @@ option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/geo option (udpa.annotations.file_status).package_version_status = ACTIVE; // [#protodoc-title: Common Geolocation Provider Configuration] +// Common geolocation provider :ref:`configuration overview `. // Common configuration shared across geolocation providers. message CommonGeoipProviderConfig { diff --git a/docs/root/configuration/http/http_filters/geoip_filter.rst b/docs/root/configuration/http/http_filters/geoip_filter.rst index 6d1d39cda7ff..3b8d83fd7c4a 100644 --- a/docs/root/configuration/http/http_filters/geoip_filter.rst +++ b/docs/root/configuration/http/http_filters/geoip_filter.rst @@ -14,12 +14,17 @@ Configuration * This filter should be configured with the type URL ``type.googleapis.com/envoy.extensions.filters.http.geoip.v3.Geoip``. * :ref:`v3 API reference ` +.. _config_geoip_providers_maxmind: + Geolocation Providers --------------------- Currently only `Maxmind ` geolocation provider is supported. This provider should be configured with the type URL ``type.googleapis.com/envoy.extensions.geoip_providers.maxmind.v3.MaxMindConfig``. * :ref:`v3 API reference ` + +.. _config_geoip_providers_common: + * :ref:`Common provider configuration ` Configuration example From 80ae14ae1bc97f58d927f8b9e2a9fdd19c09ac5f Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Tue, 12 Sep 2023 21:44:58 +0000 Subject: [PATCH 22/44] Add protos to toc tree Signed-off-by: Kateryna Nezdolii --- .../api-v3/config/geoip_provider/geoip_provider.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 docs/root/api-v3/config/geoip_provider/geoip_provider.rst diff --git a/docs/root/api-v3/config/geoip_provider/geoip_provider.rst b/docs/root/api-v3/config/geoip_provider/geoip_provider.rst new file mode 100644 index 000000000000..6754d1e3f483 --- /dev/null +++ b/docs/root/api-v3/config/geoip_provider/geoip_provider.rst @@ -0,0 +1,10 @@ +.. _api-v3_config_geoip_providers: + +Geolocation providers +===================== + +.. toctree:: + :glob: + :maxdepth: 2 + + ../../extensions/geoip_providers/*/v3/* \ No newline at end of file From 01f20306d77a6fdd7f44fec2d27fee9e56b6a66a Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Tue, 12 Sep 2023 22:10:19 +0000 Subject: [PATCH 23/44] More docs fixes Signed-off-by: Kateryna Nezdolii --- docs/root/api-v3/config/config.rst | 1 + docs/root/api-v3/config/geoip_provider/geoip_provider.rst | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/root/api-v3/config/config.rst b/docs/root/api-v3/config/config.rst index ca859c388e68..015f5e20cb50 100644 --- a/docs/root/api-v3/config/config.rst +++ b/docs/root/api-v3/config/config.rst @@ -27,6 +27,7 @@ Extensions http/header_validators http/original_ip_detection http/stateful_session + geoip_provider/geoip_provider trace/trace internal_redirect/internal_redirect path/match/path_matcher diff --git a/docs/root/api-v3/config/geoip_provider/geoip_provider.rst b/docs/root/api-v3/config/geoip_provider/geoip_provider.rst index 6754d1e3f483..2b9ad10b9f6a 100644 --- a/docs/root/api-v3/config/geoip_provider/geoip_provider.rst +++ b/docs/root/api-v3/config/geoip_provider/geoip_provider.rst @@ -7,4 +7,4 @@ Geolocation providers :glob: :maxdepth: 2 - ../../extensions/geoip_providers/*/v3/* \ No newline at end of file + ../../extensions/geoip_providers/*/v3/* From 011085f52f5fdf9bca46b56c70ca2c439608babc Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Wed, 13 Sep 2023 21:19:31 +0000 Subject: [PATCH 24/44] Fix compile time options and coverage Signed-off-by: Kateryna Nezdolii --- .../geoip_providers/maxmind/config_test.cc | 6 ++++++ .../maxmind/geoip_provider_test.cc | 20 ++++++++++++++++++ .../test_data/MaxMind-DB-test-ipv4-24.mmdb | Bin 0 -> 1298 bytes 3 files changed, 26 insertions(+) create mode 100644 test/extensions/geoip_providers/maxmind/test_data/MaxMind-DB-test-ipv4-24.mmdb diff --git a/test/extensions/geoip_providers/maxmind/config_test.cc b/test/extensions/geoip_providers/maxmind/config_test.cc index 5d2c29c9e1b0..53b40ec948f3 100644 --- a/test/extensions/geoip_providers/maxmind/config_test.cc +++ b/test/extensions/geoip_providers/maxmind/config_test.cc @@ -7,6 +7,7 @@ #include "test/mocks/server/factory_context.h" #include "test/test_common/environment.h" +#include "absl/strings/str_format.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -182,6 +183,11 @@ std::string genGeoDbFilePath(std::string db_name) { "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/" + db_name); } +TEST(MaxmindProviderConfigTest, EmptyProto) { + MaxmindProviderFactory factory; + EXPECT_TRUE(factory.createEmptyConfigProto() != nullptr); +} + TEST(MaxmindProviderConfigTest, ProviderConfigWithCorrectProto) { const auto provider_config_yaml = R"EOF( common_provider_config: diff --git a/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc b/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc index 6b06bf170524..75806181868f 100644 --- a/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc +++ b/test/extensions/geoip_providers/maxmind/geoip_provider_test.cc @@ -89,6 +89,26 @@ TEST_F(GeoipProviderTest, ValidConfigCityAndIspDbsSuccessfulLookup) { EXPECT_EQ("15169", asn_it->second); } +TEST_F(GeoipProviderTest, ValidConfigCityLookupError) { + const std::string config_yaml = R"EOF( + common_provider_config: + geo_headers_to_add: + country: "x-geo-country" + city: "x-geo-city" + city_db_path: "{{ test_rundir }}/test/extensions/geoip_providers/maxmind/test_data/MaxMind-DB-test-ipv4-24.mmdb" + )EOF"; + initializeProvider(config_yaml); + Network::Address::InstanceConstSharedPtr remote_address = + Network::Utility::parseInternetAddress("2345:0425:2CA1:0:0:0567:5673:23b5"); + Geolocation::LookupRequest lookup_rq{std::move(remote_address)}; + testing::MockFunction lookup_cb; + auto lookup_cb_std = lookup_cb.AsStdFunction(); + EXPECT_CALL(lookup_cb, Call(_)).WillRepeatedly(SaveArg<0>(&captured_lookup_response_)); + expectStats("city_db", 1, 0, 1); + provider_->lookup(std::move(lookup_rq), std::move(lookup_cb_std)); + EXPECT_EQ(0, captured_lookup_response_.size()); +} + // Tests for anonymous database replicate expectations from corresponding Maxmind tests: // https://github.com/maxmind/GeoIP2-perl/blob/main/t/GeoIP2/Database/Reader-Anonymous-IP.t TEST_F(GeoipProviderTest, ValidConfigAnonVpnSuccessfulLookup) { diff --git a/test/extensions/geoip_providers/maxmind/test_data/MaxMind-DB-test-ipv4-24.mmdb b/test/extensions/geoip_providers/maxmind/test_data/MaxMind-DB-test-ipv4-24.mmdb new file mode 100644 index 0000000000000000000000000000000000000000..71ff41e91dd38ddef1ef8ae22f3e9895f6c3a4b1 GIT binary patch literal 1298 zcmZ9`*H#lj9LMpWG4|fE$1WC>fQVf~6iAE}Y^dudJCH@PyY6lfV!_^fFQ}m0dFu=C z06c)+={a6_E-$D9{B2=`dgkFq}Pt%B7LODE4SN zhK{A<=y*DT%Ka08N$kmV3Y|))(dl#smHP{Tne16~HV^{l0AGN)KsPWC=mF*fU%BBY zuz<0UE~1O+AG(yvlb5NGT?niI)&eWla22qcT}0QYx!f#&#WYMy)Y3Yjnq3C0SHp5( z15g2MRFh4N&2$UhO1IJNbO()4`FByqPP&U$(khz2QVjS6#5vgwJOUCx4%oxVUb+wP zfc<~~4sddi*3epdh#sa#=uvu%*3ski1U(5DfW|&Wb(*9pn!jP*dNpZaqydxBNKexy zD)(m?7GN_RdPc3fDtr}Lpjq`L-k+z%#~k`hvcsujp&~hQ6ikR37z?@t%GF zIvAbwBkjMxjKQDp5!0zEF5)&ceJef6{3{5z8Djf_M-`WckhVJW0 z-4mMM>WFBK@cg(Typ(G?zC72$ij?gdnrG%jXTe|584qXx literal 0 HcmV?d00001 From f95320ec36b86b1c7712a509dc2d57dc78c16b2d Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Wed, 13 Sep 2023 21:37:11 +0000 Subject: [PATCH 25/44] Maybe fix WIN build Signed-off-by: Kateryna Nezdolii --- bazel/foreign_cc/BUILD | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bazel/foreign_cc/BUILD b/bazel/foreign_cc/BUILD index 63951afb545d..dece992e52d6 100644 --- a/bazel/foreign_cc/BUILD +++ b/bazel/foreign_cc/BUILD @@ -580,6 +580,10 @@ envoy_cmake( "BUILD_SHARED_LIBS": "no", "BUILD_TESTING": "no", }, + env = select({ + "//bazel:windows_x86_64": {"WIN32": "yes"}, + "//conditions:default": {}, + }), defines = ["MAXMIND_STATICLIB"], lib_source = "@com_github_maxmind_libmaxminddb//:all", out_static_libs = select({ From fee7009de18c88433e16772a316851c98abb9448 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Wed, 13 Sep 2023 22:08:14 +0000 Subject: [PATCH 26/44] Fix format Signed-off-by: Kateryna Nezdolii --- bazel/foreign_cc/BUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bazel/foreign_cc/BUILD b/bazel/foreign_cc/BUILD index dece992e52d6..f61d795b76fd 100644 --- a/bazel/foreign_cc/BUILD +++ b/bazel/foreign_cc/BUILD @@ -580,11 +580,11 @@ envoy_cmake( "BUILD_SHARED_LIBS": "no", "BUILD_TESTING": "no", }, + defines = ["MAXMIND_STATICLIB"], env = select({ "//bazel:windows_x86_64": {"WIN32": "yes"}, "//conditions:default": {}, }), - defines = ["MAXMIND_STATICLIB"], lib_source = "@com_github_maxmind_libmaxminddb//:all", out_static_libs = select({ "//bazel:windows_x86_64": ["libmaxminddb.lib"], From 0f1e241923cbf09fd6740da15d9d4efe0d470eea Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Thu, 14 Sep 2023 14:34:12 +0000 Subject: [PATCH 27/44] Fix platform build atrefact name Signed-off-by: Kateryna Nezdolii --- bazel/foreign_cc/BUILD | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/bazel/foreign_cc/BUILD b/bazel/foreign_cc/BUILD index f61d795b76fd..bbaf818f13bd 100644 --- a/bazel/foreign_cc/BUILD +++ b/bazel/foreign_cc/BUILD @@ -581,13 +581,9 @@ envoy_cmake( "BUILD_TESTING": "no", }, defines = ["MAXMIND_STATICLIB"], - env = select({ - "//bazel:windows_x86_64": {"WIN32": "yes"}, - "//conditions:default": {}, - }), lib_source = "@com_github_maxmind_libmaxminddb//:all", out_static_libs = select({ - "//bazel:windows_x86_64": ["libmaxminddb.lib"], - "//conditions:default": ["libmaxminddb.a"], + "//bazel:windows_x86_64": ["maxminddb.lib"], + "//conditions:default": ["maxminddb.a"], }), ) From 589223c8b9fc79960756e432c1ce4e1a3b39a25d Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Fri, 15 Sep 2023 21:32:14 +0000 Subject: [PATCH 28/44] Fix CI checks Signed-off-by: Kateryna Nezdolii --- bazel/foreign_cc/BUILD | 2 +- source/extensions/geoip_providers/common/factory_base.h | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/bazel/foreign_cc/BUILD b/bazel/foreign_cc/BUILD index bbaf818f13bd..2aaf211c9493 100644 --- a/bazel/foreign_cc/BUILD +++ b/bazel/foreign_cc/BUILD @@ -584,6 +584,6 @@ envoy_cmake( lib_source = "@com_github_maxmind_libmaxminddb//:all", out_static_libs = select({ "//bazel:windows_x86_64": ["maxminddb.lib"], - "//conditions:default": ["maxminddb.a"], + "//conditions:default": ["libmaxminddb.a"], }), ) diff --git a/source/extensions/geoip_providers/common/factory_base.h b/source/extensions/geoip_providers/common/factory_base.h index d91686275093..9376192e8d66 100644 --- a/source/extensions/geoip_providers/common/factory_base.h +++ b/source/extensions/geoip_providers/common/factory_base.h @@ -25,10 +25,6 @@ template class FactoryBase : public Geolocation::GeoipProvid stat_prefix, context); } - ProtobufTypes::MessagePtr createEmptyConfigProto() override { - return std::make_unique(); - } - std::string name() const override { return name_; } std::string category() const override { return "envoy.geoip_providers"; } From b7aa80cf51cf54c74575b73e8a10057b3b1c9bc6 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Fri, 15 Sep 2023 22:33:42 +0000 Subject: [PATCH 29/44] Fix platform related error Signed-off-by: Kateryna Nezdolii --- source/extensions/geoip_providers/maxmind/geoip_provider.h | 1 + 1 file changed, 1 insertion(+) diff --git a/source/extensions/geoip_providers/maxmind/geoip_provider.h b/source/extensions/geoip_providers/maxmind/geoip_provider.h index 8cf394a591fe..29fb57285a5e 100644 --- a/source/extensions/geoip_providers/maxmind/geoip_provider.h +++ b/source/extensions/geoip_providers/maxmind/geoip_provider.h @@ -1,5 +1,6 @@ #pragma once +#include "envoy/common/platform.h" #include "envoy/extensions/geoip_providers/maxmind/v3/maxmind.pb.h" #include "envoy/geoip/geoip_provider_driver.h" From e33798a4e0f433413d0defdce1d30a9f0bd5cad9 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Mon, 18 Sep 2023 14:53:15 +0000 Subject: [PATCH 30/44] Add skip on windows Signed-off-by: Kateryna Nezdolii --- docs/root/configuration/http/http_filters/geoip_filter.rst | 1 + test/extensions/filters/http/geoip/BUILD | 2 ++ test/extensions/geoip_providers/maxmind/BUILD | 2 ++ 3 files changed, 5 insertions(+) diff --git a/docs/root/configuration/http/http_filters/geoip_filter.rst b/docs/root/configuration/http/http_filters/geoip_filter.rst index 3b8d83fd7c4a..1834b11db351 100644 --- a/docs/root/configuration/http/http_filters/geoip_filter.rst +++ b/docs/root/configuration/http/http_filters/geoip_filter.rst @@ -19,6 +19,7 @@ Configuration Geolocation Providers --------------------- Currently only `Maxmind ` geolocation provider is supported. +Please note that Maxmind geolocation provider is not yet supported on Windows. This provider should be configured with the type URL ``type.googleapis.com/envoy.extensions.geoip_providers.maxmind.v3.MaxMindConfig``. * :ref:`v3 API reference ` diff --git a/test/extensions/filters/http/geoip/BUILD b/test/extensions/filters/http/geoip/BUILD index 30a05b991c1d..e56c8b06cb4c 100644 --- a/test/extensions/filters/http/geoip/BUILD +++ b/test/extensions/filters/http/geoip/BUILD @@ -62,6 +62,8 @@ envoy_extension_cc_test( extension_names = [ "envoy.filters.http.geoip", ], + # Until Maxmind provider compilation is fixed on Windows + tags = ["skip_on_windows"], deps = [ "//source/extensions/filters/http/geoip:config", "//source/extensions/filters/http/geoip:geoip_filter_lib", diff --git a/test/extensions/geoip_providers/maxmind/BUILD b/test/extensions/geoip_providers/maxmind/BUILD index 3c018d0a945e..46f7bf2025fb 100644 --- a/test/extensions/geoip_providers/maxmind/BUILD +++ b/test/extensions/geoip_providers/maxmind/BUILD @@ -19,6 +19,7 @@ envoy_extension_cc_test( "//test/extensions/geoip_providers/maxmind/test_data:geolocation_databases", ], extension_names = ["envoy.geoip_providers.maxmind"], + tags = ["skip_on_windows"], deps = [ "//source/extensions/geoip_providers/maxmind:config", "//source/extensions/geoip_providers/maxmind:provider_impl", @@ -35,6 +36,7 @@ envoy_extension_cc_test( "//test/extensions/geoip_providers/maxmind/test_data:geolocation_databases", ], extension_names = ["envoy.geoip_providers.maxmind"], + tags = ["skip_on_windows"], deps = [ "//envoy/registry", "//source/extensions/geoip_providers/maxmind:config", From 7e570ca686327356ca9e52bee813751a58476211 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Mon, 18 Sep 2023 14:58:48 +0000 Subject: [PATCH 31/44] Update changelog Signed-off-by: Kateryna Nezdolii --- changelogs/current.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 964a4cd719cb..1455d21ce7bc 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -272,6 +272,9 @@ new_features: change: | Added the ability to specify a custom upstream local address selector using :ref:`local_address_selector:`. +- area: geoip + change: | + Added support for :ref:`Maxmind geolocation provider `. deprecated: - area: tracing From 60ef4ac373e78ae754107a7ac3a79d5c668bbd49 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Mon, 18 Sep 2023 20:11:35 +0000 Subject: [PATCH 32/44] Try one more thing Signed-off-by: Kateryna Nezdolii --- bazel/foreign_cc/BUILD | 5 +++-- docs/root/configuration/http/http_filters/geoip_filter.rst | 1 - test/extensions/filters/http/geoip/BUILD | 3 +-- test/extensions/geoip_providers/maxmind/BUILD | 2 -- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/bazel/foreign_cc/BUILD b/bazel/foreign_cc/BUILD index 125205fb7499..7f39e3cc3895 100644 --- a/bazel/foreign_cc/BUILD +++ b/bazel/foreign_cc/BUILD @@ -586,8 +586,9 @@ envoy_cmake( "CMAKE_BUILD_TYPE": "Release", "CMAKE_INSTALL_LIBDIR": "lib", "CMAKE_CXX_COMPILER_FORCED": "on", - "BUILD_SHARED_LIBS": "no", - "BUILD_TESTING": "no", + "BUILD_SHARED_LIBS": "off", + "BUILD_TESTING": "off", + "WIN32": "off", }, defines = ["MAXMIND_STATICLIB"], lib_source = "@com_github_maxmind_libmaxminddb//:all", diff --git a/docs/root/configuration/http/http_filters/geoip_filter.rst b/docs/root/configuration/http/http_filters/geoip_filter.rst index 1834b11db351..3b8d83fd7c4a 100644 --- a/docs/root/configuration/http/http_filters/geoip_filter.rst +++ b/docs/root/configuration/http/http_filters/geoip_filter.rst @@ -19,7 +19,6 @@ Configuration Geolocation Providers --------------------- Currently only `Maxmind ` geolocation provider is supported. -Please note that Maxmind geolocation provider is not yet supported on Windows. This provider should be configured with the type URL ``type.googleapis.com/envoy.extensions.geoip_providers.maxmind.v3.MaxMindConfig``. * :ref:`v3 API reference ` diff --git a/test/extensions/filters/http/geoip/BUILD b/test/extensions/filters/http/geoip/BUILD index e56c8b06cb4c..0f50e76b5bb9 100644 --- a/test/extensions/filters/http/geoip/BUILD +++ b/test/extensions/filters/http/geoip/BUILD @@ -62,8 +62,7 @@ envoy_extension_cc_test( extension_names = [ "envoy.filters.http.geoip", ], - # Until Maxmind provider compilation is fixed on Windows - tags = ["skip_on_windows"], + # Until Maxmind provider compilation is fixed on Windows. deps = [ "//source/extensions/filters/http/geoip:config", "//source/extensions/filters/http/geoip:geoip_filter_lib", diff --git a/test/extensions/geoip_providers/maxmind/BUILD b/test/extensions/geoip_providers/maxmind/BUILD index 46f7bf2025fb..3c018d0a945e 100644 --- a/test/extensions/geoip_providers/maxmind/BUILD +++ b/test/extensions/geoip_providers/maxmind/BUILD @@ -19,7 +19,6 @@ envoy_extension_cc_test( "//test/extensions/geoip_providers/maxmind/test_data:geolocation_databases", ], extension_names = ["envoy.geoip_providers.maxmind"], - tags = ["skip_on_windows"], deps = [ "//source/extensions/geoip_providers/maxmind:config", "//source/extensions/geoip_providers/maxmind:provider_impl", @@ -36,7 +35,6 @@ envoy_extension_cc_test( "//test/extensions/geoip_providers/maxmind/test_data:geolocation_databases", ], extension_names = ["envoy.geoip_providers.maxmind"], - tags = ["skip_on_windows"], deps = [ "//envoy/registry", "//source/extensions/geoip_providers/maxmind:config", From d48580795dd2ac578d94afd092f890e2f64e16f7 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Mon, 18 Sep 2023 20:24:51 +0000 Subject: [PATCH 33/44] cleanup Signed-off-by: Kateryna Nezdolii --- test/extensions/filters/http/geoip/BUILD | 1 - 1 file changed, 1 deletion(-) diff --git a/test/extensions/filters/http/geoip/BUILD b/test/extensions/filters/http/geoip/BUILD index 0f50e76b5bb9..30a05b991c1d 100644 --- a/test/extensions/filters/http/geoip/BUILD +++ b/test/extensions/filters/http/geoip/BUILD @@ -62,7 +62,6 @@ envoy_extension_cc_test( extension_names = [ "envoy.filters.http.geoip", ], - # Until Maxmind provider compilation is fixed on Windows. deps = [ "//source/extensions/filters/http/geoip:config", "//source/extensions/filters/http/geoip:geoip_filter_lib", From 9162b2376b271d1fe7af08cc6c0da7cf16be2800 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Mon, 18 Sep 2023 21:21:33 +0000 Subject: [PATCH 34/44] Turn off building for windows Signed-off-by: Kateryna Nezdolii --- bazel/foreign_cc/BUILD | 6 ++---- docs/root/configuration/http/http_filters/geoip_filter.rst | 1 + source/extensions/geoip_providers/maxmind/BUILD | 2 ++ test/extensions/filters/http/geoip/BUILD | 1 + test/extensions/geoip_providers/maxmind/BUILD | 2 ++ 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/bazel/foreign_cc/BUILD b/bazel/foreign_cc/BUILD index 7f39e3cc3895..588e10f76b94 100644 --- a/bazel/foreign_cc/BUILD +++ b/bazel/foreign_cc/BUILD @@ -592,8 +592,6 @@ envoy_cmake( }, defines = ["MAXMIND_STATICLIB"], lib_source = "@com_github_maxmind_libmaxminddb//:all", - out_static_libs = select({ - "//bazel:windows_x86_64": ["maxminddb.lib"], - "//conditions:default": ["libmaxminddb.a"], - }), + out_static_libs = ["ibmaxminddb.a"], + tags = ["skip_on_windows"], ) diff --git a/docs/root/configuration/http/http_filters/geoip_filter.rst b/docs/root/configuration/http/http_filters/geoip_filter.rst index 3b8d83fd7c4a..1834b11db351 100644 --- a/docs/root/configuration/http/http_filters/geoip_filter.rst +++ b/docs/root/configuration/http/http_filters/geoip_filter.rst @@ -19,6 +19,7 @@ Configuration Geolocation Providers --------------------- Currently only `Maxmind ` geolocation provider is supported. +Please note that Maxmind geolocation provider is not yet supported on Windows. This provider should be configured with the type URL ``type.googleapis.com/envoy.extensions.geoip_providers.maxmind.v3.MaxMindConfig``. * :ref:`v3 API reference ` diff --git a/source/extensions/geoip_providers/maxmind/BUILD b/source/extensions/geoip_providers/maxmind/BUILD index 26e0b2d435f9..17aa70d80a47 100644 --- a/source/extensions/geoip_providers/maxmind/BUILD +++ b/source/extensions/geoip_providers/maxmind/BUILD @@ -16,6 +16,7 @@ envoy_cc_extension( name = "config", srcs = ["config.cc"], hdrs = ["config.h"], + tags = ["skip_on_windows"], deps = [ ":provider_impl", "//envoy/geoip:geoip_provider_driver_interface", @@ -31,6 +32,7 @@ envoy_cc_library( srcs = ["geoip_provider.cc"], hdrs = ["geoip_provider.h"], external_deps = ["maxmind"], + tags = ["skip_on_windows"], deps = [ "//envoy/geoip:geoip_provider_driver_interface", "@envoy_api//envoy/extensions/geoip_providers/maxmind/v3:pkg_cc_proto", diff --git a/test/extensions/filters/http/geoip/BUILD b/test/extensions/filters/http/geoip/BUILD index 30a05b991c1d..b8deedc493b6 100644 --- a/test/extensions/filters/http/geoip/BUILD +++ b/test/extensions/filters/http/geoip/BUILD @@ -62,6 +62,7 @@ envoy_extension_cc_test( extension_names = [ "envoy.filters.http.geoip", ], + tags = ["skip_on_windows"], deps = [ "//source/extensions/filters/http/geoip:config", "//source/extensions/filters/http/geoip:geoip_filter_lib", diff --git a/test/extensions/geoip_providers/maxmind/BUILD b/test/extensions/geoip_providers/maxmind/BUILD index 3c018d0a945e..46f7bf2025fb 100644 --- a/test/extensions/geoip_providers/maxmind/BUILD +++ b/test/extensions/geoip_providers/maxmind/BUILD @@ -19,6 +19,7 @@ envoy_extension_cc_test( "//test/extensions/geoip_providers/maxmind/test_data:geolocation_databases", ], extension_names = ["envoy.geoip_providers.maxmind"], + tags = ["skip_on_windows"], deps = [ "//source/extensions/geoip_providers/maxmind:config", "//source/extensions/geoip_providers/maxmind:provider_impl", @@ -35,6 +36,7 @@ envoy_extension_cc_test( "//test/extensions/geoip_providers/maxmind/test_data:geolocation_databases", ], extension_names = ["envoy.geoip_providers.maxmind"], + tags = ["skip_on_windows"], deps = [ "//envoy/registry", "//source/extensions/geoip_providers/maxmind:config", From c6d0ae77f55f9777475b002da5da4981bf7a6e55 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Mon, 18 Sep 2023 21:39:41 +0000 Subject: [PATCH 35/44] Fix Signed-off-by: Kateryna Nezdolii --- bazel/foreign_cc/BUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bazel/foreign_cc/BUILD b/bazel/foreign_cc/BUILD index 588e10f76b94..07049f7e635b 100644 --- a/bazel/foreign_cc/BUILD +++ b/bazel/foreign_cc/BUILD @@ -592,6 +592,6 @@ envoy_cmake( }, defines = ["MAXMIND_STATICLIB"], lib_source = "@com_github_maxmind_libmaxminddb//:all", - out_static_libs = ["ibmaxminddb.a"], + out_static_libs = ["libmaxminddb.a"], tags = ["skip_on_windows"], ) From ef299ec2ed0b42e6e8cc77d2e07fc489c8ed6a69 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Wed, 20 Sep 2023 22:20:15 +0000 Subject: [PATCH 36/44] Exclude windows everywhere Signed-off-by: Kateryna Nezdolii --- docs/root/configuration/http/http_filters/geoip_filter.rst | 2 +- envoy/geoip/BUILD | 1 + source/extensions/filters/http/geoip/BUILD | 2 ++ source/extensions/geoip_providers/common/BUILD | 1 + test/extensions/filters/http/geoip/BUILD | 3 +++ 5 files changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/root/configuration/http/http_filters/geoip_filter.rst b/docs/root/configuration/http/http_filters/geoip_filter.rst index 1834b11db351..a75b6bcf1fad 100644 --- a/docs/root/configuration/http/http_filters/geoip_filter.rst +++ b/docs/root/configuration/http/http_filters/geoip_filter.rst @@ -8,6 +8,7 @@ Upon a successful lookup request will be enriched with the configured geolocatio In case the configured geolocation headers are present in the incoming request, they will be overriden by the filter. Geolocation filter emits stats for the number of the successful lookups and the number of total lookups. English language is used for the geolocation lookups, the result of the lookup will be UTF-8 encoded. +Please note that Geolocation filter and providers are not yet supported on Windows. Configuration ------------- @@ -19,7 +20,6 @@ Configuration Geolocation Providers --------------------- Currently only `Maxmind ` geolocation provider is supported. -Please note that Maxmind geolocation provider is not yet supported on Windows. This provider should be configured with the type URL ``type.googleapis.com/envoy.extensions.geoip_providers.maxmind.v3.MaxMindConfig``. * :ref:`v3 API reference ` diff --git a/envoy/geoip/BUILD b/envoy/geoip/BUILD index ae7016558550..05d323b6a06b 100644 --- a/envoy/geoip/BUILD +++ b/envoy/geoip/BUILD @@ -16,6 +16,7 @@ envoy_cc_extension( hdrs = [ "geoip_provider_driver.h", ], + tags = ["skip_on_windows"], deps = [ "//envoy/config:typed_config_interface", "//envoy/network:address_interface", diff --git a/source/extensions/filters/http/geoip/BUILD b/source/extensions/filters/http/geoip/BUILD index c0e8965e08be..7d47565f71d1 100644 --- a/source/extensions/filters/http/geoip/BUILD +++ b/source/extensions/filters/http/geoip/BUILD @@ -16,6 +16,7 @@ envoy_cc_library( name = "geoip_filter_lib", srcs = ["geoip_filter.cc"], hdrs = ["geoip_filter.h"], + tags = ["skip_on_windows"], deps = [ "//envoy/geoip:geoip_provider_driver_interface", "//envoy/http:filter_interface", @@ -33,6 +34,7 @@ envoy_cc_extension( name = "config", srcs = ["config.cc"], hdrs = ["config.h"], + tags = ["skip_on_windows"], deps = [ "//envoy/geoip:geoip_provider_driver_interface", "//source/common/config:utility_lib", diff --git a/source/extensions/geoip_providers/common/BUILD b/source/extensions/geoip_providers/common/BUILD index 2817c1847a76..2f68534edc7a 100644 --- a/source/extensions/geoip_providers/common/BUILD +++ b/source/extensions/geoip_providers/common/BUILD @@ -11,6 +11,7 @@ envoy_extension_package() envoy_cc_library( name = "factory_base_lib", hdrs = ["factory_base.h"], + tags = ["skip_on_windows"], deps = [ "//envoy/geoip:geoip_provider_driver_interface", "//source/common/config:utility_lib", diff --git a/test/extensions/filters/http/geoip/BUILD b/test/extensions/filters/http/geoip/BUILD index b8deedc493b6..c3cbb1827293 100644 --- a/test/extensions/filters/http/geoip/BUILD +++ b/test/extensions/filters/http/geoip/BUILD @@ -23,6 +23,7 @@ envoy_extension_cc_test( size = "small", srcs = ["config_test.cc"], extension_names = ["envoy.filters.http.geoip"], + tags = ["skip_on_windows"], deps = [ ":geoip_mocks", "//source/common/http:message_lib", @@ -39,6 +40,7 @@ envoy_extension_cc_test( size = "small", srcs = ["geoip_filter_test.cc"], extension_names = ["envoy.filters.http.geoip"], + tags = ["skip_on_windows"], deps = [ ":dummy_cc_proto", ":geoip_mocks", @@ -78,6 +80,7 @@ envoy_extension_cc_mock( name = "geoip_mocks", hdrs = ["mocks.h"], extension_names = ["envoy.filters.http.geoip"], + tags = ["skip_on_windows"], deps = [ ":dummy_cc_proto", "//envoy/geoip:geoip_provider_driver_interface", From d5fdbf7ec0027a74c1d1c0d800d636ae382f26b2 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Tue, 26 Sep 2023 22:35:19 +0000 Subject: [PATCH 37/44] Exclude option of building on non linux Signed-off-by: Kateryna Nezdolii --- bazel/foreign_cc/BUILD | 10 +++++++++- bazel/repositories.bzl | 2 +- source/extensions/geoip_providers/maxmind/BUILD | 5 ++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/bazel/foreign_cc/BUILD b/bazel/foreign_cc/BUILD index 07049f7e635b..8d1a0d6cd2d8 100644 --- a/bazel/foreign_cc/BUILD +++ b/bazel/foreign_cc/BUILD @@ -588,10 +588,18 @@ envoy_cmake( "CMAKE_CXX_COMPILER_FORCED": "on", "BUILD_SHARED_LIBS": "off", "BUILD_TESTING": "off", - "WIN32": "off", }, defines = ["MAXMIND_STATICLIB"], lib_source = "@com_github_maxmind_libmaxminddb//:all", out_static_libs = ["libmaxminddb.a"], tags = ["skip_on_windows"], ) + +envoy_cc_library( + name = "maxmind_linux", + srcs = [], + deps = select({ + "//bazel:linux": [":maxmind"], + "//conditions:default": [], + }), +) diff --git a/bazel/repositories.bzl b/bazel/repositories.bzl index f390467d1c39..f6734b74cd41 100644 --- a/bazel/repositories.bzl +++ b/bazel/repositories.bzl @@ -1401,5 +1401,5 @@ def _com_github_maxmind_libmaxminddb(): ) native.bind( name = "maxmind", - actual = "@envoy//bazel/foreign_cc:maxmind", + actual = "@envoy//bazel/foreign_cc:maxmind_linux", ) diff --git a/source/extensions/geoip_providers/maxmind/BUILD b/source/extensions/geoip_providers/maxmind/BUILD index 17aa70d80a47..468487413702 100644 --- a/source/extensions/geoip_providers/maxmind/BUILD +++ b/source/extensions/geoip_providers/maxmind/BUILD @@ -29,7 +29,10 @@ envoy_cc_extension( envoy_cc_library( name = "provider_impl", - srcs = ["geoip_provider.cc"], + srcs = select({ + "//bazel:linux": ["geoip_provider.cc"], + "//conditions:default": [], + }), hdrs = ["geoip_provider.h"], external_deps = ["maxmind"], tags = ["skip_on_windows"], From 3e8e2d79400f7fc2f56925cf26be38a9a5bf76c3 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Tue, 26 Sep 2023 22:41:03 +0000 Subject: [PATCH 38/44] Reset back the changelog until ci is fixed Signed-off-by: Kateryna Nezdolii --- changelogs/current.yaml | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 6a46a426a416..16026af122e4 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -63,6 +63,11 @@ minor_behavior_changes: Don't append the local address to ``x-forwarded-for`` header when sending an http (not gRPC) auth request. This behavior can be reverted by setting runtime flag ``envoy.reloadable_features.ext_authz_http_send_original_xff`` to false. +- area: ext_proc + change: | + Envoy will only take + :ref:`mode_override ` + when waiting for the header responses. It will be ignored if it is in other processing states. - area: outlier detection change: | Outlier detection will always respect max_ejection_percent now. @@ -90,6 +95,11 @@ minor_behavior_changes: The redis network filter :ref:`connection_rate_limit_per_sec ` must be greater than 0. A config that sets this value to 0 will be rejected. +- area: local_rate_limit + change: | + Added new configuration field :ref:`always_consume_default_token_bucket + ` + to allow for setting if default token bucket should be always consumed or only be consumed when there is no matching descriptor. bug_fixes: # *Changes expected to improve the state of the world and are unlikely to have negative effects* @@ -212,6 +222,10 @@ new_features: - area: extension_discovery_service change: | added metric listener.listener_stat.network_extension_config_missing to track closed connections due to missing config. +- area: lua + change: | + added :ref:`downstreamRemoteAddress() ` + method to the Stream info object API. - area: quic change: | added support for QUIC listener filters with ECDS support reusing the same config API @@ -264,6 +278,12 @@ new_features: change: | added :ref:`record_headers_received_time ` to control writing request and response headers received time in trace output. +- area: zookeeper + change: | + added support for emitting per opcode request bytes metrics via :ref:`enable_per_opcode_request_bytes_metrics + `. + added support for emitting per opcode response bytes metrics via :ref:`enable_per_opcode_response_bytes_metrics + `. - area: tls change: | added fallback :ref:`fallback @@ -276,14 +296,22 @@ new_features: change: | added the support to detect and send TCP RST for raw buffer socket based connections. This is currently supported on Linux only. It can be disabled by the runtime guard ``envoy_reloadable_features_detect_and_raise_rst_tcp_connection``. - - area: upstream change: | Added the ability to specify a custom upstream local address selector using :ref:`local_address_selector:`. -- area: geoip +- area: tap + change: | + added :ref:`record_downstream_connection ` + to control writing downstream connection address info in trace output. +- area: tracing change: | - Added support for :ref:`Maxmind geolocation provider `. + Added :ref:`spawn_upstream_span + ` + to control whether to create separate upstream span for upstream request. +- area: original_dst + change: | + added support for the internal listener address recovery using the original destination listener filter. deprecated: - area: tracing @@ -292,3 +320,10 @@ deprecated: - area: tracing change: | Opencensus is deprecated and will be removed at version 1.30, since the upstream project has been abandoned. +- area: tracing + change: | + :ref:`start_child_span ` + is deprecated by + :ref:`spawn_upstream_span + `. + Please use the new field to control whether to create separate upstream span for upstream request. From 9751802362385e6cafb34befcdcd6e6b9c8de4f4 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Wed, 27 Sep 2023 22:10:27 +0000 Subject: [PATCH 39/44] Exclude more stuff Signed-off-by: Kateryna Nezdolii --- source/extensions/geoip_providers/maxmind/BUILD | 5 ++++- test/extensions/filters/http/geoip/BUILD | 5 ++++- test/extensions/geoip_providers/maxmind/BUILD | 10 ++++++++-- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/source/extensions/geoip_providers/maxmind/BUILD b/source/extensions/geoip_providers/maxmind/BUILD index 468487413702..5d9f368bf64f 100644 --- a/source/extensions/geoip_providers/maxmind/BUILD +++ b/source/extensions/geoip_providers/maxmind/BUILD @@ -14,7 +14,10 @@ envoy_extension_package() envoy_cc_extension( name = "config", - srcs = ["config.cc"], + srcs = select({ + "//bazel:linux": ["config.cc"], + "//conditions:default": [], + }), hdrs = ["config.h"], tags = ["skip_on_windows"], deps = [ diff --git a/test/extensions/filters/http/geoip/BUILD b/test/extensions/filters/http/geoip/BUILD index c3cbb1827293..6e626debcd4b 100644 --- a/test/extensions/filters/http/geoip/BUILD +++ b/test/extensions/filters/http/geoip/BUILD @@ -57,7 +57,10 @@ envoy_extension_cc_test( envoy_extension_cc_test( name = "geoip_filter_integration_test", size = "large", - srcs = ["geoip_filter_integration_test.cc"], + srcs = select({ + "//bazel:linux": ["geoip_filter_integration_test.cc"], + "//conditions:default": [], + }), data = [ "//test/extensions/geoip_providers/maxmind/test_data:geolocation_databases", ], diff --git a/test/extensions/geoip_providers/maxmind/BUILD b/test/extensions/geoip_providers/maxmind/BUILD index 46f7bf2025fb..1757c2c53c8b 100644 --- a/test/extensions/geoip_providers/maxmind/BUILD +++ b/test/extensions/geoip_providers/maxmind/BUILD @@ -14,7 +14,10 @@ envoy_package() envoy_extension_cc_test( name = "config_test", size = "small", - srcs = ["config_test.cc"], + srcs = select({ + "//bazel:linux": ["config_test.cc"], + "//conditions:default": [], + }), data = [ "//test/extensions/geoip_providers/maxmind/test_data:geolocation_databases", ], @@ -31,7 +34,10 @@ envoy_extension_cc_test( envoy_extension_cc_test( name = "geoip_provider_test", size = "small", - srcs = ["geoip_provider_test.cc"], + srcs = select({ + "//bazel:linux": ["geoip_provider_test.cc"], + "//conditions:default": [], + }), data = [ "//test/extensions/geoip_providers/maxmind/test_data:geolocation_databases", ], From 6480a0a85669b1b1484481a554421529bdd29f2a Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Thu, 28 Sep 2023 14:19:26 +0000 Subject: [PATCH 40/44] Update changelog Signed-off-by: Kateryna Nezdolii --- changelogs/current.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/changelogs/current.yaml b/changelogs/current.yaml index 336ee98e2bae..a588598b4418 100644 --- a/changelogs/current.yaml +++ b/changelogs/current.yaml @@ -320,6 +320,9 @@ new_features: - area: original_dst change: | added support for the internal listener address recovery using the original destination listener filter. +- area: geoip + change: | + Added support for :ref:`Maxmind geolocation provider `. deprecated: From b3d0b153dd23fa03041dd31f3ba4e00b56f317c4 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Fri, 29 Sep 2023 20:43:15 +0000 Subject: [PATCH 41/44] Cleanup Signed-off-by: Kateryna Nezdolii --- test/extensions/filters/http/geoip/config_test.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/test/extensions/filters/http/geoip/config_test.cc b/test/extensions/filters/http/geoip/config_test.cc index da6c6db167cd..dd538804fe21 100644 --- a/test/extensions/filters/http/geoip/config_test.cc +++ b/test/extensions/filters/http/geoip/config_test.cc @@ -128,7 +128,6 @@ TEST(GeoipFilterConfigTest, GeoipFilterConfigUnknownProvider) { TestUtility::loadFromYaml(filter_config_yaml, filter_config); NiceMock context; - // EXPECT_CALL(context, messageValidationVisitor()); GeoipFilterFactory factory; EXPECT_THROW_WITH_MESSAGE( factory.createFilterFactoryFromProtoTyped(filter_config, "geoip", context), From c3ccfd99667f81ec353e640493977f47204752a0 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Mon, 2 Oct 2023 21:05:38 +0000 Subject: [PATCH 42/44] Add explanatory comment Signed-off-by: Kateryna Nezdolii --- test/extensions/geoip_providers/maxmind/test_data/BUILD | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/extensions/geoip_providers/maxmind/test_data/BUILD b/test/extensions/geoip_providers/maxmind/test_data/BUILD index 847abf30c889..7323b7eab2ac 100644 --- a/test/extensions/geoip_providers/maxmind/test_data/BUILD +++ b/test/extensions/geoip_providers/maxmind/test_data/BUILD @@ -7,6 +7,8 @@ licenses(["notice"]) # Apache 2 envoy_package() +# Copies of certain lighweight testing Maxmind databases are included into this filegroup: +# https://github.com/maxmind/MaxMind-DB/tree/main/test-data filegroup( name = "geolocation_databases", srcs = glob(["*.mmdb"]), From b2006b7373f1778ba17a284f96de2680674bdf3f Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Mon, 2 Oct 2023 21:28:48 +0000 Subject: [PATCH 43/44] Remove single backticks Signed-off-by: Kateryna Nezdolii --- .../geoip_providers/maxmind/v3/maxmind.proto | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto b/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto index 8cbcbc946ba1..3fc7f7c16082 100644 --- a/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto +++ b/api/envoy/extensions/geoip_providers/maxmind/v3/maxmind.proto @@ -17,23 +17,23 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; option (xds.annotations.v3.file_status).work_in_progress = true; // [#protodoc-title: MaxMind Geolocation Provider] -// Configuration for the MaxMind geolocation provider. +// MaxMind geolocation provider :ref:`configuration overview `. // At least one geolocation database path :ref:`city_db_path `, // :ref:`isp_db_path ` or // :ref:`anon_db_path ` must be configured. // [#extension: envoy.geoip_providers.maxmind] message MaxMindConfig { - // Full file path to the Maxmind city database, e.g. `/etc/GeoLite2-City.mmdb`. - // Database file is expected to have `.mmdb` extension. + // Full file path to the Maxmind city database, e.g. /etc/GeoLite2-City.mmdb. + // Database file is expected to have .mmdb extension. string city_db_path = 1 [(validate.rules).string = {pattern: "^$|^.*\\.mmdb$"}]; - // Full file path to the Maxmind ASN database, e.g. `/etc/GeoLite2-ASN.mmdb`. - // Database file is expected to have `.mmdb` extension. + // Full file path to the Maxmind ASN database, e.g. /etc/GeoLite2-ASN.mmdb. + // Database file is expected to have .mmdb extension. string isp_db_path = 2 [(validate.rules).string = {pattern: "^$|^.*\\.mmdb$"}]; - // Full file path to the Maxmind anonymous IP database, e.g. `/etc/GeoIP2-Anonymous-IP.mmdb`. - // Database file is expected to have `.mmdb` extension. + // Full file path to the Maxmind anonymous IP database, e.g. /etc/GeoIP2-Anonymous-IP.mmdb. + // Database file is expected to have .mmdb extension. string anon_db_path = 3 [(validate.rules).string = {pattern: "^$|^.*\\.mmdb$"}]; // Common provider configuration that specifies which geolocation headers will be populated with geolocation data. From b861cfc69a889f573d7e4a341306e50ebd789448 Mon Sep 17 00:00:00 2001 From: Kateryna Nezdolii Date: Tue, 3 Oct 2023 08:19:07 +0000 Subject: [PATCH 44/44] Update example Signed-off-by: Kateryna Nezdolii --- docs/root/configuration/http/http_filters/geoip_filter.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/root/configuration/http/http_filters/geoip_filter.rst b/docs/root/configuration/http/http_filters/geoip_filter.rst index a75b6bcf1fad..ff5e24f04964 100644 --- a/docs/root/configuration/http/http_filters/geoip_filter.rst +++ b/docs/root/configuration/http/http_filters/geoip_filter.rst @@ -36,8 +36,8 @@ Configuration example name: envoy.filters.http.geoip typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.geoip.v3.Geoip - use_xff: true - xff_num_trusted_hops: 1 + xff_config: + xff_num_trusted_hops: 1 provider: name: "envoy.geoip_providers.maxmind" typed_config: