Back to Checks
Network Watcher has flow logs enabled and sent to a Log Analytics workspace
network_flow_log_captured_sent
Service: networkSeverity: high
OfficialBuilt-inVerified
Categories:loggingforensics-ready
Resource Type:microsoft.network/networkwatchers
Azure Network Watcher has flow logs enabled for supported targets, such as virtual networks and network security groups, and configured with Traffic Analytics to forward records to a centralized Log Analytics workspace
Risk
Missing, disabled, or non-centralized flow logging blinds visibility into network behavior, hindering detection of:
- Lateral movement and internal scanning
- C2 beacons and exfiltration patterns This degrades incident response and correlation, impacting confidentiality and integrity.
Run this check with Prowler
Run in Prowler CloudRun
prowler azure --checks network_flow_log_captured_sentRecommendation
Enable and centrally aggregate flow logs for supported Network Watcher targets, including virtual networks and network security groups, to a Log Analytics workspace.
- Enforce least privilege on log data
- Define retention and secure storage
- Use layered monitoring (e.g., Traffic Analytics)
- Ensure coverage across regions, subscriptions, and critical network segments
Remediation
CLI
az network watcher flow-log create --location <REGION> --name <FLOW_LOG_NAME> --resource-group <RESOURCE_GROUP> --target-resource-id <TARGET_RESOURCE_ID> --storage-account <STORAGE_ACCOUNT_ID> --enabled true --workspace <LOG_ANALYTICS_WORKSPACE_ID>Terraform
# Enable flow logs for a supported target and send analytics to Log Analytics
resource "azurerm_network_watcher_flow_log" "<example_resource_name>" {
name = "<example_resource_name>"
network_watcher_name = "<example_network_watcher_name>"
resource_group_name = "<example_resource_group_name>"
target_resource_id = "<example_target_resource_id>"
storage_account_id = "<example_storage_account_id>"
enabled = true
traffic_analytics {
enabled = true
workspace_id = "<example_workspace_id>"
workspace_region = "<REGION>"
workspace_resource_id = "<example_log_analytics_workspace_id>"
}
}NativeIaC
// Enable flow logs for a supported target (for example, a virtual network or NSG)
resource flowLog 'Microsoft.Network/networkWatchers/flowLogs@2023-09-01' = {
name: '<example_network_watcher_name>/<example_flow_log_name>'
location: '<REGION>'
properties: {
enabled: true
targetResourceId: '<example_target_resource_id>'
storageId: '<example_storage_account_id>'
flowAnalyticsConfiguration: {
networkWatcherFlowAnalyticsConfiguration: {
enabled: true
workspaceResourceId: '<example_log_analytics_workspace_id>'
}
}
}
}Other
1In Azure portal, go to Network Watcher > Flow logs
2Click + Create
3Select the subscription and region
4Choose the appropriate flow log type and target resource, such as a virtual network or network security group
5Set Status to On
6Select a Storage account
7Enable Traffic analytics and select the Log Analytics workspace
8Click Review + create, then Create
Check Code
from prowler.lib.check.models import Check, Check_Report_Azure
from prowler.providers.azure.services.network.network_client import network_client
class network_flow_log_captured_sent(Check):
def execute(self) -> Check_Report_Azure:
findings = []
for subscription, network_watchers in network_client.network_watchers.items():
subscription_name = network_client.subscriptions.get(
subscription, subscription
)
for network_watcher in network_watchers:
report = Check_Report_Azure(
metadata=self.metadata(), resource=network_watcher
)
report.subscription = subscription
if network_watcher.flow_logs:
report.status = "PASS"
report.status_extended = f"Network Watcher {network_watcher.name} from subscription {subscription_name} ({subscription}) has flow logs that are captured and sent to Log Analytics workspace"
has_failed = False
for flow_log in network_watcher.flow_logs:
if not has_failed:
if not flow_log.enabled:
report.status = "FAIL"
report.status_extended = f"Network Watcher {network_watcher.name} from subscription {subscription_name} ({subscription}) has flow logs disabled"
has_failed = True
elif not (
flow_log.traffic_analytics_enabled
and flow_log.workspace_resource_id
):
report.status = "FAIL"
report.status_extended = f"Network Watcher {network_watcher.name} from subscription {subscription_name} ({subscription}) has enabled flow logs that are not configured to send traffic analytics to a Log Analytics workspace"
has_failed = True
else:
report.status = "FAIL"
report.status_extended = f"Network Watcher {network_watcher.name} from subscription {subscription_name} ({subscription}) has no flow logs"
findings.append(report)
return findings