Skip to content

Complex Filtering Examples

This guide demonstrates advanced filtering techniques and real-world scenarios for querying your Panorama configuration.

Multi-Criteria Filtering

Security Audit: Find High-Risk Rules

Find overly permissive rules that pose security risks:

# Any-to-any allow rules without logging
curl -X GET "http://localhost:8000/api/v1/configs/panorama/rules/security?\
filter.source.in=any&\
filter.destination.in=any&\
filter.application.in=any&\
filter.service.in=any&\
filter.action.equals=allow&\
filter.log_end.equals=false"

Compliance Check: PCI-DSS

Find rules that might violate PCI-DSS requirements:

# Unencrypted protocols to cardholder environment
curl -X GET "http://localhost:8000/api/v1/configs/panorama/rules/security?\
filter.destination.contains=cardholder&\
filter.application.in=telnet,ftp,http&\
filter.action.equals=allow"

Network Segmentation Validation

Verify proper network segmentation:

# Direct access from untrust to internal databases
curl -X GET "http://localhost:8000/api/v1/configs/panorama/rules/security?\
filter.from.in=untrust,internet&\
filter.destination.contains=database&\
filter.action.equals=allow"

Address Object Queries

Subnet Analysis

Find all addresses in multiple subnets:

# Find addresses in either 10.0.0.0/8 or 172.16.0.0/12
curl -X GET "http://localhost:8000/api/v1/configs/panorama/addresses?\
filter.type.equals=ip-netmask" \
| jq '.items[] | select(.["ip-netmask"] | startswith("10.") or startswith("172.16"))'

FQDN Management

Find and categorize FQDN objects:

# External domains (non-.internal)
curl -X GET "http://localhost:8000/api/v1/configs/panorama/addresses?\
filter.type.equals=fqdn&\
filter.fqdn.not_contains=.internal&\
filter.fqdn.not_contains=.local"

# Cloud service domains
curl -X GET "http://localhost:8000/api/v1/configs/panorama/addresses?\
filter.type.equals=fqdn&\
filter.fqdn.regex=(amazonaws|azure|googlecloud)\.com$"

Duplicate Detection

Find potential duplicate addresses:

# Find addresses with same IP but different names
curl -X GET "http://localhost:8000/api/v1/configs/panorama/addresses?\
filter.type.equals=ip-netmask" \
| jq 'reduce .items[] as $item ({}; .[$item["ip-netmask"]] += [$item.name]) | 
  to_entries | map(select(.value | length > 1))'

Service Analysis

Port Range Analysis

Find services using specific port ranges:

# High-risk port ranges
curl -X GET "http://localhost:8000/api/v1/configs/panorama/services?\
filter.port.contains=135-139&\
filter.protocol.equals=tcp"

# Custom application ports
curl -X GET "http://localhost:8000/api/v1/configs/panorama/services?\
filter.port.gte=30000&\
filter.port.lte=32767"

Service Inventory

Categorize services by usage:

# Database services
curl -X GET "http://localhost:8000/api/v1/configs/panorama/services?\
filter.port.in=1433,1521,3306,5432,27017&\
filter.protocol.equals=tcp"

# Web services
curl -X GET "http://localhost:8000/api/v1/configs/panorama/services?\
filter.port.in=80,443,8080,8443&\
filter.protocol.equals=tcp"

Application-Based Filtering

Social Media Control

Find rules allowing social media:

# All social media applications
curl -X GET "http://localhost:8000/api/v1/configs/panorama/rules/security?\
filter.application.regex=(facebook|twitter|instagram|linkedin|tiktok)&\
filter.action.equals=allow"

File Transfer Analysis

Identify file transfer permissions:

# File transfer protocols
curl -X GET "http://localhost:8000/api/v1/configs/panorama/rules/security?\
filter.application.in=ftp,sftp,scp,dropbox,google-drive,onedrive&\
filter.action.ne=deny"

High-Risk Applications

Find rules allowing risky applications:

# P2P and anonymization tools
curl -X GET "http://localhost:8000/api/v1/configs/panorama/rules/security?\
filter.application.regex=(torrent|tor|proxy|vpn|ultrasurf)&\
filter.action.ne=deny&\
filter.disabled.equals=false"

Zone-Based Analysis

DMZ Security Posture

Analyze DMZ security configuration:

# Inbound to DMZ
curl -X GET "http://localhost:8000/api/v1/configs/panorama/rules/security?\
filter.from.in=untrust,internet&\
filter.to.in=dmz&\
filter.action.equals=allow"

# Outbound from DMZ
curl -X GET "http://localhost:8000/api/v1/configs/panorama/rules/security?\
filter.from.in=dmz&\
filter.to.not_in=dmz&\
filter.action.equals=allow"

# DMZ to internal
curl -X GET "http://localhost:8000/api/v1/configs/panorama/rules/security?\
filter.from.in=dmz&\
filter.to.in=trust,internal&\
filter.action.equals=allow"

Zero Trust Validation

Check zero trust implementation:

# Rules without user identification
curl -X GET "http://localhost:8000/api/v1/configs/panorama/rules/security?\
filter.source_user.in=any&\
filter.to.in=trust,internal&\
filter.action.equals=allow"

Tag-Based Queries

Environment Separation

Verify environment isolation:

# Production to development access
curl -X GET "http://localhost:8000/api/v1/configs/panorama/rules/security?\
filter.source.contains=prod&\
filter.destination.contains=dev&\
filter.action.equals=allow"

Critical Asset Protection

Find rules affecting critical assets:

# Access to critical tagged resources
curl -X GET "http://localhost:8000/api/v1/configs/panorama/rules/security?\
filter.destination.contains=critical&\
filter.tag.not_contains=approved&\
filter.action.equals=allow"

NAT Rule Analysis

Source NAT Audit

Find source NAT configurations:

# Outbound NAT rules
curl -X GET "http://localhost:8000/api/v1/configs/panorama/rules/nat?\
filter.from.in=trust,internal&\
filter.to.in=untrust,internet&\
filter.source_translation.exists=true"

Destination NAT Review

Analyze inbound NAT rules:

# Public to private NAT
curl -X GET "http://localhost:8000/api/v1/configs/panorama/rules/nat?\
filter.from.in=untrust,internet&\
filter.destination_translation.exists=true&\
filter.disabled.equals=false"

Complex Regex Patterns

Naming Convention Validation

Check adherence to naming standards:

# Find non-compliant rule names
curl -X GET "http://localhost:8000/api/v1/configs/panorama/rules/security?\
filter.name.regex=^(?![A-Z]{2,}-[A-Z]+-[0-9]{4}$).*"

# Find non-compliant addresses
curl -X GET "http://localhost:8000/api/v1/configs/panorama/addresses?\
filter.name.regex=^(?!(srv|web|db|app)-[a-z]+-[0-9]{2}$).*"

IP Pattern Matching

Find specific IP patterns:

# Find IPs ending in .1 (likely gateways)
curl -X GET "http://localhost:8000/api/v1/configs/panorama/addresses?\
filter.ip.regex=\\.1(/|$)&\
filter.type.equals=ip-netmask"

# Find /32 host addresses
curl -X GET "http://localhost:8000/api/v1/configs/panorama/addresses?\
filter.ip.regex=/32$&\
filter.type.equals=ip-netmask"

Performance Optimization Queries

Large Result Set Handling

Efficiently process large datasets:

# Paginated retrieval with filtering
LIMIT=100
OFFSET=0
TOTAL=999999

while [ $OFFSET -lt $TOTAL ]; do
    RESPONSE=$(curl -s "http://localhost:8000/api/v1/configs/panorama/addresses?\
    filter.type.equals=ip-netmask&\
    limit=$LIMIT&\
    offset=$OFFSET")

    TOTAL=$(echo $RESPONSE | jq '.total_items')
    echo $RESPONSE | jq '.items[]' >> all_addresses.jsonl

    OFFSET=$((OFFSET + LIMIT))
done

Parallel Queries

Execute multiple queries simultaneously:

# Parallel filtering for different object types
{
    curl -s "http://localhost:8000/api/v1/configs/panorama/addresses?filter.tag.in=production" &
    curl -s "http://localhost:8000/api/v1/configs/panorama/services?filter.tag.in=production" &
    curl -s "http://localhost:8000/api/v1/configs/panorama/rules/security?filter.tag.in=production" &
    wait
} | jq -s '.'

Python Advanced Examples

import requests
import concurrent.futures
from typing import List, Dict, Any

class AdvancedPanConfigAnalyzer:
    def __init__(self, base_url: str):
        self.base_url = base_url
        self.session = requests.Session()

    def find_security_gaps(self) -> Dict[str, List[Any]]:
        """Identify potential security gaps in configuration"""
        gaps = {}

        # Overly permissive rules
        gaps['permissive_rules'] = self._query_rules({
            'source.in': 'any',
            'destination.in': 'any',
            'action.equals': 'allow'
        })

        # Rules without logging
        gaps['no_logging'] = self._query_rules({
            'log_end.equals': 'false',
            'action.equals': 'allow',
            'disabled.equals': 'false'
        })

        # Direct internet access
        gaps['direct_internet'] = self._query_rules({
            'from.in': 'trust,internal',
            'to.in': 'untrust,internet',
            'destination.in': 'any'
        })

        return gaps

    def analyze_attack_surface(self) -> Dict[str, Any]:
        """Analyze external attack surface"""
        with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
            futures = {
                'inbound_rules': executor.submit(
                    self._query_rules, 
                    {'from.in': 'untrust,internet', 'action.equals': 'allow'}
                ),
                'public_services': executor.submit(
                    self._query_nat_rules,
                    {'from.in': 'untrust', 'destination_translation.exists': 'true'}
                ),
                'dmz_exposure': executor.submit(
                    self._query_rules,
                    {'to.in': 'dmz', 'from.in': 'untrust,internet'}
                )
            }

            results = {}
            for key, future in futures.items():
                results[key] = future.result()

            return results

    def find_unused_objects(self) -> Dict[str, List[str]]:
        """Find potentially unused configuration objects"""
        unused = {}

        # Addresses without description or tags
        addresses = self._query_addresses({
            'description.equals': '',
            'tag.exists': 'false'
        })
        unused['addresses'] = [a['name'] for a in addresses]

        # Disabled rules
        rules = self._query_rules({'disabled.equals': 'true'})
        unused['disabled_rules'] = [r['name'] for r in rules]

        # Services with 'old' or 'temp' in name
        services = self._query_services({'name.regex': '(old|temp|test)'})
        unused['temp_services'] = [s['name'] for s in services]

        return unused

    def _query_rules(self, filters: Dict[str, str]) -> List[Dict]:
        params = {f'filter.{k}': v for k, v in filters.items()}
        response = self.session.get(
            f"{self.base_url}/rules/security",
            params=params
        )
        return response.json().get('items', [])

    def _query_addresses(self, filters: Dict[str, str]) -> List[Dict]:
        params = {f'filter.{k}': v for k, v in filters.items()}
        response = self.session.get(
            f"{self.base_url}/addresses",
            params=params
        )
        return response.json().get('items', [])

    def _query_services(self, filters: Dict[str, str]) -> List[Dict]:
        params = {f'filter.{k}': v for k, v in filters.items()}
        response = self.session.get(
            f"{self.base_url}/services",
            params=params
        )
        return response.json().get('items', [])

    def _query_nat_rules(self, filters: Dict[str, str]) -> List[Dict]:
        params = {f'filter.{k}': v for k, v in filters.items()}
        response = self.session.get(
            f"{self.base_url}/rules/nat",
            params=params
        )
        return response.json().get('items', [])

# Usage
analyzer = AdvancedPanConfigAnalyzer("http://localhost:8000/api/v1/configs/panorama")

# Security gap analysis
gaps = analyzer.find_security_gaps()
print(f"Found {len(gaps['permissive_rules'])} overly permissive rules")
print(f"Found {len(gaps['no_logging'])} rules without logging")

# Attack surface analysis
attack_surface = analyzer.analyze_attack_surface()
print(f"Inbound rules: {len(attack_surface['inbound_rules'])}")
print(f"Public services: {len(attack_surface['public_services'])}")

# Cleanup candidates
unused = analyzer.find_unused_objects()
print(f"Potentially unused addresses: {len(unused['addresses'])}")
print(f"Disabled rules: {len(unused['disabled_rules'])}")

JavaScript Advanced Examples

class SecurityAuditor {
    constructor(apiUrl) {
        this.apiUrl = apiUrl;
    }

    async performComplianceCheck(standard = 'pci-dss') {
        const checks = {
            'pci-dss': {
                'unencrypted_protocols': {
                    'filter.application.in': 'telnet,ftp,http',
                    'filter.destination.contains': 'cardholder',
                    'filter.action.equals': 'allow'
                },
                'missing_logging': {
                    'filter.tag.contains': 'pci',
                    'filter.log_end.equals': 'false'
                },
                'any_source': {
                    'filter.source.in': 'any',
                    'filter.destination.contains': 'cardholder'
                }
            }
        };

        const results = {};
        const checkSet = checks[standard];

        for (const [checkName, filters] of Object.entries(checkSet)) {
            const params = new URLSearchParams(filters);
            const response = await fetch(
                `${this.apiUrl}/rules/security?${params}`
            );
            const data = await response.json();
            results[checkName] = {
                violation_count: data.total_items,
                violations: data.items
            };
        }

        return results;
    }

    async findShadowIT() {
        // Find unauthorized cloud applications
        const cloudApps = [
            'dropbox', 'google-drive', 'onedrive', 'box',
            'wetransfer', 'mega', 'mediafire'
        ];

        const params = new URLSearchParams({
            'filter.application.regex': cloudApps.join('|'),
            'filter.action.ne': 'deny',
            'filter.tag.not_contains': 'approved'
        });

        const response = await fetch(
            `${this.apiUrl}/rules/security?${params}`
        );
        return response.json();
    }

    async analyzeZeroTrust() {
        const violations = {};

        // Check for any-user rules
        const anyUserParams = new URLSearchParams({
            'filter.source_user.in': 'any',
            'filter.action.equals': 'allow'
        });
        const anyUserResp = await fetch(
            `${this.apiUrl}/rules/security?${anyUserParams}`
        );
        violations.any_user = await anyUserResp.json();

        // Check for missing MFA
        const noMfaParams = new URLSearchParams({
            'filter.tag.not_contains': 'mfa-required',
            'filter.to.in': 'trust,internal',
            'filter.from.in': 'untrust,internet'
        });
        const noMfaResp = await fetch(
            `${this.apiUrl}/rules/security?${noMfaParams}`
        );
        violations.no_mfa = await noMfaResp.json();

        return violations;
    }
}

// Usage
const auditor = new SecurityAuditor('http://localhost:8000/api/v1/configs/panorama');

// PCI-DSS compliance check
auditor.performComplianceCheck('pci-dss').then(results => {
    console.log('PCI-DSS Compliance Check Results:');
    for (const [check, data] of Object.entries(results)) {
        console.log(`${check}: ${data.violation_count} violations`);
    }
});

// Shadow IT detection
auditor.findShadowIT().then(data => {
    console.log(`Found ${data.total_items} potential shadow IT rules`);
    data.items.forEach(rule => {
        console.log(`- ${rule.name}: ${rule.application.join(', ')}`);
    });
});

// Zero Trust analysis
auditor.analyzeZeroTrust().then(violations => {
    console.log('Zero Trust Violations:');
    console.log(`Rules with any user: ${violations.any_user.total_items}`);
    console.log(`Rules missing MFA: ${violations.no_mfa.total_items}`);
});

Shell Script Examples

Automated Security Report

#!/bin/bash

API_URL="http://localhost:8000/api/v1/configs/panorama"
REPORT_DATE=$(date +%Y%m%d)
REPORT_FILE="security_report_${REPORT_DATE}.html"

# Generate HTML report
cat > $REPORT_FILE << EOF
<!DOCTYPE html>
<html>
<head>
    <title>Security Configuration Report - $REPORT_DATE</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; }
        .critical { color: red; }
        .warning { color: orange; }
        .info { color: blue; }
        table { border-collapse: collapse; width: 100%; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; }
    </style>
</head>
<body>
    <h1>Security Configuration Report</h1>
    <p>Generated: $(date)</p>
EOF

# High-risk rules
echo "<h2 class='critical'>High-Risk Rules</h2>" >> $REPORT_FILE
RISKY_RULES=$(curl -s "$API_URL/rules/security?\
filter.source.in=any&\
filter.destination.in=any&\
filter.action.equals=allow" | jq -r '.total_items')
echo "<p>Found $RISKY_RULES overly permissive rules</p>" >> $REPORT_FILE

# Rules without logging
echo "<h2 class='warning'>Rules Without Logging</h2>" >> $REPORT_FILE
NO_LOG=$(curl -s "$API_URL/rules/security?\
filter.log_end.equals=false&\
filter.disabled.equals=false" | jq -r '.total_items')
echo "<p>Found $NO_LOG active rules without logging</p>" >> $REPORT_FILE

# Disabled rules
echo "<h2 class='info'>Cleanup Candidates</h2>" >> $REPORT_FILE
DISABLED=$(curl -s "$API_URL/rules/security?\
filter.disabled.equals=true" | jq -r '.total_items')
echo "<p>Found $DISABLED disabled rules</p>" >> $REPORT_FILE

echo "</body></html>" >> $REPORT_FILE

echo "Report generated: $REPORT_FILE"

Next Steps