refactor(api): streamline mikrotik-install script and enhance synchronization logic
- Consolidated the `mikrotik-install.rsc` script to utilize a single `evofw-sync` script for improved clarity and efficiency in synchronization processes. - Removed the legacy `evofw-env` script, simplifying the token management and ensuring a more reliable update mechanism. - Updated the token generation logic to enhance security and reliability, while ensuring compatibility with RouterOS 7+. - Adjusted test assertions in `install-links.test.ts` to verify the presence of new script components and ensure accurate testing of the installation logic. These changes improve the overall robustness and maintainability of the agent installation and synchronization process.
This commit is contained in:
@@ -1,11 +1,8 @@
|
||||
# EvoFirewall MikroTik install (RouterOS 7.21+)
|
||||
# Short-link sets EvofwCpUrl / EvofwSeed / EvofwName / EvofwInstallLinkId before body.
|
||||
# Legacy: set globals, then /import file-name=mikrotik-install.rsc
|
||||
#
|
||||
# Re-import on an already-enrolled router: skips enroll, refreshes sync + scheduler (token kept).
|
||||
#
|
||||
# Sync uses GET /v1/agent/policy (JSON) + address-list rebuild — not /import of huge .rsc
|
||||
# (large /import often fails silently while apply-report still looks "ok").
|
||||
# One script only: evofw-sync (credentials + sync). Legacy evofw-env is removed.
|
||||
# Sync: GET /v1/agent/policy (JSON) → rebuild address-lists. LastHash in RAM (full rebuild after reboot).
|
||||
|
||||
:global EvofwCpUrl
|
||||
:global EvofwSeed
|
||||
@@ -19,19 +16,40 @@
|
||||
:if ([:typeof $EvofwName] = "nothing" || [:len $EvofwName] = 0) do={ :set EvofwName [/system identity get name] }
|
||||
|
||||
:local already 0
|
||||
|
||||
# Prefer token already baked into evofw-sync
|
||||
:do {
|
||||
/system script run evofw-env
|
||||
:if ([:typeof $EvofwToken] != "nothing" && [:len $EvofwToken] > 0) do={ :set already 1 }
|
||||
:local src [/system script get [find name="evofw-sync"] source]
|
||||
:local key "EvofwToken \""
|
||||
:local i [:find $src $key]
|
||||
:if ([:typeof $i] != "nil") do={
|
||||
:local rest [:pick $src ($i + [:len $key]) [:len $src]]
|
||||
:local j [:find $rest "\""]
|
||||
:if ([:typeof $j] != "nil") do={
|
||||
:local tok [:pick $rest 0 $j]
|
||||
:if ([:len $tok] > 10) do={
|
||||
:set EvofwToken $tok
|
||||
:set already 1
|
||||
}
|
||||
}
|
||||
}
|
||||
} on-error={}
|
||||
|
||||
# Legacy: migrate from evofw-env if present
|
||||
:if ($already = 0) do={
|
||||
:do {
|
||||
/system script run evofw-env
|
||||
:if ([:typeof $EvofwToken] != "nothing" && [:len $EvofwToken] > 0) do={ :set already 1 }
|
||||
} on-error={}
|
||||
}
|
||||
|
||||
:if ($already = 0) do={
|
||||
# Portable token: :rndstr is RouterOS 7+; avoid /certificate scep-server nonce (often missing).
|
||||
:local token ("evofw_" . [:rndstr length=32 from="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"])
|
||||
:if ([:len $token] < 20) do={
|
||||
:set token ("evofw_" . [:tostr [/system clock get time]] . [:tostr [/system resource get cpu-load]] . [:tostr [/system resource get free-memory]] . [:tostr [:rndnum from=100000 to=999999]])
|
||||
}
|
||||
|
||||
:local body ("{\"name\":\"" . $EvofwName . "\",\"hostname\":\"" . [/system identity get name] . "\",\"platform\":\"mikrotik\",\"token\":\"" . $token . "\",\"client_version\":\"rsc/2\"")
|
||||
:local body ("{\"name\":\"" . $EvofwName . "\",\"hostname\":\"" . [/system identity get name] . "\",\"platform\":\"mikrotik\",\"token\":\"" . $token . "\",\"client_version\":\"rsc/3\"")
|
||||
:if ([:typeof $EvofwInstallLinkId] != "nothing" && [:len $EvofwInstallLinkId] > 0) do={
|
||||
:set body ($body . ",\"install_link_id\":\"" . $EvofwInstallLinkId . "\"")
|
||||
}
|
||||
@@ -42,38 +60,29 @@
|
||||
} on-error={
|
||||
:error "evofw: enroll failed — check EvofwCpUrl / EvofwSeed / connectivity"
|
||||
}
|
||||
|
||||
:do { /system script remove [find name="evofw-env"] } on-error={}
|
||||
/system script add name=evofw-env policy=read,write,policy,test source=(" :global EvofwCpUrl \"" . $EvofwCpUrl . "\"; :global EvofwToken \"" . $token . "\"; :global EvofwLastHash \"\" ")
|
||||
:set EvofwToken $token
|
||||
:set EvofwLastHash ""
|
||||
} else={
|
||||
:put "evofw: already enrolled — updating sync script (token kept); forcing full list rebuild"
|
||||
:set EvofwLastHash ""
|
||||
:do { /system script remove [find name="evofw-env"] } on-error={}
|
||||
/system script add name=evofw-env policy=read,write,policy,test source=(" :global EvofwCpUrl \"" . $EvofwCpUrl . "\"; :global EvofwToken \"" . $EvofwToken . "\"; :global EvofwLastHash \"\" ")
|
||||
:put "evofw: already enrolled — updating single sync script (token kept)"
|
||||
}
|
||||
|
||||
# Filter rules (idempotent by comment) — names must match policy toggles below
|
||||
:do { /ip firewall filter remove [find comment~"^evofw-"] } on-error={}
|
||||
:set EvofwLastHash ""
|
||||
|
||||
# Filter rules (idempotent by comment)
|
||||
:do { /ip firewall filter remove [find comment~"^evofw-"] } on-error={}
|
||||
/ip firewall filter add chain=input action=drop src-address-list=EVOFW_DENY comment=evofw-deny-drop-input disabled=no
|
||||
/ip firewall filter add chain=forward action=drop src-address-list=EVOFW_DENY comment=evofw-deny-drop-forward disabled=no
|
||||
/ip firewall filter add chain=forward action=accept src-address-list=EVOFW_ALLOW comment=evofw-allow-accept-forward disabled=no
|
||||
/ip firewall filter add chain=forward action=drop comment=evofw-default-drop-forward disabled=yes
|
||||
|
||||
# Sync: JSON policy → rebuild address-lists (reliable for ~1k CIDRs; no nested /import)
|
||||
:do { /system script remove [find name="evofw-sync"] } on-error={}
|
||||
/system script add name=evofw-sync policy=read,write,policy,test source={
|
||||
# Build sync body as a template script, then prepend baked credentials → one script
|
||||
:do { /system script remove [find name="evofw-sync-body"] } on-error={}
|
||||
/system script add name=evofw-sync-body policy=read,write,policy,test source={
|
||||
:global EvofwCpUrl
|
||||
:global EvofwToken
|
||||
:global EvofwLastHash
|
||||
:if ([:typeof $EvofwCpUrl] = "nothing" || [:typeof $EvofwToken] = "nothing") do={
|
||||
/system script run evofw-env
|
||||
}
|
||||
:if ([:typeof $EvofwCpUrl] = "nothing" || [:typeof $EvofwToken] = "nothing") do={
|
||||
:if ([:typeof $EvofwCpUrl] = "nothing" || [:len $EvofwCpUrl] = 0 || [:typeof $EvofwToken] = "nothing" || [:len $EvofwToken] = 0) do={
|
||||
:log error "evofw: missing EvofwCpUrl/EvofwToken"
|
||||
:error "evofw env missing"
|
||||
:error "evofw missing credentials"
|
||||
}
|
||||
:if ([:typeof $EvofwLastHash] = "nothing") do={ :set EvofwLastHash "" }
|
||||
|
||||
@@ -114,8 +123,6 @@
|
||||
:do { /ip firewall filter set [find comment=evofw-default-drop-forward] disabled=yes } on-error={}
|
||||
}
|
||||
:set EvofwLastHash $hash
|
||||
:do { /system script remove [find name="evofw-env"] } on-error={}
|
||||
/system script add name=evofw-env policy=read,write,policy,test source=(" :global EvofwCpUrl \"" . $EvofwCpUrl . "\"; :global EvofwToken \"" . $EvofwToken . "\"; :global EvofwLastHash \"" . $hash . "\" ")
|
||||
:log info ("evofw: applied " . $hash)
|
||||
:set syncOk 1
|
||||
}
|
||||
@@ -138,6 +145,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
:local bodySrc [/system script get [find name="evofw-sync-body"] source]
|
||||
:local head (":global EvofwCpUrl \"" . $EvofwCpUrl . "\"; :global EvofwToken \"" . $EvofwToken . "\"; ")
|
||||
:do { /system script remove [find name="evofw-sync-body"] } on-error={}
|
||||
:do { /system script remove [find name="evofw-sync"] } on-error={}
|
||||
:do { /system script remove [find name="evofw-env"] } on-error={}
|
||||
/system script add name=evofw-sync policy=read,write,policy,test source=($head . $bodySrc)
|
||||
|
||||
:do { /system scheduler remove [find name="evofw-sync"] } on-error={}
|
||||
/system scheduler add name=evofw-sync interval=1m on-event=evofw-sync policy=read,write,policy,test
|
||||
|
||||
@@ -146,7 +160,7 @@
|
||||
}
|
||||
|
||||
:if ($already = 1) do={
|
||||
:put ("EvoFirewall updated for " . $EvofwName . " — sync script + scheduler refreshed")
|
||||
:put ("EvoFirewall updated for " . $EvofwName . " — single script evofw-sync")
|
||||
} else={
|
||||
:put ("EvoFirewall enrolled as " . $EvofwName . " — approve in UI; scheduler evofw-sync every 1m")
|
||||
:put ("EvoFirewall enrolled as " . $EvofwName . " — approve in UI; script/scheduler evofw-sync every 1m")
|
||||
}
|
||||
|
||||
@@ -143,6 +143,8 @@ describe('install-links', () => {
|
||||
expect(byId.body).toContain('evofw-deny-drop-input')
|
||||
expect(byId.body).toContain('/v1/agent/policy')
|
||||
expect(byId.body).toContain(':deserialize')
|
||||
expect(byId.body).toContain('evofw-sync-body')
|
||||
expect(byId.body).toContain('remove [find name="evofw-env"]')
|
||||
})
|
||||
|
||||
it('approved agent can fetch empty policy without rule sets', async () => {
|
||||
|
||||
Reference in New Issue
Block a user