Skip to content

Commit ecd3348

Browse files
committed
✨keep only highest priority behavior in blocklist
1 parent 17ab2be commit ecd3348

File tree

2 files changed

+69
-4
lines changed

2 files changed

+69
-4
lines changed

controlpanel/api/services/configmanager.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const Config = require('../models/Config-data')
33
const Decoy = require('../models/Decoy-data')
44
const Blocklist = require('../models/Blocklist')
55
const protectedAppService = require('./protected-app')
6+
const { sortBlocklistDuplicates } = require('../util/blocklist')
67

78
module.exports = {
89
/**
@@ -42,10 +43,12 @@ module.exports = {
4243
const protectedApp = await ProtectedApp.findOne({ where: { namespace, application } });
4344
if (!protectedApp) return { type: 'error', code: 404, message: 'Invalid namespace or application supplied' };
4445
if (!blocklist) return { type: 'error', code: 400, message: 'Invalid blocklist supplied' };
45-
if (blocklist.blocklist && blocklist.blocklist.length)
46-
Blocklist.bulkCreate(blocklist.blocklist.map(item => ({ pa_id: protectedApp.id, content: item, type: 'blocklist' })));
47-
if (blocklist.throttle && blocklist.throttle.length)
48-
Blocklist.bulkCreate(blocklist.throttle.map(item => ({ pa_id: protectedApp.id, content: item, type: 'throttle' })));
46+
const blocklistToUpdate = await sortBlocklistDuplicates(blocklist, protectedApp.id);
47+
48+
if (blocklistToUpdate.blocklist && blocklistToUpdate.blocklist.length)
49+
Blocklist.bulkCreate(blocklistToUpdate.blocklist.map(item => ({ pa_id: protectedApp.id, content: item, type: 'blocklist' })));
50+
if (blocklistToUpdate.throttle && blocklistToUpdate.throttle.length)
51+
Blocklist.bulkCreate(blocklistToUpdate.throttle.map(item => ({ pa_id: protectedApp.id, content: item, type: 'throttle' })));
4952
return { type: 'success', code: 200, message: 'Successful operation' };
5053
} catch(e) {
5154
throw e;

controlpanel/api/util/blocklist.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
const Blocklist = require('../models/Blocklist')
2+
const { Op } = require('sequelize');
3+
4+
async function sortBlocklistDuplicates(newBlocklist, pa_id) {
5+
const finalBlocklist = [];
6+
const finaleThrottlelist = [];
7+
const allSources = Object.fromEntries(['SourceIp', 'Session', 'UserAgent']
8+
.map(key => [key, [...newBlocklist.blocklist, ...newBlocklist.throttle].find(item => item[key])?.[key]])
9+
.filter(([, value]) => value !== undefined));
10+
const existingBlocklist = await Blocklist.findAll({ where: {
11+
pa_id,
12+
type: 'blocklist',
13+
[Op.or]: Object.entries(allSources).map(([key, value]) => ({
14+
[`content.${key}`]: value
15+
}))}
16+
});
17+
const existingThrottlelist = await Blocklist.findAll({ where: {
18+
pa_id,
19+
type: 'throttle',
20+
[Op.or]: Object.entries(allSources).map(([key, value]) => ({
21+
[`content.${key}`]: value
22+
}))}
23+
});
24+
for (const newItem of newBlocklist.blocklist) {
25+
const sourceKeys = ['SourceIp', 'Session', 'UserAgent'].filter(key => newItem[key] !== undefined);
26+
const match = existingBlocklist.find(existing =>
27+
sourceKeys.length > 0 &&
28+
sourceKeys.every(key => existing.content[key] === newItem[key]) &&
29+
sourceKeys.every(key => existing.content[key] !== undefined) &&
30+
sourceKeys.length === Object.keys(existing.content).filter(key => sourceKeys.includes(key) && existing.content[key] !== undefined).length);
31+
if (!match) {
32+
finalBlocklist.push(newItem);
33+
continue;
34+
}
35+
if(isNewBlocklistBehaviorPriority(match, newItem)) {
36+
Blocklist.destroy({ where: { id: match.id } })
37+
finalBlocklist.push(newItem);
38+
}
39+
}
40+
for (const newItem of newBlocklist.throttle) {
41+
const sourceKeys = ['SourceIp', 'Session', 'UserAgent'].filter(key => newItem[key] !== undefined);
42+
const match = existingThrottlelist.find(existing =>
43+
sourceKeys.length > 0 &&
44+
sourceKeys.every(key => existing.content[key] === newItem[key]) &&
45+
sourceKeys.every(key => existing.content[key] !== undefined) &&
46+
sourceKeys.length === Object.keys(existing.content).filter(key => sourceKeys.includes(key) && existing.content[key] !== undefined).length);
47+
if (match && isNewBlocklistBehaviorPriority(match, newItem)) {
48+
Blocklist.destroy({ where: { id: match.id } })
49+
finaleThrottlelist.push(newItem);
50+
}
51+
}
52+
return { blocklist: finalBlocklist, throttle: finaleThrottlelist };
53+
}
54+
55+
function isNewBlocklistBehaviorPriority(existingBlocklist, newBlocklist) {
56+
const priorities = { clone: 1, exhaust: 2, drop: 3, error: 4 };
57+
return priorities[newBlocklist.Behavior] < priorities[existingBlocklist.content.Behavior]
58+
}
59+
60+
module.exports = {
61+
sortBlocklistDuplicates
62+
}

0 commit comments

Comments
 (0)