Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 0 additions & 4 deletions agent_api/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,11 @@ def jacocoClassDirectories = files(sourceSets.main.output.files.collect {
})

dependencies {
implementation 'com.github.seancfoley:ipaddress:5.5.1'
implementation 'com.google.code.gson:gson:2.11.0'
implementation 'com.dylibso.chicory:runtime:1.7.5'
// Junixsocket imports :
implementation 'com.kohlschutter.junixsocket:junixsocket-core:2.10.1'
implementation 'com.kohlschutter.junixsocket:junixsocket-server:2.10.1'
// Subnets :
implementation 'com.github.seancfoley:ipaddress:5.3.3'

// For middleware :
compileOnly 'io.javalin:javalin:6.3.0'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public record RateLimitingConfig(long maxRequests, long windowSizeInMS, boolean
private final String route;
private final RateLimitingConfig rateLimiting;
private final List<String> allowedIPAddresses;
private transient volatile IPList allowedIPMatcher;
private final boolean graphql;
private final boolean forceProtectionOff;
public Endpoint(
Expand All @@ -21,6 +22,7 @@ public Endpoint(
this.method = method;
this.route = route;
this.allowedIPAddresses = allowedIPAddresses;
this.allowedIPMatcher = createIPList(allowedIPAddresses);
this.rateLimiting = new RateLimitingConfig(maxRequests, windowSizeMS, rateLimitingEnabled);
this.graphql = graphql;
this.forceProtectionOff = forceProtectionOff;
Expand All @@ -47,7 +49,14 @@ public boolean allowedIpAddressesEmpty() {
return allowedIPAddresses == null || allowedIPAddresses.size() == 0;
}

private IPList getOrCreateAllowedIPMatcher() {
if (allowedIPMatcher == null) {
this.allowedIPMatcher = createIPList(allowedIPAddresses);
}
return allowedIPMatcher;
}

public boolean isIpAllowed(String ip) {
return createIPList(allowedIPAddresses).matches(ip);
return getOrCreateAllowedIPMatcher().matches(ip);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,11 @@
import dev.aikido.agent_api.helpers.net.IPList;

import java.util.Collection;
import java.util.List;
import java.util.Set;

public final class IPListBuilder {
private IPListBuilder() {}

public static IPList createIPList(Collection<String> ips) {
IPList ipList = new IPList();
if (ips == null) {
return ipList; // Don't iterate over null.
}
for (String ip: ips) {
// Add ip address or subnet to IP list :
ipList.add(ip);
}

return ipList;
return new IPList(ips);
}
}
Original file line number Diff line number Diff line change
@@ -1,62 +1,28 @@
package dev.aikido.agent_api.helpers.net;

import inet.ipaddr.IPAddress;
import inet.ipaddr.IPAddressString;
import inet.ipaddr.format.util.DualIPv4v6Tries;
import java.util.Collection;
import java.util.List;

public class IPList {
private final DualIPv4v6Tries ipAddresses;
private IPMatcher matcher;

public IPList() {
this.ipAddresses = new DualIPv4v6Tries();
matcher = IPMatcher.from(List.of());
}

public IPList(Collection<String> ipAddresses) {
matcher = IPMatcher.from(ipAddresses);
}

public void add(String ipOrCIDR) {
if (ipOrCIDR == null) {
return; // Don't add if IP is null
}
IPAddress ip = new IPAddressString(ipOrCIDR).getAddress();
if (ip == null) {
return;
}
// Normalize IPv4-mapped IPv6 addresses to their IPv4 form so matching is symmetric.
if (ip.isIPv6() && ip.toIPv6().isIPv4Convertible()) {
IPAddress ipv4 = ip.toIPv6().toIPv4();
if (ipv4 != null) {
ip = ipv4;
}
}
if (ipOrCIDR.contains("/")) {
ip = ip.toPrefixBlock();
}
ipAddresses.add(ip);
matcher = matcher.add(ipOrCIDR);
}

public boolean matches(String ip) {
IPAddressString ipAddressString = new IPAddressString(ip);
if (!ipAddressString.isValid()) {
return false; // Invalid IP address
}
IPAddress ipAddress = ipAddressString.getAddress();

if (containsAddress(ipAddress)) {
return true;
}

// Also try the embedded IPv4 form for IPv4-mapped IPv6 addresses (e.g. ::ffff:23.45.67.89)
if (ipAddress.isIPv6() && ipAddress.toIPv6().isIPv4Convertible()) {
IPAddress ipv4 = ipAddress.toIPv6().toIPv4();
if (ipv4 != null && containsAddress(ipv4)) {
return true;
}
}
return false;
return matcher.matches(ip);
}

private boolean containsAddress(IPAddress ipAddress) {
return ipAddresses.elementContains(ipAddress);
}
public int length() {
return ipAddresses.size();
return matcher.size();
}
}
Loading
Loading