Skip to content

Commit

Permalink
feat(backend/routes): add sync check between web and firewall
Browse files Browse the repository at this point in the history
  • Loading branch information
Fraccs committed Apr 6, 2024
1 parent 5bbc2fb commit 15e8a95
Showing 1 changed file with 54 additions and 7 deletions.
61 changes: 54 additions & 7 deletions web/backend/src/routes/firewall.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,74 @@
import { Router } from "express"
import { cerberoEventEmitter, isFirewallConnected } from "../socket/socket"
import { Database } from "../database/db"
import { buildConfiguration, cerberoEventEmitter, isFirewallConnected } from "../socket/socket"

const firewallRoute = Router()

firewallRoute.get("/", (req, res) => {
// Get the last config that was sent from the db and
// compare it to the current web config
firewallRoute.get("/", async (req, res) => {
const redis = Database.getInstance()

const config = await buildConfiguration()
const firewallConfig = []
const firewallServicesKeys = await redis.keys("firewall:services:*")

for(const firewallServiceKey of firewallServicesKeys) {
const nfq = firewallServiceKey.split(":")[2]
const firewallService = await redis.hGetAll(firewallServiceKey)
const regexes = await redis.sMembers(`firewall:regexes:${nfq}`)

const parsedFirewallService = {
chain: "OUTPUT",
name: firewallService.name,
nfq: parseInt(firewallService.nfq),
port: parseInt(firewallService.port),
protocol: firewallService.protocol as "tcp" | "udp",
regexes: regexes
}

firewallConfig.push(parsedFirewallService)
}

// The order of the regexes MATTERS!
// If the regexes stay the same but their order changes the firewall is condidered NOT SYNCED!
return res.json({
isConnected: isFirewallConnected,
isSynced: true
isSynced: JSON.stringify(firewallConfig) === JSON.stringify(config)
})
})

// Trigger a firewall configuration update
firewallRoute.post("/", (req, res) => {
firewallRoute.post("/", async (req, res) => {
const redis = Database.getInstance()

if(!isFirewallConnected) {
return res.status(409).json({
error: "The firewall is not connected, can't update the configuration"
})
}

cerberoEventEmitter.emit("cerberoConfigUpdate")
// Update the "firewall config" in the db
// Take the "web config" and override the firewall one
const firewallKeys = await redis.keys("firewall:*")
for(const firewallKey of firewallKeys) {
await redis.del(firewallKey)
}

const servicesKeys = await redis.keys("services:*")
const regexesKeys = await redis.keys("regexes:*:active")

for(const serviceKey of servicesKeys) {
await redis.copy(serviceKey, `firewall:${serviceKey}`)
}

for(const regexesKey of regexesKeys) {
const regexesKeyParts = regexesKey.split(":")
const newRegexesKey = regexesKeyParts.filter((_, i) => i !== regexesKeyParts.length - 1).join(":")

await redis.copy(regexesKey, `firewall:${newRegexesKey}`)
}


cerberoEventEmitter.emit("cerberoConfigUpdate") // FIX: an update could fail inside of this and we would have updated the db anyways

return res.status(204).end()
})
Expand Down

0 comments on commit 15e8a95

Please sign in to comment.