From 44d30ae25a9a081fc9e60069cc0c868c88547492 Mon Sep 17 00:00:00 2001 From: halkazwini <85655443+halkazwini@users.noreply.github.com> Date: Tue, 4 Aug 2026 10:50:18 -0500 Subject: [PATCH 1/4] Add virtual network flow logs quickstart --- .../README.md | 47 +++++++++++++++ .../main.tf | 38 ++++++++++++ .../outputs.tf | 14 +++++ .../providers.tf | 18 ++++++ .../variables.tf | 60 +++++++++++++++++++ 5 files changed, 177 insertions(+) create mode 100644 quickstart/101-network-watcher-vnet-flow-logs/README.md create mode 100644 quickstart/101-network-watcher-vnet-flow-logs/main.tf create mode 100644 quickstart/101-network-watcher-vnet-flow-logs/outputs.tf create mode 100644 quickstart/101-network-watcher-vnet-flow-logs/providers.tf create mode 100644 quickstart/101-network-watcher-vnet-flow-logs/variables.tf diff --git a/quickstart/101-network-watcher-vnet-flow-logs/README.md b/quickstart/101-network-watcher-vnet-flow-logs/README.md new file mode 100644 index 000000000..3ced5d109 --- /dev/null +++ b/quickstart/101-network-watcher-vnet-flow-logs/README.md @@ -0,0 +1,47 @@ +# Enable virtual network flow logs + +This template creates a virtual network flow log for an existing virtual network. It uses the regional Network Watcher instance and creates a dedicated storage account in the Network Watcher resource group. + +## Prerequisites + +- Network Watcher is enabled in the virtual network's region. +- The `Microsoft.Insights` resource provider is registered in the subscription. +- An existing virtual network is in the same region as the Network Watcher instance. +- The deploying account can create a flow log and storage account in the Network Watcher resource group. + +## Terraform resource types + +- [azurerm_network_watcher](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/network_watcher) +- [azurerm_storage_account](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_account) +- [azurerm_network_watcher_flow_log](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/network_watcher_flow_log) +- [random_string](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) + +## Variables + +| Name | Description | Default | +|---|---|---| +| `network_watcher_name` | Name of the existing regional Network Watcher instance. | `NetworkWatcher_eastus` | +| `network_watcher_resource_group_name` | Name of the resource group that contains the Network Watcher instance. | `NetworkWatcherRG` | +| `virtual_network_id` | Resource ID of the existing virtual network to monitor. | n/a | +| `flow_log_name` | Name of the virtual network flow log. | `vnet-flow-log` | +| `flow_log_version` | Flow log format version. | `2` | +| `retention_days` | Number of days to retain flow log data. Use `0` to retain data indefinitely. | `0` | +| `storage_account_replication_type` | Replication type for the flow log storage account. | `LRS` | + +## Example + +Create a `terraform.tfvars` file with values for your existing resources: + +```hcl +network_watcher_name = "NetworkWatcher_eastus" +network_watcher_resource_group_name = "NetworkWatcherRG" +virtual_network_id = "/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks/" +``` + +Run the following commands: + +```bash +terraform init +terraform plan +terraform apply +``` \ No newline at end of file diff --git a/quickstart/101-network-watcher-vnet-flow-logs/main.tf b/quickstart/101-network-watcher-vnet-flow-logs/main.tf new file mode 100644 index 000000000..1d8a1e566 --- /dev/null +++ b/quickstart/101-network-watcher-vnet-flow-logs/main.tf @@ -0,0 +1,38 @@ +data "azurerm_network_watcher" "network_watcher" { + name = var.network_watcher_name + resource_group_name = var.network_watcher_resource_group_name +} + +resource "random_string" "storage_account_suffix" { + length = 8 + lower = true + numeric = true + special = false + upper = false +} + +resource "azurerm_storage_account" "flow_logs" { + name = "flowlogs${random_string.storage_account_suffix.result}" + resource_group_name = data.azurerm_network_watcher.network_watcher.resource_group_name + location = data.azurerm_network_watcher.network_watcher.location + account_tier = "Standard" + account_kind = "StorageV2" + account_replication_type = var.storage_account_replication_type +} + +resource "azurerm_network_watcher_flow_log" "vnet_flow_log" { + name = var.flow_log_name + network_watcher_name = data.azurerm_network_watcher.network_watcher.name + resource_group_name = data.azurerm_network_watcher.network_watcher.resource_group_name + location = data.azurerm_network_watcher.network_watcher.location + + target_resource_id = var.virtual_network_id + storage_account_id = azurerm_storage_account.flow_logs.id + enabled = true + version = var.flow_log_version + + retention_policy { + enabled = true + days = var.retention_days + } +} \ No newline at end of file diff --git a/quickstart/101-network-watcher-vnet-flow-logs/outputs.tf b/quickstart/101-network-watcher-vnet-flow-logs/outputs.tf new file mode 100644 index 000000000..66b14bf9b --- /dev/null +++ b/quickstart/101-network-watcher-vnet-flow-logs/outputs.tf @@ -0,0 +1,14 @@ +output "flow_log_id" { + description = "Resource ID of the virtual network flow log." + value = azurerm_network_watcher_flow_log.vnet_flow_log.id +} + +output "flow_log_name" { + description = "Name of the virtual network flow log." + value = azurerm_network_watcher_flow_log.vnet_flow_log.name +} + +output "storage_account_name" { + description = "Name of the storage account that contains the flow log data." + value = azurerm_storage_account.flow_logs.name +} \ No newline at end of file diff --git a/quickstart/101-network-watcher-vnet-flow-logs/providers.tf b/quickstart/101-network-watcher-vnet-flow-logs/providers.tf new file mode 100644 index 000000000..0c4e8c05e --- /dev/null +++ b/quickstart/101-network-watcher-vnet-flow-logs/providers.tf @@ -0,0 +1,18 @@ +terraform { + required_version = ">= 1.5.0" + + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 5.0" + } + random = { + source = "hashicorp/random" + version = "~> 3.7" + } + } +} + +provider "azurerm" { + features {} +} \ No newline at end of file diff --git a/quickstart/101-network-watcher-vnet-flow-logs/variables.tf b/quickstart/101-network-watcher-vnet-flow-logs/variables.tf new file mode 100644 index 000000000..924e3413c --- /dev/null +++ b/quickstart/101-network-watcher-vnet-flow-logs/variables.tf @@ -0,0 +1,60 @@ +variable "network_watcher_name" { + type = string + default = "NetworkWatcher_eastus" + description = "Name of the existing regional Network Watcher instance." +} + +variable "network_watcher_resource_group_name" { + type = string + default = "NetworkWatcherRG" + description = "Name of the resource group that contains the Network Watcher instance." +} + +variable "virtual_network_id" { + type = string + description = "Resource ID of the existing virtual network to monitor." + + validation { + condition = can(regex("(?i)^/subscriptions/[^/]+/resourceGroups/[^/]+/providers/Microsoft.Network/virtualNetworks/[^/]+$", var.virtual_network_id)) + error_message = "The virtual_network_id value must be a full Azure virtual network resource ID." + } +} + +variable "flow_log_name" { + type = string + default = "vnet-flow-log" + description = "Name of the virtual network flow log." +} + +variable "flow_log_version" { + type = number + default = 2 + description = "Flow log format version. Valid values are 1 and 2." + + validation { + condition = contains([1, 2], var.flow_log_version) + error_message = "The flow_log_version value must be 1 or 2." + } +} + +variable "retention_days" { + type = number + default = 0 + description = "Number of days to retain flow log data. Use 0 to retain data indefinitely." + + validation { + condition = var.retention_days >= 0 && var.retention_days <= 365 + error_message = "The retention_days value must be between 0 and 365." + } +} + +variable "storage_account_replication_type" { + type = string + default = "LRS" + description = "Replication type for the flow log storage account." + + validation { + condition = contains(["LRS", "GRS", "ZRS"], var.storage_account_replication_type) + error_message = "The storage_account_replication_type value must be LRS, GRS, or ZRS." + } +} \ No newline at end of file From 474bb8560e12ff4d5a93e16a3cea3a27eda790b9 Mon Sep 17 00:00:00 2001 From: halkazwini <85655443+halkazwini@users.noreply.github.com> Date: Tue, 4 Aug 2026 16:54:18 -0500 Subject: [PATCH 2/4] Clarify flow log retention lifecycle --- .../101-network-watcher-vnet-flow-logs/README.md | 12 ++++++++++-- .../101-network-watcher-vnet-flow-logs/main.tf | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/quickstart/101-network-watcher-vnet-flow-logs/README.md b/quickstart/101-network-watcher-vnet-flow-logs/README.md index 3ced5d109..8cf4a1aee 100644 --- a/quickstart/101-network-watcher-vnet-flow-logs/README.md +++ b/quickstart/101-network-watcher-vnet-flow-logs/README.md @@ -1,6 +1,6 @@ # Enable virtual network flow logs -This template creates a virtual network flow log for an existing virtual network. It uses the regional Network Watcher instance and creates a dedicated storage account in the Network Watcher resource group. +This template creates a virtual network flow log for an existing virtual network. It uses the regional Network Watcher instance and creates a dedicated storage account in the Network Watcher resource group. The storage account is dedicated to the flow log because the flow-log resource manages and might overwrite its lifecycle management rules. ## Prerequisites @@ -28,6 +28,8 @@ This template creates a virtual network flow log for an existing virtual network | `retention_days` | Number of days to retain flow log data. Use `0` to retain data indefinitely. | `0` | | `storage_account_replication_type` | Replication type for the flow log storage account. | `LRS` | +When `retention_days` is `0`, retention is disabled and logs accumulate in the storage account until they're manually deleted or the storage account is deleted. Set a value from `1` through `365` to enable automatic retention. + ## Example Create a `terraform.tfvars` file with values for your existing resources: @@ -38,10 +40,16 @@ network_watcher_resource_group_name = "NetworkWatcherRG" virtual_network_id = "/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks/" ``` +The default Network Watcher name is for East US. To use another region, set `network_watcher_name` to the existing Network Watcher instance for the virtual network's region. For example, use `NetworkWatcher_westus2` for West US 2. If the instance is in a custom resource group, also set `network_watcher_resource_group_name`. The storage account and flow log use the selected Network Watcher instance's region. + Run the following commands: ```bash terraform init terraform plan terraform apply -``` \ No newline at end of file +``` + +## Clean up resources + +Run `terraform destroy` to delete the flow log and its dedicated storage account. Deleting the storage account permanently deletes all flow logs stored in it. Terraform doesn't delete the existing virtual network or Network Watcher instance. \ No newline at end of file diff --git a/quickstart/101-network-watcher-vnet-flow-logs/main.tf b/quickstart/101-network-watcher-vnet-flow-logs/main.tf index 1d8a1e566..702ccc3f2 100644 --- a/quickstart/101-network-watcher-vnet-flow-logs/main.tf +++ b/quickstart/101-network-watcher-vnet-flow-logs/main.tf @@ -32,7 +32,7 @@ resource "azurerm_network_watcher_flow_log" "vnet_flow_log" { version = var.flow_log_version retention_policy { - enabled = true + enabled = var.retention_days > 0 days = var.retention_days } } \ No newline at end of file From d704a7dcaaa8a5b5100f0464708a1de28a1a9087 Mon Sep 17 00:00:00 2001 From: halkazwini <85655443+halkazwini@users.noreply.github.com> Date: Tue, 4 Aug 2026 16:56:04 -0500 Subject: [PATCH 3/4] Fix flow logs README formatting --- quickstart/101-network-watcher-vnet-flow-logs/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/quickstart/101-network-watcher-vnet-flow-logs/README.md b/quickstart/101-network-watcher-vnet-flow-logs/README.md index 8cf4a1aee..687175642 100644 --- a/quickstart/101-network-watcher-vnet-flow-logs/README.md +++ b/quickstart/101-network-watcher-vnet-flow-logs/README.md @@ -19,7 +19,7 @@ This template creates a virtual network flow log for an existing virtual network ## Variables | Name | Description | Default | -|---|---|---| +| --- | --- | --- | | `network_watcher_name` | Name of the existing regional Network Watcher instance. | `NetworkWatcher_eastus` | | `network_watcher_resource_group_name` | Name of the resource group that contains the Network Watcher instance. | `NetworkWatcherRG` | | `virtual_network_id` | Resource ID of the existing virtual network to monitor. | n/a | @@ -52,4 +52,4 @@ terraform apply ## Clean up resources -Run `terraform destroy` to delete the flow log and its dedicated storage account. Deleting the storage account permanently deletes all flow logs stored in it. Terraform doesn't delete the existing virtual network or Network Watcher instance. \ No newline at end of file +Run `terraform destroy` to delete the flow log and its dedicated storage account. Deleting the storage account permanently deletes all flow logs stored in it. Terraform doesn't delete the existing virtual network or Network Watcher instance. From 9ad29598952234fa279062fdb5342f1ef7ec1283 Mon Sep 17 00:00:00 2001 From: halkazwini <85655443+halkazwini@users.noreply.github.com> Date: Tue, 4 Aug 2026 17:02:42 -0500 Subject: [PATCH 4/4] Clarify flow log retention wording --- quickstart/101-network-watcher-vnet-flow-logs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstart/101-network-watcher-vnet-flow-logs/README.md b/quickstart/101-network-watcher-vnet-flow-logs/README.md index 687175642..00f28dbfc 100644 --- a/quickstart/101-network-watcher-vnet-flow-logs/README.md +++ b/quickstart/101-network-watcher-vnet-flow-logs/README.md @@ -28,7 +28,7 @@ This template creates a virtual network flow log for an existing virtual network | `retention_days` | Number of days to retain flow log data. Use `0` to retain data indefinitely. | `0` | | `storage_account_replication_type` | Replication type for the flow log storage account. | `LRS` | -When `retention_days` is `0`, retention is disabled and logs accumulate in the storage account until they're manually deleted or the storage account is deleted. Set a value from `1` through `365` to enable automatic retention. +When `retention_days` is `0`, automatic deletion based on age is disabled. Flow logs continue to be stored and accumulate in the storage account until you manually delete them or delete the storage account. Set a value from `1` through `365` to automatically delete logs after that number of days. ## Example