0

Update Firewall Configuration

by
Published Apr 8, 2025

Process updates to modify the existing firewall config for a project

Script vercel Verified

The script

Submitted by hugo697 Bun
Verified 428 days ago
1
//native
2
type Vercel = {
3
  token: string;
4
};
5
/**
6
 * Update Firewall Configuration
7
 * Process updates to modify the existing firewall config for a project
8
 */
9
export async function main(
10
  auth: Vercel,
11
  projectId: string | undefined,
12
  teamId: string | undefined,
13
  slug: string | undefined,
14
  body:
15
    | { action: "firewallEnabled"; id?: null; value: false | true }
16
    | {
17
        action: "rules.insert";
18
        id?: null;
19
        value: {
20
          name: string;
21
          description?: string;
22
          active: false | true;
23
          conditionGroup: {
24
            conditions: {
25
              type:
26
                | "host"
27
                | "path"
28
                | "method"
29
                | "header"
30
                | "query"
31
                | "cookie"
32
                | "target_path"
33
                | "raw_path"
34
                | "ip_address"
35
                | "region"
36
                | "protocol"
37
                | "scheme"
38
                | "environment"
39
                | "user_agent"
40
                | "geo_continent"
41
                | "geo_country"
42
                | "geo_country_region"
43
                | "geo_city"
44
                | "geo_as_number"
45
                | "ja4_digest"
46
                | "ja3_digest"
47
                | "rate_limit_api_id";
48
              op:
49
                | "re"
50
                | "eq"
51
                | "neq"
52
                | "ex"
53
                | "nex"
54
                | "inc"
55
                | "ninc"
56
                | "pre"
57
                | "suf"
58
                | "sub"
59
                | "gt"
60
                | "gte"
61
                | "lt"
62
                | "lte";
63
              neg?: false | true;
64
              key?: string;
65
              value?: string | number | string[];
66
            }[];
67
          }[];
68
          action: {
69
            mitigate?: {
70
              action:
71
                | "log"
72
                | "challenge"
73
                | "deny"
74
                | "bypass"
75
                | "rate_limit"
76
                | "redirect";
77
              rateLimit?: {
78
                algo: "fixed_window" | "token_bucket";
79
                window: number;
80
                limit: number;
81
                keys: string[];
82
                action?: "log" | "challenge" | "deny" | "rate_limit";
83
              };
84
              redirect?: { location: string; permanent: false | true };
85
              actionDuration?: string;
86
              bypassSystem?: false | true;
87
            };
88
          };
89
        };
90
      }
91
    | {
92
        action: "rules.update";
93
        id: string;
94
        value: {
95
          name: string;
96
          description?: string;
97
          active: false | true;
98
          conditionGroup: {
99
            conditions: {
100
              type:
101
                | "host"
102
                | "path"
103
                | "method"
104
                | "header"
105
                | "query"
106
                | "cookie"
107
                | "target_path"
108
                | "raw_path"
109
                | "ip_address"
110
                | "region"
111
                | "protocol"
112
                | "scheme"
113
                | "environment"
114
                | "user_agent"
115
                | "geo_continent"
116
                | "geo_country"
117
                | "geo_country_region"
118
                | "geo_city"
119
                | "geo_as_number"
120
                | "ja4_digest"
121
                | "ja3_digest"
122
                | "rate_limit_api_id";
123
              op:
124
                | "re"
125
                | "eq"
126
                | "neq"
127
                | "ex"
128
                | "nex"
129
                | "inc"
130
                | "ninc"
131
                | "pre"
132
                | "suf"
133
                | "sub"
134
                | "gt"
135
                | "gte"
136
                | "lt"
137
                | "lte";
138
              neg?: false | true;
139
              key?: string;
140
              value?: string | number | string[];
141
            }[];
142
          }[];
143
          action: {
144
            mitigate?: {
145
              action:
146
                | "log"
147
                | "challenge"
148
                | "deny"
149
                | "bypass"
150
                | "rate_limit"
151
                | "redirect";
152
              rateLimit?: {
153
                algo: "fixed_window" | "token_bucket";
154
                window: number;
155
                limit: number;
156
                keys: string[];
157
                action?: "log" | "challenge" | "deny" | "rate_limit";
158
              };
159
              redirect?: { location: string; permanent: false | true };
160
              actionDuration?: string;
161
              bypassSystem?: false | true;
162
            };
163
          };
164
        };
165
      }
166
    | { action: "rules.remove"; id: string; value?: null }
167
    | { action: "rules.priority"; id: string; value: number }
168
    | {
169
        action: "crs.update";
170
        id:
171
          | "sd"
172
          | "ma"
173
          | "lfi"
174
          | "rfi"
175
          | "rce"
176
          | "php"
177
          | "gen"
178
          | "xss"
179
          | "sqli"
180
          | "sf"
181
          | "java";
182
        value: { active: false | true; action: "log" | "deny" };
183
      }
184
    | { action: "crs.disable"; id?: null; value?: null }
185
    | {
186
        action: "ip.insert";
187
        id?: null;
188
        value: {
189
          hostname: string;
190
          ip: string;
191
          notes?: string;
192
          action: "log" | "challenge" | "deny" | "bypass";
193
        };
194
      }
195
    | {
196
        action: "ip.update";
197
        id: string;
198
        value: {
199
          hostname: string;
200
          ip: string;
201
          notes?: string;
202
          action: "log" | "challenge" | "deny" | "bypass";
203
        };
204
      }
205
    | { action: "ip.remove"; id: string; value?: null }
206
    | {
207
        action: "managedRules.update";
208
        id: string;
209
        value: { action?: "log" | "challenge" | "deny"; active: false | true };
210
      }
211
    | { action: "managedRuleGroup.update"; id: string; value: {} },
212
) {
213
  const url = new URL(`https://api.vercel.com/v1/security/firewall/config`);
214
  for (const [k, v] of [
215
    ["projectId", projectId],
216
    ["teamId", teamId],
217
    ["slug", slug],
218
  ]) {
219
    if (v !== undefined && v !== "" && k !== undefined) {
220
      url.searchParams.append(k, v);
221
    }
222
  }
223
  const response = await fetch(url, {
224
    method: "PATCH",
225
    headers: {
226
      "Content-Type": "application/json",
227
      Authorization: "Bearer " + auth.token,
228
    },
229
    body: JSON.stringify(body),
230
  });
231
  if (!response.ok) {
232
    const text = await response.text();
233
    throw new Error(`${response.status} ${text}`);
234
  }
235
  return await response.json();
236
}
237