Skip to content

Commit 8401e48

Browse files
authored
Merge pull request #194 from AikidoSec/allow-country
Added support for allowed lists
2 parents 02d574a + dd2b315 commit 8401e48

File tree

28 files changed

+276
-141
lines changed

28 files changed

+276
-141
lines changed

.github/workflows/build.yml

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
build_libs:
1414
runs-on: ${{ matrix.os }}
1515
container:
16-
image: ubuntu:20.04
16+
image: ubuntu:22.04
1717
strategy:
1818
matrix:
1919
os: [ ubuntu-24.04 ]
@@ -92,7 +92,7 @@ jobs:
9292
9393
build_php_extension:
9494
runs-on: ${{ matrix.os }}
95-
container: ubuntu:20.04
95+
container: ubuntu:22.04
9696
strategy:
9797
matrix:
9898
php_version: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4']
@@ -123,7 +123,7 @@ jobs:
123123
echo "AIKIDO_ARTIFACT=aikido-extension-php-${{ matrix.php_version }}" >> $GITHUB_ENV
124124
125125
- name: Setup PHP
126-
uses: shivammathur/setup-php@cf4cade2721270509d5b1c766ab3549210a39a2a # v2 # v2
126+
uses: shivammathur/setup-php@27853eb8b46dc01c33bf9fef67d98df2683c3be2 # v2
127127
with:
128128
php-version: ${{ matrix.php_version }}
129129
extensions: curl
@@ -163,7 +163,7 @@ jobs:
163163
build_rpm:
164164
runs-on: ${{ matrix.os }}
165165
container:
166-
image: centos:8
166+
image: quay.io/centos/centos:stream9
167167
strategy:
168168
matrix:
169169
os: ['ubuntu-24.04']
@@ -175,9 +175,6 @@ jobs:
175175

176176
- name: Install rpmdevtools
177177
run: |
178-
cd /etc/yum.repos.d/
179-
sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
180-
sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
181178
yum -y install epel-release
182179
yum -y install rpmdevtools
183180
yum -y install jq
@@ -260,7 +257,7 @@ jobs:
260257
build_deb:
261258
runs-on: ${{ matrix.os }}
262259
container:
263-
image: ubuntu:20.04
260+
image: ubuntu:22.04
264261
strategy:
265262
matrix:
266263
os: [ ubuntu-24.04 ]
@@ -328,11 +325,11 @@ jobs:
328325
test_php_centos:
329326
runs-on: ${{ matrix.os }}
330327
container:
331-
image: centos:8
328+
image: quay.io/centos/centos:stream9
332329
needs: [ build_rpm ]
333330
strategy:
334331
matrix:
335-
php_version: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4']
332+
php_version: ['7.4', '8.0', '8.1', '8.2', '8.3', '8.4']
336333
server: ['nginx-php-fpm', 'apache-mod-php', 'php-built-in']
337334
os: ['ubuntu-24.04']
338335
fail-fast: false
@@ -344,11 +341,8 @@ jobs:
344341
run: |
345342
uname -a
346343
cat /etc/centos-release
347-
cd /etc/yum.repos.d/
348-
sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*
349-
sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*
350344
yum install -y yum-utils
351-
yum install -y https://rpms.remirepo.net/enterprise/remi-release-8.4.rpm
345+
dnf install -y https://rpms.remirepo.net/enterprise/remi-release-9.rpm
352346
yum install -y gcc
353347
yum install -y python3-devel
354348
pip3 install flask
@@ -361,6 +355,7 @@ jobs:
361355
yum install -y mod_php
362356
yum install -y nginx
363357
yum install -y php-fpm
358+
dnf install -y procps-ng
364359
365360
- name: Get Arch
366361
run: echo "ARCH=$(uname -m)" >> $GITHUB_ENV
@@ -448,7 +443,7 @@ jobs:
448443
a2enmod rewrite
449444
450445
- name: Setup PHP
451-
uses: shivammathur/setup-php@9e72090525849c5e82e596468b86eb55e9cc5401 # v2
446+
uses: shivammathur/setup-php@27853eb8b46dc01c33bf9fef67d98df2683c3be2
452447
with:
453448
php-version: ${{ matrix.php_version }}
454449
extensions: curl, sqlite3

lib/agent/aikido_types/init_data.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,15 @@ type CloudConfigData struct {
5959
ReceivedAnyStats bool `json:"receivedAnyStats"`
6060
Block *bool `json:"block,omitempty"`
6161
BlockedIpsList map[string]IpBlocklist
62+
AllowedIpsList map[string]IpBlocklist
6263
BlockedUserAgents string
6364
MonitoredIpsList map[string]IpBlocklist
6465
MonitoredUserAgents string
6566
UserAgentDetails map[string]string
6667
}
6768

68-
type BlockedIpsData struct {
69+
type IpsData struct {
70+
Key string `json:"key"`
6971
Source string `json:"source"`
7072
Description string `json:"description"`
7173
Ips []string `json:"ips"`
@@ -79,9 +81,10 @@ type UserAgentDetails struct {
7981
type ListsConfigData struct {
8082
Success bool `json:"success"`
8183
ServiceId int `json:"serviceId"`
82-
BlockedIpAddresses []BlockedIpsData `json:"blockedIPAddresses"`
84+
BlockedIpAddresses []IpsData `json:"blockedIPAddresses"`
85+
AllowedIpAddresses []IpsData `json:"allowedIPAddresses"`
8386
BlockedUserAgents string `json:"blockedUserAgents"`
84-
MonitoredIpAddresses []BlockedIpsData `json:"monitoredIpAddresses"`
87+
MonitoredIpAddresses []IpsData `json:"monitoredIpAddresses"`
8588
MonitoredUserAgents string `json:"monitoredUserAgents"`
8689
UserAgentDetails []UserAgentDetails `json:"userAgentDetails"`
8790
}

lib/agent/cloud/common.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,10 @@ func ApplyCloudConfig() {
123123
UpdateRateLimitingConfig()
124124
}
125125

126-
func UpdateIpsLists(BlockedIps []BlockedIpsData) map[string]IpBlocklist {
126+
func UpdateIpsLists(ipLists []IpsData) map[string]IpBlocklist {
127127
m := make(map[string]IpBlocklist)
128-
for _, blockedIpsGroup := range BlockedIps {
129-
m[blockedIpsGroup.Source] = IpBlocklist{Description: blockedIpsGroup.Description, Ips: blockedIpsGroup.Ips}
128+
for _, ipList := range ipLists {
129+
m[ipList.Key] = IpBlocklist{Description: ipList.Description, Ips: ipList.Ips}
130130
}
131131
return m
132132
}
@@ -147,6 +147,7 @@ func UpdateListsConfig() bool {
147147

148148
CloudConfig.BlockedIpsList = UpdateIpsLists(tempListsConfig.BlockedIpAddresses)
149149
CloudConfig.MonitoredIpsList = UpdateIpsLists(tempListsConfig.MonitoredIpAddresses)
150+
CloudConfig.AllowedIpsList = UpdateIpsLists(tempListsConfig.AllowedIpAddresses)
150151

151152
CloudConfig.BlockedUserAgents = tempListsConfig.BlockedUserAgents
152153
CloudConfig.MonitoredUserAgents = tempListsConfig.MonitoredUserAgents
@@ -166,7 +167,7 @@ func StoreCloudConfig(configReponse []byte) bool {
166167
tempCloudConfig := CloudConfigData{}
167168
err := json.Unmarshal(configReponse, &tempCloudConfig)
168169
if err != nil {
169-
log.Warnf("Failed to unmarshal cloud config!")
170+
log.Warnf("Failed to unmarshal cloud config: %v", err)
170171
return false
171172
}
172173
if tempCloudConfig.ConfigUpdatedAt <= globals.CloudConfig.ConfigUpdatedAt {

lib/agent/go.sum

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek
88
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
99
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
1010
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
11+
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
1112
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
1213
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
1314
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=

lib/agent/grpc/request.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -251,10 +251,10 @@ func getRateLimitingStatus(method, route, routeParsed, user, ip string) *protos.
251251
return &protos.RateLimitingStatus{Block: false}
252252
}
253253

254-
func getIpsList(ipsList map[string]IpBlocklist) map[string]*protos.IpBlockList {
255-
m := make(map[string]*protos.IpBlockList)
254+
func getIpsList(ipsList map[string]IpBlocklist) map[string]*protos.IpList {
255+
m := make(map[string]*protos.IpList)
256256
for ipBlocklistSource, ipBlocklist := range ipsList {
257-
m[ipBlocklistSource] = &protos.IpBlockList{Description: ipBlocklist.Description, Ips: ipBlocklist.Ips}
257+
m[ipBlocklistSource] = &protos.IpList{Description: ipBlocklist.Description, Ips: ipBlocklist.Ips}
258258
}
259259
return m
260260
}
@@ -274,6 +274,7 @@ func getCloudConfig(configUpdatedAt int64) *protos.CloudConfig {
274274
BlockedUserIds: globals.CloudConfig.BlockedUserIds,
275275
BypassedIps: globals.CloudConfig.BypassedIps,
276276
BlockedIps: getIpsList(globals.CloudConfig.BlockedIpsList),
277+
AllowedIps: getIpsList(globals.CloudConfig.AllowedIpsList),
277278
BlockedUserAgents: globals.CloudConfig.BlockedUserAgents,
278279
MonitoredIps: getIpsList(globals.CloudConfig.MonitoredIpsList),
279280
MonitoredUserAgents: globals.CloudConfig.MonitoredUserAgents,

lib/ipc.proto

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,22 +77,24 @@ message CloudConfigUpdatedAt {
7777
int64 configUpdatedAt = 1;
7878
}
7979

80-
message IpBlockList {
81-
string description = 1;
82-
repeated string ips = 2;
80+
message IpList {
81+
string key = 1;
82+
string description = 2;
83+
repeated string ips = 3;
8384
}
8485

8586
message CloudConfig {
8687
int64 configUpdatedAt = 1;
8788
repeated Endpoint endpoints = 2;
8889
repeated string blockedUserIds = 3;
8990
repeated string bypassedIps = 4;
90-
map<string, IpBlockList> blockedIps = 5;
91-
string blockedUserAgents = 6;
92-
map<string, IpBlockList> monitoredIps = 7;
93-
string monitoredUserAgents = 8;
94-
map<string, string> userAgentDetails = 9;
95-
bool block = 10;
91+
map<string, IpList> blockedIps = 5;
92+
map<string, IpList> allowedIps = 6;
93+
string blockedUserAgents = 7;
94+
map<string, IpList> monitoredIps = 8;
95+
string monitoredUserAgents = 9;
96+
map<string, string> userAgentDetails = 10;
97+
bool block = 11;
9698
}
9799

98100
message RateLimitingStatus {

lib/request-processor/aikido_types/config.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ type EndpointKey struct {
4646
Route string
4747
}
4848

49-
type IpBlockList struct {
49+
type IpList struct {
50+
Key string
5051
Description string
5152
IpSet netipx.IPSet
5253
}
@@ -57,9 +58,10 @@ type CloudConfigData struct {
5758
WildcardEndpoints map[string][]WildcardEndpointData
5859
BlockedUserIds map[string]bool
5960
BypassedIps *netipx.IPSet
60-
BlockedIps map[string]IpBlockList
61+
BlockedIps map[string]IpList
62+
AllowedIps map[string]IpList
6163
BlockedUserAgents *regexp.Regexp
62-
MonitoredIps map[string]IpBlockList
64+
MonitoredIps map[string]IpList
6365
MonitoredUserAgents *regexp.Regexp
6466
UserAgentDetails map[string]*regexp.Regexp
6567
Block int

lib/request-processor/context/cache.go

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -215,22 +215,19 @@ func ContextSetIsEndpointIpAllowed() {
215215

216216
endpointConfig := GetEndpointConfig()
217217
if endpointConfig != nil {
218-
isEndpointIpAllowed = utils.IsIpAllowed(endpointConfig.AllowedIPAddresses, ip)
218+
isEndpointIpAllowed = utils.IsIpAllowedOnEndpoint(endpointConfig.AllowedIPAddresses, ip)
219219
}
220220

221221
if isEndpointIpAllowed == utils.NoConfig {
222222
for _, wildcardEndpointConfig := range GetWildcardEndpointsConfig() {
223-
isEndpointIpAllowed = utils.IsIpAllowed(wildcardEndpointConfig.AllowedIPAddresses, ip)
223+
isEndpointIpAllowed = utils.IsIpAllowedOnEndpoint(wildcardEndpointConfig.AllowedIPAddresses, ip)
224224
if isEndpointIpAllowed != utils.NoConfig {
225225
break
226226
}
227227
}
228228
}
229229

230-
isEndpointIpAllowedBool := true
231-
if isEndpointIpAllowed == utils.NotAllowed {
232-
isEndpointIpAllowedBool = false
233-
}
230+
isEndpointIpAllowedBool := isEndpointIpAllowed != utils.NotFound
234231

235232
Context.IsEndpointIpAllowed = &isEndpointIpAllowedBool
236233
}

lib/request-processor/grpc/client.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,15 +211,20 @@ func OnMiddlewareInstalled() {
211211
log.Debugf("OnMiddlewareInstalled sent via socket")
212212
}
213213

214-
func OnMonitoredIpMatch(lists []string) {
214+
func OnMonitoredIpMatch(lists []utils.IpListMatch) {
215215
if client == nil || len(lists) == 0 {
216216
return
217217
}
218218

219219
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
220220
defer cancel()
221221

222-
_, err := client.OnMonitoredIpMatch(ctx, &protos.MonitoredIpMatch{Lists: lists})
222+
protosLists := []string{}
223+
for _, list := range lists {
224+
protosLists = append(protosLists, list.Key)
225+
}
226+
227+
_, err := client.OnMonitoredIpMatch(ctx, &protos.MonitoredIpMatch{Lists: protosLists})
223228
if err != nil {
224229
log.Warnf("Could not call OnMonitoredIpMatch")
225230
return

lib/request-processor/grpc/config.go

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,19 @@ var (
1717
cloudConfigTicker = time.NewTicker(1 * time.Minute)
1818
)
1919

20+
func buildIpList(cloudIpList map[string]*protos.IpList) map[string]IpList {
21+
ipList := map[string]IpList{}
22+
for ipListKey, protoIpList := range cloudIpList {
23+
ipSet, err := utils.BuildIpList(protoIpList.Description, protoIpList.Ips)
24+
if err != nil {
25+
log.Errorf("Error building IP list: %s\n", err)
26+
continue
27+
}
28+
ipList[ipListKey] = *ipSet
29+
}
30+
return ipList
31+
}
32+
2033
func getEndpointData(ep *protos.Endpoint) EndpointData {
2134
allowedIPSet, err := utils.BuildIpSet(ep.AllowedIPAddresses)
2235
if err != nil {
@@ -50,19 +63,6 @@ func storeWildcardEndpointConfig(ep *protos.Endpoint) {
5063
globals.CloudConfig.WildcardEndpoints[ep.Method] = append(wildcardRoutes, WildcardEndpointData{RouteRegex: wildcardRouteCompiled, Data: getEndpointData(ep)})
5164
}
5265

53-
func buildIpListFromProto(monitoredIpsList map[string]*protos.IpBlockList) map[string]IpBlockList {
54-
m := map[string]IpBlockList{}
55-
for ipBlocklistSource, ipBlocklist := range monitoredIpsList {
56-
ipBlocklist, err := utils.BuildIpBlocklist(ipBlocklistSource, ipBlocklist.Description, ipBlocklist.Ips)
57-
if err != nil {
58-
log.Errorf("Error building IP blocklist: %s\n", err)
59-
continue
60-
}
61-
m[ipBlocklistSource] = *ipBlocklist
62-
}
63-
return m
64-
}
65-
6666
func buildUserAgentsRegexpFromProto(userAgents string) *regexp.Regexp {
6767
if userAgents == "" {
6868
return nil
@@ -121,12 +121,14 @@ func setCloudConfig(cloudConfigFromAgent *protos.CloudConfig) {
121121
globals.CloudConfig.Block = 0
122122
}
123123

124-
globals.CloudConfig.BlockedIps = buildIpListFromProto(cloudConfigFromAgent.BlockedIps)
125-
globals.CloudConfig.MonitoredIps = buildIpListFromProto(cloudConfigFromAgent.MonitoredIps)
124+
globals.CloudConfig.BlockedIps = buildIpList(cloudConfigFromAgent.BlockedIps)
125+
globals.CloudConfig.MonitoredIps = buildIpList(cloudConfigFromAgent.MonitoredIps)
126126

127127
globals.CloudConfig.BlockedUserAgents = buildUserAgentsRegexpFromProto(cloudConfigFromAgent.BlockedUserAgents)
128128
globals.CloudConfig.MonitoredUserAgents = buildUserAgentsRegexpFromProto(cloudConfigFromAgent.MonitoredUserAgents)
129129

130+
globals.CloudConfig.AllowedIps = buildIpList(cloudConfigFromAgent.AllowedIps)
131+
130132
globals.CloudConfig.UserAgentDetails = buildUserAgentDetailsFromProto(cloudConfigFromAgent.UserAgentDetails)
131133

132134
// Force garbage collection to ensure that the IP blocklists temporary memory is released ASAP

0 commit comments

Comments
 (0)