diff --git a/compliance/frameworks/cis_azure_benchmark.json b/compliance/frameworks/cis_azure_benchmark.json index f46959c..f4e3ba5 100644 --- a/compliance/frameworks/cis_azure_benchmark.json +++ b/compliance/frameworks/cis_azure_benchmark.json @@ -107,11 +107,11 @@ "control_id": "8.3", "control_name": "Ensure that 'OS patching' is enabled for virtual machines", "description": "The virtual machine does not have automatic OS patching enabled. CIS 8.3 requires that OS patches are applied in a timely manner. Unpatched VMs are vulnerable to known exploits targeting unpatched OS vulnerabilities." - }, + }, "AZ-KV-001": { "control_id": "8.5", "control_name": "Ensure the Key Vault is Recoverable", - "description": "Azure Key Vault soft delete should be enabled on all Key Vaults. The soft delete feature allows recovery of deleted vaults and vault objects (keys, secrets, certificates) for a configurable retention period (7\u201390 days), protecting against accidental or malicious deletion." + "description": "Azure Key Vault soft delete should be enabled on all Key Vaults. The soft delete feature allows recovery of deleted vaults and vault objects (keys, secrets, certificates) for a configurable retention period (7–90 days), protecting against accidental or malicious deletion." }, "AZ-STOR-003": { "control_id": "3.7", @@ -151,7 +151,7 @@ "AZ-DB-004": { "control_id": "4.1.2", "control_name": "Ensure that 'Allow access to Azure services' for SQL Servers is disabled", - "description": "Enabling 'Allow access to Azure services' on a SQL Server firewall creates a rule that permits any Azure-hosted resource \u2014 including services from other tenants \u2014 to connect to the server. This significantly increases the attack surface. Access should be restricted to specific trusted IP ranges or private endpoints." + "description": "Enabling 'Allow access to Azure services' on a SQL Server firewall creates a rule that permits any Azure-hosted resource — including services from other tenants — to connect to the server. This significantly increases the attack surface. Access should be restricted to specific trusted IP ranges or private endpoints." }, "AZ-IDN-004": { "control_id": "1.14", @@ -163,10 +163,14 @@ "control_name": "Ensure that the expiration date is set on all certificates", "description": "A certificate stored in Azure Key Vault is expiring within 30 days and does not have auto-renewal configured. CIS 8.5 requires that expiration dates are monitored and certificates are renewed before expiry to prevent service outages and broken authentication flows." }, + "AZ-NET-013": { + "control_id": "6.4", + "control_name": "Ensure that Azure Firewall is enabled on Virtual Networks", + "description": "Virtual Networks that do not have an Azure Firewall deployed rely solely on Network Security Groups for perimeter defence. NSGs provide no deep packet inspection, threat intelligence filtering, or centralised traffic logging. Azure Firewall should be deployed in a dedicated subnet to inspect and control all inbound and outbound traffic." "AZ-NET-014": { "control_id": "6.4", "control_name": "Ensure that Azure Firewall is enabled on Virtual Networks", "description": "VNet peering connections with allowGatewayTransit or useRemoteGateways enabled allow traffic to route between network segments through shared gateways. This can break network segmentation and enable lateral movement between zones that should remain isolated. Peering connections should be reviewed and gateway transit disabled unless explicitly required and documented." } } -} +} \ No newline at end of file diff --git a/compliance/frameworks/iso27001.json b/compliance/frameworks/iso27001.json index c4a9814..1914e3e 100644 --- a/compliance/frameworks/iso27001.json +++ b/compliance/frameworks/iso27001.json @@ -101,18 +101,13 @@ "AZ-CMP-003": { "control_id": "A.12.2.1", "control_name": "Controls against malware", - "description": "The virtual machine does not have a recognised endpoint protection extension installed. A.12.2.1 requires that detection, prevention and recovery controls are implemented to protect against malware." + "description": "The virtual machine does not have a recognised endpoint protection extension installed. A.12.2.1 requires that detection, prevention and recovery controls are implemented to protect against malware. Without endpoint protection, malware executing on the VM will not be detected or prevented." }, "AZ-CMP-004": { "control_id": "A.12.6.1", "control_name": "Management of technical vulnerabilities", "description": "The virtual machine does not have automatic OS patching enabled. A.12.6.1 requires that information about technical vulnerabilities is obtained and the organisation's exposure evaluated. Without automatic patching, known OS vulnerabilities remain unmitigated." }, - "AZ-CMP-003": { - "control_id": "A.12.2.1", - "control_name": "Controls against malware", - "description": "The virtual machine does not have a recognised endpoint protection extension installed. A.12.2.1 requires that detection, prevention and recovery controls are implemented to protect against malware. Without endpoint protection, malware executing on the VM will not be detected or prevented." - }, "AZ-KV-001": { "control_id": "A.17.2.1", "control_name": "Availability of information processing facilities", @@ -168,10 +163,14 @@ "control_name": "Management of privileged access rights", "description": "The allocation and use of privileged access rights should be restricted and controlled. PIM enforces just-in-time access with time limits and approval workflows, ensuring privileged access rights are tightly managed and not permanently assigned." }, + "AZ-NET-013": { + "control_id": "A.13.1.1", + "control_name": "Network controls", + "description": "Virtual Networks without an Azure Firewall rely solely on Network Security Groups for perimeter defence. NSGs provide no deep packet inspection, threat intelligence filtering, or centralised traffic logging. Networks should be managed and controlled using a dedicated firewall to inspect and control all inbound and outbound traffic." "AZ-NET-014": { "control_id": "A.13.1.1", "control_name": "Network controls", "description": "VNet peering connections with gateway transit enabled allow traffic to flow between network segments through shared gateways, potentially bypassing network controls. Networks should be managed and controlled to protect information in systems and applications. Gateway transit on peering connections should be disabled unless explicitly required." } } -} +} \ No newline at end of file diff --git a/compliance/frameworks/nist_csf.json b/compliance/frameworks/nist_csf.json index 6acbd25..9f218fd 100644 --- a/compliance/frameworks/nist_csf.json +++ b/compliance/frameworks/nist_csf.json @@ -163,10 +163,14 @@ "control_name": "Access permissions and authorizations are managed", "description": "PIM ensures privileged access permissions are managed with time-bound activation and approval workflows. Without PIM, permanently assigned admin roles violate the principle of least privilege and increase the blast radius of compromised accounts." }, + "AZ-NET-013": { + "control_id": "PR.AC-5", + "control_name": "Network integrity is protected", + "description": "Virtual Networks without an Azure Firewall rely solely on Network Security Groups for perimeter defence. NSGs provide no deep packet inspection, threat intelligence filtering, or centralised traffic logging. PR.AC-5 requires that network integrity is protected. Azure Firewall should be deployed to inspect and control all inbound and outbound traffic and enforce network integrity boundaries." "AZ-NET-014": { "control_id": "PR.AC-5", "control_name": "Network integrity is protected", "description": "VNet peering with gateway transit enabled allows traffic to cross network boundaries through shared gateways, undermining network segmentation. PR.AC-5 requires that network integrity is protected. Disabling gateway transit on peering connections enforces boundary integrity between network zones." } } -} +} \ No newline at end of file diff --git a/compliance/frameworks/soc2.json b/compliance/frameworks/soc2.json index 0b1fb6e..b554f75 100644 --- a/compliance/frameworks/soc2.json +++ b/compliance/frameworks/soc2.json @@ -111,18 +111,13 @@ "AZ-CMP-003": { "control_id": "CC6.8", "control_name": "Prevents or Detects Unauthorized or Malicious Software", - "description": "The virtual machine does not have a recognised endpoint protection extension installed. CC6.8 requires that controls are implemented to prevent or detect and act upon the introduction of unauthorised or malicious software." + "description": "The virtual machine does not have a recognised endpoint protection extension installed. CC6.8 requires that controls are implemented to prevent or detect and act upon the introduction of unauthorized or malicious software. Without endpoint protection, malicious code executing on the VM will not be detected or blocked." }, "AZ-CMP-004": { "control_id": "CC7.1", "control_name": "System Vulnerabilities are Identified and Managed", "description": "The virtual machine does not have automatic OS patching enabled. CC7.1 requires that vulnerabilities in system components are identified and managed through a defined process. Without automatic patching, known OS vulnerabilities are left unmitigated and exploitable." }, - "AZ-CMP-003": { - "control_id": "CC6.8", - "control_name": "Prevents or Detects Unauthorized or Malicious Software", - "description": "The virtual machine does not have a recognised endpoint protection extension installed. CC6.8 requires that controls are implemented to prevent or detect and act upon the introduction of unauthorized or malicious software. Without endpoint protection, malicious code executing on the VM will not be detected or blocked." - }, "AZ-KV-001": { "control_id": "A1.2", "control_name": "Environmental Threats and Recovery", @@ -156,17 +151,21 @@ "AZ-DB-004": { "control_id": "CC6.6", "control_name": "Restricts Access from Outside the Network Boundary", - "description": "Enabling 'Allow access to Azure services' on a SQL Server firewall creates a rule that permits any Azure-hosted resource \u2014 including services from other tenants \u2014 to connect to the database. CC6.6 requires that access from outside the network boundary is restricted to authorised sources. Disabling this setting and replacing it with explicit firewall rules or private endpoints enforces the network boundary and ensures only known and trusted systems can reach the SQL Server." + "description": "Enabling 'Allow access to Azure services' on a SQL Server firewall creates a rule that permits any Azure-hosted resource — including services from other tenants — to connect to the database. CC6.6 requires that access from outside the network boundary is restricted to authorised sources. Disabling this setting and replacing it with explicit firewall rules or private endpoints enforces the network boundary and ensures only known and trusted systems can reach the SQL Server." }, "AZ-IDN-004": { "control_id": "CC6.3", "control_name": "Role-based access control", "description": "PIM provides role-based access control with time-bound activation for privileged roles. Without PIM, admin roles are permanently assigned with no controls, violating the requirement for managed and restricted privileged access." }, + "AZ-NET-013": { + "control_id": "CC6.6", + "control_name": "Restricts Access from Outside the Network Boundary", + "description": "Virtual Networks without an Azure Firewall rely solely on Network Security Groups for perimeter defence. NSGs provide no deep packet inspection, threat intelligence filtering, or centralised traffic logging. CC6.6 requires that access from outside the network boundary is restricted and controlled through appropriate logical access controls. Azure Firewall should be deployed to inspect and control all inbound and outbound traffic." "AZ-NET-014": { "control_id": "CC6.6", "control_name": "Restricts Access from Outside the Network Boundary", "description": "VNet peering with allowGatewayTransit or useRemoteGateways enabled allows traffic to cross network boundaries through shared gateways, weakening the logical separation between network zones. CC6.6 requires that logical access from outside the network boundary is restricted and controlled. Gateway transit on peering connections should be disabled to enforce boundary separation." } } -} +} \ No newline at end of file diff --git a/playbooks/cli/fix_az_net_013.sh b/playbooks/cli/fix_az_net_013.sh new file mode 100644 index 0000000..060303c --- /dev/null +++ b/playbooks/cli/fix_az_net_013.sh @@ -0,0 +1,33 @@ +#!/bin/bash +set -euo pipefail + +RESOURCE_GROUP=$1 +VNET_NAME=$2 + +if [ -z "$RESOURCE_GROUP" ] || [ -z "$VNET_NAME" ]; then + echo "Usage: $0 " + exit 1 +fi + +echo "Deploying Azure Firewall for VNet: $VNET_NAME in resource group: $RESOURCE_GROUP..." + +az network vnet subnet create \ + --resource-group "$RESOURCE_GROUP" \ + --vnet-name "$VNET_NAME" \ + --name AzureFirewallSubnet \ + --address-prefixes 10.0.1.0/26 + +az network public-ip create \ + --resource-group "$RESOURCE_GROUP" \ + --name "${VNET_NAME}-fw-pip" \ + --sku Standard \ + --allocation-method Static + +az network firewall create \ + --resource-group "$RESOURCE_GROUP" \ + --name "${VNET_NAME}-firewall" \ + --sku-name AZFW_VNet \ + --sku-tier Standard + +echo "Azure Firewall deployed for VNet: $VNET_NAME" +echo "Note: Configure network and application rules to control traffic before routing through the firewall." \ No newline at end of file diff --git a/scanner/rules/az_net_013.py b/scanner/rules/az_net_013.py new file mode 100644 index 0000000..b750602 --- /dev/null +++ b/scanner/rules/az_net_013.py @@ -0,0 +1,53 @@ +"""AZ-NET-013: Azure Firewall not enabled on Virtual Network.""" +from typing import Any, Dict, List + +RULE_ID = "AZ-NET-013" +RULE_NAME = "Azure Firewall Not Enabled on Virtual Network" +SEVERITY = "HIGH" +CATEGORY = "Network" +FRAMEWORKS = { + "CIS": "6.4", + "NIST": "PR.AC-5", + "ISO27001": "A.13.1.1", + "SOC2": "CC6.6" +} +DESCRIPTION = ( + "The Virtual Network does not have an Azure Firewall deployed. " + "Without Azure Firewall, the VNet relies solely on Network Security " + "Groups for perimeter defence, which provides no deep packet " + "inspection, threat intelligence filtering, or centralised traffic " + "logging. This leaves the network vulnerable to lateral movement " + "and data exfiltration." +) +REMEDIATION = ( + "Deploy an Azure Firewall in a dedicated AzureFirewallSubnet within " + "the Virtual Network. Configure network and application rules to " + "control inbound and outbound traffic. Enable diagnostic logging to " + "a Log Analytics workspace." +) +PLAYBOOK = "playbooks/cli/fix_az_net_013.sh" + + +def scan(azure_client: Any, subscription_id: str) -> List[Dict[str, Any]]: + findings: List[Dict[str, Any]] = [] + for vnet in azure_client.get_virtual_networks(): + parsed = azure_client.parse_resource_id(vnet.id) + resource_group = parsed["resource_group"] + vnet_name = parsed["name"] + firewalls = azure_client.get_azure_firewalls(resource_group) + if not firewalls: + findings.append({ + "rule_id": RULE_ID, + "rule_name": RULE_NAME, + "severity": SEVERITY, + "category": CATEGORY, + "resource_id": vnet.id, + "resource_name": vnet_name, + "resource_type": "Microsoft.Network/virtualNetworks", + "description": DESCRIPTION, + "remediation": REMEDIATION, + "playbook": PLAYBOOK, + "frameworks": FRAMEWORKS, + "metadata": {"resource_group": resource_group} + }) + return findings \ No newline at end of file