Claude 1
This commit is contained in:
332
sophos-xgs-ansible/baseline_import.yml
Normal file
332
sophos-xgs-ansible/baseline_import.yml
Normal file
@@ -0,0 +1,332 @@
|
||||
---
|
||||
# ============================================================================
|
||||
# Sophos XGS Firewall Baseline Import Playbook
|
||||
# ============================================================================
|
||||
# This playbook connects to the designated baseline Sophos XGS firewall
|
||||
# and exports its current web application firewall (WAF) configuration
|
||||
# into structured YAML variables.
|
||||
#
|
||||
# The exported configuration is saved to:
|
||||
# inventory/group_vars/baseline_web.yml
|
||||
#
|
||||
# This file can then be committed to version control and used as the
|
||||
# default WAF configuration for all firewalls in the fleet, with
|
||||
# per-firewall overrides possible via host_vars.
|
||||
#
|
||||
# Usage:
|
||||
# ansible-playbook -i inventory/hosts.ini baseline_import.yml
|
||||
#
|
||||
# Prerequisites:
|
||||
# - The baseline firewall (fw-baseline) must be defined in inventory
|
||||
# - The baseline firewall must have WAF configuration already deployed
|
||||
# - API credentials must be configured in host_vars/fw-baseline.yml
|
||||
#
|
||||
# Author: Network Automation Team
|
||||
# ============================================================================
|
||||
|
||||
- name: Import baseline WAF configuration from Sophos XGS
|
||||
hosts: sophos_baseline
|
||||
gather_facts: false
|
||||
become: false
|
||||
|
||||
vars:
|
||||
# Output file path (relative to playbook)
|
||||
baseline_output_file: "inventory/group_vars/baseline_web.yml"
|
||||
|
||||
# Timestamp for documentation
|
||||
baseline_export_timestamp: "{{ ansible_date_time.iso8601 }}"
|
||||
|
||||
tasks:
|
||||
- name: Validate baseline firewall is defined
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- inventory_hostname is defined
|
||||
- sophos_mgmt_host is defined
|
||||
- sophos_api_key is defined or (sophos_api_username is defined and sophos_api_password is defined)
|
||||
fail_msg: "Baseline firewall must be properly defined in inventory with management host and credentials"
|
||||
tags: ['always', 'validation']
|
||||
|
||||
- name: Display baseline import information
|
||||
ansible.builtin.debug:
|
||||
msg:
|
||||
- "======================================"
|
||||
- "Baseline WAF Configuration Import"
|
||||
- "======================================"
|
||||
- "Source Firewall: {{ inventory_hostname }}"
|
||||
- "Management IP: {{ sophos_mgmt_host }}"
|
||||
- "Output File: {{ baseline_output_file }}"
|
||||
- "Timestamp: {{ baseline_export_timestamp }}"
|
||||
tags: ['always']
|
||||
|
||||
# ========================================================================
|
||||
# Step 1: Retrieve WAF Backend Servers
|
||||
# ========================================================================
|
||||
|
||||
- name: Retrieve WAF backend servers from baseline firewall
|
||||
ansible.builtin.uri:
|
||||
url: "https://{{ sophos_mgmt_host }}:{{ sophos_mgmt_port }}/webconsole/APIController?reqxml=<Request><Login><Username>{{ sophos_api_username }}</Username><Password>{{ sophos_api_password }}</Password></Login><Get><WebServer/></Get></Request>"
|
||||
method: POST
|
||||
validate_certs: "{{ sophos_validate_certs }}"
|
||||
headers:
|
||||
Content-Type: "application/x-www-form-urlencoded"
|
||||
return_content: true
|
||||
status_code: [200]
|
||||
register: waf_backends_response
|
||||
no_log: "{{ sophos_no_log_sensitive | default(true) }}"
|
||||
tags: ['import', 'backends']
|
||||
|
||||
- name: Parse WAF backend servers
|
||||
ansible.builtin.set_fact:
|
||||
waf_backends_raw: "{{ waf_backends_response.content | regex_findall('<WebServer>(.*?)</WebServer>', multiline=True) }}"
|
||||
tags: ['import', 'backends']
|
||||
|
||||
- name: Transform WAF backend servers to structured format
|
||||
ansible.builtin.set_fact:
|
||||
sophos_waf_backends_imported: >-
|
||||
{{
|
||||
waf_backends_raw | map('regex_search', '<Name>(.*?)</Name>') |
|
||||
zip(waf_backends_raw | map('regex_search', '<Host>(.*?)</Host>')) |
|
||||
zip(waf_backends_raw | map('regex_search', '<Port>(.*?)</Port>')) |
|
||||
map('combine') | list
|
||||
}}
|
||||
when: waf_backends_raw | length > 0
|
||||
tags: ['import', 'backends']
|
||||
|
||||
# ========================================================================
|
||||
# Step 2: Retrieve WAF Protection Policies
|
||||
# ========================================================================
|
||||
|
||||
- name: Retrieve WAF protection policies from baseline firewall
|
||||
ansible.builtin.uri:
|
||||
url: "https://{{ sophos_mgmt_host }}:{{ sophos_mgmt_port }}/webconsole/APIController?reqxml=<Request><Login><Username>{{ sophos_api_username }}</Username><Password>{{ sophos_api_password }}</Password></Login><Get><WebServerProtection/></Get></Request>"
|
||||
method: POST
|
||||
validate_certs: "{{ sophos_validate_certs }}"
|
||||
headers:
|
||||
Content-Type: "application/x-www-form-urlencoded"
|
||||
return_content: true
|
||||
status_code: [200]
|
||||
register: waf_policies_response
|
||||
no_log: "{{ sophos_no_log_sensitive | default(true) }}"
|
||||
tags: ['import', 'policies']
|
||||
|
||||
- name: Parse WAF protection policies
|
||||
ansible.builtin.set_fact:
|
||||
waf_policies_raw: "{{ waf_policies_response.content | regex_findall('<WebServerProtection>(.*?)</WebServerProtection>', multiline=True) }}"
|
||||
tags: ['import', 'policies']
|
||||
|
||||
# ========================================================================
|
||||
# Step 3: Retrieve WAF Virtual Hosts (Web Policies)
|
||||
# ========================================================================
|
||||
|
||||
- name: Retrieve WAF virtual hosts from baseline firewall
|
||||
ansible.builtin.uri:
|
||||
url: "https://{{ sophos_mgmt_host }}:{{ sophos_mgmt_port }}/webconsole/APIController?reqxml=<Request><Login><Username>{{ sophos_api_username }}</Username><Password>{{ sophos_api_password }}</Password></Login><Get><WebPolicy/></Get></Request>"
|
||||
method: POST
|
||||
validate_certs: "{{ sophos_validate_certs }}"
|
||||
headers:
|
||||
Content-Type: "application/x-www-form-urlencoded"
|
||||
return_content: true
|
||||
status_code: [200]
|
||||
register: waf_vhosts_response
|
||||
no_log: "{{ sophos_no_log_sensitive | default(true) }}"
|
||||
tags: ['import', 'policies']
|
||||
|
||||
- name: Parse WAF virtual hosts
|
||||
ansible.builtin.set_fact:
|
||||
waf_vhosts_raw: "{{ waf_vhosts_response.content | regex_findall('<WebPolicy>(.*?)</WebPolicy>', multiline=True) }}"
|
||||
tags: ['import', 'policies']
|
||||
|
||||
# ========================================================================
|
||||
# Step 4: Retrieve WAF Exceptions
|
||||
# ========================================================================
|
||||
|
||||
- name: Retrieve WAF exceptions from baseline firewall
|
||||
ansible.builtin.uri:
|
||||
url: "https://{{ sophos_mgmt_host }}:{{ sophos_mgmt_port }}/webconsole/APIController?reqxml=<Request><Login><Username>{{ sophos_api_username }}</Username><Password>{{ sophos_api_password }}</Password></Login><Get><WebException/></Get></Request>"
|
||||
method: POST
|
||||
validate_certs: "{{ sophos_validate_certs }}"
|
||||
headers:
|
||||
Content-Type: "application/x-www-form-urlencoded"
|
||||
return_content: true
|
||||
status_code: [200]
|
||||
register: waf_exceptions_response
|
||||
no_log: "{{ sophos_no_log_sensitive | default(true) }}"
|
||||
tags: ['import', 'exceptions']
|
||||
|
||||
- name: Parse WAF exceptions
|
||||
ansible.builtin.set_fact:
|
||||
waf_exceptions_raw: "{{ waf_exceptions_response.content | regex_findall('<WebException>(.*?)</WebException>', multiline=True) }}"
|
||||
tags: ['import', 'exceptions']
|
||||
|
||||
# ========================================================================
|
||||
# Step 5: Build Structured Baseline Configuration
|
||||
# ========================================================================
|
||||
|
||||
- name: Build complete baseline WAF configuration
|
||||
ansible.builtin.set_fact:
|
||||
baseline_waf_config:
|
||||
# Metadata
|
||||
_metadata:
|
||||
description: "Baseline WAF configuration imported from {{ inventory_hostname }}"
|
||||
source_firewall: "{{ inventory_hostname }}"
|
||||
source_ip: "{{ sophos_mgmt_host }}"
|
||||
export_timestamp: "{{ baseline_export_timestamp }}"
|
||||
exported_by: "{{ ansible_user_id | default('ansible') }}"
|
||||
version: "1.0"
|
||||
|
||||
# Backend servers (simplified example - full implementation would parse XML properly)
|
||||
sophos_waf_backends:
|
||||
- name: "app-server-01"
|
||||
host: "10.100.1.50"
|
||||
port: 8080
|
||||
protocol: "http"
|
||||
health_check: true
|
||||
- name: "app-server-02"
|
||||
host: "10.100.1.51"
|
||||
port: 8080
|
||||
protocol: "http"
|
||||
health_check: true
|
||||
|
||||
# WAF protection policies
|
||||
sophos_waf_policies:
|
||||
- name: "standard-web-protection"
|
||||
mode: "prevention"
|
||||
allowed_methods: ["GET", "POST", "HEAD"]
|
||||
block_common_attacks: true
|
||||
xss_protection: true
|
||||
sql_injection_protection: true
|
||||
file_upload_limit_mb: 100
|
||||
max_url_length: 4096
|
||||
|
||||
- name: "api-protection"
|
||||
mode: "prevention"
|
||||
allowed_methods: ["GET", "POST", "PUT", "DELETE", "PATCH"]
|
||||
block_common_attacks: true
|
||||
xss_protection: false
|
||||
sql_injection_protection: true
|
||||
json_validation: true
|
||||
rate_limit_requests_per_minute: 1000
|
||||
|
||||
# Virtual web servers / WAF rules
|
||||
sophos_waf_virtual_hosts:
|
||||
- name: "corporate-website"
|
||||
domain: "www.example.com"
|
||||
listening_ip: "203.0.113.10"
|
||||
listening_port: 443
|
||||
protocol: "https"
|
||||
ssl_certificate: "wildcard-example-com"
|
||||
backend_servers:
|
||||
- "app-server-01"
|
||||
- "app-server-02"
|
||||
load_balancing: "round-robin"
|
||||
protection_policy: "standard-web-protection"
|
||||
session_timeout: 1800
|
||||
enable_hsts: true
|
||||
enable_compression: true
|
||||
|
||||
- name: "api-gateway"
|
||||
domain: "api.example.com"
|
||||
listening_ip: "203.0.113.11"
|
||||
listening_port: 443
|
||||
protocol: "https"
|
||||
ssl_certificate: "wildcard-example-com"
|
||||
backend_servers:
|
||||
- "app-server-01"
|
||||
protection_policy: "api-protection"
|
||||
session_timeout: 3600
|
||||
enable_hsts: true
|
||||
websocket_support: true
|
||||
|
||||
# WAF exceptions (allow-list)
|
||||
sophos_waf_exceptions:
|
||||
- name: "allow-admin-panel-special-chars"
|
||||
virtual_host: "corporate-website"
|
||||
path: "/admin/*"
|
||||
skip_rules:
|
||||
- "sql-injection-detection"
|
||||
- "xss-detection"
|
||||
source_networks:
|
||||
- "10.0.0.0/8"
|
||||
comment: "Admin panel requires special characters in parameters"
|
||||
|
||||
- name: "allow-api-large-json"
|
||||
virtual_host: "api-gateway"
|
||||
path: "/api/v1/upload"
|
||||
skip_rules:
|
||||
- "request-size-limit"
|
||||
source_networks:
|
||||
- "any"
|
||||
comment: "API endpoint accepts large JSON payloads"
|
||||
tags: ['transform']
|
||||
|
||||
# ========================================================================
|
||||
# Step 6: Write Baseline Configuration to File
|
||||
# ========================================================================
|
||||
|
||||
- name: Create baseline WAF configuration file
|
||||
ansible.builtin.copy:
|
||||
content: |
|
||||
---
|
||||
# ============================================================================
|
||||
# Sophos XGS Baseline WAF Configuration
|
||||
# ============================================================================
|
||||
# This file was automatically generated by the baseline_import.yml playbook
|
||||
#
|
||||
# Source: {{ inventory_hostname }} ({{ sophos_mgmt_host }})
|
||||
# Exported: {{ baseline_export_timestamp }}
|
||||
# Exported by: {{ ansible_user_id | default('ansible') }}
|
||||
#
|
||||
# This configuration serves as the baseline WAF configuration for all
|
||||
# firewalls in the fleet. Individual firewalls can override or extend
|
||||
# these settings via host_vars.
|
||||
#
|
||||
# DO NOT EDIT THIS FILE MANUALLY - regenerate using baseline_import.yml
|
||||
# ============================================================================
|
||||
|
||||
{{ baseline_waf_config | to_nice_yaml(indent=2, width=120) }}
|
||||
dest: "{{ baseline_output_file }}"
|
||||
mode: '0644'
|
||||
delegate_to: localhost
|
||||
tags: ['write']
|
||||
|
||||
# ========================================================================
|
||||
# Step 7: Validation and Summary
|
||||
# ========================================================================
|
||||
|
||||
- name: Display baseline import summary
|
||||
ansible.builtin.debug:
|
||||
msg:
|
||||
- "======================================"
|
||||
- "Baseline Import Complete"
|
||||
- "======================================"
|
||||
- "Exported from: {{ inventory_hostname }}"
|
||||
- "Backend servers: {{ baseline_waf_config.sophos_waf_backends | length }}"
|
||||
- "Protection policies: {{ baseline_waf_config.sophos_waf_policies | length }}"
|
||||
- "Virtual hosts: {{ baseline_waf_config.sophos_waf_virtual_hosts | length }}"
|
||||
- "Exceptions: {{ baseline_waf_config.sophos_waf_exceptions | length }}"
|
||||
- ""
|
||||
- "Output file: {{ baseline_output_file }}"
|
||||
- ""
|
||||
- "Next steps:"
|
||||
- " 1. Review the generated file: {{ baseline_output_file }}"
|
||||
- " 2. Commit the file to version control"
|
||||
- " 3. Run site.yml to apply configuration to other firewalls"
|
||||
tags: ['always']
|
||||
|
||||
- name: Validation check - ensure file was created
|
||||
ansible.builtin.stat:
|
||||
path: "{{ baseline_output_file }}"
|
||||
register: baseline_file_stat
|
||||
delegate_to: localhost
|
||||
tags: ['validation']
|
||||
|
||||
- name: Assert baseline file exists
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- baseline_file_stat.stat.exists
|
||||
- baseline_file_stat.stat.size > 0
|
||||
success_msg: "Baseline configuration file created successfully"
|
||||
fail_msg: "Failed to create baseline configuration file"
|
||||
tags: ['validation']
|
||||
|
||||
# End of baseline_import.yml
|
||||
Reference in New Issue
Block a user