Are you familiar with Watcher? What you want to do is possible but it will need to be customized to your environment.
In a general sense, I think the easiest way to do this is to run the watch at a regular interval (for example, once per day) and then for each device, count the number of distinct IP addresses. And if that device has more than 1 IP, then clearly it's changed.
So for example, here's the query part of the Watch:
"body": {
"size": 0,
"query": {
"bool": {
"filter": [
{
"range": {
"@timestamp": {
"gte": "now-1d/d",
"lte": "now"
}
}
}
]
}
},
"aggs": {
"devices": {
"terms": {
"field": "devicename",
"size": 10000
},
"aggs": {
"distinct_ips": {
"cardinality": {
"field": "ip"
}
},
"ips": {
"terms": {
"field": "ip",
"size": 10000
}
}
}
}
}
}
And in the condition part, you could do something like:
"condition": {
"script": """
return ctx.payload.aggregations.devices.buckets.stream().anyMatch(b -> b.distinct_ips.value > 1);
"""
},
As for the actions
section, you will need a transform
section to filter and flatten the results. Something like:
"transform": {
"script": """
return ctx.payload.aggregations.devices.buckets.stream().filter(b -> b.distinct_ips.value > 1).flatMap(b -> b.ips.buckets.stream().map(innerB -> ['ip':innerB.key,'device':b.key])).collect(Collectors.toList());
"""
},
And when you actually alert you can iterate thought the output with something similar to:
{{#ctx.payload._value}}
device:{{device}} has {{ip}}
{{/ctx.payload._value}}
to produce an output that looks like:
device:foo has 168.72.100.1
device:foo has 168.72.100.17
Full example here