--- # ============================================================================ # 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={{ sophos_api_username }}{{ sophos_api_password }}" 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('(.*?)', 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', '(.*?)') | zip(waf_backends_raw | map('regex_search', '(.*?)')) | zip(waf_backends_raw | map('regex_search', '(.*?)')) | 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={{ sophos_api_username }}{{ sophos_api_password }}" 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('(.*?)', 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={{ sophos_api_username }}{{ sophos_api_password }}" 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('(.*?)', 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={{ sophos_api_username }}{{ sophos_api_password }}" 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('(.*?)', 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