0

Commit

by
Published today

Commit the candidate configuration on a firewall, or on Panorama itself (PAN-OS XML API, type=commit). Set admins for a partial commit of only those administrators' changes. Returns the commit job id to follow with Get job status, or a null job id with the device message when there is nothing to commit. On Panorama this does not push to firewalls: use Push to device group.

Script palo_alto_panos Verified

The script

Submitted by hugo989 Bun
Verified 7 hours ago
1
import { XMLParser } from "fast-xml-parser"
2

3
/**
4
 * Commit
5
 * Commit the candidate configuration on a firewall, or on Panorama itself (PAN-OS XML API, type=commit). Set admins for a partial commit of only those administrators' changes. Returns the commit job id to follow with Get job status, or a null job id with the device message when there is nothing to commit. On Panorama this does not push to firewalls: use Push to device group.
6
 */
7
export async function main(
8
  auth: RT.PaloAltoPanos,
9
  description: string | undefined,
10
  admins: string[] | undefined
11
) {
12
  let cmd = "<commit>"
13
  if (description) cmd += `<description>${xmlEscape(description)}</description>`
14
  if (admins?.length) {
15
    cmd += `<partial><admin>${admins.map((a) => `<member>${xmlEscape(a)}</member>`).join("")}</admin></partial>`
16
  }
17
  cmd += "</commit>"
18

19
  const res = await xmlApi(auth, { type: "commit", cmd })
20
  return {
21
    job_id: res.result?.job != null ? String(res.result.job) : null,
22
    message:
23
      res.result?.msg?.line ??
24
      res.result?.msg ??
25
      res.msg?.line ??
26
      res.msg ??
27
      null,
28
  }
29
}
30

31
function xmlEscape(s: string) {
32
  return s
33
    .replace(/&/g, "&amp;")
34
    .replace(/</g, "&lt;")
35
    .replace(/>/g, "&gt;")
36
    .replace(/"/g, "&quot;")
37
    .replace(/'/g, "&apos;")
38
}
39

40
async function xmlApi(auth: RT.PaloAltoPanos, params: { [key: string]: string }) {
41
  const url = new URL("/api/", auth.base_url)
42
  for (const [key, value] of Object.entries(params)) {
43
    url.searchParams.set(key, value)
44
  }
45
  const response = await fetch(url, {
46
    method: "POST",
47
    headers: { "X-PAN-KEY": auth.api_key },
48
  })
49
  const text = await response.text()
50
  if (!response.ok) {
51
    throw new Error(`${response.status} ${text}`)
52
  }
53
  const parsed = new XMLParser({
54
    ignoreAttributes: false,
55
    attributeNamePrefix: "@",
56
    parseTagValue: false,
57
  }).parse(text)
58
  if (parsed.response?.["@status"] !== "success") {
59
    throw new Error(`${response.status} ${text}`)
60
  }
61
  return parsed.response
62
}
63