1 | |
2 |
|
3 | |
4 | * List security rules |
5 | * List the security policy rules of a firewall vsys, or the pre or post rules of a Panorama device group or the shared location (PAN-OS REST API), in rulebase order. PAN-OS returns every rule of the rulebase in one response; the API does not paginate. |
6 | */ |
7 | export async function main( |
8 | auth: RT.PaloAltoPanos, |
9 | location: "vsys" | "device-group" | "shared" | undefined, |
10 | vsys: string | undefined, |
11 | device_group: string | undefined, |
12 | rulebase: "pre" | "post" | undefined |
13 | ) { |
14 | const version = await restApiVersion(auth) |
15 | const url = new URL( |
16 | `/restapi/${version}/Policies/${ruleResource(location, rulebase)}`, |
17 | auth.base_url |
18 | ) |
19 | setLocation(url, location, vsys, device_group) |
20 |
|
21 | const response = await fetch(url, { |
22 | headers: { "X-PAN-KEY": auth.api_key, Accept: "application/json" }, |
23 | }) |
24 | const text = await response.text() |
25 | if (!response.ok) { |
26 | throw new Error(`${response.status} ${text}`) |
27 | } |
28 | const data = JSON.parse(text) |
29 | if (data["@status"] !== "success") { |
30 | throw new Error(`${response.status} ${text}`) |
31 | } |
32 | return data |
33 | } |
34 |
|
35 | |
36 | function ruleResource( |
37 | location: string | undefined, |
38 | rulebase: string | undefined |
39 | ) { |
40 | if ((location || "vsys") === "vsys") return "SecurityRules" |
41 | return rulebase === "post" ? "SecurityPostRules" : "SecurityPreRules" |
42 | } |
43 |
|
44 | function setLocation( |
45 | url: URL, |
46 | location: string | undefined, |
47 | vsys: string | undefined, |
48 | device_group: string | undefined |
49 | ) { |
50 | const loc = location || "vsys" |
51 | url.searchParams.set("location", loc) |
52 | if (loc === "vsys") { |
53 | url.searchParams.set("vsys", vsys || "vsys1") |
54 | } else if (loc === "device-group") { |
55 | if (!device_group) { |
56 | throw new Error("device_group is required when location is device-group") |
57 | } |
58 | url.searchParams.set("device-group", device_group) |
59 | } |
60 | } |
61 |
|
62 | async function restApiVersion(auth: RT.PaloAltoPanos) { |
63 | if (auth.rest_api_version) return auth.rest_api_version |
64 | const url = new URL("/api/", auth.base_url) |
65 | url.searchParams.set("type", "op") |
66 | url.searchParams.set("cmd", "<show><system><info></info></system></show>") |
67 | const response = await fetch(url, { headers: { "X-PAN-KEY": auth.api_key } }) |
68 | const text = await response.text() |
69 | if (!response.ok || text.includes('status="error"')) { |
70 | throw new Error(`${response.status} ${text}`) |
71 | } |
72 | const match = text.match(/<sw-version>(\d+)\.(\d+)/) |
73 | if (!match) { |
74 | throw new Error( |
75 | `Could not read sw-version from show system info; set rest_api_version on the resource. ${text}` |
76 | ) |
77 | } |
78 | return `v${match[1]}.${match[2]}` |
79 | } |
80 |
|