Playbook Examples
This page provides real-world examples of Ansible playbooks using the Palo Alto Networks Strata Cloud Manager Ansible Collection. These examples demonstrate common use cases and best practices for automating SCM management.
Basic Object Management
Creating Address Objects and Groups
---
- name: Manage Address Objects
hosts: localhost
gather_facts: false
vars_files:
- vault.yaml # Contains encrypted credentials
vars:
provider:
client_id: "{{ client_id }}"
client_secret: "{{ client_secret }}"
tsg_id: "{{ tsg_id }}"
tasks:
# Create individual address objects
- name: Create Address Objects
cdot65.scm.address:
provider: "{{ provider }}"
name: "{{ item.name }}"
folder: "Texas"
description: "{{ item.description }}"
ip_netmask: "{{ item.ip }}"
state: present
loop:
- { name: "web-server-1", description: "Web Server 1", ip: "10.1.1.1/32" }
- { name: "web-server-2", description: "Web Server 2", ip: "10.1.1.2/32" }
- { name: "app-server-1", description: "App Server 1", ip: "10.1.2.1/32" }
- { name: "app-server-2", description: "App Server 2", ip: "10.1.2.2/32" }
# Create address groups
- name: Create Address Groups
cdot65.scm.address_group:
provider: "{{ provider }}"
name: "{{ item.name }}"
folder: "Texas"
description: "{{ item.description }}"
static:
- "{{ item.members[0] }}"
- "{{ item.members[1] }}"
state: present
loop:
- { name: "web-servers", description: "Web Servers", members: ["web-server-1", "web-server-2"] }
- { name: "app-servers", description: "App Servers", members: ["app-server-1", "app-server-2"] }
# Commit changes
- name: Commit Changes
cdot65.scm.commit:
provider: "{{ provider }}"
description: "Add address objects and groups"
folders: ["Texas"]
Creating Service Objects and Groups
---
- name: Manage Service Objects
hosts: localhost
gather_facts: false
vars_files:
- vault.yaml
vars:
provider:
client_id: "{{ client_id }}"
client_secret: "{{ client_secret }}"
tsg_id: "{{ tsg_id }}"
tasks:
# Create service objects
- name: Create Service Objects
cdot65.scm.service:
provider: "{{ provider }}"
name: "{{ item.name }}"
folder: "Texas"
description: "{{ item.description }}"
protocol:
"{{ item.protocol_type }}":
port: "{{ item.port }}"
state: present
loop:
- { name: "http", description: "HTTP", protocol_type: "tcp", port: "80" }
- { name: "https", description: "HTTPS", protocol_type: "tcp", port: "443" }
- { name: "ssh", description: "SSH", protocol_type: "tcp", port: "22" }
- { name: "rdp", description: "RDP", protocol_type: "tcp", port: "3389" }
# Create service group
- name: Create Service Group
cdot65.scm.service_group:
provider: "{{ provider }}"
name: "web-services"
folder: "Texas"
description: "Web Services"
members: ["http", "https"]
state: present
# Commit changes
- name: Commit Changes
cdot65.scm.commit:
provider: "{{ provider }}"
description: "Add service objects and groups"
folders: ["Texas"]
Security Policy Management
Creating Security Rules
---
- name: Manage Security Rules
hosts: localhost
connection: local
gather_facts: false
tasks:
# Create security zones
- name: Create Security Zones
cdot65.scm.security_zone:
name: "{{ item.name }}"
folder: "SharedFolder"
description: "{{ item.description }}"
loop:
- { name: "Internet", description: "Internet Zone" }
- { name: "DMZ", description: "DMZ Zone" }
- { name: "Internal", description: "Internal Zone" }
# Create inbound web access rule
- name: Create Inbound Web Access Rule
cdot65.scm.security_rule:
name: "Allow-Inbound-Web"
folder: "SharedFolder"
description: "Allow inbound web traffic"
source_zones: ["Internet"]
destination_zones: ["DMZ"]
source_addresses: ["any"]
destination_addresses: ["web-servers"]
applications: ["web-browsing", "ssl"]
services: ["application-default"]
action: "allow"
log_end: true
# Create outbound access rule
- name: Create Outbound Access Rule
cdot65.scm.security_rule:
name: "Allow-Outbound-Web"
folder: "SharedFolder"
description: "Allow outbound web traffic"
source_zones: ["Internal"]
destination_zones: ["Internet"]
source_addresses: ["internal-clients"]
destination_addresses: ["any"]
applications: ["web-browsing", "ssl"]
services: ["application-default"]
action: "allow"
log_end: true
# Create rule with security profiles
- name: Create Rule with Security Profiles
cdot65.scm.security_rule:
name: "Allow-Inspected-Web"
folder: "SharedFolder"
description: "Allow web traffic with security inspection"
source_zones: ["Internal"]
destination_zones: ["Internet"]
source_addresses: ["internal-clients"]
destination_addresses: ["any"]
applications: ["web-browsing", "ssl"]
services: ["application-default"]
action: "allow"
log_end: true
profile_type: "profiles"
antivirus_profile: "default-antivirus"
anti_spyware_profile: "default-anti-spyware"
vulnerability_profile: "default-vulnerability"
url_filtering_profile: "default-url-filtering"
# Commit changes
- name: Commit Changes
cdot65.scm.commit:
description: "Add security rules"
Network Configuration
Remote Network Configuration
---
- name: Configure Remote Networks
hosts: localhost
connection: local
gather_facts: false
tasks:
# Create IKE Crypto Profile
- name: Create IKE Crypto Profile
cdot65.scm.ike_crypto_profile:
name: "Standard-IKE-Crypto"
folder: "SharedFolder"
description: "Standard IKE crypto profile"
dh_groups: ["group14"]
encryptions: ["aes-256-cbc"]
authentications: ["sha256"]
# Create IPsec Crypto Profile
- name: Create IPsec Crypto Profile
cdot65.scm.ipsec_crypto_profile:
name: "Standard-IPsec-Crypto"
folder: "SharedFolder"
description: "Standard IPsec crypto profile"
esp_encryptions: ["aes-256-cbc"]
esp_authentications: ["sha256"]
dh_group: "group14"
lifetime_seconds: 3600
# Create IKE Gateway
- name: Create IKE Gateway
cdot65.scm.ike_gateway:
name: "Branch-Office-Gateway"
folder: "SharedFolder"
description: "Branch Office VPN Gateway"
version: "ikev2"
peer_address: "198.51.100.1"
interface: "ethernet1/1"
pre_shared_key: "{{ ike_psk }}" # Should be in vault
local_id_type: "ipaddr"
local_id_value: "203.0.113.1"
peer_id_type: "ipaddr"
peer_id_value: "198.51.100.1"
crypto_profile: "Standard-IKE-Crypto"
# Create Remote Network
- name: Create Remote Network
cdot65.scm.remote_network:
name: "Branch-Office-VPN"
folder: "SharedFolder"
description: "Branch Office VPN Connection"
ike_gateway: "Branch-Office-Gateway"
ipsec_crypto_profile: "Standard-IPsec-Crypto"
tunnel_interface: "tunnel.1"
region: "us-east"
# Commit changes
- name: Commit Changes
cdot65.scm.commit:
description: "Add remote network configuration"
Configuration Deployment
Deploy Configuration to Firewalls
---
- name: Deploy Configurations
hosts: localhost
connection: local
gather_facts: false
tasks:
# Commit any pending changes
- name: Commit Changes
cdot65.scm.commit:
description: "Pre-deployment commit"
register: commit_result
# Push configuration to device group
- name: Push Configuration to Device Group
cdot65.scm.push_config:
device_groups:
- "Branch-Offices"
description: "Weekly security policy update"
register: push_result
when: commit_result.changed
# Monitor push job
- name: Monitor Push Job
cdot65.scm.job_info:
job_id: "{{ push_result.job_id }}"
register: job_status
until: job_status.status == "COMPLETED" or job_status.status == "FAILED"
retries: 30
delay: 10
when: push_result is defined and push_result.job_id is defined
# Report deployment status
- name: Report Deployment Status
debug:
msg: "Deployment status: {{ job_status.status }}"
when: job_status is defined
Workflow Examples
Security Policy Update Workflow
---
- name: Security Policy Update Workflow
hosts: localhost
connection: local
gather_facts: false
vars:
policy_folder: "SecurityPolicies"
policy_change_ticket: "CHG0012345"
deploy_to_prod: false
tasks:
# Create new address objects
- name: Create New Address Objects
cdot65.scm.address:
name: "{{ item.name }}"
folder: "{{ policy_folder }}"
description: "{{ item.description }} ({{ policy_change_ticket }})"
ip_netmask: "{{ item.ip }}"
loop: "{{ new_address_objects }}"
# Create new application rule
- name: Create Application Access Rule
cdot65.scm.security_rule:
name: "Allow-App-Traffic-{{ policy_change_ticket }}"
folder: "{{ policy_folder }}"
description: "Allow application traffic ({{ policy_change_ticket }})"
source_zones: ["Internal"]
destination_zones: ["DMZ"]
source_addresses: ["internal-clients"]
destination_addresses: "{{ new_address_objects | map(attribute='name') | list }}"
applications: ["web-browsing", "ssl"]
services: ["application-default"]
action: "allow"
log_end: true
position: "before"
reference_rule: "Default-Deny"
# Commit changes
- name: Commit Changes
cdot65.scm.commit:
description: "Security rule update for {{ policy_change_ticket }}"
register: commit_result
# Deploy to test firewalls only
- name: Deploy to Test Environment
cdot65.scm.push_config:
device_groups:
- "Test-Firewalls"
description: "Test deployment for {{ policy_change_ticket }}"
register: push_result
# Deploy to production if flag is set
- name: Deploy to Production
cdot65.scm.push_config:
device_groups:
- "Production-Firewalls"
description: "Production deployment for {{ policy_change_ticket }}"
register: prod_push_result
when: deploy_to_prod | bool
Multi-Tenant Configuration
---
- name: Multi-Tenant Configuration
hosts: localhost
connection: local
gather_facts: false
vars:
tenants:
- name: "Tenant-A"
folder: "Tenant-A"
prefix: "A"
networks:
- "10.1.0.0/16"
- "192.168.1.0/24"
- name: "Tenant-B"
folder: "Tenant-B"
prefix: "B"
networks:
- "10.2.0.0/16"
- "192.168.2.0/24"
tasks:
# Loop through each tenant
- name: Configure Each Tenant
include_tasks: tenant_config.yml
loop: "{{ tenants }}"
loop_control:
loop_var: tenant
# File: tenant_config.yml
# - name: Create Tenant Folder
# cdot65.scm.folder:
# name: "{{ tenant.folder }}"
#
# - name: Create Tenant Networks
# cdot65.scm.address:
# name: "{{ tenant.prefix }}-Net-{{ index }}"
# folder: "{{ tenant.folder }}"
# ip_netmask: "{{ network }}"
# loop: "{{ tenant.networks }}"
# loop_control:
# index_var: index
#
# - name: Create Tenant Tags
# cdot65.scm.tag:
# name: "{{ tenant.name }}"
# folder: "{{ tenant.folder }}"
# color: "color{{ 5 + loop.index }}"
#
# - name: Create Address Group
# cdot65.scm.address_group:
# name: "{{ tenant.prefix }}-Networks"
# folder: "{{ tenant.folder }}"
# static_members: "{{ tenant.networks | map('regex_replace', '^(.*)$', tenant.prefix + '-Net-\\1') | list }}"
#
# - name: Create Tenant Zone
# cdot65.scm.security_zone:
# name: "{{ tenant.prefix }}-Zone"
# folder: "{{ tenant.folder }}"
#
# - name: Create Tenant Rules
# cdot65.scm.security_rule:
# name: "{{ tenant.prefix }}-Outbound"
# folder: "{{ tenant.folder }}"
# source_zones: ["{{ tenant.prefix }}-Zone"]
# destination_zones: ["Internet"]
# source_addresses: ["{{ tenant.prefix }}-Networks"]
# destination_addresses: ["any"]
# action: "allow"
Inventory and Reporting
Inventory-Based Configuration
---
- name: Configure Firewalls Based on Inventory
hosts: scm_firewalls
connection: local
gather_facts: false
tasks:
# Create zones based on inventory
- name: Create Security Zones
cdot65.scm.security_zone:
name: "{{ item }}-Zone"
folder: "SharedFolder"
description: "Zone for {{ item }}"
loop: "{{ groups | select('match', '^location_.*') | list | map('regex_replace', '^location_(.*)$', '\\1') | list }}"
# Create address objects from inventory hosts
- name: Create Address Objects for Hosts
cdot65.scm.address:
name: "host-{{ inventory_hostname }}"
folder: "SharedFolder"
description: "Host {{ inventory_hostname }}"
ip_netmask: "{{ ansible_host }}/32"
when: ansible_host is defined
SCM Reporting
---
- name: Generate SCM Configuration Report
hosts: localhost
connection: local
gather_facts: false
tasks:
# Gather information on security rules
- name: Get Security Rules
cdot65.scm.security_rule_info:
folder: "SharedFolder"
register: security_rules
# Generate report on unused rules
- name: Find Unused Rules
set_fact:
unused_rules: "{{ security_rules.rules | selectattr('hit_count', 'equalto', 0) | list }}"
when: security_rules.rules is defined
# Create CSV report
- name: Create Unused Rules Report
copy:
content: "Rule Name,Description,Last Modified,Hit Count\n{{ unused_rules | map(attribute='name') | zip(unused_rules | map(attribute='description'), unused_rules | map(attribute='last_modified'), unused_rules | map(attribute='hit_count')) | map('join', ',') | join('\n') }}"
dest: "./unused_rules_report.csv"
when: unused_rules is defined and unused_rules | length > 0
Integration with Other Platforms
ServiceNow Integration
---
- name: SCM and ServiceNow Integration
hosts: localhost
connection: local
gather_facts: false
vars:
snow_instance: "{{ lookup('env', 'SNOW_INSTANCE') }}"
snow_username: "{{ lookup('env', 'SNOW_USERNAME') }}"
snow_password: "{{ lookup('env', 'SNOW_PASSWORD') }}"
change_number: "CHG0012345"
tasks:
# Get change request details
- name: Get Change Request Details
uri:
url: "https://{{ snow_instance }}.service-now.com/api/now/table/change_request?number={{ change_number }}"
method: GET
user: "{{ snow_username }}"
password: "{{ snow_password }}"
force_basic_auth: yes
return_content: yes
headers:
Accept: application/json
register: change_result
# Extract change details
- name: Extract Change Details
set_fact:
change_details: "{{ change_result.json.result[0] }}"
change_description: "{{ change_result.json.result[0].description }}"
when: change_result.json.result | length > 0
# Implement firewall changes
- name: Implement Firewall Changes
cdot65.scm.security_rule:
name: "Rule-{{ change_number }}"
folder: "SharedFolder"
description: "{{ change_description | default('Rule for ' + change_number) }}"
source_zones: ["Internal"]
destination_zones: ["DMZ"]
source_addresses: ["any"]
destination_addresses: ["web-servers"]
applications: ["web-browsing", "ssl"]
action: "allow"
register: rule_result
when: change_details is defined
# Update ServiceNow with implementation status
- name: Update Change Request
uri:
url: "https://{{ snow_instance }}.service-now.com/api/now/table/change_request/{{ change_details.sys_id }}"
method: PATCH
user: "{{ snow_username }}"
password: "{{ snow_password }}"
force_basic_auth: yes
body_format: json
body:
work_notes: "Firewall rule implemented via Ansible. Rule ID: {{ rule_result.scm_object.id }}"
state: "3" # Implement state
headers:
Content-Type: application/json
when: rule_result is defined and rule_result.changed
These examples demonstrate various usage scenarios for the SCM Ansible Collection. For more specific guidance or advanced examples, refer to the Module Reference and Using Roles documentation.