diff --git a/docs/changelog/108780.yaml b/docs/changelog/108780.yaml new file mode 100644 index 000000000000..40e66326e6b9 --- /dev/null +++ b/docs/changelog/108780.yaml @@ -0,0 +1,6 @@ +pr: 108780 +summary: Add `continent_code` support to the geoip processor +area: Ingest Node +type: enhancement +issues: + - 85820 diff --git a/docs/reference/ingest/processors/geoip.asciidoc b/docs/reference/ingest/processors/geoip.asciidoc index a8c6a8f647c7..e85165a28dcb 100644 --- a/docs/reference/ingest/processors/geoip.asciidoc +++ b/docs/reference/ingest/processors/geoip.asciidoc @@ -48,11 +48,11 @@ field instead. *Depends on what is available in `database_file`: * If a GeoLite2 City or GeoIP2 City database is used, then the following fields may be added under the `target_field`: `ip`, -`country_iso_code`, `country_name`, `continent_name`, `region_iso_code`, `region_name`, `city_name`, `timezone`, +`country_iso_code`, `country_name`, `continent_code`, `continent_name`, `region_iso_code`, `region_name`, `city_name`, `timezone`, and `location`. The fields actually added depend on what has been found and which properties were configured in `properties`. * If a GeoLite2 Country or GeoIP2 Country database is used, then the following fields may be added under the `target_field`: `ip`, -`country_iso_code`, `country_name` and `continent_name`. The fields actually added depend on what has been found and which properties -were configured in `properties`. +`country_iso_code`, `country_name`, `continent_code`, and `continent_name`. The fields actually added depend on what has been found +and which properties were configured in `properties`. * If the GeoLite2 ASN database is used, then the following fields may be added under the `target_field`: `ip`, `asn`, `organization_name` and `network`. The fields actually added depend on what has been found and which properties were configured in `properties`. @@ -67,10 +67,10 @@ The fields actually added depend on what has been found and which properties wer `organization_name`, `network`, `isp`, `isp_organization`, `mobile_country_code`, and `mobile_network_code`. The fields actually added depend on what has been found and which properties were configured in `properties`. * If the GeoIP2 Enterprise database is used, then the following fields may be added under the `target_field`: `ip`, -`country_iso_code`, `country_name`, `continent_name`, `region_iso_code`, `region_name`, `city_name`, `timezone`, `location`, `asn`, -`organization_name`, `network`, `hosting_provider`, `tor_exit_node`, `anonymous_vpn`, `anonymous`, `public_proxy`, `residential_proxy`, -`domain`, `isp`, `isp_organization`, `mobile_country_code`, `mobile_network_code`, `user_type`, and `connection_type`. The fields -actually added depend on what has been found and which properties were configured in `properties`. +`country_iso_code`, `country_name`, `continent_code`, `continent_name`, `region_iso_code`, `region_name`, `city_name`, `timezone`, +`location`, `asn`, `organization_name`, `network`, `hosting_provider`, `tor_exit_node`, `anonymous_vpn`, `anonymous`, `public_proxy`, +`residential_proxy`, `domain`, `isp`, `isp_organization`, `mobile_country_code`, `mobile_network_code`, `user_type`, and +`connection_type`. The fields actually added depend on what has been found and which properties were configured in `properties`. Here is an example that uses the default city database and adds the geographical information to the `geoip` field based on the `ip` field: diff --git a/modules/ingest-geoip/src/main/java/org/elasticsearch/ingest/geoip/Database.java b/modules/ingest-geoip/src/main/java/org/elasticsearch/ingest/geoip/Database.java index fe7f03529a42..aa8656dc14d9 100644 --- a/modules/ingest-geoip/src/main/java/org/elasticsearch/ingest/geoip/Database.java +++ b/modules/ingest-geoip/src/main/java/org/elasticsearch/ingest/geoip/Database.java @@ -30,6 +30,7 @@ enum Database { Set.of( Property.IP, Property.COUNTRY_ISO_CODE, + Property.CONTINENT_CODE, Property.COUNTRY_NAME, Property.CONTINENT_NAME, Property.REGION_ISO_CODE, @@ -49,7 +50,7 @@ enum Database { ) ), Country( - Set.of(Property.IP, Property.CONTINENT_NAME, Property.COUNTRY_NAME, Property.COUNTRY_ISO_CODE), + Set.of(Property.IP, Property.CONTINENT_CODE, Property.CONTINENT_NAME, Property.COUNTRY_NAME, Property.COUNTRY_ISO_CODE), Set.of(Property.CONTINENT_NAME, Property.COUNTRY_NAME, Property.COUNTRY_ISO_CODE) ), Asn( @@ -82,6 +83,7 @@ enum Database { Property.IP, Property.COUNTRY_ISO_CODE, Property.COUNTRY_NAME, + Property.CONTINENT_CODE, Property.CONTINENT_NAME, Property.REGION_ISO_CODE, Property.REGION_NAME, @@ -235,6 +237,7 @@ enum Database { IP, COUNTRY_ISO_CODE, COUNTRY_NAME, + CONTINENT_CODE, CONTINENT_NAME, REGION_ISO_CODE, REGION_NAME, diff --git a/modules/ingest-geoip/src/main/java/org/elasticsearch/ingest/geoip/GeoIpProcessor.java b/modules/ingest-geoip/src/main/java/org/elasticsearch/ingest/geoip/GeoIpProcessor.java index 8e7f5d575378..e39705a71f56 100644 --- a/modules/ingest-geoip/src/main/java/org/elasticsearch/ingest/geoip/GeoIpProcessor.java +++ b/modules/ingest-geoip/src/main/java/org/elasticsearch/ingest/geoip/GeoIpProcessor.java @@ -234,6 +234,12 @@ public final class GeoIpProcessor extends AbstractProcessor { geoData.put("country_name", countryName); } } + case CONTINENT_CODE -> { + String continentCode = continent.getCode(); + if (continentCode != null) { + geoData.put("continent_code", continentCode); + } + } case CONTINENT_NAME -> { String continentName = continent.getName(); if (continentName != null) { @@ -307,6 +313,12 @@ public final class GeoIpProcessor extends AbstractProcessor { geoData.put("country_name", countryName); } } + case CONTINENT_CODE -> { + String continentCode = continent.getCode(); + if (continentCode != null) { + geoData.put("continent_code", continentCode); + } + } case CONTINENT_NAME -> { String continentName = continent.getName(); if (continentName != null) { @@ -485,6 +497,12 @@ public final class GeoIpProcessor extends AbstractProcessor { geoData.put("country_name", countryName); } } + case CONTINENT_CODE -> { + String continentCode = continent.getCode(); + if (continentCode != null) { + geoData.put("continent_code", continentCode); + } + } case CONTINENT_NAME -> { String continentName = continent.getName(); if (continentName != null) { diff --git a/modules/ingest-geoip/src/test/java/org/elasticsearch/ingest/geoip/GeoIpProcessorFactoryTests.java b/modules/ingest-geoip/src/test/java/org/elasticsearch/ingest/geoip/GeoIpProcessorFactoryTests.java index 99330224451c..663ae1152246 100644 --- a/modules/ingest-geoip/src/test/java/org/elasticsearch/ingest/geoip/GeoIpProcessorFactoryTests.java +++ b/modules/ingest-geoip/src/test/java/org/elasticsearch/ingest/geoip/GeoIpProcessorFactoryTests.java @@ -196,7 +196,7 @@ public class GeoIpProcessorFactoryTests extends ESTestCase { equalTo( "[properties] illegal property value [" + asnProperty - + "]. valid values are [IP, COUNTRY_ISO_CODE, COUNTRY_NAME, CONTINENT_NAME]" + + "]. valid values are [IP, COUNTRY_ISO_CODE, COUNTRY_NAME, CONTINENT_CODE, CONTINENT_NAME]" ) ); } @@ -278,7 +278,7 @@ public class GeoIpProcessorFactoryTests extends ESTestCase { e.getMessage(), equalTo( "[properties] illegal property value [invalid]. valid values are [IP, COUNTRY_ISO_CODE, " - + "COUNTRY_NAME, CONTINENT_NAME, REGION_ISO_CODE, REGION_NAME, CITY_NAME, TIMEZONE, LOCATION]" + + "COUNTRY_NAME, CONTINENT_CODE, CONTINENT_NAME, REGION_ISO_CODE, REGION_NAME, CITY_NAME, TIMEZONE, LOCATION]" ) ); diff --git a/modules/ingest-geoip/src/test/java/org/elasticsearch/ingest/geoip/GeoIpProcessorTests.java b/modules/ingest-geoip/src/test/java/org/elasticsearch/ingest/geoip/GeoIpProcessorTests.java index 6eb4e9b1acb5..6276155d9f08 100644 --- a/modules/ingest-geoip/src/test/java/org/elasticsearch/ingest/geoip/GeoIpProcessorTests.java +++ b/modules/ingest-geoip/src/test/java/org/elasticsearch/ingest/geoip/GeoIpProcessorTests.java @@ -80,10 +80,11 @@ public class GeoIpProcessorTests extends ESTestCase { assertThat(ingestDocument.getSourceAndMetadata().get("source_field"), equalTo("8.8.8.8")); @SuppressWarnings("unchecked") Map geoData = (Map) ingestDocument.getSourceAndMetadata().get("target_field"); - assertThat(geoData.size(), equalTo(6)); + assertThat(geoData.size(), equalTo(7)); assertThat(geoData.get("ip"), equalTo("8.8.8.8")); assertThat(geoData.get("country_iso_code"), equalTo("US")); assertThat(geoData.get("country_name"), equalTo("United States")); + assertThat(geoData.get("continent_code"), equalTo("NA")); assertThat(geoData.get("continent_name"), equalTo("North America")); assertThat(geoData.get("timezone"), equalTo("America/Chicago")); Map location = new HashMap<>(); @@ -197,10 +198,11 @@ public class GeoIpProcessorTests extends ESTestCase { assertThat(ingestDocument.getSourceAndMetadata().get("source_field"), equalTo(address)); @SuppressWarnings("unchecked") Map geoData = (Map) ingestDocument.getSourceAndMetadata().get("target_field"); - assertThat(geoData.size(), equalTo(9)); + assertThat(geoData.size(), equalTo(10)); assertThat(geoData.get("ip"), equalTo(address)); assertThat(geoData.get("country_iso_code"), equalTo("US")); assertThat(geoData.get("country_name"), equalTo("United States")); + assertThat(geoData.get("continent_code"), equalTo("NA")); assertThat(geoData.get("continent_name"), equalTo("North America")); assertThat(geoData.get("region_iso_code"), equalTo("US-FL")); assertThat(geoData.get("region_name"), equalTo("Florida")); @@ -260,10 +262,11 @@ public class GeoIpProcessorTests extends ESTestCase { assertThat(ingestDocument.getSourceAndMetadata().get("source_field"), equalTo("82.170.213.79")); @SuppressWarnings("unchecked") Map geoData = (Map) ingestDocument.getSourceAndMetadata().get("target_field"); - assertThat(geoData.size(), equalTo(4)); + assertThat(geoData.size(), equalTo(5)); assertThat(geoData.get("ip"), equalTo("82.170.213.79")); assertThat(geoData.get("country_iso_code"), equalTo("NL")); assertThat(geoData.get("country_name"), equalTo("Netherlands")); + assertThat(geoData.get("continent_code"), equalTo("EU")); assertThat(geoData.get("continent_name"), equalTo("Europe")); } @@ -435,10 +438,11 @@ public class GeoIpProcessorTests extends ESTestCase { assertThat(ingestDocument.getSourceAndMetadata().get("source_field"), equalTo(ip)); @SuppressWarnings("unchecked") Map geoData = (Map) ingestDocument.getSourceAndMetadata().get("target_field"); - assertThat(geoData.size(), equalTo(23)); + assertThat(geoData.size(), equalTo(24)); assertThat(geoData.get("ip"), equalTo(ip)); assertThat(geoData.get("country_iso_code"), equalTo("US")); assertThat(geoData.get("country_name"), equalTo("United States")); + assertThat(geoData.get("continent_code"), equalTo("NA")); assertThat(geoData.get("continent_name"), equalTo("North America")); assertThat(geoData.get("region_iso_code"), equalTo("US-NY")); assertThat(geoData.get("region_name"), equalTo("New York")); diff --git a/modules/ingest-geoip/src/test/java/org/elasticsearch/ingest/geoip/MaxMindSupportTests.java b/modules/ingest-geoip/src/test/java/org/elasticsearch/ingest/geoip/MaxMindSupportTests.java index a465ae7cd799..eb958ef0ced8 100644 --- a/modules/ingest-geoip/src/test/java/org/elasticsearch/ingest/geoip/MaxMindSupportTests.java +++ b/modules/ingest-geoip/src/test/java/org/elasticsearch/ingest/geoip/MaxMindSupportTests.java @@ -75,6 +75,7 @@ public class MaxMindSupportTests extends ESTestCase { private static final Set CITY_SUPPORTED_FIELDS = Set.of( "city.name", + "continent.code", "continent.name", "country.isoCode", "country.name", @@ -88,7 +89,6 @@ public class MaxMindSupportTests extends ESTestCase { "city.confidence", "city.geoNameId", "city.names", - "continent.code", "continent.geoNameId", "continent.names", "country.confidence", @@ -156,9 +156,13 @@ public class MaxMindSupportTests extends ESTestCase { private static final Set CONNECT_TYPE_SUPPORTED_FIELDS = Set.of("connectionType"); private static final Set CONNECT_TYPE_UNSUPPORTED_FIELDS = Set.of("ipAddress", "network"); - private static final Set COUNTRY_SUPPORTED_FIELDS = Set.of("continent.name", "country.isoCode", "country.name"); - private static final Set COUNTRY_UNSUPPORTED_FIELDS = Set.of( + private static final Set COUNTRY_SUPPORTED_FIELDS = Set.of( + "continent.name", + "country.isoCode", "continent.code", + "country.name" + ); + private static final Set COUNTRY_UNSUPPORTED_FIELDS = Set.of( "continent.geoNameId", "continent.names", "country.confidence", @@ -209,6 +213,7 @@ public class MaxMindSupportTests extends ESTestCase { private static final Set ENTERPRISE_SUPPORTED_FIELDS = Set.of( "city.name", + "continent.code", "continent.name", "country.isoCode", "country.name", @@ -238,7 +243,6 @@ public class MaxMindSupportTests extends ESTestCase { "city.confidence", "city.geoNameId", "city.names", - "continent.code", "continent.geoNameId", "continent.names", "country.confidence",