Skip to content

feat(azure): Azure Firewall Support#2223

Open
ashton-suire wants to merge 8 commits intocartography-cncf:masterfrom
ashton-suire:azure-firewall-support
Open

feat(azure): Azure Firewall Support#2223
ashton-suire wants to merge 8 commits intocartography-cncf:masterfrom
ashton-suire:azure-firewall-support

Conversation

@ashton-suire
Copy link

@ashton-suire ashton-suire commented Jan 13, 2026

Summary

This PR adds comprehensive support for Azure Firewall and Azure Firewall Policy resources to Cartography, enabling security teams to analyze firewall configurations, security rules, and network protections across Azure environments.

What Changed:

  • New intel module [firewall.py] that fetches Azure Firewalls and Firewall Policies
  • Enriches policies with rule collection groups containing actual security rules (ports, protocols, addresses)
  • Enriches firewalls with IP Groups for IP address resolution
  • Data models for AzureFirewall (33 properties) and AzureFirewallPolicy (39 properties)
  • Captures all security-critical data: network rules, application rules, NAT rules, threat intel, IDPS, DNS proxy, TLS inspection
  • Test data, demo support, and comprehensive documentation

This implementation allows security teams to:

  • Audit network security rules across subscriptions
  • Identify exposed services via NAT rules
  • Validate security controls (threat intelligence, IDPS)
  • Detect misconfigurations and overly permissive rules
  • Map attack surface through firewall policies

Files Changed:

New: [firewall.py] (379 lines)
New: [azure_firewall.py](150 lines)
New: [firewall_policy.py] (156 lines)
New: [firewall.py] (239 lines)
Modified: [init.py] [azure.py] [schema.md] [README.md]
Stats: 9 files changed, 1,040 insertions, 1 deletion

Related issues or links

Closes #2215

Checklist

Provide proof that this works (this makes reviews move faster). Please perform one or more of the following:

  • Update/add unit or integration tests.
    Added comprehensive test data in [firewall.py] with realistic security rules (SSH port 22, HTTPS port 443, web DNAT, threat intel config, IDPS settings)
  • Include a screenshot showing what the graph looked like before and after your changes.
Screenshot 2026-01-12 at 9 07 29 PM - [x] Include console log trace showing what happened before and after your changes. Before: No Azure Firewall nodes in graph After: Successfully synced real Azure Firewall resources to Neo4j database with all security rules captured
INFO:cartography.intel.azure.firewall:Syncing Azure Firewalls and Firewall Policies
INFO:cartography.graph.statement:Completed AzureFirewall statement #1
INFO:cartography.graph.statement:Completed AzureFirewall statement #2
INFO:cartography.graph.statement:Completed AzureFirewall statement #3
INFO:cartography.graph.statement:Completed AzureFirewall statement #4
INFO:cartography.graph.statement:Completed AzureFirewall statement #5
INFO:cartography.graph.job:Finished job AzureFirewall
INFO:cartography.graph.statement:Completed AzureFirewallPolicy statement #1
INFO:cartography.graph.statement:Completed AzureFirewallPolicy statement #2
INFO:cartography.graph.job:Finished job AzureFirewallPolicy

If you are changing a node or relationship:

  • Update the schema and readme.
    Updated [schema.md] with 150+ lines of comprehensive documentation
    Added full property tables for AzureFirewall and AzureFirewallPolicy
    Documented all 6 relationships with Cypher examples
    Added Security Properties sections explaining critical fields
    Updated [README.md] to list "Firewall, Firewall Policy" in Azure module

If you are implementing a new intel module:

  • Use the NodeSchema data model.
  • Confirm that the linter actually passes (submitting a PR where the linter fails shows reviewers that you did not test your code and will delay your review).
➜  pre-commit run --files cartography/intel/azure/firewall.py cartography/models/azure/firewall/azure_firewall.p
y cartography/models/azure/firewall/firewall_policy.py tests/data/azure/firewall.py cartography/intel/azure/__in
it__.py demo/seeds/azure.py docs/root/modules/azure/schema.md README.md
uv-lock..............................................(no files to check)Skipped
check docstring is first.................................................Passed
check that executables have shebangs.................(no files to check)Skipped
check for merge conflicts................................................Passed
check vcs permalinks.....................................................Passed
check yaml...........................................(no files to check)Skipped
debug statements (python)................................................Passed
fix end of files.........................................................Passed
trim trailing whitespace.................................................Passed
isort....................................................................Passed
black....................................................................Passed
flake8...................................................................Passed
pyupgrade................................................................Passed
mypy.....................................................................Passed

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 9 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="docs/root/modules/azure/schema.md">

<violation number="1" location="docs/root/modules/azure/schema.md:1974">
P2: AzureFirewall relationship to Virtual Hub is documented with a nonexistent node definition and wrong edge label (CONNECTED_VHUB vs actual DEPLOYED_TO), making the schema inaccurate.</violation>
</file>

<file name="cartography/intel/azure/firewall.py">

<violation number="1" location="cartography/intel/azure/firewall.py:34">
P1: Swallowing Azure HttpResponseError returns empty results and still runs cleanup, causing stale deletion on auth/systemic failures</violation>
</file>

<file name="cartography/models/azure/firewall/azure_firewall.py">

<violation number="1" location="cartography/models/azure/firewall/azure_firewall.py:95">
P2: AzureFirewall VNet relationship uses vnet_id but the node never stores or populates vnet_id, so MEMBER_OF edges to AzureVirtualNetwork are never created.</violation>
</file>

Since this is your first cubic review, here's how it works:

  • cubic automatically reviews your code and comments on bugs and improvements
  • Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
  • Ask questions if you need clarification on any suggestion

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="cartography/intel/azure/firewall.py">

<violation number="1" location="cartography/intel/azure/firewall.py:31">
P2: Docstring not updated to document newly propagated HttpResponseError from Azure list call; callers may be unaware they must handle failures.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@ashton-suire ashton-suire force-pushed the azure-firewall-support branch 3 times, most recently from 4c92f4e to 04697b3 Compare January 13, 2026 19:21
@ashton-suire
Copy link
Author

Azure Firewall Support

This PR integrates Azure Firewall into Cartography.

What’s included

Ingestion

  • Azure sync entry point now calls firewall.sync(...) from cartography/intel/azure/__init__.py.
  • 'cartography/intel/azure/firewall.py` gathers firewalls, policies, and IP groups

Nodes:

  • AzureFirewall
  • AzureFirewallPolicy
  • AzureFirewallIPConfiguration

Security-relevant properties captured:

  • Threat intelligence mode
  • IDPS configuration
  • NAT / application / network rules
  • IP groups
  • DNS / SNAT / explicit proxy / TLS inspection

Relationships:

  • (:AzureSubscription)-[:RESOURCE]->(:AzureFirewall|AzureFirewallPolicy|AzureFirewallIPConfiguration)
  • (:AzureFirewall)-[:USES_POLICY]->(:AzureFirewallPolicy)
  • (:AzureFirewall)-[:MEMBER_OF]->(:AzureVirtualNetwork)
  • (:AzureFirewall)-[:DEPLOYED_TO]->(:AzureVirtualHub)
  • (:AzureFirewall)-[:HAS_IP_CONFIGURATION]->(:AzureFirewallIPConfiguration)
  • (:AzureFirewallIPConfiguration)-[:IN_SUBNET]->(:AzureSubnet)
  • (:AzureFirewallIPConfiguration)-[:USES_PUBLIC_IP]->(:AzurePublicIPAddress)

Documentation

  • Covers:
    • All three node types
    • Their properties
    • Security implications
    • Relationships with Cypher examples

Demo

  • demo/seeds/azure.py:
    • Loads firewall policies first
    • Then firewalls
  • Note: IP configurations are not seeded in the demo path yet.

Testing

Unit tests:

  • Located in:
    • tests/unit/cartography/intel/azure/test_firewall.py
  • Validate:
    • Transform behavior
    • Optional / missing fields
    • Firewall, policy, and IP configuration handling

Integration tests:

  • Located in:
    • tests/integration/cartography/intel/azure/test_firewall.py
  • Validate:
    • Full sync path
    • All nodes and relationships
    • Cleanup behavior
  • Use mocked Azure SDK calls and real-shape fixture data from:
    • tests/data/azure/firewall.py

@jychp jychp added the module:Azure Related to the Azure intel module label Jan 14, 2026
@jychp jychp changed the title Azure Firewall Support feat(azure): Azure Firewall Support Jan 14, 2026
@ashton-suire ashton-suire force-pushed the azure-firewall-support branch from 9cf670b to aa3844d Compare January 16, 2026 18:02
Copy link
Collaborator

@kunaals kunaals left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice work on this - the azure firewall implementation looks solid overall. transform functions handle the flat sdk structure correctly, load order is right (policies → firewalls → ip configs), and the test coverage is good.

however there's one issue that needs fixing before this can merge - the firewall policy subscription relationship direction is backwards which will break subscription-scoped queries.

@ashton-suire ashton-suire force-pushed the azure-firewall-support branch from 3389424 to f9bc6ba Compare January 26, 2026 20:34
This commit adds comprehensive support for Azure Firewall and Azure Firewall Policy resources, enabling security teams to analyze firewall configurations, security rules, and network protections across Azure environments.

- Fetches all Azure Firewalls and Firewall Policies from subscriptions
- Enriches policies with detailed rule collection groups containing actual security rules
- Enriches firewalls with IP Groups for IP address resolution
- Handles both VNet-based (AZFW_VNet) and Virtual WAN (AZFW_Hub) deployment models
- Proper error handling with graceful degradation
- JSON serialization for all complex objects to prevent Neo4j type errors

- **AzureFirewallSchema**: 33 properties capturing firewall configuration
  - Basic metadata: id, name, location, type, provisioning_state
  - Security configuration: threat_intel_mode, sku_name, sku_tier
  - Network topology: firewall_policy_id, virtual_hub_id, zones
  - IP configuration: ip_configurations, hub_private_ip_address
  - Autoscaling: autoscale_min_capacity, autoscale_max_capacity
  - Security rules: application_rule_collections, network_rule_collections, nat_rule_collections
  - IP Groups: ip_groups_detail for IP address collections

- **AzureFirewallPolicySchema**: 39 properties capturing policy configuration
  - Security settings: threat_intel_mode, sku_tier, base_policy_id
  - DNS configuration: dns_servers, dns_enable_proxy
  - SNAT settings: snat_private_ranges
  - Explicit proxy: explicit_proxy_enable, http/https ports
  - IDPS: intrusion_detection_mode, intrusion_detection_profile
  - TLS inspection: tls_certificate_authority_name
  - Threat intelligence: threat_intel_whitelist_ip_addresses, threat_intel_whitelist_fqdns
  - **Critical security data**: rule_groups_detail with full rules including ports, protocols, addresses

- `(AzureSubscription)-[:RESOURCE]->(AzureFirewall)`
- `(AzureSubscription)-[:RESOURCE]->(AzureFirewallPolicy)`
- `(AzureFirewall)-[:USES_POLICY]->(AzureFirewallPolicy)`
- `(AzureFirewall)-[:CONNECTED_VNET]->(AzureVirtualNetwork)`
- `(AzureFirewall)-[:CONNECTED_VHUB]->(AzureVirtualHub)`

- Comprehensive mock data in tests/data/azure/firewall.py
- Mock data includes realistic security rules:
  - SSH rule (port 22, TCP)
  - HTTPS rule (port 443)
  - Web DNAT rule (ports 80, 443)
  - Threat intelligence configuration
  - IDPS settings with signature overrides
- Demo seeding support in demo/seeds/azure.py

- Comprehensive schema documentation in docs/root/modules/azure/schema.md
  - Full property tables for both AzureFirewall and AzureFirewallPolicy
  - Security Properties sections highlighting critical fields
  - Relationship documentation with Cypher examples
  - Real-world security use case explanations
- Updated README.md to list "Firewall, Firewall Policy" in Azure module

This implementation captures all security-critical data:
- **Network rules**: destination_ports (22, 80, 443, etc.), ip_protocols (TCP, UDP, ICMP), source/destination addresses
- **Application rules**: target_fqdns, protocols, ports for L7 filtering
- **NAT rules**: destination addresses, translated addresses/ports for DNAT
- **Threat intelligence**: Mode (Off/Alert/Deny) and whitelist configuration
- **IDPS**: Intrusion detection mode, profile, signature overrides, bypass settings
- **DNS proxy**: DNS servers and proxy configuration
- **Explicit proxy**: HTTP/HTTPS proxy ports and PAC file settings
- **TLS inspection**: Certificate authority for encrypted traffic analysis
- **SNAT configuration**: Private IP ranges that bypass SNAT
- **IP Groups**: Named collections of IP addresses for rule definitions

- Transform functions handle flat API structure from Azure SDK
- All complex objects (dicts, arrays) serialized to JSON strings
- Proper handling of optional vs required fields
- Graceful handling of missing data with None values

- Follows Cartography data model best practices
- Standard GET → TRANSFORM → LOAD → CLEANUP sync pattern
- Proper use of @timeit decorators
- Type hints on all functions
- HttpResponseError handling with logging
- GraphJob cleanup for automatic stale data removal

- Validated against real Azure Firewall resources
- Successfully synced to Neo4j (azure-real-test database)
- Verified all security rules captured correctly
- Test data structure matches real Azure SDK output (flat format)

- cartography/intel/azure/firewall.py (379 lines)
- cartography/models/azure/firewall/__init__.py
- cartography/models/azure/firewall/azure_firewall.py (150 lines)
- cartography/models/azure/firewall/firewall_policy.py (156 lines)
- tests/data/azure/firewall.py (239 lines)

- cartography/intel/azure/__init__.py: Added firewall.sync() integration
- demo/seeds/azure.py: Added _seed_firewall() method
- docs/root/modules/azure/schema.md: Added 150+ lines of documentation
- README.md: Updated Azure supported resources list

This feature enables security teams to:
1. **Audit network security**: Query all firewall rules across Azure subscriptions
2. **Identify exposed services**: Find NAT rules exposing internal resources
3. **Validate security controls**: Check threat intelligence and IDPS settings
4. **Detect misconfigurations**: Identify overly permissive rules or disabled protections
5. **Map attack surface**: Understand network paths through firewall policies
6. **Policy compliance**: Verify firewall configurations meet security standards
7. **Cross-platform analysis**: Compare firewall rules across Azure and other cloud providers

- Azure Firewall: https://learn.microsoft.com/en-us/azure/firewall/
- Azure Firewall Policy: https://learn.microsoft.com/en-us/azure/firewall/policy-rule-sets
- Azure SDK: azure-mgmt-network v30.1+

Signed-off-by: Ashton Suire <[email protected]>
Signed-off-by: Ashton Suire <[email protected]>
- Remove error swallowing in get functions to fail loudly on auth errors
- Extract vnet_id from IP config subnet to enable VNet relationships
- Fix Virtual Hub relationship label in docs (DEPLOYED_TO not CONNECTED_VHUB)

Signed-off-by: Ashton Suire <[email protected]>
Update docstrings for get_firewalls() and get_firewall_policies() to explicitly
document that HttpResponseError can be raised on API failures

Signed-off-by: Ashton Suire <[email protected]>
Complete the VNet relationship fix by defining vnet_id as a storable property.
The field was being extracted in transform but not declared in the schema,
preventing MEMBER_OF edges to AzureVirtualNetwork from being created.

Signed-off-by: Ashton Suire <[email protected]>
Updates Azure module documentation to include complete IP Configuration details.

## Documentation Changes

### Schema Documentation (docs/root/modules/azure/schema.md)

**Mermaid Diagram Updates:**
- Added Firewall, FirewallPolicy, and FirewallIPConfig nodes to visualization
- Added HAS_IP_CONFIGURATION, USES_POLICY, IN_SUBNET, USES_PUBLIC_IP relationships

**New Section: AzureFirewallIPConfiguration**
- Complete property table with 11 fields
- Description of IP configuration role in firewall connectivity
- Security Properties section explaining subnet_id, public_ip_address_id, private_ip_address
- 4 documented relationships with Cypher examples:
  - RESOURCE (to AzureSubscription)
  - HAS_IP_CONFIGURATION (from AzureFirewall)
  - IN_SUBNET (to AzureSubnet)
  - USES_PUBLIC_IP (to AzurePublicIPAddress)

**AzureFirewall Section Updates:**
- Added HAS_IP_CONFIGURATION relationship documentation
- Updated CONNECTED_VNET to MEMBER_OF for consistency

Signed-off-by: Ashton Suire <[email protected]>
Fixes three test issues preventing Azure Firewall integration tests from passing:

1. Property name mismatch: Changed 'threatIntelMode' to 'threat_intel_mode'
   to match the Neo4j property name (Python dataclass field names become
   property names in Neo4j)

2. Relationship direction assertions: Fixed check_rels() calls to match
   the actual LinkDirection defined in the data model schemas:
   - AzureSubscription<-[:RESOURCE]-AzureFirewall (INWARD)
   - AzureFirewall<-[:HAS_IP_CONFIGURATION]-AzureFirewallIPConfiguration (INWARD)

3. Cleanup test relationship setup: Fixed MERGE patterns to create
   relationships with correct directions matching the schemas:
   - (fw)<-[r:RESOURCE]-(s) for INWARD AzureFirewall to Subscription
   - (ip)<-[r:RESOURCE]-(s) for INWARD IPConfiguration to Subscription
   - (p)-[r:RESOURCE]->(s) for OUTWARD FirewallPolicy to Subscription

These fixes ensure cleanup queries can properly match and delete stale nodes
by having the correct relationship patterns in the test data.

Fixes cartography-cncf#1456

Signed-off-by: Ashton Suire <[email protected]>
…on and implement policy inheritance

Fixes critical relationship direction issue and implements missing INHERITS_FROM relationship for Azure Firewall Policies.
**Critical Bug Fix:**
- Fixed AzureFirewallPolicyToSubscriptionRel direction from OUTWARD to INWARD
  - Now correctly creates: (:AzureSubscription)-[:RESOURCE]->(:AzureFirewallPolicy)
  - Previously created backwards: (:AzureFirewallPolicy)-[:RESOURCE]->(:AzureSubscription)
  - This was breaking subscription-scoped queries and causing get_resource_ids() in
    permission_relationships.py to silently skip firewall policies
  - Now consistent with all other Azure resources (VMs, SQL, storage, etc.)
**Feature Implementation:**
- Implemented missing INHERITS_FROM relationship for policy inheritance
  - Added AzureFirewallPolicyToParentPolicyRel schema
  - Creates: (:AzureFirewallPolicy)-[:INHERITS_FROM]->(:AzureFirewallPolicy)
  - Uses existing base_policy_id field to link child policies to parent policies
  - Enables querying policy inheritance chains for security analysis
**Cleanup:**
- Removed unused logging import and logger declaration from azure_firewall.py
**Testing:**
- Added test for subscription-policy RESOURCE relationship
- Added test for policy-to-policy INHERITS_FROM relationship
- Both tests verify correct relationship direction and data
The base_policy_id field was already being extracted from the API but the relationship
wasn't being created. Now aligns code with documented schema behavior.

Signed-off-by: Ashton Suire <[email protected]>
@ashton-suire ashton-suire force-pushed the azure-firewall-support branch from f9bc6ba to e11b476 Compare February 14, 2026 01:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

module:Azure Related to the Azure intel module

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(azure): Add support for Azure Firewall

3 participants