Skip to content

Commit 0dd1342

Browse files
Merge pull request #173 from AikidoSec/fix-monitoring-ip-issues
IP/UA Stats: Clean up
2 parents 841ad6b + 2f34f4d commit 0dd1342

File tree

5 files changed

+60
-26
lines changed

5 files changed

+60
-26
lines changed

agent_api/src/main/java/dev/aikido/agent_api/collectors/WebRequestCollector.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import dev.aikido.agent_api.context.Context;
55
import dev.aikido.agent_api.context.ContextObject;
66
import dev.aikido.agent_api.context.RouteMetadata;
7+
import dev.aikido.agent_api.storage.ServiceConfigStore;
78
import dev.aikido.agent_api.storage.ServiceConfiguration;
89
import dev.aikido.agent_api.storage.statistics.StatisticsStore;
910

@@ -43,11 +44,11 @@ public static Res report(ContextObject newContext) {
4344
if (endpointAllowlistRes != null)
4445
return endpointAllowlistRes;
4546

46-
Res blockedIpsRes = checkBlockedIps(newContext.getRemoteAddress(), config);
47+
Res blockedIpsRes = checkBlockedIps(newContext.getRemoteAddress());
4748
if (blockedIpsRes != null)
4849
return blockedIpsRes;
4950

50-
return checkBlockedUserAgents(newContext.getHeader("user-agent"), config);
51+
return checkBlockedUserAgents(newContext.getHeader("user-agent"));
5152
}
5253

5354
private static Res checkEndpointAllowlist(RouteMetadata routeMetadata, String remoteAddress, ServiceConfiguration config) {
@@ -60,8 +61,8 @@ private static Res checkEndpointAllowlist(RouteMetadata routeMetadata, String re
6061
return null; // not blocked
6162
}
6263

63-
private static Res checkBlockedIps(String remoteAddress, ServiceConfiguration config) {
64-
ServiceConfiguration.BlockedResult ipBlocked = config.isIpBlocked(remoteAddress);
64+
private static Res checkBlockedIps(String remoteAddress) {
65+
ServiceConfiguration.BlockedResult ipBlocked = ServiceConfigStore.isIpBlocked(remoteAddress);
6566
if (ipBlocked.blocked()) {
6667
String msg = "Your IP address is blocked. Reason: " + ipBlocked.description();
6768
msg += " (Your IP: " + remoteAddress + ")";
@@ -70,11 +71,11 @@ private static Res checkBlockedIps(String remoteAddress, ServiceConfiguration co
7071
return null; // not blocked
7172
}
7273

73-
private static Res checkBlockedUserAgents(String userAgent, ServiceConfiguration config) {
74+
private static Res checkBlockedUserAgents(String userAgent) {
7475
if (userAgent == null || userAgent.isEmpty()) {
7576
return null; // not blocked
7677
}
77-
if (config.isBlockedUserAgent(userAgent)) {
78+
if (ServiceConfigStore.isBlockedUserAgent(userAgent)) {
7879
String msg = "You are not allowed to access this resource because you have been identified as a bot.";
7980
return new Res(msg, 403);
8081
}

agent_api/src/main/java/dev/aikido/agent_api/storage/ServiceConfigStore.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import dev.aikido.agent_api.helpers.logging.LogManager;
66
import dev.aikido.agent_api.helpers.logging.Logger;
77

8-
import java.util.Optional;
98
import java.util.concurrent.locks.ReentrantReadWriteLock;
109

1110
public final class ServiceConfigStore {
@@ -24,6 +23,24 @@ public static ServiceConfiguration getConfig() {
2423
}
2524
}
2625

26+
public static ServiceConfiguration.BlockedResult isIpBlocked(String ip) {
27+
mutex.readLock().lock();
28+
try {
29+
return config.isIpBlocked(ip);
30+
} finally {
31+
mutex.readLock().unlock();
32+
}
33+
}
34+
35+
public static boolean isBlockedUserAgent(String userAgent) {
36+
mutex.readLock().lock();
37+
try {
38+
return config.isBlockedUserAgent(userAgent);
39+
} finally {
40+
mutex.readLock().unlock();
41+
}
42+
}
43+
2744
public static void updateFromAPIResponse(APIResponse apiResponse) {
2845
mutex.writeLock().lock();
2946
try {

agent_api/src/main/java/dev/aikido/agent_api/storage/ServiceConfiguration.java

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,15 +91,20 @@ public BlockedResult isIpBlocked(String ip) {
9191
return new BlockedResult(true, "not in allowlist");
9292
}
9393

94-
// Check for blocked ip addresses
94+
// Check for monitored IP addresses
95+
List<ParsedFirewallLists.Match> monitoredIpMatches = firewallLists.matchMonitoredIps(ip);
96+
for (ParsedFirewallLists.Match monitoredMatch: monitoredIpMatches) {
97+
StatisticsStore.incrementIpHits(monitoredMatch.key());
98+
}
99+
100+
// Check for blocked IP addresses
95101
List<ParsedFirewallLists.Match> blockedIpMatches = firewallLists.matchBlockedIps(ip);
96-
for (ParsedFirewallLists.Match match : blockedIpMatches) {
97-
StatisticsStore.incrementIpHits(match.key());
102+
for (ParsedFirewallLists.Match blockedMatch : blockedIpMatches) {
103+
StatisticsStore.incrementIpHits(blockedMatch.key());
98104
}
99-
for (ParsedFirewallLists.Match match : firewallLists.matchBlockedIps(ip)) {
100-
if (match.block()) {
101-
return new BlockedResult(true, match.description());
102-
}
105+
if (!blockedIpMatches.isEmpty()) {
106+
String description = blockedIpMatches.get(0).description();
107+
return new BlockedResult(true, description);
103108
}
104109

105110
return new BlockedResult(false, null);

agent_api/src/main/java/dev/aikido/agent_api/storage/service_configuration/ParsedFirewallLists.java

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
public class ParsedFirewallLists {
1414
private final List<IPEntry> blockedIps = new ArrayList<>();
15+
private final List<IPEntry> monitoredIps = new ArrayList<>();
1516
private final List<IPEntry> allowedIps = new ArrayList<>();
1617
private final List<UADetailsEntry> uaDetails = new ArrayList<>();
1718
private Pattern blockedUserAgents = null;
@@ -25,12 +26,23 @@ public List<Match> matchBlockedIps(String ip) {
2526
List<Match> matches = new ArrayList<>();
2627
for (IPEntry entry : this.blockedIps) {
2728
if (entry.ips().matches(ip)) {
28-
matches.add(new Match(entry.key(), !entry.monitor(), entry.description()));
29+
matches.add(new Match(entry.key(), entry.description()));
2930
}
3031
}
3132
return matches;
3233
}
3334

35+
public List<Match> matchMonitoredIps(String ip) {
36+
List<Match> matches = new ArrayList<>();
37+
for (IPEntry entry : this.monitoredIps) {
38+
if (entry.ips().matches(ip)) {
39+
matches.add(new Match(entry.key(), entry.description()));
40+
}
41+
}
42+
return matches;
43+
}
44+
45+
3446
// returns true if one or more matches has been found with allowlist.
3547
public boolean matchesAllowedIps(String ip) {
3648
if (this.allowedIps.isEmpty()) {
@@ -67,31 +79,30 @@ public UABlockedResult matchBlockedUserAgents(String userAgent) {
6779
}
6880

6981
public void update(ReportingApi.APIListsResponse response) {
70-
blockedIps.clear();
7182
updateBlockedIps(response.blockedIPAddresses());
7283
updateMonitoredIps(response.monitoredIPAddresses());
73-
7484
updateAllowedIps(response.allowedIPAddresses());
75-
7685
updateBlockedAndMonitoredUAs(response.blockedUserAgents(), response.monitoredUserAgents());
7786
updateUADetails(response.userAgentDetails());
7887
}
7988

8089
public void updateBlockedIps(List<ReportingApi.ListsResponseEntry> blockedIpLists) {
90+
this.blockedIps.clear();
8191
if (blockedIpLists == null)
8292
return;
8393
for (ReportingApi.ListsResponseEntry entry : blockedIpLists) {
8494
IPList ipList = createIPList(entry.ips());
85-
blockedIps.add(new IPEntry(/* monitor */ false, entry.key(), entry.source(), entry.description(), ipList));
95+
this.blockedIps.add(new IPEntry(entry.key(), entry.source(), entry.description(), ipList));
8696
}
8797
}
8898

8999
public void updateMonitoredIps(List<ReportingApi.ListsResponseEntry> monitoredIpsList) {
100+
this.monitoredIps.clear();
90101
if (monitoredIpsList == null)
91102
return;
92103
for (ReportingApi.ListsResponseEntry entry : monitoredIpsList) {
93104
IPList ipList = createIPList(entry.ips());
94-
blockedIps.add(new IPEntry(/* monitor */ true, entry.key(), entry.source(), entry.description(), ipList));
105+
this.monitoredIps.add(new IPEntry(entry.key(), entry.source(), entry.description(), ipList));
95106
}
96107
}
97108

@@ -101,8 +112,7 @@ public void updateAllowedIps(List<ReportingApi.ListsResponseEntry> allowedIpList
101112
return;
102113
for (ReportingApi.ListsResponseEntry entry : allowedIpLists) {
103114
IPList ipList = createIPList(entry.ips());
104-
boolean shouldMonitor = false; // we don't monitor allowed ips
105-
allowedIps.add(new IPEntry(shouldMonitor, entry.key(), entry.source(), entry.description(), ipList));
115+
allowedIps.add(new IPEntry(entry.key(), entry.source(), entry.description(), ipList));
106116
}
107117
}
108118

@@ -124,13 +134,13 @@ public void updateBlockedAndMonitoredUAs(String blockedUAs, String monitoredUAs)
124134
}
125135

126136

127-
public record Match(String key, boolean block, String description) {
137+
public record Match(String key, String description) {
128138
}
129139

130140
public record UABlockedResult(boolean block, List<String> matchedKeys) {
131141
}
132142

133-
private record IPEntry(boolean monitor, String key, String source, String description, IPList ips) {
143+
private record IPEntry(String key, String source, String description, IPList ips) {
134144
}
135145

136146
private record UADetailsEntry(String key, Pattern pattern) {

agent_api/src/test/java/background/cloud/ReportingAPITest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,14 @@ public void testParsedListsResponse() {
109109
assertEquals(1, matches.size());
110110
assertEquals("geo-1", matches.get(0).key());
111111
assertEquals("geo restrictions", matches.get(0).description());
112-
assertTrue(matches.get(0).block());
113112

114113
matches = parsed.matchBlockedIps("5.6.7.8");
114+
assertEquals(0, matches.size());
115+
116+
matches = parsed.matchMonitoredIps("5.6.7.8");
115117
assertEquals(1, matches.size());
116118
assertEquals("geo-2", matches.get(0).key());
117119
assertEquals("should not be blocked", matches.get(0).description());
118-
assertFalse(matches.get(0).block());
119120

120121
matches = parsed.matchBlockedIps("2.3.4.5");
121122
assertEquals(0, matches.size());

0 commit comments

Comments
 (0)