Skip to content

Commit 17b34b6

Browse files
authored
Merge pull request #143 from bsyk/upsert_rule
Update existing rule
2 parents 9e9fc1e + a5de303 commit 17b34b6

File tree

2 files changed

+56
-4
lines changed

2 files changed

+56
-4
lines changed

cf_gateway_rule_create.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { createZeroTrustRule, getZeroTrustLists } from "./lib/api.js";
1+
import { getZeroTrustLists, upsertZeroTrustRule } from "./lib/api.js";
22
import { BLOCK_BASED_ON_SNI } from "./lib/constants.js";
33
import { notifyWebhook } from "./lib/helpers.js";
44

@@ -13,7 +13,7 @@ const wirefilterDNSExpression = lists.reduce((previous, current) => {
1313

1414
console.log("Creating DNS rule...");
1515
// .slice removes the trailing ' or '
16-
await createZeroTrustRule(wirefilterDNSExpression.slice(0, -4), "CGPS Filter Lists", ["dns"]);
16+
await upsertZeroTrustRule(wirefilterDNSExpression.slice(0, -4), "CGPS Filter Lists", ["dns"]);
1717

1818
// Optionally create a rule that matches the SNI.
1919
// This only works for users who proxy their traffic through Cloudflare.
@@ -26,7 +26,7 @@ if (BLOCK_BASED_ON_SNI) {
2626

2727
console.log("Creating SNI rule...");
2828
// .slice removes the trailing ' or '
29-
await createZeroTrustRule(wirefilterSNIExpression.slice(0, -4), "CGPS Filter Lists - SNI Based Filtering", ["l4"]);
29+
await upsertZeroTrustRule(wirefilterSNIExpression.slice(0, -4), "CGPS Filter Lists - SNI Based Filtering", ["l4"]);
3030
}
3131

3232
// Send a notification to the webhook

lib/api.js

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { BLOCK_PAGE_ENABLED, LIST_ITEM_SIZE } from "./constants.js";
1+
import { BLOCK_PAGE_ENABLED, DEBUG, LIST_ITEM_SIZE } from "./constants.js";
22
import { requestGateway } from "./helpers.js";
33

44
/**
@@ -140,6 +140,25 @@ export const deleteZeroTrustListsAtOnce = async (lists) => {
140140
export const getZeroTrustRules = () =>
141141
requestGateway("/rules", { method: "GET" });
142142

143+
/**
144+
* Upserts a Zero Trust rule.
145+
* If a rule with the same name exists, will update it. Otherwise create a new rule.
146+
* @param {string} wirefilterExpression The expression to be used for the rule.
147+
* @param {string} name The name of the rule.
148+
* @param {string[]} filters The filters to be used for the rule. Default is ["dns"]. Possible values are ["dns", "http", "l4", "egress"].
149+
* @returns {Promise<Object>}
150+
*/
151+
export const upsertZeroTrustRule = async (wirefilterExpression, name = "CGPS Filter Lists", filters = ["dns"]) => {
152+
const { result: existingRules} = await getZeroTrustRules();
153+
const existingRule = existingRules.find(rule => rule.name === name);
154+
if (existingRule) {
155+
if (DEBUG) console.log(`Found "${existingRule.name}" in rules, updating...`);
156+
return updateZeroTrustRule(existingRule.id, wirefilterExpression, name, filters);
157+
}
158+
if (DEBUG) console.log(`No existing rule named "${existingRule.name}", creating...`);
159+
return createZeroTrustRule(wirefilterExpression, name, filters);
160+
}
161+
143162
/**
144163
* Creates a Zero Trust rule.
145164
*
@@ -172,6 +191,39 @@ export const createZeroTrustRule = async (wirefilterExpression, name = "CGPS Fil
172191
}
173192
};
174193

194+
/**
195+
* Updates a Zero Trust rule.
196+
*
197+
* API docs: https://developers.cloudflare.com/api/operations/zero-trust-gateway-rules-update-zero-trust-gateway-rule
198+
* @param {number} id The ID of the rule to be updated.
199+
* @param {string} wirefilterExpression The expression to be used for the rule.
200+
* @param {string} name The name of the rule.
201+
* @param {string[]} filters The filters to be used for the rule.
202+
* @returns {Promise<Object>}
203+
*/
204+
export const updateZeroTrustRule = async (id, wirefilterExpression, name = "CGPS Filter Lists", filters = ["dns"]) => {
205+
try {
206+
await requestGateway(`/rules/${id}`, {
207+
method: "PUT",
208+
body: JSON.stringify({
209+
// Name and action are required fields, even if they haven't changed.
210+
// And enabled must always be set to true, otherwise the rule will be disabled if omitted.
211+
name,
212+
action: "block",
213+
enabled: true,
214+
rule_settings: { "block_page_enabled": BLOCK_PAGE_ENABLED, "block_reason": "Blocked by CGPS, check your filter lists if this was a mistake." },
215+
filters,
216+
traffic: wirefilterExpression,
217+
}),
218+
});
219+
220+
console.log("Updated existing rule successfully");
221+
} catch (err) {
222+
console.error(`Error occurred while updating rule - ${err.toString()}`);
223+
throw err;
224+
}
225+
};
226+
175227
/**
176228
* Deletes a Zero Trust rule.
177229
*

0 commit comments

Comments
 (0)