import { XMLParser } from "fast-xml-parser"
/**
* Push to device group
* Push the committed Panorama configuration to the firewalls of a device group (PAN-OS XML API, type=commit&action=all, commit-all shared-policy). Commit on Panorama first. Set devices (firewall serial numbers) to push to only those members; set exclude_template to leave out template changes. Returns the job id to follow with Get job status.
*/
export async function main(
auth: RT.PaloAltoPanos,
device_group: string,
description: string | undefined,
devices: string[] | undefined,
exclude_template: boolean | undefined
) {
let entry = `<entry name="${xmlEscape(device_group)}"`
if (devices?.length) {
entry += `><devices>${devices.map((d) => `<entry name="${xmlEscape(d)}"/>`).join("")}</devices></entry>`
} else {
entry += "/>"
}
let cmd = `<commit-all><shared-policy><device-group>${entry}</device-group>`
if (description) cmd += `<description>${xmlEscape(description)}</description>`
if (exclude_template) cmd += "<include-template>no</include-template>"
cmd += "</shared-policy></commit-all>"
const res = await xmlApi(auth, { type: "commit", action: "all", cmd })
return {
job_id: res.result?.job != null ? String(res.result.job) : null,
message:
res.result?.msg?.line ??
res.result?.msg ??
res.msg?.line ??
res.msg ??
null,
}
}
function xmlEscape(s: string) {
return s
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'")
}
async function xmlApi(auth: RT.PaloAltoPanos, params: { [key: string]: string }) {
const url = new URL("/api/", auth.base_url)
for (const [key, value] of Object.entries(params)) {
url.searchParams.set(key, value)
}
const response = await fetch(url, {
method: "POST",
headers: { "X-PAN-KEY": auth.api_key },
})
const text = await response.text()
if (!response.ok) {
throw new Error(`${response.status} ${text}`)
}
const parsed = new XMLParser({
ignoreAttributes: false,
attributeNamePrefix: "@",
parseTagValue: false,
}).parse(text)
if (parsed.response?.["@status"] !== "success") {
throw new Error(`${response.status} ${text}`)
}
return parsed.response
}
Submitted by hugo989 7 hours ago