Enrich IP address with custom mmdb database using ingest pipeline

I have below document in elasticsearch

{
        "_index": "test",
        "_id": "guv6X5cBSvotes9C4gZS",
        "_score": 1,
        "_source": {
          "name": "Alice",
          "source.ip": "172.22.1.11"
        }
}

Now i have custom mmdb file . where i have mapping for these ip. In my mmdb file i have only single field i.e. user which tells about the ownership of ip.

Now how can i integrate this custom mmdb file in ingest pipeline.
I tried using geoip processor but it is giving error

Unsupported file

But mmdb file is correct because i used it in other application.
Please suggest some solution.

Hi @kuldeep_gupta

What your are trying with the geoip processor will not work ... period. The geoip processor expects certain fields etc

What you need to do is load the data you used to created the mmdb file into an index into elasticsearch and use the enrich processor.

Take a look at this, it describes the process this is the common approach for what you are trying to do

3 Likes

Hello @stephenb

As per you suggestion i tried this.

PUT user_mapping
{
  "mappings": {
    "properties": {
      "ip": { "type": "ip_range" },
      "user": { "type": "keyword" }
    }
  }
}

POST /_bulk
{"index": {"_index": "user_mapping", "_id": "user-doc-1"}}
{"ip": "172.16.104.16/28", "user": "Alice"}
{"index": {"_index": "user_mapping", "_id": "user-doc-2"}}
{"ip": "172.16.102.64/28", "user": "BoB"}

PUT _enrich/policy/user_enrichment_policy
{
  "match": {
    "indices": ["user_mapping"],
    "match_field": "ip",
    "enrich_fields": ["user"]
  }
}

POST _enrich/policy/user_enrichment_policy/_execute

POST /_ingest/pipeline/_simulate?verbose=true
{
  "pipeline": {
    "processors": [
      {
        "enrich": {
          "policy_name": "user_enrichment_policy",
          "field": "source.ip",
          "target_field": "enrich_user",
          "max_matches": "1",
          "ignore_failure": true,
          "on_failure": [
            {
              "set": {
                "field": "user_enrichment_error",
                "value": "User Enrichment Error {{ _ingest.on_failure_message }}"
              }
            }
          ]
        }
      }
    ],
    "on_failure": [
      {
        "set": {
          "field": "pipeline_failure.processor_type",
          "value": "{{ _ingest.on_failure_processor_type }}"
        }
      },
      {
        "set": {
          "field": "pipeline_failure.processor_tag",
          "value": "{{ _ingest.on_failure_processor_tag }}"
        }
      },
      {
        "set": {
          "field": "pipeline_failure.message",
          "value": "{{ _ingest.on_failure_message }}"
        }
      }
    ]
  },
  "docs": [
    {
      "_id": "GFk-X5cBY6REVzo7i86y",
      "_index": "processor_test",
      "_source": {
        "source": {
          "address": "172.16.104.17",
          "ip": "172.16.104.17"
        }
      }
    }
  ]
}


All of the above commands executed successfully.But on simulation i am getting below output

{
  "docs": [
    {
      "processor_results": [
        {
          "processor_type": "enrich",
          "status": "success",
          "doc": {
            "_index": "processor_test",
            "_id": "GFk-X5cBY6REVzo7i86y",
            "_version": "-3",
            "_source": {
              "source": {
                "address": "172.16.104.17",
                "ip": "172.16.104.17"
              }
            },
            "_ingest": {
              "pipeline": "_simulate_pipeline",
              "timestamp": "2025-06-12T14:00:20.381Z"
            }
          }
        }
      ]
    }
  ]
}

user_mapping index data is correct.
Please help!

It is not, you put this as the value 172.16.104.16/28, this is treat a keyword, so it will only match if the value from the other document it is exactly the same.

You need to add each individual ip as a document.

@leandrojmp IP Ranges Work... :slight_smile:

@kuldeep_gupta I am looking why yours is not

PUT /networks
{
  "mappings": {
    "properties": {
      "range": { "type": "ip_range" },
      "name": { "type": "keyword" },
      "department": { "type": "keyword" }
    }
  }
}

PUT /networks/_doc/1?refresh=wait_for
{
  "range": "10.100.0.0/16",
  "name": "production",
  "department": "OPS"
}

PUT /_enrich/policy/networks-policy
{
  "range": {
    "indices": "networks",
    "match_field": "range",
    "enrich_fields": ["name", "department"]
  }
}

POST /_enrich/policy/networks-policy/_execute?wait_for_completion=false


POST /_ingest/pipeline/_simulate?verbose=true
{
  "pipeline": {
    "processors": [
      {
        "enrich": {
          "description": "Add 'network' data based on 'ip'",
          "policy_name": "networks-policy",
          "field": "ip",
          "target_field": "network",
          "max_matches": "10"
        }
      }
    ]
  },
  "docs": [
    {
      "_source": {
        "ip": "10.100.34.1"
      }
    }
  ]
}

# results

{
  "docs": [
    {
      "processor_results": [
        {
          "processor_type": "enrich",
          "status": "success",
          "description": "Add 'network' data based on 'ip'",
          "doc": {
            "_index": "_index",
            "_version": "-3",
            "_id": "_id",
            "_source": {
              "ip": "10.100.34.1",
              "network": [
                {
                  "name": "production",
                  "range": "10.100.0.0/16",
                  "department": "OPS"
                }
              ]
            },
            "_ingest": {
              "pipeline": "_simulate_pipeline",
              "timestamp": "2025-06-12T15:31:50.895342675Z"
            }
          }
        }
      ]
    }
  ]
}

Didn't know, that last time I tested enrich was a long time ago, don't think this existed at the time.

It seems that it was implemented on 7.16, so if the OP version is not 7.16 or higher it may not work.

Correct but I am having issue with his example working... working on it

@kuldeep_gupta Exactly what version are you on?

Hi @stephenb
Thanks i got it now :melting_face:
It is working now. it was my silly mistake

@kuldeep_gupta Cool!!

Please show the correction for others... as they may try your code above

1 Like

I found it... you must use range as the enrich type to use ranges

Use the create enrich policy API to create an enrich policy with the range policy type. This policy must include:

PUT _enrich/policy/user_enrichment_policy
{
  "match": {  << WRONG
    "indices": ["user_mapping"],
    "match_field": "range",
    "enrich_fields": ["user"]
  }
}
PUT _enrich/policy/user_enrichment_policy
{
  "range": { <<< CORRECT
    "indices": ["user_mapping"],
    "match_field": "range",
    "enrich_fields": ["user"]
  }
}
1 Like

PUT _enrich/policy/user_enrichment_policy
{
  "range": {  <=== 
    "indices": ["user_mapping"],
    "match_field": "ip",
    "enrich_fields": ["user"]
  }
}

Need to define query type .
I changed it from match => range

BTW i am using 8.12.0 version

2 Likes