<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Palo Alto Networks NGFW Best Practice Assessment (BPA) via the Posture API in General Topics</title>
    <link>https://live.paloaltonetworks.com/t5/general-topics/palo-alto-networks-ngfw-best-practice-assessment-bpa-via-the/m-p/1261352#M126845</link>
    <description>&lt;H1&gt;Palo Alto Networks NGFW Best Practice Assessment (BPA) via the Posture API&lt;/H1&gt;
&lt;P&gt;&lt;STRONG&gt;Client &amp;amp; Partner Implementation Guide — Windows PowerShell Workflow&lt;/STRONG&gt;&lt;/P&gt;
&lt;H2&gt;Purpose&lt;/H2&gt;
&lt;P&gt;This guide provides a practical end-to-end procedure for generating an on-demand &lt;STRONG&gt;Best Practice Assessment (BPA)&lt;/STRONG&gt; from a Palo Alto Networks firewall configuration using the &lt;STRONG&gt;Strata Cloud Manager Posture API&lt;/STRONG&gt;.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;Current workflow&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;The legacy manual On-Demand BPA dashboard was scheduled for deprecation on April 30, 2026. The Posture API is the current programmatic path for uploading NGFW/Panorama configuration files and retrieving machine-readable BPA results.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;Version:&lt;/STRONG&gt; 1.0&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Published:&lt;/STRONG&gt; August 2026&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Audience:&lt;/STRONG&gt; Customers, partners, presales, and security engineering teams&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;This document is implementation guidance. Palo Alto Networks UI labels and APIs can evolve; verify against current official documentation before production automation.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;HR /&gt;
&lt;H2&gt;Document Control&lt;/H2&gt;
&lt;TABLE style="border-collapse: collapse; width: 100%;" border="1" cellspacing="0" cellpadding="6"&gt;
&lt;THEAD&gt;
&lt;TR&gt;
&lt;TH&gt;Item&lt;/TH&gt;
&lt;TH&gt;Details&lt;/TH&gt;
&lt;/TR&gt;
&lt;/THEAD&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;STRONG&gt;Document&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD&gt;Palo Alto Networks NGFW BPA via Posture API&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;STRONG&gt;Scope&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD&gt;On-demand BPA from firewall XML configuration&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;STRONG&gt;Platform&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD&gt;Strata Cloud Manager Posture API&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;STRONG&gt;Shell&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD&gt;Windows PowerShell + &lt;CODE&gt;curl.exe&lt;/CODE&gt;&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;STRONG&gt;Sensitive inputs&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD&gt;Client Secret, OAuth token, signed upload URL, firewall XML configuration&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;
&lt;HR /&gt;
&lt;H2&gt;Contents&lt;/H2&gt;
&lt;OL&gt;
&lt;LI&gt;[Background and Migration Context](#1-background-and-migration-context)&lt;/LI&gt;
&lt;LI&gt;[Workflow Overview](#2-workflow-overview)&lt;/LI&gt;
&lt;LI&gt;[Prerequisites and Information to Collect](#3-prerequisites-and-information-to-collect)&lt;/LI&gt;
&lt;LI&gt;[Create the Palo Alto Networks Service Account](#4-create-the-palo-alto-networks-service-account)&lt;/LI&gt;
&lt;LI&gt;[Export the Firewall Configuration XML](#5-export-the-firewall-configuration-xml)&lt;/LI&gt;
&lt;LI&gt;[Run the BPA Workflow in PowerShell](#6-run-the-bpa-workflow-in-powershell)&lt;/LI&gt;
&lt;LI&gt;[Download and Format the BPA Result](#7-download-and-format-the-bpa-result)&lt;/LI&gt;
&lt;LI&gt;[Optional — Convert the BPA Best-Practice Results to CSV](#8-optional--convert-the-bpa-best-practice-results-to-csv)&lt;/LI&gt;
&lt;LI&gt;[Recommended Official References](#9-recommended-official-references)&lt;/LI&gt;
&lt;/OL&gt;
&lt;HR /&gt;
&lt;H1&gt;1. Background and Migration Context&lt;/H1&gt;
&lt;P&gt;Palo Alto Networks has moved the on-demand BPA workflow toward the &lt;STRONG&gt;Strata Cloud Manager Posture API&lt;/STRONG&gt;. The API accepts a configuration file from an NGFW or Panorama, processes it against Palo Alto Networks best-practice checks, and provides the assessment as structured JSON for downstream review or automation.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;Deprecation context&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;A Palo Alto Networks LIVEcommunity discussion captured the platform notice stating that the On-Demand BPA dashboard would be deprecated on April 30, 2026 and that customers should transition to the new Posture API. The Posture API documentation identifies the on-demand Best Practice report API as an available module.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;This guide focuses on a &lt;STRONG&gt;standalone NGFW export&lt;/STRONG&gt; and a &lt;STRONG&gt;Windows PowerShell workflow&lt;/STRONG&gt;. The same general API pattern can also be used with Panorama configuration files when the request metadata and configuration file are appropriate.&lt;/P&gt;
&lt;HR /&gt;
&lt;H1&gt;2. Workflow Overview&lt;/H1&gt;
&lt;P&gt;The workflow is:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Create a service account in &lt;STRONG&gt;Palo Alto Networks Common Services &amp;gt; Identity &amp;amp; Access&lt;/STRONG&gt;.&lt;/LI&gt;
&lt;LI&gt;Assign an API-capable role and securely record the &lt;STRONG&gt;Client ID&lt;/STRONG&gt;, &lt;STRONG&gt;Client Secret&lt;/STRONG&gt;, and &lt;STRONG&gt;TSG ID&lt;/STRONG&gt;.&lt;/LI&gt;
&lt;LI&gt;Export a named firewall configuration snapshot as XML.&lt;/LI&gt;
&lt;LI&gt;Use OAuth 2.0 client credentials to obtain an access token.&lt;/LI&gt;
&lt;LI&gt;Create a BPA upload task and receive a task ID plus a signed upload URL.&lt;/LI&gt;
&lt;LI&gt;Upload the XML configuration to the signed URL.&lt;/LI&gt;
&lt;LI&gt;Poll the BPA task until the status is &lt;CODE&gt;COMPLETED&lt;/CODE&gt; or &lt;CODE&gt;FAILED&lt;/CODE&gt;.&lt;/LI&gt;
&lt;LI&gt;Download the JSON result.&lt;/LI&gt;
&lt;LI&gt;Optionally convert the best-practice checks into a readable CSV.&lt;/LI&gt;
&lt;/OL&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;Important — API concurrency limit&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;The config-upload endpoint can return HTTP &lt;CODE&gt;429&lt;/CODE&gt; when the maximum number of active jobs is reached. Current Palo Alto Networks API documentation states a limit of five active jobs.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;HR /&gt;
&lt;H1&gt;3. Prerequisites and Information to Collect&lt;/H1&gt;
&lt;P&gt;Before starting, make sure you have:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Palo Alto Networks Hub / Activation Console access with permission to manage &lt;STRONG&gt;Identity &amp;amp; Access&lt;/STRONG&gt;.&lt;/LI&gt;
&lt;LI&gt;Administrative access to the target firewall sufficient to save and export a named configuration snapshot.&lt;/LI&gt;
&lt;LI&gt;Windows PowerShell.&lt;/LI&gt;
&lt;LI&gt;Windows &lt;CODE&gt;curl.exe&lt;/CODE&gt;.&lt;/LI&gt;
&lt;LI&gt;Outbound HTTPS access to:&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;auth.apps.paloaltonetworks.com&lt;/CODE&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;api.strata.paloaltonetworks.com&lt;/CODE&gt;&lt;/LI&gt;
&lt;LI&gt;Signed cloud-storage upload/download URLs returned by the API.&lt;/LI&gt;
&lt;LI&gt;The firewall:&lt;/LI&gt;
&lt;LI&gt;Model family&lt;/LI&gt;
&lt;LI&gt;Model&lt;/LI&gt;
&lt;LI&gt;Serial number&lt;/LI&gt;
&lt;LI&gt;PAN-OS version&lt;/LI&gt;
&lt;LI&gt;Requester name and email.&lt;/LI&gt;
&lt;LI&gt;A secure location for the exported XML and generated BPA report.&lt;/LI&gt;
&lt;/UL&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;Security — Configuration sensitivity&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;A firewall configuration can reveal policy structure, addresses, objects, user information, certificates/keys metadata, and internal architecture. Treat the XML file and BPA output as confidential security data.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;HR /&gt;
&lt;H1&gt;4. Create the Palo Alto Networks Service Account&lt;/H1&gt;
&lt;P&gt;Open the Palo Alto Networks Hub:&lt;/P&gt;
&lt;P&gt;&lt;A href="https://apps.paloaltonetworks.com/hub" target="_blank" rel="noopener"&gt;https://apps.paloaltonetworks.com/hub&lt;/A&gt;&lt;/P&gt;
&lt;H2&gt;4.1 Open Identity &amp;amp; Access&lt;/H2&gt;
&lt;P&gt;From the Hub / Activation Console, navigate to:&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Common Services &amp;gt; Identity &amp;amp; Access&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Select the tenant/TSG against which the API call will run.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="JeanPaul222_0-1786098299046.png" style="width: 400px;"&gt;&lt;img src="https://live.paloaltonetworks.com/t5/image/serverpage/image-id/72214iD9A939891502F8A7/image-size/medium?v=v2&amp;amp;px=400" role="button" title="JeanPaul222_0-1786098299046.png" alt="JeanPaul222_0-1786098299046.png" /&gt;&lt;/span&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;H2&gt;4.2 Add an Identity / Service Account&lt;/H2&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="JeanPaul222_1-1786098312985.png" style="width: 400px;"&gt;&lt;img src="https://live.paloaltonetworks.com/t5/image/serverpage/image-id/72215iBA8885FDA1404F01/image-size/medium?v=v2&amp;amp;px=400" role="button" title="JeanPaul222_1-1786098312985.png" alt="JeanPaul222_1-1786098312985.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;4.3 Create the Service Account&lt;/H2&gt;
&lt;P&gt;Create a clearly named service account dedicated to BPA/API usage.&lt;/P&gt;
&lt;P&gt;Use a name that allows the account owner and purpose to be identified during audits.&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="JeanPaul222_2-1786098327651.png" style="width: 400px;"&gt;&lt;img src="https://live.paloaltonetworks.com/t5/image/serverpage/image-id/72216i8524AEBE04EBBC04/image-size/medium?v=v2&amp;amp;px=400" role="button" title="JeanPaul222_2-1786098327651.png" alt="JeanPaul222_2-1786098327651.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;4.4 Save the Client ID, Client Secret, and TSG ID&lt;/H2&gt;
&lt;P&gt;Record the following values:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Client ID&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Client Secret&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Tenant Service Group (TSG) ID&lt;/STRONG&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;Palo Alto Networks documentation warns that the &lt;STRONG&gt;Client Secret cannot be retrieved again after creation&lt;/STRONG&gt;. If it is lost, reset or rotate the service account credentials.&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="JeanPaul222_3-1786098347950.png" style="width: 400px;"&gt;&lt;img src="https://live.paloaltonetworks.com/t5/image/serverpage/image-id/72217i22D88D6B7DAE61F6/image-size/medium?v=v2&amp;amp;px=400" role="button" title="JeanPaul222_3-1786098347950.png" alt="JeanPaul222_3-1786098347950.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;Security — Credential handling&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Store the Client Secret in an approved password/secret manager. Never place a real Client Secret, bearer token, or signed upload/download URL in client documentation, tickets, email, chat, or LIVEcommunity posts.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;H2&gt;4.5 Assign Roles&lt;/H2&gt;
&lt;P&gt;For the broad-access setup described in this workflow, assign:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Apps &amp;amp; Services:&lt;/STRONG&gt; All Apps &amp;amp; Services&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Role:&lt;/STRONG&gt; Superuser&lt;/LI&gt;
&lt;/UL&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Superuser provides unrestricted access. Use the minimum privileges appropriate for your environment whenever possible.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;HR /&gt;
&lt;H1&gt;5. Export the Firewall Configuration XML&lt;/H1&gt;
&lt;H2&gt;5.1 Save a Named Configuration Snapshot&lt;/H2&gt;
&lt;P&gt;On the firewall GUI, navigate to:&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Device &amp;gt; Setup &amp;gt; Operations&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Under &lt;STRONG&gt;Configuration Management&lt;/STRONG&gt;:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Select &lt;STRONG&gt;Save named configuration snapshot&lt;/STRONG&gt;.&lt;/LI&gt;
&lt;LI&gt;Enter a descriptive file name.&lt;/LI&gt;
&lt;LI&gt;Save the snapshot.&lt;/LI&gt;
&lt;/OL&gt;
&lt;H2&gt;5.2 Export the Named Configuration Snapshot&lt;/H2&gt;
&lt;P&gt;Still under:&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Device &amp;gt; Setup &amp;gt; Operations&lt;/STRONG&gt;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Select &lt;STRONG&gt;Export named configuration snapshot&lt;/STRONG&gt;.&lt;/LI&gt;
&lt;LI&gt;Choose the snapshot.&lt;/LI&gt;
&lt;LI&gt;Export it to the administrative workstation.&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;Palo Alto Networks exports the configuration as XML.&lt;/P&gt;
&lt;H2&gt;5.3 Record Device Metadata&lt;/H2&gt;
&lt;P&gt;Before opening PowerShell, record the values that will be used in the BPA request body:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Firewall family&lt;/LI&gt;
&lt;LI&gt;Model&lt;/LI&gt;
&lt;LI&gt;Serial number&lt;/LI&gt;
&lt;LI&gt;PAN-OS version&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;Use values that match the device whose XML configuration is being uploaded.&lt;/P&gt;
&lt;HR /&gt;
&lt;H1&gt;6. Run the BPA Workflow in PowerShell&lt;/H1&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;Important — PowerShell syntax&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;The commands below are provided inside fenced code blocks so that underscores, dollar signs, URLs, backticks, and other PowerShell characters remain unchanged when copied.&lt;/P&gt;
&lt;P&gt;Copy the entire command or block exactly as shown. When a command uses a PowerShell continuation backtick (`&lt;CODE&gt; &lt;/CODE&gt; ``), the backtick must be the final character on that line.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;H2&gt;Step 1 — Get an OAuth Access Token&lt;/H2&gt;
&lt;P&gt;Replace the placeholder values with the credentials from the Palo Alto Networks service account.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;$tokenResponse = Invoke-RestMethod -Method Post `
    -Uri "https://auth.apps.paloaltonetworks.com/oauth2/access_token" `
    -ContentType "application/x-www-form-urlencoded" `
    -Body @{
        grant_type    = "client_credentials"
        client_id     = "PASTE_YOUR_CLIENT_ID"
        client_secret = "PASTE_YOUR_CLIENT_SECRET"
        scope         = "tsg_id:PASTE_YOUR_TSG_ID"
    }

$token = $tokenResponse.access_token
$tokenResponse&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;The OAuth access token is stored in:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;$token&lt;/CODE&gt;&lt;/PRE&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;Security&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Do not post the real value of &lt;CODE&gt;$tokenResponse&lt;/CODE&gt;, &lt;CODE&gt;$token&lt;/CODE&gt;, your Client ID, or your Client Secret publicly.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;HR /&gt;
&lt;H2&gt;Step 2 — Prepare Headers and the BPA Request Body&lt;/H2&gt;
&lt;P&gt;Replace the placeholder values with the actual firewall and requester information.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;$headers = @{
    Authorization = "Bearer $token"
    Accept        = "application/json"
}

$body = @{
    family            = "FW_MODEL_FAMILY_E.g:400"
    model             = "MODEL_E.g:PA-450"
    "requester-email" = "YOUR_EMAIL"
    "requester-name"  = "YOUR_NAME"
    serial            = "FW_SERIAL_NB"
    version           = "FW_VERSION"
} | ConvertTo-Json&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Example values could look like:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;CODE&gt;family = "400"&lt;/CODE&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;model = "PA-450"&lt;/CODE&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;version = "12.1.7"&lt;/CODE&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;Use the actual values for the firewall being assessed.&lt;/P&gt;
&lt;HR /&gt;
&lt;H2&gt;Step 3 — Create the BPA Upload Task&lt;/H2&gt;
&lt;P&gt;Run:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;$bpa = Invoke-RestMethod -Method Post `
    -Uri "https://api.strata.paloaltonetworks.com/posture/checks/v1/reports/config-file-upload" `
    -Headers $headers `
    -ContentType "application/json" `
    -Body $body

$taskId = $bpa.task_id
$uploadUrl = $bpa.upload_url

$bpa&lt;/CODE&gt;&lt;/PRE&gt;
&lt;H3&gt;Expected Result&lt;/H3&gt;
&lt;P&gt;The response should contain:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;A BPA task/tracking ID&lt;/LI&gt;
&lt;LI&gt;A signed upload URL&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;The values are stored in:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;$taskId
$uploadUrl&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Keep the same PowerShell window/session open so these variables remain available.&lt;/P&gt;
&lt;HR /&gt;
&lt;H2&gt;Step 4 — Select and Validate the Raw XML File&lt;/H2&gt;
&lt;P&gt;Set &lt;CODE&gt;$src&lt;/CODE&gt; to the actual location of the exported firewall XML file.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;$src="C:\Users\YourUser\Downloads\FirewallConfig.xml"&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Validate the path:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;Test-Path $src&lt;/CODE&gt;&lt;/PRE&gt;
&lt;H3&gt;Expected Result&lt;/H3&gt;
&lt;PRE&gt;&lt;CODE class="language-text"&gt;True&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Do not continue until &lt;CODE&gt;Test-Path&lt;/CODE&gt; returns &lt;CODE&gt;True&lt;/CODE&gt;.&lt;/P&gt;
&lt;HR /&gt;
&lt;H2&gt;Step 5 — Upload the Raw XML to the Signed URL&lt;/H2&gt;
&lt;P&gt;Run:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;curl.exe -v `
    -X PUT "$uploadUrl" `
    -H "Content-Type: text/plain" `
    -H "Content-Encoding: gzip" `
    --data-binary "@$src"&lt;/CODE&gt;&lt;/PRE&gt;
&lt;BLOCKQUOTE&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="JeanPaul222_4-1786098422565.png" style="width: 400px;"&gt;&lt;img src="https://live.paloaltonetworks.com/t5/image/serverpage/image-id/72218i003616278D68FC62/image-size/medium?v=v2&amp;amp;px=400" role="button" title="JeanPaul222_4-1786098422565.png" alt="JeanPaul222_4-1786098422565.png" /&gt;&lt;/span&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;HR /&gt;
&lt;H2&gt;Step 6 — Poll the BPA Task Until Completion&lt;/H2&gt;
&lt;P&gt;Run:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;curl.exe -v `
    -X GET "https://api.strata.paloaltonetworks.com/posture/checks/v1/reports/$taskId/bpa-result" `
    -H "Authorization: Bearer $token" `
    -H "Accept: application/json"&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;The documented task states include:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;CODE&gt;QUEUED&lt;/CODE&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;IN_PROGRESS&lt;/CODE&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;COMPLETED&lt;/CODE&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;FAILED&lt;/CODE&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;Continue to the download step only after the BPA status is:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-text"&gt;COMPLETED&lt;BR /&gt;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="JeanPaul222_5-1786098493750.png" style="width: 400px;"&gt;&lt;img src="https://live.paloaltonetworks.com/t5/image/serverpage/image-id/72219i7C675F7E13C571CF/image-size/medium?v=v2&amp;amp;px=400" role="button" title="JeanPaul222_5-1786098493750.png" alt="JeanPaul222_5-1786098493750.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;H1&gt;7. Download and Format the BPA Result&lt;/H1&gt;
&lt;H2&gt;7.1 Retrieve the Completed BPA Response&lt;/H2&gt;
&lt;P&gt;Run:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;$response = Invoke-RestMethod -Uri "https://api.strata.paloaltonetworks.com/posture/checks/v1/reports/$taskId/bpa-result" -Headers @{ "Accept"="application/json"; "Authorization"="Bearer $token" }&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;To inspect the returned object:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;$response | ConvertTo-Json -Depth 20&lt;/CODE&gt;&lt;/PRE&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;If the download property is empty&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;First confirm that the task status is &lt;CODE&gt;COMPLETED&lt;/CODE&gt;. API response schemas can evolve, so the returned payload should be treated as the source of truth.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;HR /&gt;
&lt;H2&gt;7.2 Extract the Download URL&lt;/H2&gt;
&lt;P&gt;Run:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;$downloadUrl = $response.result.custom_check_url&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Confirm that the variable contains a URL:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;$downloadUrl&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;It should return an HTTPS URL rather than a blank value.&lt;/P&gt;
&lt;HR /&gt;
&lt;H2&gt;7.3 Download the Raw JSON Result&lt;/H2&gt;
&lt;P&gt;To download the report into the current PowerShell directory:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;Invoke-WebRequest -Uri $downloadUrl -OutFile "BPA_Report_$($taskId).json"&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;To download the report directly into the current user's &lt;STRONG&gt;Downloads&lt;/STRONG&gt; folder:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;$rawJsonPath = Join-Path $HOME "Downloads\BPA_Report_$($taskId).json"; Invoke-WebRequest -Uri $downloadUrl -OutFile $rawJsonPath; Write-Host "BPA report downloaded to: $rawJsonPath"&lt;/CODE&gt;&lt;/PRE&gt;
&lt;HR /&gt;
&lt;H2&gt;7.4 Optional — Save a Formatted / Indented JSON Copy&lt;/H2&gt;
&lt;P&gt;The following single PowerShell command downloads the returned JSON, parses it, formats it with indentation, and saves it under the user's Downloads folder:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;$downloadPath = Join-Path $HOME "Downloads\BPA_Report_$($taskId).json"; $reportContent = Invoke-RestMethod -Uri $downloadUrl; $reportContent | ConvertTo-Json -Depth 100 | Set-Content -Path $downloadPath -Encoding UTF8; Write-Host "Report downloaded and formatted at: $downloadPath"&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;The generated file will look similar to:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-text"&gt;C:\Users\&amp;lt;username&amp;gt;\Downloads\BPA_Report_&amp;lt;task-id&amp;gt;.json&lt;/CODE&gt;&lt;/PRE&gt;
&lt;HR /&gt;
&lt;H1&gt;8. Optional — Convert the BPA Best-Practice Results to CSV&lt;/H1&gt;
&lt;P&gt;The following PowerShell command flattens the nested best-practice warning/check structure into rows that can be filtered more easily in Excel.&lt;/P&gt;
&lt;P&gt;It also sanitizes the device hostname before using it in the Windows filename.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Run this after &lt;CODE&gt;$reportContent&lt;/CODE&gt; has been populated in Step 7.4.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;$deviceName=[string]$reportContent.information.device_hostname; if([string]::IsNullOrWhiteSpace($deviceName)){$deviceName="UnknownDevice"}; $safeDeviceName=$deviceName -replace '[&amp;lt;&amp;gt;:"/\\|?*]','_'; $csvPath=Join-Path $HOME "Downloads\BPA_$($safeDeviceName)_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv"; $rows=foreach($section in $reportContent.best_practices.PSObject.Properties){if($null -eq $section.Value){continue}; foreach($configType in $section.Value.PSObject.Properties){if($null -eq $configType.Value){continue}; foreach($item in @($configType.Value)){if($null -eq $item -or $null -eq $item.warnings){continue}; foreach($check in @($item.warnings)){if($null -eq $check){continue}; $status=if($check.check_excluded -eq $true){"Excluded"}elseif($check.check_passed -eq $true){"Passed"}else{"Failed"}; $configName=if($item.configuration.name){[string]$item.configuration.name}elseif($item.configuration.location){[string]$item.configuration.location}else{[string]$configType.Name}; $failedFields=if($null -ne $check.failed_fields){$check.failed_fields | ConvertTo-Json -Depth 100 -Compress}else{""}; [pscustomobject][ordered]@{"Device Hostname"=$deviceName;"Device IP"=[string]$reportContent.information.device_ip_address;"PAN-OS Version"=[string]$reportContent.information.PanOS_version;"Section"=[string]$section.Name;"Configuration Type"=[string]$configType.Name;"Configuration Name"=$configName;"Location"=[string]$item.configuration.location;"Status"=$status;"Check ID"=$check.check_id;"Check Type"=[string]$check.check_type;"Check Name"=[string]$check.check_name;"Check Message"=[string]$check.check_message;"Failed Fields"=$failedFields;"Excluded"=if($check.check_excluded -eq $true){"Yes"}else{"No"};"Defined By"=[string]$check.defined_by;"UUID"=[string]$check.uuid}}}}}; $rows | Export-Csv -Path $csvPath -NoTypeInformation -Encoding UTF8; Write-Host "Readable CSV created at: $csvPath"; Invoke-Item $csvPath&lt;/CODE&gt;&lt;/PRE&gt;
&lt;H3&gt;Result&lt;/H3&gt;
&lt;P&gt;The command:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Reads the firewall hostname from the BPA JSON.&lt;/LI&gt;
&lt;LI&gt;Replaces characters that are invalid in Windows filenames.&lt;/LI&gt;
&lt;LI&gt;Iterates through the &lt;CODE&gt;best_practices&lt;/CODE&gt; sections.&lt;/LI&gt;
&lt;LI&gt;Extracts each warning/check.&lt;/LI&gt;
&lt;LI&gt;Assigns a readable status:&lt;/LI&gt;
&lt;/OL&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;CODE&gt;Passed&lt;/CODE&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;Failed&lt;/CODE&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;Excluded&lt;/CODE&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;OL&gt;
&lt;LI&gt;Exports the results to a timestamped CSV file in the user's Downloads folder.&lt;/LI&gt;
&lt;LI&gt;Opens the generated CSV automatically.&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;Example output filename:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-text"&gt;BPA_LBCRPA-450_20260807_124500.csv&lt;/CODE&gt;&lt;/PRE&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;Schema dependency&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;The CSV conversion assumes the BPA JSON contains &lt;CODE&gt;information&lt;/CODE&gt; and &lt;CODE&gt;best_practices&lt;/CODE&gt; structures consistent with the current report shape. If Palo Alto Networks changes the JSON schema, inspect the raw JSON and adjust the field paths.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;HR /&gt;
&lt;H1&gt;9. Recommended Official References&lt;/H1&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="https://pan.dev/scm/api/config/posture-management/introduction-posture/" target="_blank" rel="noopener"&gt;Palo Alto Networks Developer — Posture API Introduction&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="https://pan.dev/scm/api/config/posture-management/initiate-config-upload/" target="_blank" rel="noopener"&gt;Palo Alto Networks Developer — Initiate a Configuration Upload&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="https://pan.dev/scm/api/config/posture-management/get-bpa-result-by-id/" target="_blank" rel="noopener"&gt;Palo Alto Networks Developer — Get BPA Processing Status&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="https://pan.dev/scm/docs/getstarted/" target="_blank" rel="noopener"&gt;Palo Alto Networks Developer — Getting Started / OAuth&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="https://pan.dev/scm/docs/service-accounts/" target="_blank" rel="noopener"&gt;Palo Alto Networks Developer — Service Accounts&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="https://docs.paloaltonetworks.com/common-services/identity-and-access-access-management/manage-identity-and-access/add-service-accounts" target="_blank" rel="noopener"&gt;Palo Alto Networks Docs — Add a Service Account through Common Services&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="https://docs.paloaltonetworks.com/common-services/identity-and-access-access-management/manage-identity-and-access/about-roles-and-permissions" target="_blank" rel="noopener"&gt;Palo Alto Networks Docs — Roles and Permissions&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="https://docs.paloaltonetworks.com/ngfw/administration/firewall-administration/manage-configuration-backups/save-and-export-firewall-configurations" target="_blank" rel="noopener"&gt;Palo Alto Networks Docs — Save and Export Firewall Configurations&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="https://live.paloaltonetworks.com/t5/strata-cloud-manager/bd-p/Strata-Cloud-Manager" target="_blank" rel="noopener"&gt;Palo Alto Networks LIVEcommunity — Strata Cloud Manager Discussions&lt;/A&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;HR /&gt;
&lt;H2&gt;Author&lt;/H2&gt;
&lt;P&gt;&lt;STRONG&gt;JeanPaul Mansour | Systems Engineer&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Crestan International&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;A href="https://www.crestanint.com" target="_blank" rel="noopener"&gt;www.crestanint.com&lt;/A&gt;&lt;/P&gt;
&lt;HR /&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;Community note&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;If you use this workflow in production, validate the returned API schema and endpoint behavior against the latest Palo Alto Networks documentation before incorporating it into automation.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;</description>
    <pubDate>Fri, 07 Aug 2026 10:31:42 GMT</pubDate>
    <dc:creator>JeanPaul222</dc:creator>
    <dc:date>2026-08-07T10:31:42Z</dc:date>
    <item>
      <title>Palo Alto Networks NGFW Best Practice Assessment (BPA) via the Posture API</title>
      <link>https://live.paloaltonetworks.com/t5/general-topics/palo-alto-networks-ngfw-best-practice-assessment-bpa-via-the/m-p/1261352#M126845</link>
      <description>&lt;H1&gt;Palo Alto Networks NGFW Best Practice Assessment (BPA) via the Posture API&lt;/H1&gt;
&lt;P&gt;&lt;STRONG&gt;Client &amp;amp; Partner Implementation Guide — Windows PowerShell Workflow&lt;/STRONG&gt;&lt;/P&gt;
&lt;H2&gt;Purpose&lt;/H2&gt;
&lt;P&gt;This guide provides a practical end-to-end procedure for generating an on-demand &lt;STRONG&gt;Best Practice Assessment (BPA)&lt;/STRONG&gt; from a Palo Alto Networks firewall configuration using the &lt;STRONG&gt;Strata Cloud Manager Posture API&lt;/STRONG&gt;.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;Current workflow&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;The legacy manual On-Demand BPA dashboard was scheduled for deprecation on April 30, 2026. The Posture API is the current programmatic path for uploading NGFW/Panorama configuration files and retrieving machine-readable BPA results.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;Version:&lt;/STRONG&gt; 1.0&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Published:&lt;/STRONG&gt; August 2026&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Audience:&lt;/STRONG&gt; Customers, partners, presales, and security engineering teams&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;This document is implementation guidance. Palo Alto Networks UI labels and APIs can evolve; verify against current official documentation before production automation.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;HR /&gt;
&lt;H2&gt;Document Control&lt;/H2&gt;
&lt;TABLE style="border-collapse: collapse; width: 100%;" border="1" cellspacing="0" cellpadding="6"&gt;
&lt;THEAD&gt;
&lt;TR&gt;
&lt;TH&gt;Item&lt;/TH&gt;
&lt;TH&gt;Details&lt;/TH&gt;
&lt;/TR&gt;
&lt;/THEAD&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;STRONG&gt;Document&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD&gt;Palo Alto Networks NGFW BPA via Posture API&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;STRONG&gt;Scope&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD&gt;On-demand BPA from firewall XML configuration&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;STRONG&gt;Platform&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD&gt;Strata Cloud Manager Posture API&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;STRONG&gt;Shell&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD&gt;Windows PowerShell + &lt;CODE&gt;curl.exe&lt;/CODE&gt;&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;STRONG&gt;Sensitive inputs&lt;/STRONG&gt;&lt;/TD&gt;
&lt;TD&gt;Client Secret, OAuth token, signed upload URL, firewall XML configuration&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;
&lt;HR /&gt;
&lt;H2&gt;Contents&lt;/H2&gt;
&lt;OL&gt;
&lt;LI&gt;[Background and Migration Context](#1-background-and-migration-context)&lt;/LI&gt;
&lt;LI&gt;[Workflow Overview](#2-workflow-overview)&lt;/LI&gt;
&lt;LI&gt;[Prerequisites and Information to Collect](#3-prerequisites-and-information-to-collect)&lt;/LI&gt;
&lt;LI&gt;[Create the Palo Alto Networks Service Account](#4-create-the-palo-alto-networks-service-account)&lt;/LI&gt;
&lt;LI&gt;[Export the Firewall Configuration XML](#5-export-the-firewall-configuration-xml)&lt;/LI&gt;
&lt;LI&gt;[Run the BPA Workflow in PowerShell](#6-run-the-bpa-workflow-in-powershell)&lt;/LI&gt;
&lt;LI&gt;[Download and Format the BPA Result](#7-download-and-format-the-bpa-result)&lt;/LI&gt;
&lt;LI&gt;[Optional — Convert the BPA Best-Practice Results to CSV](#8-optional--convert-the-bpa-best-practice-results-to-csv)&lt;/LI&gt;
&lt;LI&gt;[Recommended Official References](#9-recommended-official-references)&lt;/LI&gt;
&lt;/OL&gt;
&lt;HR /&gt;
&lt;H1&gt;1. Background and Migration Context&lt;/H1&gt;
&lt;P&gt;Palo Alto Networks has moved the on-demand BPA workflow toward the &lt;STRONG&gt;Strata Cloud Manager Posture API&lt;/STRONG&gt;. The API accepts a configuration file from an NGFW or Panorama, processes it against Palo Alto Networks best-practice checks, and provides the assessment as structured JSON for downstream review or automation.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;Deprecation context&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;A Palo Alto Networks LIVEcommunity discussion captured the platform notice stating that the On-Demand BPA dashboard would be deprecated on April 30, 2026 and that customers should transition to the new Posture API. The Posture API documentation identifies the on-demand Best Practice report API as an available module.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;This guide focuses on a &lt;STRONG&gt;standalone NGFW export&lt;/STRONG&gt; and a &lt;STRONG&gt;Windows PowerShell workflow&lt;/STRONG&gt;. The same general API pattern can also be used with Panorama configuration files when the request metadata and configuration file are appropriate.&lt;/P&gt;
&lt;HR /&gt;
&lt;H1&gt;2. Workflow Overview&lt;/H1&gt;
&lt;P&gt;The workflow is:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Create a service account in &lt;STRONG&gt;Palo Alto Networks Common Services &amp;gt; Identity &amp;amp; Access&lt;/STRONG&gt;.&lt;/LI&gt;
&lt;LI&gt;Assign an API-capable role and securely record the &lt;STRONG&gt;Client ID&lt;/STRONG&gt;, &lt;STRONG&gt;Client Secret&lt;/STRONG&gt;, and &lt;STRONG&gt;TSG ID&lt;/STRONG&gt;.&lt;/LI&gt;
&lt;LI&gt;Export a named firewall configuration snapshot as XML.&lt;/LI&gt;
&lt;LI&gt;Use OAuth 2.0 client credentials to obtain an access token.&lt;/LI&gt;
&lt;LI&gt;Create a BPA upload task and receive a task ID plus a signed upload URL.&lt;/LI&gt;
&lt;LI&gt;Upload the XML configuration to the signed URL.&lt;/LI&gt;
&lt;LI&gt;Poll the BPA task until the status is &lt;CODE&gt;COMPLETED&lt;/CODE&gt; or &lt;CODE&gt;FAILED&lt;/CODE&gt;.&lt;/LI&gt;
&lt;LI&gt;Download the JSON result.&lt;/LI&gt;
&lt;LI&gt;Optionally convert the best-practice checks into a readable CSV.&lt;/LI&gt;
&lt;/OL&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;Important — API concurrency limit&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;The config-upload endpoint can return HTTP &lt;CODE&gt;429&lt;/CODE&gt; when the maximum number of active jobs is reached. Current Palo Alto Networks API documentation states a limit of five active jobs.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;HR /&gt;
&lt;H1&gt;3. Prerequisites and Information to Collect&lt;/H1&gt;
&lt;P&gt;Before starting, make sure you have:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Palo Alto Networks Hub / Activation Console access with permission to manage &lt;STRONG&gt;Identity &amp;amp; Access&lt;/STRONG&gt;.&lt;/LI&gt;
&lt;LI&gt;Administrative access to the target firewall sufficient to save and export a named configuration snapshot.&lt;/LI&gt;
&lt;LI&gt;Windows PowerShell.&lt;/LI&gt;
&lt;LI&gt;Windows &lt;CODE&gt;curl.exe&lt;/CODE&gt;.&lt;/LI&gt;
&lt;LI&gt;Outbound HTTPS access to:&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;auth.apps.paloaltonetworks.com&lt;/CODE&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;api.strata.paloaltonetworks.com&lt;/CODE&gt;&lt;/LI&gt;
&lt;LI&gt;Signed cloud-storage upload/download URLs returned by the API.&lt;/LI&gt;
&lt;LI&gt;The firewall:&lt;/LI&gt;
&lt;LI&gt;Model family&lt;/LI&gt;
&lt;LI&gt;Model&lt;/LI&gt;
&lt;LI&gt;Serial number&lt;/LI&gt;
&lt;LI&gt;PAN-OS version&lt;/LI&gt;
&lt;LI&gt;Requester name and email.&lt;/LI&gt;
&lt;LI&gt;A secure location for the exported XML and generated BPA report.&lt;/LI&gt;
&lt;/UL&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;Security — Configuration sensitivity&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;A firewall configuration can reveal policy structure, addresses, objects, user information, certificates/keys metadata, and internal architecture. Treat the XML file and BPA output as confidential security data.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;HR /&gt;
&lt;H1&gt;4. Create the Palo Alto Networks Service Account&lt;/H1&gt;
&lt;P&gt;Open the Palo Alto Networks Hub:&lt;/P&gt;
&lt;P&gt;&lt;A href="https://apps.paloaltonetworks.com/hub" target="_blank" rel="noopener"&gt;https://apps.paloaltonetworks.com/hub&lt;/A&gt;&lt;/P&gt;
&lt;H2&gt;4.1 Open Identity &amp;amp; Access&lt;/H2&gt;
&lt;P&gt;From the Hub / Activation Console, navigate to:&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Common Services &amp;gt; Identity &amp;amp; Access&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Select the tenant/TSG against which the API call will run.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="JeanPaul222_0-1786098299046.png" style="width: 400px;"&gt;&lt;img src="https://live.paloaltonetworks.com/t5/image/serverpage/image-id/72214iD9A939891502F8A7/image-size/medium?v=v2&amp;amp;px=400" role="button" title="JeanPaul222_0-1786098299046.png" alt="JeanPaul222_0-1786098299046.png" /&gt;&lt;/span&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;H2&gt;4.2 Add an Identity / Service Account&lt;/H2&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="JeanPaul222_1-1786098312985.png" style="width: 400px;"&gt;&lt;img src="https://live.paloaltonetworks.com/t5/image/serverpage/image-id/72215iBA8885FDA1404F01/image-size/medium?v=v2&amp;amp;px=400" role="button" title="JeanPaul222_1-1786098312985.png" alt="JeanPaul222_1-1786098312985.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;4.3 Create the Service Account&lt;/H2&gt;
&lt;P&gt;Create a clearly named service account dedicated to BPA/API usage.&lt;/P&gt;
&lt;P&gt;Use a name that allows the account owner and purpose to be identified during audits.&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="JeanPaul222_2-1786098327651.png" style="width: 400px;"&gt;&lt;img src="https://live.paloaltonetworks.com/t5/image/serverpage/image-id/72216i8524AEBE04EBBC04/image-size/medium?v=v2&amp;amp;px=400" role="button" title="JeanPaul222_2-1786098327651.png" alt="JeanPaul222_2-1786098327651.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;H2&gt;4.4 Save the Client ID, Client Secret, and TSG ID&lt;/H2&gt;
&lt;P&gt;Record the following values:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Client ID&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Client Secret&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Tenant Service Group (TSG) ID&lt;/STRONG&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;Palo Alto Networks documentation warns that the &lt;STRONG&gt;Client Secret cannot be retrieved again after creation&lt;/STRONG&gt;. If it is lost, reset or rotate the service account credentials.&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="JeanPaul222_3-1786098347950.png" style="width: 400px;"&gt;&lt;img src="https://live.paloaltonetworks.com/t5/image/serverpage/image-id/72217i22D88D6B7DAE61F6/image-size/medium?v=v2&amp;amp;px=400" role="button" title="JeanPaul222_3-1786098347950.png" alt="JeanPaul222_3-1786098347950.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;Security — Credential handling&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Store the Client Secret in an approved password/secret manager. Never place a real Client Secret, bearer token, or signed upload/download URL in client documentation, tickets, email, chat, or LIVEcommunity posts.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;H2&gt;4.5 Assign Roles&lt;/H2&gt;
&lt;P&gt;For the broad-access setup described in this workflow, assign:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;Apps &amp;amp; Services:&lt;/STRONG&gt; All Apps &amp;amp; Services&lt;/LI&gt;
&lt;LI&gt;&lt;STRONG&gt;Role:&lt;/STRONG&gt; Superuser&lt;/LI&gt;
&lt;/UL&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Superuser provides unrestricted access. Use the minimum privileges appropriate for your environment whenever possible.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;HR /&gt;
&lt;H1&gt;5. Export the Firewall Configuration XML&lt;/H1&gt;
&lt;H2&gt;5.1 Save a Named Configuration Snapshot&lt;/H2&gt;
&lt;P&gt;On the firewall GUI, navigate to:&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Device &amp;gt; Setup &amp;gt; Operations&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Under &lt;STRONG&gt;Configuration Management&lt;/STRONG&gt;:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Select &lt;STRONG&gt;Save named configuration snapshot&lt;/STRONG&gt;.&lt;/LI&gt;
&lt;LI&gt;Enter a descriptive file name.&lt;/LI&gt;
&lt;LI&gt;Save the snapshot.&lt;/LI&gt;
&lt;/OL&gt;
&lt;H2&gt;5.2 Export the Named Configuration Snapshot&lt;/H2&gt;
&lt;P&gt;Still under:&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Device &amp;gt; Setup &amp;gt; Operations&lt;/STRONG&gt;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Select &lt;STRONG&gt;Export named configuration snapshot&lt;/STRONG&gt;.&lt;/LI&gt;
&lt;LI&gt;Choose the snapshot.&lt;/LI&gt;
&lt;LI&gt;Export it to the administrative workstation.&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;Palo Alto Networks exports the configuration as XML.&lt;/P&gt;
&lt;H2&gt;5.3 Record Device Metadata&lt;/H2&gt;
&lt;P&gt;Before opening PowerShell, record the values that will be used in the BPA request body:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Firewall family&lt;/LI&gt;
&lt;LI&gt;Model&lt;/LI&gt;
&lt;LI&gt;Serial number&lt;/LI&gt;
&lt;LI&gt;PAN-OS version&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;Use values that match the device whose XML configuration is being uploaded.&lt;/P&gt;
&lt;HR /&gt;
&lt;H1&gt;6. Run the BPA Workflow in PowerShell&lt;/H1&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;Important — PowerShell syntax&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;The commands below are provided inside fenced code blocks so that underscores, dollar signs, URLs, backticks, and other PowerShell characters remain unchanged when copied.&lt;/P&gt;
&lt;P&gt;Copy the entire command or block exactly as shown. When a command uses a PowerShell continuation backtick (`&lt;CODE&gt; &lt;/CODE&gt; ``), the backtick must be the final character on that line.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;H2&gt;Step 1 — Get an OAuth Access Token&lt;/H2&gt;
&lt;P&gt;Replace the placeholder values with the credentials from the Palo Alto Networks service account.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;$tokenResponse = Invoke-RestMethod -Method Post `
    -Uri "https://auth.apps.paloaltonetworks.com/oauth2/access_token" `
    -ContentType "application/x-www-form-urlencoded" `
    -Body @{
        grant_type    = "client_credentials"
        client_id     = "PASTE_YOUR_CLIENT_ID"
        client_secret = "PASTE_YOUR_CLIENT_SECRET"
        scope         = "tsg_id:PASTE_YOUR_TSG_ID"
    }

$token = $tokenResponse.access_token
$tokenResponse&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;The OAuth access token is stored in:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;$token&lt;/CODE&gt;&lt;/PRE&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;Security&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Do not post the real value of &lt;CODE&gt;$tokenResponse&lt;/CODE&gt;, &lt;CODE&gt;$token&lt;/CODE&gt;, your Client ID, or your Client Secret publicly.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;HR /&gt;
&lt;H2&gt;Step 2 — Prepare Headers and the BPA Request Body&lt;/H2&gt;
&lt;P&gt;Replace the placeholder values with the actual firewall and requester information.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;$headers = @{
    Authorization = "Bearer $token"
    Accept        = "application/json"
}

$body = @{
    family            = "FW_MODEL_FAMILY_E.g:400"
    model             = "MODEL_E.g:PA-450"
    "requester-email" = "YOUR_EMAIL"
    "requester-name"  = "YOUR_NAME"
    serial            = "FW_SERIAL_NB"
    version           = "FW_VERSION"
} | ConvertTo-Json&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Example values could look like:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;CODE&gt;family = "400"&lt;/CODE&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;model = "PA-450"&lt;/CODE&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;version = "12.1.7"&lt;/CODE&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;Use the actual values for the firewall being assessed.&lt;/P&gt;
&lt;HR /&gt;
&lt;H2&gt;Step 3 — Create the BPA Upload Task&lt;/H2&gt;
&lt;P&gt;Run:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;$bpa = Invoke-RestMethod -Method Post `
    -Uri "https://api.strata.paloaltonetworks.com/posture/checks/v1/reports/config-file-upload" `
    -Headers $headers `
    -ContentType "application/json" `
    -Body $body

$taskId = $bpa.task_id
$uploadUrl = $bpa.upload_url

$bpa&lt;/CODE&gt;&lt;/PRE&gt;
&lt;H3&gt;Expected Result&lt;/H3&gt;
&lt;P&gt;The response should contain:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;A BPA task/tracking ID&lt;/LI&gt;
&lt;LI&gt;A signed upload URL&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;The values are stored in:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;$taskId
$uploadUrl&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Keep the same PowerShell window/session open so these variables remain available.&lt;/P&gt;
&lt;HR /&gt;
&lt;H2&gt;Step 4 — Select and Validate the Raw XML File&lt;/H2&gt;
&lt;P&gt;Set &lt;CODE&gt;$src&lt;/CODE&gt; to the actual location of the exported firewall XML file.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;$src="C:\Users\YourUser\Downloads\FirewallConfig.xml"&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Validate the path:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;Test-Path $src&lt;/CODE&gt;&lt;/PRE&gt;
&lt;H3&gt;Expected Result&lt;/H3&gt;
&lt;PRE&gt;&lt;CODE class="language-text"&gt;True&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Do not continue until &lt;CODE&gt;Test-Path&lt;/CODE&gt; returns &lt;CODE&gt;True&lt;/CODE&gt;.&lt;/P&gt;
&lt;HR /&gt;
&lt;H2&gt;Step 5 — Upload the Raw XML to the Signed URL&lt;/H2&gt;
&lt;P&gt;Run:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;curl.exe -v `
    -X PUT "$uploadUrl" `
    -H "Content-Type: text/plain" `
    -H "Content-Encoding: gzip" `
    --data-binary "@$src"&lt;/CODE&gt;&lt;/PRE&gt;
&lt;BLOCKQUOTE&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="JeanPaul222_4-1786098422565.png" style="width: 400px;"&gt;&lt;img src="https://live.paloaltonetworks.com/t5/image/serverpage/image-id/72218i003616278D68FC62/image-size/medium?v=v2&amp;amp;px=400" role="button" title="JeanPaul222_4-1786098422565.png" alt="JeanPaul222_4-1786098422565.png" /&gt;&lt;/span&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;HR /&gt;
&lt;H2&gt;Step 6 — Poll the BPA Task Until Completion&lt;/H2&gt;
&lt;P&gt;Run:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;curl.exe -v `
    -X GET "https://api.strata.paloaltonetworks.com/posture/checks/v1/reports/$taskId/bpa-result" `
    -H "Authorization: Bearer $token" `
    -H "Accept: application/json"&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;The documented task states include:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;CODE&gt;QUEUED&lt;/CODE&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;IN_PROGRESS&lt;/CODE&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;COMPLETED&lt;/CODE&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;FAILED&lt;/CODE&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;Continue to the download step only after the BPA status is:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-text"&gt;COMPLETED&lt;BR /&gt;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="JeanPaul222_5-1786098493750.png" style="width: 400px;"&gt;&lt;img src="https://live.paloaltonetworks.com/t5/image/serverpage/image-id/72219i7C675F7E13C571CF/image-size/medium?v=v2&amp;amp;px=400" role="button" title="JeanPaul222_5-1786098493750.png" alt="JeanPaul222_5-1786098493750.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;H1&gt;7. Download and Format the BPA Result&lt;/H1&gt;
&lt;H2&gt;7.1 Retrieve the Completed BPA Response&lt;/H2&gt;
&lt;P&gt;Run:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;$response = Invoke-RestMethod -Uri "https://api.strata.paloaltonetworks.com/posture/checks/v1/reports/$taskId/bpa-result" -Headers @{ "Accept"="application/json"; "Authorization"="Bearer $token" }&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;To inspect the returned object:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;$response | ConvertTo-Json -Depth 20&lt;/CODE&gt;&lt;/PRE&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;If the download property is empty&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;First confirm that the task status is &lt;CODE&gt;COMPLETED&lt;/CODE&gt;. API response schemas can evolve, so the returned payload should be treated as the source of truth.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;HR /&gt;
&lt;H2&gt;7.2 Extract the Download URL&lt;/H2&gt;
&lt;P&gt;Run:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;$downloadUrl = $response.result.custom_check_url&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Confirm that the variable contains a URL:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;$downloadUrl&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;It should return an HTTPS URL rather than a blank value.&lt;/P&gt;
&lt;HR /&gt;
&lt;H2&gt;7.3 Download the Raw JSON Result&lt;/H2&gt;
&lt;P&gt;To download the report into the current PowerShell directory:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;Invoke-WebRequest -Uri $downloadUrl -OutFile "BPA_Report_$($taskId).json"&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;To download the report directly into the current user's &lt;STRONG&gt;Downloads&lt;/STRONG&gt; folder:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;$rawJsonPath = Join-Path $HOME "Downloads\BPA_Report_$($taskId).json"; Invoke-WebRequest -Uri $downloadUrl -OutFile $rawJsonPath; Write-Host "BPA report downloaded to: $rawJsonPath"&lt;/CODE&gt;&lt;/PRE&gt;
&lt;HR /&gt;
&lt;H2&gt;7.4 Optional — Save a Formatted / Indented JSON Copy&lt;/H2&gt;
&lt;P&gt;The following single PowerShell command downloads the returned JSON, parses it, formats it with indentation, and saves it under the user's Downloads folder:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;$downloadPath = Join-Path $HOME "Downloads\BPA_Report_$($taskId).json"; $reportContent = Invoke-RestMethod -Uri $downloadUrl; $reportContent | ConvertTo-Json -Depth 100 | Set-Content -Path $downloadPath -Encoding UTF8; Write-Host "Report downloaded and formatted at: $downloadPath"&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;The generated file will look similar to:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-text"&gt;C:\Users\&amp;lt;username&amp;gt;\Downloads\BPA_Report_&amp;lt;task-id&amp;gt;.json&lt;/CODE&gt;&lt;/PRE&gt;
&lt;HR /&gt;
&lt;H1&gt;8. Optional — Convert the BPA Best-Practice Results to CSV&lt;/H1&gt;
&lt;P&gt;The following PowerShell command flattens the nested best-practice warning/check structure into rows that can be filtered more easily in Excel.&lt;/P&gt;
&lt;P&gt;It also sanitizes the device hostname before using it in the Windows filename.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;Run this after &lt;CODE&gt;$reportContent&lt;/CODE&gt; has been populated in Step 7.4.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;PRE&gt;&lt;CODE class="language-powershell"&gt;$deviceName=[string]$reportContent.information.device_hostname; if([string]::IsNullOrWhiteSpace($deviceName)){$deviceName="UnknownDevice"}; $safeDeviceName=$deviceName -replace '[&amp;lt;&amp;gt;:"/\\|?*]','_'; $csvPath=Join-Path $HOME "Downloads\BPA_$($safeDeviceName)_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv"; $rows=foreach($section in $reportContent.best_practices.PSObject.Properties){if($null -eq $section.Value){continue}; foreach($configType in $section.Value.PSObject.Properties){if($null -eq $configType.Value){continue}; foreach($item in @($configType.Value)){if($null -eq $item -or $null -eq $item.warnings){continue}; foreach($check in @($item.warnings)){if($null -eq $check){continue}; $status=if($check.check_excluded -eq $true){"Excluded"}elseif($check.check_passed -eq $true){"Passed"}else{"Failed"}; $configName=if($item.configuration.name){[string]$item.configuration.name}elseif($item.configuration.location){[string]$item.configuration.location}else{[string]$configType.Name}; $failedFields=if($null -ne $check.failed_fields){$check.failed_fields | ConvertTo-Json -Depth 100 -Compress}else{""}; [pscustomobject][ordered]@{"Device Hostname"=$deviceName;"Device IP"=[string]$reportContent.information.device_ip_address;"PAN-OS Version"=[string]$reportContent.information.PanOS_version;"Section"=[string]$section.Name;"Configuration Type"=[string]$configType.Name;"Configuration Name"=$configName;"Location"=[string]$item.configuration.location;"Status"=$status;"Check ID"=$check.check_id;"Check Type"=[string]$check.check_type;"Check Name"=[string]$check.check_name;"Check Message"=[string]$check.check_message;"Failed Fields"=$failedFields;"Excluded"=if($check.check_excluded -eq $true){"Yes"}else{"No"};"Defined By"=[string]$check.defined_by;"UUID"=[string]$check.uuid}}}}}; $rows | Export-Csv -Path $csvPath -NoTypeInformation -Encoding UTF8; Write-Host "Readable CSV created at: $csvPath"; Invoke-Item $csvPath&lt;/CODE&gt;&lt;/PRE&gt;
&lt;H3&gt;Result&lt;/H3&gt;
&lt;P&gt;The command:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Reads the firewall hostname from the BPA JSON.&lt;/LI&gt;
&lt;LI&gt;Replaces characters that are invalid in Windows filenames.&lt;/LI&gt;
&lt;LI&gt;Iterates through the &lt;CODE&gt;best_practices&lt;/CODE&gt; sections.&lt;/LI&gt;
&lt;LI&gt;Extracts each warning/check.&lt;/LI&gt;
&lt;LI&gt;Assigns a readable status:&lt;/LI&gt;
&lt;/OL&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;CODE&gt;Passed&lt;/CODE&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;Failed&lt;/CODE&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;CODE&gt;Excluded&lt;/CODE&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;OL&gt;
&lt;LI&gt;Exports the results to a timestamped CSV file in the user's Downloads folder.&lt;/LI&gt;
&lt;LI&gt;Opens the generated CSV automatically.&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;Example output filename:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class="language-text"&gt;BPA_LBCRPA-450_20260807_124500.csv&lt;/CODE&gt;&lt;/PRE&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;Schema dependency&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;The CSV conversion assumes the BPA JSON contains &lt;CODE&gt;information&lt;/CODE&gt; and &lt;CODE&gt;best_practices&lt;/CODE&gt; structures consistent with the current report shape. If Palo Alto Networks changes the JSON schema, inspect the raw JSON and adjust the field paths.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;HR /&gt;
&lt;H1&gt;9. Recommended Official References&lt;/H1&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="https://pan.dev/scm/api/config/posture-management/introduction-posture/" target="_blank" rel="noopener"&gt;Palo Alto Networks Developer — Posture API Introduction&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="https://pan.dev/scm/api/config/posture-management/initiate-config-upload/" target="_blank" rel="noopener"&gt;Palo Alto Networks Developer — Initiate a Configuration Upload&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="https://pan.dev/scm/api/config/posture-management/get-bpa-result-by-id/" target="_blank" rel="noopener"&gt;Palo Alto Networks Developer — Get BPA Processing Status&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="https://pan.dev/scm/docs/getstarted/" target="_blank" rel="noopener"&gt;Palo Alto Networks Developer — Getting Started / OAuth&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="https://pan.dev/scm/docs/service-accounts/" target="_blank" rel="noopener"&gt;Palo Alto Networks Developer — Service Accounts&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="https://docs.paloaltonetworks.com/common-services/identity-and-access-access-management/manage-identity-and-access/add-service-accounts" target="_blank" rel="noopener"&gt;Palo Alto Networks Docs — Add a Service Account through Common Services&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="https://docs.paloaltonetworks.com/common-services/identity-and-access-access-management/manage-identity-and-access/about-roles-and-permissions" target="_blank" rel="noopener"&gt;Palo Alto Networks Docs — Roles and Permissions&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="https://docs.paloaltonetworks.com/ngfw/administration/firewall-administration/manage-configuration-backups/save-and-export-firewall-configurations" target="_blank" rel="noopener"&gt;Palo Alto Networks Docs — Save and Export Firewall Configurations&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="https://live.paloaltonetworks.com/t5/strata-cloud-manager/bd-p/Strata-Cloud-Manager" target="_blank" rel="noopener"&gt;Palo Alto Networks LIVEcommunity — Strata Cloud Manager Discussions&lt;/A&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;HR /&gt;
&lt;H2&gt;Author&lt;/H2&gt;
&lt;P&gt;&lt;STRONG&gt;JeanPaul Mansour | Systems Engineer&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Crestan International&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;&lt;A href="https://www.crestanint.com" target="_blank" rel="noopener"&gt;www.crestanint.com&lt;/A&gt;&lt;/P&gt;
&lt;HR /&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;STRONG&gt;Community note&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;If you use this workflow in production, validate the returned API schema and endpoint behavior against the latest Palo Alto Networks documentation before incorporating it into automation.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;</description>
      <pubDate>Fri, 07 Aug 2026 10:31:42 GMT</pubDate>
      <guid>https://live.paloaltonetworks.com/t5/general-topics/palo-alto-networks-ngfw-best-practice-assessment-bpa-via-the/m-p/1261352#M126845</guid>
      <dc:creator>JeanPaul222</dc:creator>
      <dc:date>2026-08-07T10:31:42Z</dc:date>
    </item>
  </channel>
</rss>

