Advanced Topics
This guide covers advanced topics and techniques for using the Palo Alto Networks SCM Ansible Collection in more complex scenarios.
Dynamic Inventory Integration
Using the SCM Inventory Plugin with Terraform
Combine Terraform-managed infrastructure with SCM dynamic inventory:
# scm_terraform.yml
plugin: cdot65.scm.inventory
keyed_groups:
- prefix: terraform_
key: tags.Terraform
compose:
terraform_managed: "'terraform' in (tags|default({}))"
# In playbook:
- name: Configure Terraform-managed firewalls
hosts: terraform_true
tasks:
- name: Apply baseline configuration
cdot65.scm.bootstrap:
bootstrap_folder: "Terraform-Managed"
Hybrid Cloud Inventory
Combine multiple inventory sources for hybrid environments:
# inventory.yml
---
plugin: cdot65.scm.inventory
device_groups:
- "Cloud-Firewalls"
compose:
deployment_type: "'cloud'"
---
plugin: aws_ec2
regions:
- us-east-1
- us-west-2
filters:
tag:Type: firewall
compose:
deployment_type: "'aws'"
Workflow Automation
GitOps Workflow for SCM
Implement a GitOps workflow for SCM configurations:
---
- name: GitOps Workflow for SCM
hosts: localhost
connection: local
vars:
git_repo: "https://github.com/example/scm-configs.git"
git_branch: "{{ lookup('env', 'CI_COMMIT_BRANCH') | default('main', true) }}"
config_path: "./scm-configs"
tasks:
# Clone Git repository
- name: Clone configuration repository
git:
repo: "{{ git_repo }}"
dest: "{{ config_path }}"
version: "{{ git_branch }}"
# Load configuration from YAML files
- name: Load configuration files
include_vars:
dir: "{{ config_path }}/{{ item }}"
name: "{{ item }}"
loop:
- "address_objects"
- "security_rules"
- "service_objects"
# Apply address objects
- name: Apply address objects
cdot65.scm.address:
name: "{{ item.name }}"
folder: "{{ item.folder }}"
description: "{{ item.description | default(omit) }}"
ip_netmask: "{{ item.ip_netmask | default(omit) }}"
ip_range: "{{ item.ip_range | default(omit) }}"
fqdn: "{{ item.fqdn | default(omit) }}"
tags: "{{ item.tags | default(omit) }}"
loop: "{{ address_objects.objects }}"
# Similar tasks for other object types
# Commit and tag changes
- name: Commit changes
cdot65.scm.commit:
description: "GitOps deployment from {{ git_branch }} ({{ lookup('env', 'CI_COMMIT_SHA') | default('local', true) }})"
Multi-Step Approval Workflow
Implement approvals for security policy changes:
---
- name: Request Security Policy Change
hosts: localhost
connection: local
vars:
change_request_id: "CHG{{ lookup('pipe', 'date +%Y%m%d%H%M%S') }}"
approver_email: "security-team@example.com"
tasks:
# Create candidate rule but don't commit
- name: Create candidate security rule
cdot65.scm.security_rule:
name: "Rule-{{ change_request_id }}"
folder: "Pending-Approval"
description: "Pending approval: {{ change_request_id }}"
source_zones: ["{{ source_zone }}"]
destination_zones: ["{{ destination_zone }}"]
source_addresses: ["{{ source_address }}"]
destination_addresses: ["{{ destination_address }}"]
applications: ["{{ application }}"]
action: "allow"
register: rule_result
# Send approval request
- name: Send approval email
mail:
host: smtp.example.com
port: 25
to: "{{ approver_email }}"
subject: "Security Rule Approval Request: {{ change_request_id }}"
body: |
A new security rule requires approval:
Rule ID: {{ rule_result.scm_object.id }}
Name: Rule-{{ change_request_id }}
Source: {{ source_zone }}
Destination: {{ destination_zone }}
Application: {{ application }}
Approve at: https://scm.example.com/pending/{{ change_request_id }}
Advanced Deployment Strategies
Rolling Deployment
Implement a rolling deployment strategy:
---
- name: Rolling Firewall Deployment
hosts: localhost
connection: local
vars:
device_groups:
- name: "US-East-Firewalls"
max_parallel: 2
wait_time: 300 # seconds
- name: "US-West-Firewalls"
max_parallel: 2
wait_time: 300
- name: "EMEA-Firewalls"
max_parallel: 3
wait_time: 300
tasks:
# Commit changes first
- name: Commit configuration changes
cdot65.scm.commit:
description: "Preparing for rolling deployment"
register: commit_result
# Deploy to each device group in sequence
- name: Rolling deployment to device groups
block:
# Get devices in the group
- name: Get devices in group
cdot65.scm.device_group_info:
name: "{{ item.name }}"
register: device_group
# Deploy to subsets of devices
- name: Deploy to device subset
include_tasks: deploy_subset.yml
vars:
device_subset: "{{ device_group.devices[start_idx:end_idx] }}"
wait_time: "{{ item.wait_time }}"
loop: "{{ range(0, device_group.devices|length, item.max_parallel)|list }}"
loop_control:
loop_var: start_idx
vars:
end_idx: "{{ [start_idx + item.max_parallel, device_group.devices|length] | min }}"
loop: "{{ device_groups }}"
Validation and Rollback
Implement validation and automatic rollback:
---
- name: Deploy with Validation and Rollback
hosts: localhost
connection: local
vars:
max_retry_attempts: 3
validation_wait: 60 # seconds
tasks:
# Store current configuration version
- name: Get current configuration version
cdot65.scm.version_info:
folder: "SharedFolder"
register: current_version
# Make changes
- name: Apply security rule changes
cdot65.scm.security_rule:
name: "New-Application-Rule"
folder: "SharedFolder"
description: "Allow new application"
source_zones: ["Internal"]
destination_zones: ["External"]
applications: ["custom-app"]
action: "allow"
register: rule_result
# Commit changes
- name: Commit changes
cdot65.scm.commit:
description: "New application rule deployment"
register: commit_result
# Deploy with validation
- name: Deploy and validate
block:
# Push to test device
- name: Push to test device
cdot65.scm.push_config:
devices:
- "test-firewall.example.com"
register: push_result
# Wait for deployment
- name: Wait for deployment
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
# Validate deployment
- name: Validate deployment
cdot65.scm.validate_config:
device: "test-firewall.example.com"
tests:
- type: "connectivity"
source_ip: "10.0.0.10"
destination_ip: "8.8.8.8"
application: "dns"
register: validation
failed_when: not validation.passed
rescue:
# Rollback on failure
- name: Rollback to previous version
cdot65.scm.rollback:
folder: "SharedFolder"
version: "{{ current_version.version }}"
register: rollback_result
- name: Commit rollback
cdot65.scm.commit:
description: "Rollback due to validation failure"
- name: Push rollback
cdot65.scm.push_config:
devices:
- "test-firewall.example.com"
- name: Fail with rollback message
fail:
msg: "Deployment failed validation and was rolled back to version {{ current_version.version }}"
Custom Module Integration
Creating a Custom SCM Module Wrapper
Create custom wrapper modules for specific use cases:
#!/usr/bin/python
# custom_modules/scm_compliance_rule.py
DOCUMENTATION = '''
---
module: scm_compliance_rule
short_description: Creates pre-configured compliant security rules
description:
- Creates security rules in SCM that comply with organizational standards
options:
name:
description: Rule name
required: true
folder:
description: SCM folder
required: true
# Additional parameters...
'''
from ansible.module_utils.basic import AnsibleModule
import ansible_collections.cdot65.scm.plugins.module_utils.scm as scm_utils
def run_module():
module_args = dict(
name=dict(type='str', required=True),
folder=dict(type='str', required=True),
rule_type=dict(type='str', required=True, choices=['outbound-web', 'inbound-web', 'internal']),
# Additional parameters...
)
result = dict(
changed=False,
scm_object=None,
)
module = AnsibleModule(
argument_spec=module_args,
supports_check_mode=True
)
# Map rule types to standardized configurations
rule_templates = {
'outbound-web': {
'source_zones': ['Internal'],
'destination_zones': ['Internet'],
'applications': ['web-browsing', 'ssl'],
'profile_type': 'profiles',
'url_filtering_profile': 'default-url-filtering'
},
# Additional templates...
}
# Create parameters for the underlying module
rule_params = rule_templates.get(module.params['rule_type']).copy()
rule_params.update({
'name': module.params['name'],
'folder': module.params['folder'],
'log_end': True
})
# Use SCM utilities to create the rule
scm_client = scm_utils.get_scm_client(module)
if module.check_mode:
result['changed'] = True
module.exit_json(**result)
try:
rule_result = scm_client.security_rule.create(rule_params)
result['changed'] = True
result['scm_object'] = rule_result
except Exception as e:
module.fail_json(msg=f"Error creating compliance rule: {str(e)}")
module.exit_json(**result)
if __name__ == '__main__':
run_module()
Integrating with External CMDB
Connect SCM with an external CMDB:
---
- name: Integrate SCM with CMDB
hosts: localhost
connection: local
vars:
cmdb_url: "https://cmdb.example.com/api"
cmdb_token: "{{ lookup('env', 'CMDB_TOKEN') }}"
tasks:
# Get server information from CMDB
- name: Query CMDB for servers
uri:
url: "{{ cmdb_url }}/servers"
headers:
Authorization: "Bearer {{ cmdb_token }}"
return_content: yes
register: cmdb_servers
# Process CMDB data
- name: Process CMDB servers
set_fact:
web_servers: "{{ cmdb_servers.json | json_query('[?tags.contains(@, `web`)]') }}"
app_servers: "{{ cmdb_servers.json | json_query('[?tags.contains(@, `app`)]') }}"
db_servers: "{{ cmdb_servers.json | json_query('[?tags.contains(@, `db`)]') }}"
# Create address objects from CMDB data
- name: Create address objects from CMDB
cdot65.scm.address:
name: "{{ item.hostname }}"
folder: "CMDB-Managed"
description: "CMDB managed server: {{ item.hostname }}"
ip_netmask: "{{ item.ip_address }}/32"
tags:
- "cmdb-managed"
- "{{ item.environment }}"
loop: "{{ web_servers + app_servers + db_servers }}"
register: address_results
# Create address groups
- name: Create address groups
cdot65.scm.address_group:
name: "{{ item.key }}-servers"
folder: "CMDB-Managed"
description: "CMDB {{ item.key }} servers"
static_members: "{{ item.value | map(attribute='hostname') | list }}"
loop:
- { key: "web", value: "{{ web_servers }}" }
- { key: "app", value: "{{ app_servers }}" }
- { key: "db", value: "{{ db_servers }}" }
when: item.value | length > 0
# Commit changes
- name: Commit CMDB changes
cdot65.scm.commit:
description: "CMDB synchronization"
Performance Optimization
Parallel Task Execution
Optimize performance with parallel execution:
---
- name: Parallel SCM Configuration
hosts: localhost
connection: local
vars:
max_parallel: 10
folders:
- "Prod"
- "Dev"
- "Test"
- "QA"
tasks:
# Async tasks for parallel processing
- name: Create security zones in parallel
cdot65.scm.security_zone:
name: "Zone-{{ item }}"
folder: "{{ item }}"
description: "Zone for {{ item }}"
loop: "{{ folders }}"
async: 300
poll: 0
register: async_results
# Wait for all async tasks to complete
- name: Wait for async tasks
async_status:
jid: "{{ async_result_item.ansible_job_id }}"
loop: "{{ async_results.results }}"
loop_control:
loop_var: async_result_item
register: async_poll_results
until: async_poll_results.finished
retries: 30
delay: 10
Bulk Operations
Optimize with bulk operations:
---
- name: Bulk Operations
hosts: localhost
connection: local
vars:
csv_file: "address_objects.csv"
tasks:
# Read CSV file
- name: Read CSV file
community.general.read_csv:
path: "{{ csv_file }}"
register: csv_data
# Process in batches
- name: Process in batches
block:
- name: Create address objects in batches
cdot65.scm.bulk_address:
folder: "SharedFolder"
objects: "{{ batch_items }}"
loop: "{{ csv_data.list | batch(20) | list }}"
loop_control:
loop_var: batch_items
rescue:
- name: Fall back to individual creation
cdot65.scm.address:
name: "{{ item.name }}"
folder: "SharedFolder"
ip_netmask: "{{ item.ip_netmask }}"
loop: "{{ csv_data.list }}"
Advanced Debugging and Logging
Comprehensive Logging
Implement comprehensive logging:
---
- name: SCM with Advanced Logging
hosts: localhost
connection: local
vars:
log_file: "/var/log/ansible/scm_operations.log"
debug_mode: true
tasks:
# Setup logging
- name: Ensure log directory exists
file:
path: "/var/log/ansible"
state: directory
mode: '0755'
become: true
# Log the start of operations
- name: Log operation start
copy:
content: |
--------------------------------------
SCM Operation: {{ ansible_date_time.iso8601 }}
User: {{ lookup('env', 'USER') }}
Playbook: {{ playbook_dir | basename }}/{{ ansible_play_name }}
--------------------------------------
dest: "{{ log_file }}"
mode: '0644'
append: yes
become: true
# Perform operations with debug
- name: Create address with debug
cdot65.scm.address:
name: "test-server"
folder: "SharedFolder"
ip_netmask: "10.1.1.1/32"
debug: "{{ debug_mode }}"
register: address_result
# Log the operation results
- name: Log operation result
copy:
content: |
Operation: Create address object
Status: {{ 'Success' if address_result.changed else 'No change' }}
Object ID: {{ address_result.scm_object.id | default('N/A') }}
--------------------------------------
dest: "{{ log_file }}"
mode: '0644'
append: yes
become: true
Integration with Cloud Providers
Multi-Cloud Security Management
Manage security across multiple clouds:
---
- name: Multi-Cloud Security Management
hosts: localhost
connection: local
vars:
aws_regions:
- us-east-1
- us-west-2
azure_resource_groups:
- "production-rg"
- "development-rg"
tasks:
# Get AWS security groups
- name: Get AWS security groups
amazon.aws.ec2_group_info:
region: "{{ item }}"
loop: "{{ aws_regions }}"
register: aws_security_groups
# Get Azure NSGs
- name: Get Azure NSGs
azure.azcollection.azure_rm_securitygroup_info:
resource_group: "{{ item }}"
loop: "{{ azure_resource_groups }}"
register: azure_nsgs
# Create address objects for all cloud resources
- name: Create AWS VPC address objects
cdot65.scm.address:
name: "AWS-VPC-{{ item.vpc_id }}"
folder: "Cloud-Resources"
description: "AWS VPC {{ item.vpc_id }} CIDR"
ip_netmask: "{{ item.cidr_block }}"
tags:
- "aws"
- "vpc"
loop: "{{ aws_vpcs.vpcs }}"
when: aws_vpcs is defined
# Create security rules based on cloud security groups
- name: Create SCM rules from AWS security groups
cdot65.scm.security_rule:
name: "AWS-SG-{{ item.group_id | replace('sg-', '') }}"
folder: "Cloud-Resources"
description: "AWS Security Group {{ item.group_name }}"
source_zones: ["AWS-Cloud"]
destination_zones: ["AWS-Cloud"]
source_addresses: ["any"]
destination_addresses: ["AWS-VPC-{{ item.vpc_id }}"]
applications: "{{ sg_apps[item.group_id] | default(['any']) }}"
services: "{{ sg_services[item.group_id] | default(['application-default']) }}"
action: "allow"
loop: "{{ aws_security_groups | json_query('results[*].security_groups[*]') | flatten }}"
vars:
sg_apps: {} # Mapping of SG to applications
sg_services: {} # Mapping of SG to services
These advanced examples demonstrate the depth and flexibility of the SCM Ansible Collection for complex enterprise environments and automation workflows.