iron-skillet Administrator & Developer Guide

Generated April 2026 from PaloAltoNetworks/iron-skillet at 9833373

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

Unofficial, AI-generated guide for a Palo Alto Networks open-source repository; not reviewed by Palo Alto Networks.

iron-skillet is the Palo Alto Networks day-1 configuration baseline — a curated set of Jinja2-templated PAN-OS XML snippets, pre-rendered full configurations, set-command CLI scripts, and Skillet playlists that encode hardened defaults for the NGFW and Panorama. There is no runtime, no daemon, no API: the deliverable is configuration. The repo is a build-tree of templates and the audience is the engineer who will load the rendered output onto a Palo Alto Networks device.

This guide is for administrators, security architects, and developers who want to integrate IronSkillet into a device-bring-up pipeline, extend it with site-specific snippets, audit its security posture, or fork it for a custom PAN-OS version.


1. Architecture Overview

IronSkillet is a template package, not a service. It has three artifact tiers — snippets, playlists, and pre-rendered configs — and a small toolchain that converts between them.

1.1 What it does

Given a Palo Alto Networks NGFW or Panorama in factory state, IronSkillet produces XML (or set-command CLI text) that, when imported and committed, configures:

  • Management-plane hardening — login banner, password complexity (12-char min, complexity rules, 24-history), 5-attempt admin lockout, 10-minute idle timeout, auto-acquire commit lock, configurable API key lifetime, optional SSH-only management, optional static or DHCP management IP.
  • System services — DNS, NTP, timezone (UTC), hostname, SNMPv3 access setting, dynamic-update schedules (threats every 30 min, antivirus hourly, WildFire real-time, GlobalProtect data-file hourly).
  • Threat prevention profiles — antivirus, anti-spyware (with DNS sinkhole IPv4 / IPv6), vulnerability protection, file-blocking, URL filtering, WildFire analysis, SSL decryption profile.
  • Profile groups — Outbound, Inbound, Internal, Alert-All, Default.
  • Custom URL categories — Block, Allow, Custom-No-Decrypt.
  • Tags — Outbound, Inbound, Internal, iron-skillet-version.
  • Rulebase scaffolding — default security rules, sample security rules, decryption rules, and zone-protection profiles.
  • Logging — shared log-settings (email, syslog, log-forwarding, user-id-forwarding, HIP-forwarding, GlobalProtect-forwarding, IP-tag-forwarding, correlation-forwarding) plus log-forwarding profiles for traffic / threat / WildFire / URL / data / tunnel / auth log types.
  • Reports & email — simple report set, report group, email scheduler.
  • Panorama overlay — same surface, applied to a configurable template-stack (STACK) and device-group (DEVICE_GROUP), with shared / not-shared / DG-template / DG-stack variants.

1.2 Architecture diagram

                        ┌──────────────────────────┐
                        │   templates/panos/       │
                        │   templates/panorama/    │
                        │   .meta-cnc.yaml         │
                        │   (snippets + variables) │
                        └────────────┬─────────────┘
                                     │
                                     │ select subset
                                     │
                  ┌──────────────────▼──────────────────┐
                  │   playlists/panos/*.skillet.yaml    │
                  │   playlists/panorama/*.skillet.yaml │
                  │   (curated playlists, "include" +   │
                  │    "when" conditionals)             │
                  └──────────────────┬──────────────────┘
                                     │
                                     │ render
                                     │
        ┌──────────────────┬─────────▼─────────┬──────────────────┐
        │                  │                   │                  │
        │  SLI tool        │  Panhandler       │  pan-cnc /       │
        │  (CLI, sli)      │  (Docker GUI)     │  legacy archive  │
        │                  │                   │  scripts         │
        └─────────┬────────┴────────┬──────────┴────────┬─────────┘
                  │                 │                   │
                  └─────────────────┼───────────────────┘
                                    │
                                    │ Jinja2 substitution + md5_hash filter
                                    │
                ┌───────────────────▼───────────────────┐
                │  Rendered output:                     │
                │   • iron_skillet_panos_full.xml       │
                │   • iron_skillet_panorama_full.xml    │
                │   • iron_skillet_panos_full.conf      │  (set commands)
                │   • iron_skillet_panos_full.xlsx      │  (variable spreadsheet)
                └───────────────────┬───────────────────┘
                                    │
                                    │ load_config / load_set / web UI import
                                    │
                ┌───────────────────▼───────────────────┐
                │  PAN-OS NGFW or Panorama device       │
                │  (candidate config → commit)          │
                └───────────────────────────────────────┘

1.3 Component inventory

Component Path Role
PAN-OS snippet master templates/panos/snippets/.meta-cnc.yaml Embedded-element snippets + variable inventory for the NGFW
Panorama snippet master templates/panorama/snippets/.meta-cnc.yaml Same, for Panorama (shared values)
Panorama legacy variants templates/panorama/snippets_dgtemplate_shared/, snippets_dgstack_notshared/, snippets_notshared/ Legacy skillet model (separate XML files); deprecated per their READMEs
Pre-rendered NGFW XML templates/panos/full/iron_skillet_panos_full.xml Full IronSkillet XML for NGFW
Pre-rendered Panorama XML templates/panorama/full/iron_skillet_panorama_full.xml Full IronSkillet XML for Panorama
Set-command output templates/panos/set_commands/, templates/panorama/set_commands/ Pre-rendered set commands and .xlsx
Baseline templates/panos/baseline/baseline.xml, templates/panorama/baseline/baseline.xml Empty starting config (rollback target)
NGFW playlists playlists/panos/panos_*.skillet.yaml Alert-only, device-hardening, full, security-profiles
Panorama playlists playlists/panorama/panorama_*.skillet.yaml Device-hardening, notshared (full + dgstack), shared (full + dgtemplate + security-profiles)
Loadable configs loadable_configs/sample-{cloud-AWS,cloud-Azure,cloud-GCP,mgmt-dhcp,mgmt-static,set-commands}/ Pre-rendered, ready-to-load XML/CONF for six common scenarios
Validations validations/panos/IronSkillet_assessment_panos/, IronSkillet_v10x_update_panos/ Skillet-Validation reports for posture checks
Shared report template validations/shared_report/report.yml Validation dashboard (stats_block + table) shared across versions
Build script tools/build_all.sh Regenerates full templates, loadable configs, and spreadsheets
Submodule helper tools/update_submodules.sh Keeps cross-version submodule pointers in sync
Archive scripts tools/archive/build_all.py, build_full_templates.py, create_loadable_configs.py, create_set_spreadsheet.py, test_full_config.py, test_set_commands.py Legacy Python helpers, pre-SLI
Sphinx docs docs/conf.py, docs/index.rst, docs/notice.rst, docs/Makefile Hosted at iron-skillet.readthedocs.io
Submodule mounts submodules/, .gitmodules Cross-PAN-OS-version overlays

1.4 Technology stack

Layer Technology Notes
Templating Jinja2 (>=2.10.1) {{ VAR }} substitution + {% if %}, custom md5_hash filter
Skillet schema .meta-cnc.yaml (legacy) and .skillet.yaml (current) Embedded-element model uses the latter
Rendering toolchain SLI (pip install sli), Panhandler (Docker), pan-cnc All consume the same .meta-cnc.yaml / .skillet.yaml
Output formats PAN-OS XML, PAN-OS set-command CLI, Excel .xlsx Spreadsheet generated via XlsxWriter
Documentation Sphinx (docs/Makefile, docs/conf.py), readthedocs Static
Submodule layout git submodules per PAN-OS major.minor tools/update_submodules.sh

Note

The repo's design rationale is that every PAN-OS major.minor lives on a parallel branch (e.g. panos_v10_1) instead of inside a version subdirectory of one branch. This keeps schema changes between PAN-OS versions cleanly bisectable and means a checkout at commit 9833373 on panos_v10_1 shows exactly the 10.1 templates — no other version's XML mixed in.

1.5 Data flow for the main workflow

The "fresh device bring-up" flow walks left-to-right through the diagram:

  1. The operator selects a playlist (e.g. panos_full.skillet.yaml).
  2. They supply variable values (or accept defaults) via SLI / Panhandler.
  3. The renderer:
    • Resolves include: directives — pulls each named snippet from templates/panos/snippets/.meta-cnc.yaml.
    • Evaluates when: clauses (e.g. config_admin_user == 'yes') and drops snippets whose condition is false.
    • Substitutes {{ VAR }} placeholders, applying filters such as md5_hash for the admin password.
    • Concatenates the resulting XML elements in playlist order at the correct XPaths.
  4. The operator imports the rendered XML via the device UI or via sli load_config -uc. The device places it in the candidate configuration.
  5. commit activates it.

2. System Requirements

2.1 Target devices

Device Supported Versions Notes
PAN-OS NGFW Branch panos_v10_1 carries the 10.1 templates Older versions live on parallel branches
Panorama Same branch model — panos_v10_1 ships Panorama 10.1 templates Variants for shared / not-shared / DG-template / DG-stack topologies

2.2 Build-host requirements

For administrators who plan to render templates on a build host (CI, operator workstation):

Requirement Detail
Operating system Linux, macOS, or Windows (anywhere Python or Docker runs)
Python (for SLI and archive scripts) Python 3.6+ for sli; Python 3.7–3.9 for the legacy tools/archive/ scripts due to MarkupSafe==1.0 and PyYAML==5.4 pins
Docker (for Panhandler) Any modern Docker engine that can pull paloaltonetworks/panhandler
Disk A clone is ~50 MB; rendered output per scenario is <2 MB
Network Outbound to GitHub for clone, optional outbound to the device's management IP for sli load_config / API push

2.3 Python dependencies (legacy archive only)

tools/archive/requirements.txt — used only by the historical build_all.py / build_full_templates.py / create_loadable_configs.py flow:

Jinja2>=2.10.1
MarkupSafe==1.0
oyaml==0.7
passlib==1.7.1
PyYAML==5.4
XlsxWriter==1.1.2
requests==2.22.0
pexpect==4.7.0
pan-python==0.14.0

Note

SLI / Panhandler / pan-cnc do not use this requirements file — their dependencies are managed by their own packaging. Only run pip install -r tools/archive/requirements.txt if you specifically need the archived scripts.

2.4 Licenses needed on the device

Skillet feature Required PAN-OS license
Antivirus profiles Antivirus subscription
Anti-spyware + DNS sinkhole Threat Prevention
Vulnerability profiles Threat Prevention
URL filtering profiles URL Filtering subscription
WildFire analysis profiles WildFire subscription
SSL decryption profiles (Decryption is included; no additional license)
INCLUDE_PAN_EDL=yes external dynamic lists Threat Prevention

Important

Loading IronSkillet on a device without the matching subscriptions won't break the commit, but the corresponding profile actions become no-ops at traffic time. The default rulebase is built around active subscriptions; treat the licenses as a hard prerequisite.


3. Configuration Reference

This is the complete inventory of variables, files, and snippets at commit 9833373 on the panos_v10_1 branch. Use it as the canonical source of truth — when the README, the spreadsheet, or a downstream clone disagree, the .meta-cnc.yaml files win.

3.1 Configuration files

File Format Location Purpose
Snippet master (NGFW) YAML (.meta-cnc.yaml) templates/panos/snippets/.meta-cnc.yaml Snippet bodies + variable inventory for PAN-OS NGFW
Snippet master (Panorama) YAML templates/panorama/snippets/.meta-cnc.yaml Same, Panorama
Full XML output (NGFW) XML templates/panos/full/iron_skillet_panos_full.xml Rendered full NGFW config
Full XML output (Panorama) XML templates/panorama/full/iron_skillet_panorama_full.xml Rendered full Panorama config
Full set-command (NGFW) text templates/panos/set_commands/iron_skillet_panos_full.conf Rendered full NGFW set-command CLI
Full set-command (Panorama) text templates/panorama/set_commands/iron_skillet_panorama_full.conf Rendered full Panorama set-command CLI
Variable spreadsheet (NGFW) Excel templates/panos/set_commands/iron_skillet_panos_full.xlsx Variable + set-command spreadsheet
Variable spreadsheet (Panorama) Excel templates/panorama/set_commands/iron_skillet_panorama_full.xlsx Same, Panorama
Baseline (NGFW) XML templates/panos/baseline/baseline.xml Rollback target for NGFW
Baseline (Panorama) XML templates/panorama/baseline/baseline.xml Rollback target for Panorama
NGFW playlists YAML playlists/panos/panos_*.skillet.yaml 4 playlists
Panorama playlists YAML playlists/panorama/panorama_*.skillet.yaml 6 playlists
Loadable configs XML / .conf loadable_configs/sample-*/ 12 ready-to-load files (6 scenarios x 2 device types)
Sphinx config Python docs/conf.py Documentation generator
Sphinx Makefile Make docs/Makefile (SPHINXPROJ = iron-skillet, BUILDDIR = _build) Builds the readthedocs site
Build orchestrator Bash tools/build_all.sh Regenerate full templates / loadable configs / spreadsheets
Submodule helper Bash tools/update_submodules.sh Keep cross-version submodule pointers fresh
Archive build Python tools/archive/build_all.py Legacy build orchestrator
Archive sub-builds Python tools/archive/build_full_templates.py, create_loadable_configs.py, create_set_spreadsheet.py, test_full_config.py, test_set_commands.py Pre-SLI helpers
Validation report (shared) YAML validations/shared_report/report.yml Skillet-Validation dashboard schema
NGFW assessment validation YAML validations/panos/IronSkillet_assessment_panos/.meta-cnc.yaml Posture-check skillet
NGFW v10x update validation YAML validations/panos/IronSkillet_v10x_update_panos/.meta-cnc.yaml Update-pre-flight skillet
Repo gitignore text .gitignore
Submodule manifest text .gitmodules
Repo metadata Markdown README.md, CONTRIBUTING.md, SUPPORT.md, LICENSE

3.2 NGFW variables — complete inventory

Every variable defined in templates/panos/snippets/.meta-cnc.yaml at commit 9833373. The Type column maps to the type_hint: field; the Toggle column captures toggle_hint: parent gating.

Variable Type Default Toggle Description
config_mgmt_intf dropdown (yes/no) no — Render management-interface IP settings
config_admin_user dropdown (yes/no) no — Create the IronSkillet admin user
config_dns dropdown (yes/no) no — Render DNS settings
MGMT_TYPE dropdown (dhcp-client/static) dhcp-client config_mgmt_intf == yes Management IP mode
MGMT_IP ip_address 192.0.2.6 MGMT_TYPE == static Management IP
MGMT_MASK ip_address 255.255.255.0 MGMT_TYPE == static Management netmask
MGMT_DG ip_address 192.0.2.7 MGMT_TYPE == static Management default gateway
DNS_1 ip_address 8.8.8.8 config_dns == yes Primary DNS
DNS_2 ip_address 8.8.4.4 config_dns == yes Secondary DNS
FW_NAME text panos-01 — Firewall hostname
NTP_1 text 0.pool.ntp.org — Primary NTP
NTP_2 text 1.pool.ntp.org — Secondary NTP
API_KEY_LIFETIME text 525600 — API key lifetime in minutes (one year)
ADMINISTRATOR_USERNAME text adminuser config_admin_user == yes Admin username
ADMINISTRATOR_PASSWORD password adminuser config_admin_user == yes Admin password (hashed via md5_hash)
SYSLOG_SERVER text 192.0.2.2 — Syslog server IP
EMAIL_PROFILE_GATEWAY text 192.0.2.1 — SMTP gateway for email alerts
EMAIL_PROFILE_FROM text [email removed] — From-address for email alerts
EMAIL_PROFILE_TO text [email removed] — To-address for email alerts
SINKHOLE_IPV4 text sinkhole.paloaltonetworks.com — DNS sinkhole FQDN (anti-spyware)
SINKHOLE_IPV6 ip_address 2600:5200::1 — DNS sinkhole IPv6
INCLUDE_PAN_EDL dropdown (yes/no) no — Include predefined PAN External Dynamic Lists in the rulebase

Important

The ADMINISTRATOR_PASSWORD default (adminuser) is a placeholder. Override it before rendering. The Jinja md5_hash filter writes its hash into the rendered XML's <phash> element — see Section 7.4 on handling rendered configs.

3.3 Panorama variables — complete inventory

From templates/panorama/snippets/.meta-cnc.yaml:

Variable Type Default Toggle Description
config_admin_panorama dropdown (yes/no) no — Render Panorama admin user
config_mgmt_intf_panorama dropdown (yes/no) no — Render Panorama management-IP settings
PANORAMA_TYPE dropdown (static/cloud) static config_mgmt_intf_panorama == yes Static IP or cloud (DHCP)
PANORAMA_IP ip_address 192.168.55.7 PANORAMA_TYPE == static Panorama mgmt IP
PANORAMA_MASK ip_address 255.255.255.0 PANORAMA_TYPE == static Panorama netmask
PANORAMA_DG ip_address 192.168.55.2 PANORAMA_TYPE == static Panorama default gateway
PANORAMA_NAME text panorama01 — Panorama hostname
DNS_1 ip_address 8.8.8.8 — Primary DNS
DNS_2 ip_address 8.8.4.4 — Secondary DNS
NTP_1 text 0.pool.ntp.org — Primary NTP
NTP_2 text 1.pool.ntp.org — Secondary NTP
CONFIG_EXPORT_IP text 192.0.2.3 — Scheduled-config-export destination
ADMINISTRATOR_USERNAME text adminuser — Admin user
ADMINISTRATOR_PASSWORD password adminuser — Admin password (md5-hashed)
API_KEY_LIFETIME text 525600 — Same as NGFW
EMAIL_PROFILE_GATEWAY text 192.0.2.1 — SMTP gateway
EMAIL_PROFILE_FROM text [email removed] — From-address
EMAIL_PROFILE_TO text [email removed] — To-address
SYSLOG_SERVER text 192.0.2.2 — Syslog destination
SINKHOLE_IPV4 text sinkhole.paloaltonetworks.com — DNS sinkhole FQDN
SINKHOLE_IPV6 ip_address 2600:5200::1 — DNS sinkhole IPv6
INCLUDE_PAN_EDL dropdown (yes/no) no — Include PAN EDLs
STACK text sample_stack — Template-stack name (interpolated into XPaths)
FW_NAME text sample — Device name for managed NGFW
MGMT_TYPE dropdown (dhcp-client/static) dhcp-client — Managed-firewall mgmt-IP mode
MGMT_IP ip_address 192.0.2.6 MGMT_TYPE == static Managed-firewall mgmt IP
MGMT_MASK ip_address 255.255.255.0 MGMT_TYPE == static Managed-firewall netmask
MGMT_DG ip_address 192.0.2.7 MGMT_TYPE == static Managed-firewall default gateway
DEVICE_GROUP text sample_devicegroup — Device-group name (interpolated into XPaths)

3.4 Playlist override variables

Playlist files in playlists/ can re-declare variables. The override matrix:

Playlist Adds / overrides
playlists/panos/panos_full.skillet.yaml config_mgmt_intf, config_admin_user, config_dns (re-declared)
playlists/panos/panos_alert_only.skillet.yaml None — uses snippet defaults
playlists/panos/panos_device_hardening.skillet.yaml None
playlists/panos/panos_security_profiles.skillet.yaml None
playlists/panorama/panorama_shared_full.skillet.yaml config_admin_panorama, config_mgmt_intf_panorama
playlists/panorama/panorama_notshared_full.skillet.yaml config_admin_panorama, config_mgmt_intf_panorama, STACK, DEVICE_GROUP
playlists/panorama/panorama_notshared_dgstack.skillet.yaml STACK, DEVICE_GROUP
playlists/panorama/panorama_shared_dgtemplate.skillet.yaml None
playlists/panorama/panorama_shared_security_profiles.skillet.yaml None
playlists/panorama/panorama_device_hardening.skillet.yaml None

3.5 Snippet inventory (NGFW)

The named snippets in the master templates/panos/snippets/.meta-cnc.yaml, each with its target XPath:

Snippet (parent.element) Target XPath
panos_ngfw_device_system_mgmt_ip_10_1.ironskillet_device_system_mgmt_type /config/devices/entry/deviceconfig/system
panos_ngfw_device_system_dns_10_1.ironskillet_device_system_servers /config/devices/entry/deviceconfig/system/dns-setting
panos_ngfw_device_system_10_1.ironskillet_device_system_dynamic_updates /config/devices/entry/deviceconfig/system
panos_ngfw_device_system_10_1.ironskillet_device_system_snmp /config/devices/entry/deviceconfig/system
panos_ngfw_device_system_10_1.ironskillet_device_system_ntp /config/devices/entry/deviceconfig/system
panos_ngfw_device_system_10_1.ironskillet_device_system_login_banner /config/devices/entry/deviceconfig/system
panos_ngfw_device_system_10_1.ironskillet_device_system_timezone /config/devices/entry/deviceconfig/system
panos_ngfw_device_system_10_1.ironskillet_device_system_hostname /config/devices/entry/deviceconfig/system
panos_ngfw_device_setting_10_1.ironskillet_device_setting_ctd /config/devices/entry/deviceconfig/setting
panos_ngfw_device_setting_10_1.ironskillet_device_setting /config/devices/entry/deviceconfig/setting (management/admin-lockout/idle/api/commit-lock)
panos_ngfw_device_setting_10_1.ironskillet_device_setting_wildfire /config/devices/entry/deviceconfig/setting (file-size limits + verdict reporting)
panos_ngfw_device_setting_10_1.ironskillet_device_setting_config /config/devices/entry/deviceconfig/setting (rematch=yes)
panos_ngfw_device_setting_10_1.ironskillet_device_setting_application /config/devices/entry/deviceconfig/setting
panos_ngfw_device_setting_10_1.ironskillet_device_setting_logging /config/devices/entry/deviceconfig/setting
panos_ngfw_device_setting_10_1.ironskillet_device_setting_tcp /config/devices/entry/deviceconfig/setting (TCP hardening)
panos_ngfw_device_setting_10_1.ironskillet_device_setting_packet_buffer /config/devices/entry/deviceconfig/setting
panos_ngfw_mgt_config_users_10_1.ironskillet_mgmt_config_users /config/mgt-config/users
panos_ngfw_password_complexity_10_1.ironskillet_password_complexity /config/mgt-config/password-complexity
panos_ngfw_shared_log_settings_10_1.ironskillet_shared_log_settings /config/shared/log-settings
panos_ngfw_tag_10_1.ironskillet_tag_outbound / _inbound / _internal / _ironskillet_version /config/devices/entry/vsys/entry[@name='vsys1']/tag
panos_ngfw_log_settings_profiles_10_1.* /config/devices/entry/vsys/entry[@name='vsys1']/log-settings/profiles
panos_ngfw_profile_custom_urlFiltering_10_1.* /config/devices/entry/vsys/entry[@name='vsys1']/profiles/custom-url-category
panos_ngfw_profile_decryption_10_1.* /config/devices/entry/vsys/entry[@name='vsys1']/profiles/decryption
panos_ngfw_profile_antivirus_10_1.* /config/devices/entry/vsys/entry[@name='vsys1']/profiles/virus
panos_ngfw_profile_spyware_10_1.* /config/devices/entry/vsys/entry[@name='vsys1']/profiles/spyware
panos_ngfw_profile_vulnerability_10_1.* /config/devices/entry/vsys/entry[@name='vsys1']/profiles/vulnerability
panos_ngfw_profile_file-blocking_10_1.* /config/devices/entry/vsys/entry[@name='vsys1']/profiles/file-blocking
panos_ngfw_profile_urlFiltering_10_1.* /config/devices/entry/vsys/entry[@name='vsys1']/profiles/url-filtering
panos_ngfw_profile_wildfire_analysis_10_1.* /config/devices/entry/vsys/entry[@name='vsys1']/profiles/wildfire-analysis
panos_ngfw_profile_group_10_1.* /config/devices/entry/vsys/entry[@name='vsys1']/profile-group
panos_ngfw_rulebase_default_security_rules_10_1.* /config/devices/entry/vsys/entry[@name='vsys1']/rulebase/default-security-rules
panos_ngfw_rulebase_security_10_1.* /config/devices/entry/vsys/entry[@name='vsys1']/rulebase/security
panos_ngfw_rulebase_decryption_10_1.* /config/devices/entry/vsys/entry[@name='vsys1']/rulebase/decryption
panos_ngfw_zone_protection_10_1.* /config/devices/entry/vsys/entry[@name='vsys1']/network/profiles/zone-protection-profile
panos_ngfw_reports_simple_10_1.* /config/shared/reports (or vsys1 reports)
panos_ngfw_report_group_simple_10_1.* /config/shared/report-group
panos_ngfw_email_scheduler_10_1.* /config/shared/email-scheduler

3.6 Hardened defaults — what the snippets actually write

Selected high-value defaults baked into the rendered XML:

Setting Value Snippet
Login banner "You have accessed a protected system. Log off immediately if you are not an authorized user." ironskillet_device_system_login_banner
Timezone UTC ironskillet_device_system_timezone
Threats update every 30 min @ minute 2, threshold 48 ironskillet_device_system_dynamic_updates
Antivirus update hourly @ minute 4 same
WildFire update real-time same
GlobalProtect data file hourly @ minute 40 same
GlobalProtect clientless VPN hourly @ minute 50 same
SNMP version v3 only ironskillet_device_system_snmp
Admin lockout 5 failed attempts, 30-minute lockout ironskillet_device_setting
Idle timeout 10 minutes same
Auto-acquire commit lock enabled same
Max rows in CSV export 1,048,576 same
Password min length 12 ironskillet_password_complexity
Password complexity ≥1 upper, ≥1 lower, ≥1 numeric, ≥1 special same
Password history 24 entries same
New-password differs by 3 characters same
TCP urgent-data clear ironskillet_device_setting_tcp
TCP drop-zero-flag yes same
TCP strip-mptcp-option yes same
Session packet-buffer protection enabled ironskillet_device_setting_packet_buffer
Rematch sessions on commit yes ironskillet_device_setting_config
Log suppression disabled ironskillet_device_setting_logging
Custom URL categories Block, Allow, Custom-No-Decrypt ironskillet_custom_url_category_*
Tags Outbound, Inbound, Internal, iron-skillet-version (version 0.0.2 for 10.1) ironskillet_tag_*
Sample syslog profile Sample_Syslog_Profile → Sample_Syslog, UDP/514, BSD/LOG_USER ironskillet_shared_log_settings
Sample email profile Sample_Email_Profile, display Threat_Alerts, SMTP same

3.7 Annotated rendering walkthrough — fresh-NGFW scenario

A typical "fresh greenfield NGFW" render with custom values overrides the toggles and a handful of identity variables:

# my-overrides.yaml — input to SLI / Panhandler
config_mgmt_intf: 'yes'
config_admin_user: 'yes'
config_dns: 'yes'

MGMT_TYPE: static
MGMT_IP: 10.50.1.5
MGMT_MASK: 255.255.255.0
MGMT_DG: 10.50.1.1

DNS_1: 10.50.1.10
DNS_2: 10.50.1.11

FW_NAME: corp-fw-01
NTP_1: ntp1.example.com
NTP_2: ntp2.example.com

ADMINISTRATOR_USERNAME: secadmin
ADMINISTRATOR_PASSWORD: <strong-password-meeting-12-char-policy>

SYSLOG_SERVER: 10.50.1.50
EMAIL_PROFILE_GATEWAY: smtp.example.com
EMAIL_PROFILE_FROM: [email removed]
EMAIL_PROFILE_TO: [email removed]

INCLUDE_PAN_EDL: 'yes'
sli template -sd ./iron-skillet -ad \
  -n skillet_full_panos_v10_1 \
  ./out/

The renderer:

  1. Loads the snippet master, resolves the panos_full playlist's include list.
  2. Evaluates every when: clause against the overrides — three toggles are now yes, so panos_ngfw_device_system_mgmt_ip_10_1, panos_ngfw_device_system_dns_10_1, and panos_ngfw_mgt_config_users_10_1 all render.
  3. Applies the md5_hash filter to ADMINISTRATOR_PASSWORD and writes the result into <phash>.
  4. Concatenates the snippet bodies in playlist order into iron_skillet_panos_full.xml.

4. Deployment & Scaling

4.1 Single-device bring-up

The default deployment unit is one device, one rendered XML, one commit. Steps:

  1. git clone and git checkout the matching panos_v10_1 branch.
  2. Render with SLI (sli template -sd . -ad -n skillet_full_panos_v10_1 ./out/) or use the pre-rendered loadable_configs/sample-* files.
  3. Push: sli load_config -uc ./out/iron_skillet_panos_full.xml (or import via the web UI).
  4. Commit on the device.

4.2 Fleet rollout via Panorama

The Panorama playlists (ironskillet_panorama_shared_10_1, ironskillet_panorama_notshared_10_1, etc.) are designed to put IronSkillet's profiles, tags, custom URL categories, log-forwarding, and rulebase into a Panorama device-group + template-stack, so that a single Panorama push applies the baseline to every managed firewall.

Panorama (post-IronSkillet)
├── template-stack: {{STACK}}
│   ├── deviceconfig/system  → DNS, NTP, banner, dynamic-updates, ...
│   ├── deviceconfig/setting → admin-lockout, idle-timeout, TCP hardening
│   └── mgt-config           → admin user, password complexity
├── device-group: {{DEVICE_GROUP}}
│   ├── tag                  → Outbound, Inbound, Internal, iron-skillet-version
│   ├── profiles             → virus, spyware, vulnerability, file-blocking,
│   │                          url-filtering, wildfire-analysis, decryption,
│   │                          custom-url-category
│   ├── profile-group        → outbound, inbound, internal, alert_all, default
│   ├── pre-rulebase         → security + decryption
│   └── post-rulebase        → default-security-rules
└── shared
    └── log-settings         → email, syslog, log-forwarding, userid, hip,
                               correlation, gp, ip-tag forwarding

4.3 CI/CD render pipelines

A typical pipeline:

# .gitlab-ci.yml or GitHub Actions equivalent
stages: [render, validate, distribute]

render:
  image: python:3.9
  script:
    - pip install sli
    - git submodule update --init
    - sli template -sd . -ad -n skillet_full_panos_v10_1 ./out/
  artifacts:
    paths: [out/]

validate:
  image: python:3.9
  script:
    - apt-get update && apt-get install -y libxml2-utils
    - xmllint --noout out/iron_skillet_panos_full.xml
    - xmllint --noout out/iron_skillet_panorama_full.xml

distribute:
  script:
    - sli load_config -uc out/iron_skillet_panos_full.xml

4.4 Multi-version maintenance

When you fork IronSkillet to support a new PAN-OS version:

  1. Branch from the closest existing version branch (git checkout -b panos_v10_2 panos_v10_1).
  2. Update version-suffixed snippet names (*_10_1 → *_10_2) and the skillet name: / label: fields throughout.
  3. Verify XML schema compatibility against a 10.2 device — load the rendered candidate config and capture commit-time errors.
  4. Patch any newly-required elements (10.2-only features) and remove anything deprecated.
  5. Regenerate the loadable configs via tools/build_all.sh.
  6. Update submodules/ pointers via tools/update_submodules.sh.

Important

Issue #178 is the open feature-request for 11.1 / 11.2 / 12.1 support. Until it merges, those PAN-OS versions are not on a maintained branch and you'll need to fork-and-port if you must run them now.

4.5 Scaling considerations

IronSkillet is stateless build artefacts, so "scaling" mostly means:

  • Rendering throughput — a single sli template invocation takes seconds. Even a fleet of 1000+ firewalls is bottlenecked by per-device commit time, not render time.
  • Distribution — the rendered XML is <2 MB. Push via Panorama (one XML, fan-out to N firewalls) or via per-device sli load_config.
  • Variable inventory size — keep variable count under ~50 per scenario; beyond that, operators struggle with the form.

5. Operations

5.1 Day-to-day runbook

Task Command / location Frequency
Pull upstream changes git fetch origin && git checkout panos_v10_1 && git pull --ff-only Monthly or on advisory
Re-render after pull sli template -sd . -ad -n skillet_full_panos_v10_1 ./out/ After every pull
Sync submodules bash tools/update_submodules.sh After version-branch updates
Regenerate loadable_configs/ bash tools/build_all.sh Before publishing a tag
XML lint xmllint --noout out/*.xml After every render
Deploy to firewall sli load_config -uc out/iron_skillet_panos_full.xml Per device bring-up
Deploy to Panorama UI import + commit + push to devices Per fleet change
Validate posture Run IronSkillet_assessment_panos skillet via SLI After deploy + quarterly
Pre-update check Run IronSkillet_v10x_update_panos skillet Before PAN-OS upgrade

Note

The two validation skillets in validations/panos/ produce a green/red dashboard via validations/shared_report/report.yml. The shared report's pre_processing Jinja block tallies pass / fail / total for the operator.

5.2 Monitoring

There is no IronSkillet runtime to monitor. Monitor the device that IronSkillet was loaded onto:

  • Syslog target (the value of SYSLOG_SERVER) should show traffic, threat, WildFire, URL, data, tunnel, and auth log streams.
  • Email destination (EMAIL_PROFILE_TO) should receive the Email_Critical_System_Logs and Email_Malicious_Verdicts alerts.
  • Scheduled config exports (Panorama only, CONFIG_EXPORT_IP) should land at the SCP/FTP target on schedule.

5.3 Backup & rollback

Always save a snapshot before loading IronSkillet:

Device → Setup → Operations → Save named configuration snapshot
  → name: pre-ironskillet-YYYYMMDD

Roll back via:

Device → Setup → Operations → Load named configuration snapshot
  → pick the pre-ironskillet snapshot → Commit

Or load the in-repo templates/panos/baseline/baseline.xml for a factory-style empty baseline.

Tip

A two-step rollback is more forgiving: load the snapshot, run Save candidate configuration, then commit. That gives you one more "Revert to running configuration" exit before you're locked into the rollback.

5.4 Audit & evidence

Iron-skillet writes an explicit version tag at /config/devices/entry/vsys/entry[@name='vsys1']/tag/entry[@name='iron-skillet-version'] with comment version 0.0.2 for 10.1 - version of this IronSkillet template file. Use it as audit evidence:

ssh admin@firewall 'show config running' | grep iron-skillet-version

5.5 Common operations checklist

  • [ ] Cloned the repo at the correct branch (panos_v10_1).
  • [ ] Submodules updated (tools/update_submodules.sh).
  • [ ] Variables overridden — particularly ADMINISTRATOR_PASSWORD, SYSLOG_SERVER, EMAIL_PROFILE_*, FW_NAME, NTP/DNS.
  • [ ] Rendered output xmllint-clean.
  • [ ] Pre-load snapshot saved on the device.
  • [ ] Loaded as candidate config; previewed the diff in the UI.
  • [ ] Committed.
  • [ ] Validation skillet run and dashboard green.
  • [ ] Rendered XML stored in a controlled location (encrypted, ACL'd).
  • [ ] Admin password rotated post-commit; API key regenerated.

6. Performance

IronSkillet is a build-time tool — the "performance" axis is render time and the impact the rendered config has on the device.

6.1 Render performance

Metric Typical value
sli template for skillet_full_panos_v10_1 <5 seconds on a modern laptop
sli spreadsheet for skillet_set_command_panos_v10_1 <10 seconds (Excel write is the long pole)
Full tools/build_all.sh rebuild <60 seconds (regenerates 12 loadable configs + 2 spreadsheets)
Repo clone <30 seconds on a typical broadband connection

6.2 Device-side impact

The rendered config has measurable effects on device behavior:

Setting Effect
Idle timeout = 10 minutes Web-UI sessions log out faster than the PAN-OS default
Auto-acquire commit lock Two concurrent admins can't both commit
Admin lockout 5 attempts / 30 min Brute-force attempts get locked out quickly; legitimate typo-prone admins also get locked
Dynamic updates every 30 min (threats) Slightly higher mgmt-plane CPU than the PAN-OS default
Packet-buffer protection enabled Slightly higher dataplane CPU; protects against PBP exhaustion
Rematch sessions on commit Existing sessions re-evaluated against the new rulebase — useful for security, but disruptive if a rulebase change blocks a category that was previously allowed
Log suppression off Higher syslog and management-plane log volume

Note

The "rematch sessions on commit" setting is a deliberate IronSkillet choice: when you push a new rulebase, every existing flow is re-tested. That makes IronSkillet's security stance "fail closed on commit" — but it also means a too-aggressive commit can drop established connections.

6.3 Storage on the device

Item Approximate size
Loaded XML <2 MB
Per-day log volume (with all profiles + log-forwarding) Highly site-dependent; typical 10–500 MB/day for a medium branch

7. Security

IronSkillet's reason for existing is security hardening. This section covers the security controls the rendered config enforces, the secrets the rendered config contains, and the operational steps required to keep both safe.

7.1 Authentication & authorization

The rendered config writes:

  • A superuser admin entry under /config/mgt-config/users when config_admin_user == 'yes'. The username is ADMINISTRATOR_USERNAME, the password is the MD5 hash of ADMINISTRATOR_PASSWORD (Jinja filter md5_hash), stored in <phash>.
  • A password-complexity policy at /config/mgt-config/password-complexity: length 12, at least one upper / lower / numeric / special, blocked username inclusion, 24-entry history, must differ by 3 characters from the previous password.
  • An admin-lockout policy at /config/devices/entry/deviceconfig/setting/management/admin-lockout: 5 failed attempts, 30-minute lockout.
  • An idle-timeout of 10 minutes for management sessions.
  • An API-key lifetime of API_KEY_LIFETIME minutes (default 525600 = one year). API keys minted by the device after the load are bounded by this lifetime.

7.2 Input validation

IronSkillet's variable forms enforce typing at render time (type_hint: ip_address rejects non-IP input in Panhandler, dropdowns constrain values to dd_list members). The renderer fails fast if an unbound variable appears in a Jinja substitution.

7.3 Secrets handling

The repo itself does not carry production secrets. Defaults are deliberate placeholders (adminuser / adminuser, 192.0.2.x, 8.8.8.8). The expectation is that the operator overrides them at render time via SLI / Panhandler.

Important

Never commit a rendered IronSkillet XML file with real credentials or real management IPs back to a public repository. The defaults are public; the moment you override them, the rendered output becomes sensitive.

7.4 Treat rendered configurations as sensitive

IronSkillet's deliverable is a rendered PAN-OS configuration. The rendered XML is not sanitized: it carries the admin password hash (<phash>, written by the md5_hash filter from ADMINISTRATOR_PASSWORD), and once the device is in service the saved configuration also holds whatever the operator adds later, such as downstream service credentials (LDAP, RADIUS, TACACS+, SNMP, syslog) and certificates.

Handle rendered and saved configurations as credential material:

  1. Set a strong ADMINISTRATOR_PASSWORD at render time (the default adminuser is a placeholder).
  2. Restrict ACLs on saved XML / set-command output (POSIX 0600, NTFS owner-only) and encrypt it at rest if it sits on shared storage.
  3. Rotate API keys minted during the build pipeline at the end of the deployment window, and keep API_KEY_LIFETIME no longer than you need.
  4. Never commit or share a rendered configuration with real values outside a need-to-know channel; remove <phash>, server-profile credentials and certificate blocks first.

7.5 Network security

The rendered config enforces:

  • SNMPv3 only — snmp-setting/access-setting/version/v3. SNMPv1/v2c are disallowed.
  • TCP hardening — urgent-data: clear, drop-zero-flag: yes, check-timestamp-option: yes, strip-mptcp-option: yes.
  • Session packet-buffer protection enabled.
  • Default zone-protection profile wired into the zone-protection snippet at /config/devices/.../network/profiles/zone-protection-profile.
  • Default rulebase including the IronSkillet "default-security-rules" override and a curated security/decryption rulebase.

7.6 Logging & audit

The rendered config wires every log type — traffic, threat, WildFire, URL, data, tunnel, auth — to the Sample_Syslog_Profile (UDP/514, BSD format, LOG_USER facility) and emails critical system logs and malicious WildFire verdicts via the Sample_Email_Profile. Log suppression is disabled (<log-suppression>no</log-suppression>) so that nothing gets aggregated away. The shared log-settings cover config, system, user-id, HIP, GlobalProtect, IP-tag, and correlation forwarding.

7.7 PAN-OS subscriptions

Section 2.4 already lists the licenses required for the threat profiles to act. From a security-control perspective: the rendered profiles exist regardless of license, but the device cannot enforce them without the relevant subscription. Verify subscriptions before relying on the IronSkillet baseline as a security control.

Warning

A profile group attached to a rule on a device without a Threat Prevention license logs a license-warning at commit time but does not block the commit. The rule will pass traffic without threat inspection. Always confirm request license info shows the required subscriptions before attesting that IronSkillet is enforced.

7.8 Hardening checklist (operator-side)

  • [ ] Restricted ACLs on rendered configurations: every rendered iron_skillet_*_full.xml and iron_skillet_*_full.conf is stored on owner-only filesystem permissions (POSIX 0600 / NTFS owner-only) and never checked into a shared or public repo. Versioned-config storage encrypts at rest.
  • [ ] Post-deploy API key rotation cadence: every IronSkillet load triggers an immediate API key rotation for the device, and a recurring rotation no less often than the configured API_KEY_LIFETIME. API keys minted during the build pipeline are revoked at the end of the deployment window.
  • [ ] Downstream credential rotation policy: LDAP bind, RADIUS shared secret, TACACS+ key, SNMP community / SNMPv3 user, and syslog credentials that are added to the IronSkillet-derived configuration are rotated on the same cadence as the rendered config (or on every deploy, whichever is shorter), and old credentials are revoked at their respective directory / IdP / SIEM.

8. Developer Internals

This section is the contributor's view: how the templates are structured, how to add a new snippet, how to add a new PAN-OS version, and how the test pattern works.

8.1 Repository structure

iron-skillet/
├── README.md
├── CONTRIBUTING.md
├── SUPPORT.md
├── LICENSE
├── .gitignore
├── .gitmodules
├── docs/                    Sphinx site (readthedocs)
│   ├── conf.py
│   ├── index.rst
│   ├── notice.rst
│   └── Makefile
├── templates/               Snippet masters + pre-rendered output
│   ├── README.md
│   ├── panos/
│   │   ├── snippets/.meta-cnc.yaml          (HIGH triage, 112209c)
│   │   ├── full/                            (rendered XML)
│   │   ├── set_commands/                    (rendered set-command)
│   │   └── baseline/baseline.xml
│   └── panorama/
│       ├── snippets/.meta-cnc.yaml          (HIGH, 134929c)
│       ├── snippets_dgtemplate_shared/      (legacy, README marked deprecated)
│       ├── snippets_dgstack_notshared/      (legacy)
│       ├── snippets_notshared/              (legacy)
│       ├── full/
│       ├── set_commands/
│       └── baseline/baseline.xml
├── playlists/
│   ├── README.md
│   ├── panos/                               (4 .skillet.yaml files)
│   └── panorama/                            (6 .skillet.yaml files)
├── loadable_configs/        12 ready-to-load files (6 scenarios x 2 device types)
├── validations/             Validation skillets + shared report
│   ├── README.md
│   ├── panos/
│   │   ├── IronSkillet_assessment_panos/
│   │   └── IronSkillet_v10x_update_panos/
│   └── shared_report/report.yml
├── tools/                   Build orchestration
│   ├── README.md
│   ├── build_all.sh
│   ├── update_submodules.sh
│   ├── .gitignore
│   └── archive/             Pre-SLI Python helpers (deprecated path)
└── submodules/              Cross-version submodule mounts

8.2 Adding a new snippet to an existing version

  1. Edit templates/panos/snippets/.meta-cnc.yaml (or the Panorama master). Append a new entry under snippets::
    - name: panos_ngfw_<group>_10_1.ironskillet_<descriptive_name>
      xpath: /config/devices/entry[@name='localhost.localdomain']/...
      element: |-
          <your-element>
            <child>{{ YOUR_VAR }}</child>
          </your-element>
      cmd: set
      when: <optional Jinja predicate>
    
  2. If the snippet introduces a new variable, add it to the variables: block at the top of the same file with name, description, default, type_hint, optional dd_list, optional toggle_hint, and help_text.
  3. Add the snippet's name to the relevant playlists in playlists/panos/. Place it in dependency order — after any snippets it depends on, before any that depend on it.
  4. Regenerate the full XML, set-commands, and loadable configs:
    bash tools/build_all.sh
    
  5. Run the validation skillet to confirm the rendered output still passes posture checks.

8.3 The snippet-vs-full-config decision

When deciding whether a new feature should be a snippet or live in a hand-rolled full XML:

  • Snippet if it's a reusable unit that any playlist might want to include or exclude (e.g. a new threat profile, a new tag).
  • Full config is derived. Don't hand-edit the full/ XML — it's rebuilt by the renderer from the snippets via tools/build_all.sh.

8.4 Adding a new PAN-OS version

  1. Branch from the closest existing version branch: git checkout -b panos_v10_2 panos_v10_1.
  2. Find-and-replace the version suffix throughout — every snippet name, every parent skillet name: / label:, every playlist include: reference (*_10_1 → *_10_2).
  3. Build a candidate render against a 10.2 device; capture commit errors. PAN-OS 10.2 may have schema additions (new XML elements) or removals.
  4. Patch each snippet whose schema changed.
  5. Regenerate via tools/build_all.sh.
  6. Update submodules/ pointers via tools/update_submodules.sh.
  7. Tag the branch.

Note

The repo's README explicitly does not document a programmatic migration helper between versions — it's a human-driven port. Issue #178 (request for 11.1 / 11.2 / 12.1 branches) is outstanding; contributors who port to those versions can submit the work as a new branch via the standard CONTRIBUTING.md flow.

8.5 How variables resolve at render time

Render-time variable resolution is a layered lookup:

  1. The renderer reads the master .meta-cnc.yaml's variables: block — that's the schema.
  2. It overlays the playlist's variables: block (if any) — playlist declarations override snippet defaults.
  3. It overlays the operator's input (CLI args, Panhandler form, YAML override file) — operator input wins.
  4. For each snippet selected by the playlist, it evaluates the when: clause against the merged variable map. Falsy → snippet skipped.
  5. Surviving snippets have their element: body run through Jinja2 with the merged variable map. Filters used in the repo: md5_hash (exactly one use, the admin password) and the standard Jinja filter set.
  6. Rendered snippet XML is concatenated at the snippet's xpath.

8.6 Testing pattern

Two test layers exist in this commit:

  • Static: xmllint --noout out/iron_skillet_panos_full.xml runs as part of the build to confirm the rendered XML parses.
  • Validation skillets: validations/panos/IronSkillet_assessment_panos/ and validations/panos/IronSkillet_v10x_update_panos/ ship as Skillet-Validation packages. Run them via SLI against a candidate configuration; they emit a YAML report consumed by validations/shared_report/report.yml to produce a green/red dashboard with Total Checks, Checks Passed, and Checks Failed counters.
  • Legacy archive tests: tools/archive/test_full_config.py and test_set_commands.py exist but are part of the deprecated archive pipeline; new contributors should rely on the validation skillets and xmllint.

8.7 Code patterns and conventions

  • Snippet naming: panos_ngfw_<area>_<version>.ironskillet_<thing>. The first half identifies the playlist that owns the snippet; the ironskillet_* half identifies the specific element within. The version suffix is load-bearing — the renderer uses it to dispatch to the correct branch's snippet master.
  • XPath style: Always rooted at /config/devices/entry[@name='localhost.localdomain']/... for NGFW. Panorama snippets that touch a managed device's config wrap the path in /config/devices/entry[@name='localhost.localdomain']/template-stack/entry[@name='{{STACK}}']/.../localhost.localdomain/....
  • element: style: YAML literal block (|-) preserves whitespace. Indent the XML body two spaces under the literal-block marker.
  • when: style: Quote string comparisons (config_admin_user == 'yes'). Keep the comparison fully on one line.
  • Variable names: ALL_CAPS for substituted values, lower_snake for toggles (config_*).

8.8 Potential improvements

Areas where contributions are welcome:

  • Fix the spreadsheet sinkhole default (issue #177) — the iron_skillet_panos_full.xlsx ships an outdated default for the IPv4 sinkhole; sync it with templates/panos/snippets/.meta-cnc.yaml.
  • Resolve Panhandler ingestion warnings (issue #172) — some legacy snippet directories still ship .meta-cnc.yaml referencing external XML files; either modernize to embedded-element or remove.
  • Add maintained 11.1 / 11.2 / 12.1 branches (issue #178).
  • Expand the validation skillets to cover every IronSkillet element, not just the high-level posture indicators.
  • Replace MarkupSafe==1.0 and PyYAML==5.4 pins in tools/archive/requirements.txt so the archive scripts can run on Python 3.11+.

8.9 Contributing guide

The repo's CONTRIBUTING.md is the canonical contributor onboarding. At a high level: branch, edit, render, lint, validate, PR against the relevant version branch (don't PR against main).


9. Integration Points

iron-skillet is a build artifact, so "integration" means: which tools consume it, which devices receive it, and which systems are downstream.

9.1 Skillet-runner integrations

Tool Role Consumes
SLI (gitlab.com/panw-gse/as/sli) Maintained CLI runner templates/*/snippets/.meta-cnc.yaml, playlists/*/*.skillet.yaml
Panhandler (live.paloaltonetworks.com) Docker GUI Same
pan-cnc Programmatic rendering Same
tools/archive/build_full_templates.py Legacy in-repo build templates/*/snippets/.meta-cnc.yaml

9.2 Device integrations

Target Mechanism Driver
PAN-OS NGFW XML import via Device → Setup → Operations Manual or sli load_config -uc
PAN-OS NGFW Set-command paste in configure mode Manual or sli load_set -uc
Panorama XML import via Panorama → Setup → Operations Manual or sli load_config -uc
Panorama-managed firewalls Push from Panorama Panorama's commit-and-push

9.3 Downstream system integrations (after device load)

The rendered config wires the device into your environment:

Downstream system Variable Default Used in
Syslog SIEM SYSLOG_SERVER 192.0.2.2 Sample_Syslog_Profile UDP/514 BSD/LOG_USER
SMTP EMAIL_PROFILE_GATEWAY, EMAIL_PROFILE_FROM, EMAIL_PROFILE_TO 192.0.2.1 / [email removed] / [email removed] Sample_Email_Profile for critical system + WildFire verdict alerts
NTP NTP_1, NTP_2 0.pool.ntp.org / 1.pool.ntp.org Device clock
DNS DNS_1, DNS_2 8.8.8.8 / 8.8.4.4 Device resolution
DNS sinkhole SINKHOLE_IPV4, SINKHOLE_IPV6 sinkhole.paloaltonetworks.com / 2600:5200::1 Anti-spyware DNS-sinkhole
Palo Alto threat content (implicit) updates.paloaltonetworks.com Dynamic-update schedule
Scheduled config export (Panorama) CONFIG_EXPORT_IP 192.0.2.3 Panorama config snapshot destination

9.4 Validation reporting integration

The validations/shared_report/report.yml is the integration surface for Skillet-Validation viewers: it defines a stats block (Total / Passed / Failed) and a results table that any Skillet-Validation-compatible viewer (Panhandler, custom dashboards) can render. The pre_processing Jinja block is the data-shaping contract: viewers feed it raw data.<check> results and receive a {checks: [...], stats: {...}} JSON object back.

9.5 Cross-version submodule integration

.gitmodules and tools/update_submodules.sh define how this branch references sibling PAN-OS version branches. The submodules/ directory acts as a mount point for cross-version overlays — useful when a multi-version build job needs all branches reachable from one working tree.

# typical multi-version setup
git clone https://github.com/PaloAltoNetworks/iron-skillet.git
cd iron-skillet
bash tools/update_submodules.sh
ls submodules/   # version-branch mounts

Tip

If you maintain a private fleet that runs multiple PAN-OS versions simultaneously (mid-upgrade phase), keep one IronSkillet checkout per version branch in CI rather than relying on submodules — the submodule layout shines when one operator workflow needs cross-version visibility, not when CI bakes a single version's artifacts.

9.6 External documentation

The repo links out to: