Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
9637798
Good place to checkpoint
MattAlp Oct 2, 2025
3129e57
Fixed codegen bug, completed first pass of Network Direction ESQL fun…
MattAlp Oct 2, 2025
13fe69d
Further refactoring back to keyword return type
MattAlp Oct 4, 2025
07b6c8f
Duplicate tests from NetworkDirectionProcessor into NetworkDirectionu…
MattAlp Oct 6, 2025
319552e
Change how extraction of IP from BytesRef is performed
MattAlp Oct 6, 2025
1fd1e51
Copied over NetworkDirectionUtils tests to the NetworkDirection funct…
MattAlp Oct 6, 2025
08647b2
Add remaining test types
MattAlp Oct 6, 2025
c4196a2
Address the buffer re-use bug; get tests to pass
MattAlp Oct 6, 2025
295931a
Remove to-dos following code review
MattAlp Oct 7, 2025
584de17
Extend csv tests and register as an example
MattAlp Oct 7, 2025
1502b71
Docs and CSV test, singular
MattAlp Oct 7, 2025
737eae0
Tests work great now
MattAlp Oct 7, 2025
b80ef49
Change up some of the CSV tests
MattAlp Oct 7, 2025
5e24512
Change up some of the CSV tests pt. 2
MattAlp Oct 7, 2025
f98b9e0
Spotless gets it done
MattAlp Oct 7, 2025
0e7ba55
Update docs/changelog/136133.yaml
MattAlp Oct 7, 2025
e1b1e67
Merge branch 'main' into network_direction_esql_function
MattAlp Oct 7, 2025
463cd79
[CI] Auto commit changes from spotless
Oct 7, 2025
d810ecf
Fix sorting of expected outputs for multicluster CSV IP run
MattAlp Oct 8, 2025
af8038c
Cleaning up checkstyle violations
MattAlp Oct 8, 2025
d788b52
Modify function usage example in CSV tests
MattAlp Oct 8, 2025
22d301a
Update test formatting as well
MattAlp Oct 8, 2025
095106c
Create test case creaion helper method
MattAlp Oct 14, 2025
8c400af
[CI] Auto commit changes from spotless
Oct 14, 2025
925d793
Change caps for netdir func
MattAlp Oct 14, 2025
c17a755
Update NetworkDirection exception handling & add new CSV tests
MattAlp Oct 14, 2025
dab3921
Correct usage of forbidden APIs
MattAlp Oct 14, 2025
24d8f30
Add netdir alias for network_direction ESQL function
MattAlp Oct 14, 2025
a766c77
Merge branch 'main' into network_direction_esql_function
MattAlp Oct 14, 2025
6a34869
[CI] Auto commit changes from spotless
Oct 14, 2025
18e39e6
Stragglers
MattAlp Oct 14, 2025
ec37f64
Specify that function is in preview mode
MattAlp Oct 21, 2025
9d125a1
Merge branch 'main' into network_direction_esql_function
MattAlp Oct 21, 2025
756fc5a
Change import
MattAlp Oct 22, 2025
432ab46
Merge branch 'main' into network_direction_esql_function
MattAlp Oct 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/changelog/136133.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pr: 136133
summary: Implement `network_direction` function
area: ES|QL
type: enhancement
issues: []

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -10,47 +10,25 @@
package org.elasticsearch.ingest.common;

import org.elasticsearch.cluster.metadata.ProjectId;
import org.elasticsearch.common.network.CIDRUtils;
import org.elasticsearch.common.network.InetAddresses;
import org.elasticsearch.common.network.NetworkDirectionUtils;
import org.elasticsearch.ingest.AbstractProcessor;
import org.elasticsearch.ingest.ConfigurationUtils;
import org.elasticsearch.ingest.IngestDocument;
import org.elasticsearch.ingest.Processor;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.script.TemplateScript;

import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import static org.elasticsearch.ingest.ConfigurationUtils.newConfigurationException;
import static org.elasticsearch.ingest.ConfigurationUtils.readBooleanProperty;

public class NetworkDirectionProcessor extends AbstractProcessor {
static final byte[] UNDEFINED_IP4 = new byte[] { 0, 0, 0, 0 };
static final byte[] UNDEFINED_IP6 = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
static final byte[] BROADCAST_IP4 = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };

public static final String TYPE = "network_direction";

public static final String DIRECTION_INTERNAL = "internal";
public static final String DIRECTION_EXTERNAL = "external";
public static final String DIRECTION_INBOUND = "inbound";
public static final String DIRECTION_OUTBOUND = "outbound";

private static final String LOOPBACK_NAMED_NETWORK = "loopback";
private static final String GLOBAL_UNICAST_NAMED_NETWORK = "global_unicast";
private static final String UNICAST_NAMED_NETWORK = "unicast";
private static final String LINK_LOCAL_UNICAST_NAMED_NETWORK = "link_local_unicast";
private static final String INTERFACE_LOCAL_NAMED_NETWORK = "interface_local_multicast";
private static final String LINK_LOCAL_MULTICAST_NAMED_NETWORK = "link_local_multicast";
private static final String MULTICAST_NAMED_NETWORK = "multicast";
private static final String UNSPECIFIED_NAMED_NETWORK = "unspecified";
private static final String PRIVATE_NAMED_NETWORK = "private";
private static final String PUBLIC_NAMED_NETWORK = "public";

private final String sourceIpField;
private final String destinationIpField;
private final String targetField;
Expand Down Expand Up @@ -140,96 +118,10 @@ private String getDirection(IngestDocument d) throws Exception {
return null;
}

boolean sourceInternal = isInternal(networks, sourceIpAddrString);
boolean destinationInternal = isInternal(networks, destIpAddrString);

if (sourceInternal && destinationInternal) {
return DIRECTION_INTERNAL;
}
if (sourceInternal) {
return DIRECTION_OUTBOUND;
}
if (destinationInternal) {
return DIRECTION_INBOUND;
}
return DIRECTION_EXTERNAL;
}

private static boolean isInternal(List<String> networks, String ip) {
for (String network : networks) {
if (inNetwork(ip, network)) {
return true;
}
}
return false;
}

private static boolean inNetwork(String ip, String network) {
InetAddress address = InetAddresses.forString(ip);
return switch (network) {
case LOOPBACK_NAMED_NETWORK -> isLoopback(address);
case GLOBAL_UNICAST_NAMED_NETWORK, UNICAST_NAMED_NETWORK -> isUnicast(address);
case LINK_LOCAL_UNICAST_NAMED_NETWORK -> isLinkLocalUnicast(address);
case INTERFACE_LOCAL_NAMED_NETWORK -> isInterfaceLocalMulticast(address);
case LINK_LOCAL_MULTICAST_NAMED_NETWORK -> isLinkLocalMulticast(address);
case MULTICAST_NAMED_NETWORK -> isMulticast(address);
case UNSPECIFIED_NAMED_NETWORK -> isUnspecified(address);
case PRIVATE_NAMED_NETWORK -> isPrivate(ip);
case PUBLIC_NAMED_NETWORK -> isPublic(ip);
default -> CIDRUtils.isInRange(ip, network);
};
}

private static boolean isLoopback(InetAddress ip) {
return ip.isLoopbackAddress();
}

private static boolean isUnicast(InetAddress ip) {
return Arrays.equals(ip.getAddress(), BROADCAST_IP4) == false
&& isUnspecified(ip) == false
&& isLoopback(ip) == false
&& isMulticast(ip) == false
&& isLinkLocalUnicast(ip) == false;
}

private static boolean isLinkLocalUnicast(InetAddress ip) {
return ip.isLinkLocalAddress();
}

private static boolean isInterfaceLocalMulticast(InetAddress ip) {
return ip.isMCNodeLocal();
}

private static boolean isLinkLocalMulticast(InetAddress ip) {
return ip.isMCLinkLocal();
}

private static boolean isMulticast(InetAddress ip) {
return ip.isMulticastAddress();
}

private static boolean isUnspecified(InetAddress ip) {
var address = ip.getAddress();
return Arrays.equals(UNDEFINED_IP4, address) || Arrays.equals(UNDEFINED_IP6, address);
}

private static boolean isPrivate(String ip) {
return CIDRUtils.isInRange(ip, "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16", "fd00::/8");
}

private static boolean isPublic(String ip) {
return isLocalOrPrivate(ip) == false;
}
boolean sourceInternal = NetworkDirectionUtils.isInternal(networks, sourceIpAddrString);
boolean destinationInternal = NetworkDirectionUtils.isInternal(networks, destIpAddrString);

private static boolean isLocalOrPrivate(String ip) {
var address = InetAddresses.forString(ip);
return isPrivate(ip)
|| isLoopback(address)
|| isUnspecified(address)
|| isLinkLocalUnicast(address)
|| isLinkLocalMulticast(address)
|| isInterfaceLocalMulticast(address)
|| Arrays.equals(address.getAddress(), BROADCAST_IP4);
return NetworkDirectionUtils.getDirection(sourceInternal, destinationInternal);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ public void testInvalidNetwork() throws Exception {
assertThat(e.getMessage(), containsString("'invalid' is not an IP string literal."));
}

// These tests copy the data from the NetworkDirectionUtils tests
public void testCIDR() throws Exception {
testNetworkDirectionProcessor(buildEvent("10.0.1.1", "192.168.1.2"), new String[] { "10.0.0.0/8" }, "outbound");
testNetworkDirectionProcessor(buildEvent("192.168.1.2", "10.0.1.1"), new String[] { "10.0.0.0/8" }, "inbound");
Expand Down
Loading
Loading