diff --git a/modules/azure-localnet-gateway/.terraform-docs.yml b/modules/azure-localnet-gateway/.terraform-docs.yml new file mode 100644 index 000000000..3a69365ff --- /dev/null +++ b/modules/azure-localnet-gateway/.terraform-docs.yml @@ -0,0 +1,48 @@ +formatter: "markdown" + +version: "" + +header-from: docs/header.md +footer-from: docs/footer.md + +recursive: + enabled: false + path: modules + include-main: true + +sections: + hide: [] + show: [] + +content: "" + +output: + file: "README.md" + mode: inject + template: |- + + {{ .Content }} + + +output-values: + enabled: false + from: "" + +sort: + enabled: true + by: name + +settings: + anchor: true + color: true + default: true + description: false + escape: true + hide-empty: false + html: true + indent: 2 + lockfile: true + read-comments: true + required: true + sensitive: true + type: true diff --git a/modules/azure-localnet-gateway/README.md b/modules/azure-localnet-gateway/README.md new file mode 100644 index 000000000..f62def968 --- /dev/null +++ b/modules/azure-localnet-gateway/README.md @@ -0,0 +1,88 @@ + +# **Azure Local Network Gateway Terraform Module** + +## Overview + +This module provisions and manages Azure Local Network Gateways for Site-to-Site VPN connections using the [azurerm\_local\_network\_gateway](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/local_network_gateway) resource. It is suitable for production, staging, and development environments, y puede integrarse en proyectos Terraform más grandes o usarse de forma independiente. + +## Key Features + +- **Multiple Gateway Support**: Create one or more Azure Local Network Gateways with flexible configuration. +- **Custom Address Spaces**: Define custom address spaces and gateway IPs for each local network. +- **Tag Inheritance and Customization**: Inherit tags from the resource group or specify custom tags for all resources. +- **Extensible and Modular**: Designed for easy extension and integration with other Azure network modules. + +## Basic Usage + +See the main README and the `_examples/` directory for usage examples. + +```hcl +module "localnet_gateway" { + source = "./modules/azure-localnet-gateway" + localnet = [ + { + local_gateway_name = "example-gateway" + location = "westeurope" + resource_group_name = "example-rg" + local_gateway_ip = "203.0.113.1" + local_gateway_address_space = ["10.1.0.0/16"] + tags_from_rg = true + tags = { + environment = "dev" + } + } + ] +} +``` + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.7.0 | +| [azurerm](#requirement\_azurerm) | 4.58.0 | + +## Providers + +| Name | Version | +|------|---------| +| [azurerm](#provider\_azurerm) | 4.58.0 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [azurerm_local_network_gateway.this](https://registry.terraform.io/providers/hashicorp/azurerm/4.58.0/docs/resources/local_network_gateway) | resource | +| [azurerm_resource_group.this](https://registry.terraform.io/providers/hashicorp/azurerm/4.58.0/docs/data-sources/resource_group) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [localnet](#input\_localnet) | List of local network gateway objects |
list(object({
local_gateway_name = string
location = string
resource_group_name = string
local_gateway_ip = string
local_gateway_address_space = list(string)
tags_from_rg = optional(bool)
tags = optional(map(string))
})) | `[]` | no |
+
+## Outputs
+
+No outputs.
+
+## Examples
+
+For detailed examples, refer to the [module examples](https://github.com/prefapp/tfm/tree/main/modules/azure-localnet-gateway/_examples):
+
+- [basic\_localnet](https://github.com/prefapp/tfm/tree/main/modules/azure-localnet-gateway/_examples/basic\_localnet) - Basic local network gateway example.
+- [multiple\_address\_spaces](https://github.com/prefapp/tfm/tree/main/modules/azure-localnet-gateway/_examples/multiple\_address\_spaces) - Example with multiple address spaces.
+- [with\_tags\_from\_rg](https://github.com/prefapp/tfm/tree/main/modules/azure-localnet-gateway/_examples/with\_tags\_from\_rg) - Example inheriting tags from the resource group.
+
+## Remote resources
+
+- **Azure Local Network Gateway**: [azurerm\_local\_network\_gateway documentation](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/local_network_gateway)
+- **Terraform Azure Provider**: [Terraform Provider documentation](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs)
+
+## Support
+
+For issues, questions, or contributions related to this module, please visit the [repository's issue tracker](https://github.com/prefapp/tfm/issues).
+
\ No newline at end of file
diff --git a/modules/azure-localnet-gateway/_examples/basic_localnet/example.tf b/modules/azure-localnet-gateway/_examples/basic_localnet/example.tf
new file mode 100644
index 000000000..474c3870a
--- /dev/null
+++ b/modules/azure-localnet-gateway/_examples/basic_localnet/example.tf
@@ -0,0 +1,12 @@
+module "localnet_gateway" {
+ source = "../../"
+ localnet = [{
+ local_gateway_name = "example-local-gw"
+ location = "westeurope"
+ resource_group_name = "example-rg"
+ local_gateway_ip = "203.0.113.1"
+ local_gateway_address_space = ["10.1.0.0/16"]
+ tags_from_rg = false
+ tags = { environment = "dev" }
+ }]
+}
diff --git a/modules/azure-localnet-gateway/_examples/basic_localnet/example.yaml b/modules/azure-localnet-gateway/_examples/basic_localnet/example.yaml
new file mode 100644
index 000000000..6e973afeb
--- /dev/null
+++ b/modules/azure-localnet-gateway/_examples/basic_localnet/example.yaml
@@ -0,0 +1,10 @@
+localnet:
+ - local_gateway_name: example-local-gw
+ location: westeurope
+ resource_group_name: example-rg
+ local_gateway_ip: 203.0.113.1
+ local_gateway_address_space:
+ - 10.1.0.0/16
+ tags_from_rg: false
+ tags:
+ environment: dev
diff --git a/modules/azure-localnet-gateway/_examples/multiple_address_spaces/example.tf b/modules/azure-localnet-gateway/_examples/multiple_address_spaces/example.tf
new file mode 100644
index 000000000..d142b1358
--- /dev/null
+++ b/modules/azure-localnet-gateway/_examples/multiple_address_spaces/example.tf
@@ -0,0 +1,12 @@
+module "localnet_gateway" {
+ source = "../../"
+ localnet = [{
+ local_gateway_name = "multi-space-gw"
+ location = "westeurope"
+ resource_group_name = "example-rg"
+ local_gateway_ip = "203.0.113.2"
+ local_gateway_address_space = ["10.1.0.0/16", "10.2.0.0/16"]
+ tags_from_rg = false
+ tags = { environment = "test" }
+ }]
+}
diff --git a/modules/azure-localnet-gateway/_examples/multiple_address_spaces/example.yaml b/modules/azure-localnet-gateway/_examples/multiple_address_spaces/example.yaml
new file mode 100644
index 000000000..f5575e07c
--- /dev/null
+++ b/modules/azure-localnet-gateway/_examples/multiple_address_spaces/example.yaml
@@ -0,0 +1,11 @@
+localnet:
+ - local_gateway_name: multi-space-gw
+ location: westeurope
+ resource_group_name: example-rg
+ local_gateway_ip: 203.0.113.2
+ local_gateway_address_space:
+ - 10.1.0.0/16
+ - 10.2.0.0/16
+ tags_from_rg: false
+ tags:
+ environment: test
diff --git a/modules/azure-localnet-gateway/_examples/with_tags_from_rg/example.tf b/modules/azure-localnet-gateway/_examples/with_tags_from_rg/example.tf
new file mode 100644
index 000000000..a9a04d4df
--- /dev/null
+++ b/modules/azure-localnet-gateway/_examples/with_tags_from_rg/example.tf
@@ -0,0 +1,12 @@
+module "localnet_gateway" {
+ source = "../../"
+ localnet = [{
+ local_gateway_name = "tagged-gw"
+ location = "westeurope"
+ resource_group_name = "example-rg"
+ local_gateway_ip = "203.0.113.3"
+ local_gateway_address_space = ["10.3.0.0/16"]
+ tags_from_rg = true
+ tags = { custom = "yes" }
+ }]
+}
diff --git a/modules/azure-localnet-gateway/_examples/with_tags_from_rg/example.yaml b/modules/azure-localnet-gateway/_examples/with_tags_from_rg/example.yaml
new file mode 100644
index 000000000..5401add82
--- /dev/null
+++ b/modules/azure-localnet-gateway/_examples/with_tags_from_rg/example.yaml
@@ -0,0 +1,10 @@
+localnet:
+ - local_gateway_name: tagged-gw
+ location: westeurope
+ resource_group_name: example-rg
+ local_gateway_ip: 203.0.113.3
+ local_gateway_address_space:
+ - 10.3.0.0/16
+ tags_from_rg: true
+ tags:
+ custom: "yes"
diff --git a/modules/azure-localnet-gateway/data.tf b/modules/azure-localnet-gateway/data.tf
new file mode 100644
index 000000000..5a4e55297
--- /dev/null
+++ b/modules/azure-localnet-gateway/data.tf
@@ -0,0 +1,7 @@
+## DATA SOURCES SECTION
+
+# https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/virtual_network
+data "azurerm_resource_group" "this" {
+ for_each = { for idx, s in var.localnet : idx => s }
+ name = each.value.resource_group_name
+}
diff --git a/modules/azure-localnet-gateway/docs/footer.md b/modules/azure-localnet-gateway/docs/footer.md
new file mode 100644
index 000000000..b4e31edc1
--- /dev/null
+++ b/modules/azure-localnet-gateway/docs/footer.md
@@ -0,0 +1,16 @@
+## Examples
+
+For detailed examples, refer to the [module examples](https://github.com/prefapp/tfm/tree/main/modules/azure-localnet-gateway/_examples):
+
+- [basic_localnet](https://github.com/prefapp/tfm/tree/main/modules/azure-localnet-gateway/_examples/basic_localnet) - Basic local network gateway example.
+- [multiple_address_spaces](https://github.com/prefapp/tfm/tree/main/modules/azure-localnet-gateway/_examples/multiple_address_spaces) - Example with multiple address spaces.
+- [with_tags_from_rg](https://github.com/prefapp/tfm/tree/main/modules/azure-localnet-gateway/_examples/with_tags_from_rg) - Example inheriting tags from the resource group.
+
+## Remote resources
+
+- **Azure Local Network Gateway**: [azurerm_local_network_gateway documentation](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/local_network_gateway)
+- **Terraform Azure Provider**: [Terraform Provider documentation](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs)
+
+## Support
+
+For issues, questions, or contributions related to this module, please visit the [repository's issue tracker](https://github.com/prefapp/tfm/issues).
diff --git a/modules/azure-localnet-gateway/docs/header.md b/modules/azure-localnet-gateway/docs/header.md
new file mode 100644
index 000000000..0f2997113
--- /dev/null
+++ b/modules/azure-localnet-gateway/docs/header.md
@@ -0,0 +1,35 @@
+# **Azure Local Network Gateway Terraform Module**
+
+## Overview
+
+This module provisions and manages Azure Local Network Gateways for Site-to-Site VPN connections using the [azurerm_local_network_gateway](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/local_network_gateway) resource. It is suitable for production, staging, and development environments, y puede integrarse en proyectos Terraform más grandes o usarse de forma independiente.
+
+## Key Features
+
+- **Multiple Gateway Support**: Create one or more Azure Local Network Gateways with flexible configuration.
+- **Custom Address Spaces**: Define custom address spaces and gateway IPs for each local network.
+- **Tag Inheritance and Customization**: Inherit tags from the resource group or specify custom tags for all resources.
+- **Extensible and Modular**: Designed for easy extension and integration with other Azure network modules.
+
+## Basic Usage
+
+See the main README and the `_examples/` directory for usage examples.
+
+```hcl
+module "localnet_gateway" {
+ source = "./modules/azure-localnet-gateway"
+ localnet = [
+ {
+ local_gateway_name = "example-gateway"
+ location = "westeurope"
+ resource_group_name = "example-rg"
+ local_gateway_ip = "203.0.113.1"
+ local_gateway_address_space = ["10.1.0.0/16"]
+ tags_from_rg = true
+ tags = {
+ environment = "dev"
+ }
+ }
+ ]
+}
+```
diff --git a/modules/azure-localnet-gateway/locals.tf b/modules/azure-localnet-gateway/locals.tf
new file mode 100644
index 000000000..9d87d5e2f
--- /dev/null
+++ b/modules/azure-localnet-gateway/locals.tf
@@ -0,0 +1,12 @@
+## LOCALS SECTION
+
+locals {
+ # Handle tags based on whether to use resource group tags or module-defined tags for each local network gateway (key = idx)
+ tags = { for idx, s in var.localnet :
+ idx => (
+ coalesce(s.tags_from_rg, false)
+ ? merge(lookup(data.azurerm_resource_group.this, idx, null) != null ? data.azurerm_resource_group.this[idx].tags : {}, try(s.tags, {}))
+ : try(s.tags, {})
+ )
+ }
+}
diff --git a/modules/azure-localnet-gateway/main.tf b/modules/azure-localnet-gateway/main.tf
new file mode 100644
index 000000000..5832ca34e
--- /dev/null
+++ b/modules/azure-localnet-gateway/main.tf
@@ -0,0 +1,12 @@
+## LOCAL NETWORK GATEWAY SECTION
+
+# https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/local_network_gateway
+resource "azurerm_local_network_gateway" "this" {
+ for_each = { for idx, s in var.localnet : idx => s }
+ name = each.value.local_gateway_name
+ location = each.value.location
+ resource_group_name = each.value.resource_group_name
+ gateway_address = each.value.local_gateway_ip
+ address_space = each.value.local_gateway_address_space
+ tags = local.tags[each.key]
+}
diff --git a/modules/azure-localnet-gateway/variables.tf b/modules/azure-localnet-gateway/variables.tf
new file mode 100644
index 000000000..8bcf9ad16
--- /dev/null
+++ b/modules/azure-localnet-gateway/variables.tf
@@ -0,0 +1,15 @@
+## VARIABLES SECTION
+
+variable "localnet" {
+ description = "List of local network gateway objects"
+ type = list(object({
+ local_gateway_name = string
+ location = string
+ resource_group_name = string
+ local_gateway_ip = string
+ local_gateway_address_space = list(string)
+ tags_from_rg = optional(bool)
+ tags = optional(map(string))
+ }))
+ default = []
+}
diff --git a/modules/azure-localnet-gateway/versions.tf b/modules/azure-localnet-gateway/versions.tf
new file mode 100644
index 000000000..64c91805b
--- /dev/null
+++ b/modules/azure-localnet-gateway/versions.tf
@@ -0,0 +1,10 @@
+terraform {
+ required_version = ">= 1.7.0"
+
+ required_providers {
+ azurerm = {
+ source = "hashicorp/azurerm"
+ version = "4.58.0"
+ }
+ }
+}
diff --git a/modules/azure-vnet-gateway-connection/.terraform-docs.yml b/modules/azure-vnet-gateway-connection/.terraform-docs.yml
new file mode 100644
index 000000000..3a69365ff
--- /dev/null
+++ b/modules/azure-vnet-gateway-connection/.terraform-docs.yml
@@ -0,0 +1,48 @@
+formatter: "markdown"
+
+version: ""
+
+header-from: docs/header.md
+footer-from: docs/footer.md
+
+recursive:
+ enabled: false
+ path: modules
+ include-main: true
+
+sections:
+ hide: []
+ show: []
+
+content: ""
+
+output:
+ file: "README.md"
+ mode: inject
+ template: |-
+
+ {{ .Content }}
+
+
+output-values:
+ enabled: false
+ from: ""
+
+sort:
+ enabled: true
+ by: name
+
+settings:
+ anchor: true
+ color: true
+ default: true
+ description: false
+ escape: true
+ hide-empty: false
+ html: true
+ indent: 2
+ lockfile: true
+ read-comments: true
+ required: true
+ sensitive: true
+ type: true
diff --git a/modules/azure-vnet-gateway-connection/README.md b/modules/azure-vnet-gateway-connection/README.md
new file mode 100644
index 000000000..be7ab5d35
--- /dev/null
+++ b/modules/azure-vnet-gateway-connection/README.md
@@ -0,0 +1,121 @@
+
+# **Azure Virtual Network Gateway Connection Terraform Module**
+
+## Overview
+
+This module provisions and manages Azure Virtual Network Gateway Connections for Site-to-Site (S2S), VNet-to-VNet, and ExpressRoute VPNs. It supports advanced configuration, including custom IPsec/IKE policies, NAT rules, BGP, and shared key management via Azure Key Vault.
+
+It is suitable for production, staging, and development environments, and can be integrated into larger Terraform projects or used standalone.
+
+## Key Features
+
+- **S2S, VNet-to-VNet, and ExpressRoute Support**: Create connections between Azure VNets, on-premises networks, or ExpressRoute circuits.
+- **Custom IPsec/IKE Policies**: Fine-grained control over encryption, integrity, and key exchange settings.
+- **NAT Rule Integration**: Attach ingress and egress NAT rules to connections.
+- **Key Vault Integration**: Securely manage shared keys using Azure Key Vault.
+- **Tag Inheritance and Customization**: Inherit tags from the resource group or specify custom tags for all resources.
+- **Extensible and Modular**: Designed for easy extension and integration with other Azure network modules.
+
+## Basic Usage
+
+See the main README and the `_examples/` directory for usage examples.
+
+```hcl
+module "vnet_gateway_connection" {
+ source = "./modules/azure-vnet-gateway-connection"
+ connection = [{
+ name = "example-connection"
+ location = "westeurope"
+ resource_group_name = "example-rg"
+ gateway_name = "example-vnet-gw"
+ local_gateway_name = "example-local-gw"
+ local_gateway_resource_group_name = "example-local-rg"
+ keyvault_vault_name = "example-kv"
+ keyvault_vault_rg = "example-kv-rg"
+ keyvault_secret_name = "vpn-shared-key"
+ type = "IPsec"
+ connection_mode = "InitiatorOnly"
+ connection_protocol = "IKEv2"
+ enable_bgp = false
+ express_route_gateway_bypass = false
+ dpd_timeout_seconds = 30
+ routing_weight = 0
+ use_policy_based_traffic_selectors = false
+ ipsec_policy = {
+ dh_group = "DHGroup14"
+ ike_encryption = "AES256"
+ ike_integrity = "SHA256"
+ ipsec_encryption = "AES256"
+ ipsec_integrity = "SHA256"
+ pfs_group = "PFS2"
+ sa_datasize = 0
+ sa_lifetime = 28800
+ }
+ egress_nat_rule_ids = []
+ ingress_nat_rule_ids = []
+ local_azure_ip_address_enabled = false
+ tags_from_rg = true
+ tags = {
+ environment = "dev"
+ application = "example-app"
+ }
+ }]
+}
+```
+
+## Requirements
+
+| Name | Version |
+|------|---------|
+| [terraform](#requirement\_terraform) | >= 1.7.0 |
+| [azurerm](#requirement\_azurerm) | 4.58.0 |
+
+## Providers
+
+| Name | Version |
+|------|---------|
+| [azurerm](#provider\_azurerm) | 4.58.0 |
+
+## Modules
+
+No modules.
+
+## Resources
+
+| Name | Type |
+|------|------|
+| [azurerm_virtual_network_gateway_connection.this](https://registry.terraform.io/providers/hashicorp/azurerm/4.58.0/docs/resources/virtual_network_gateway_connection) | resource |
+| [azurerm_key_vault.s2s](https://registry.terraform.io/providers/hashicorp/azurerm/4.58.0/docs/data-sources/key_vault) | data source |
+| [azurerm_key_vault_secret.s2s](https://registry.terraform.io/providers/hashicorp/azurerm/4.58.0/docs/data-sources/key_vault_secret) | data source |
+| [azurerm_local_network_gateway.this](https://registry.terraform.io/providers/hashicorp/azurerm/4.58.0/docs/data-sources/local_network_gateway) | data source |
+| [azurerm_resource_group.this](https://registry.terraform.io/providers/hashicorp/azurerm/4.58.0/docs/data-sources/resource_group) | data source |
+| [azurerm_virtual_network_gateway.this](https://registry.terraform.io/providers/hashicorp/azurerm/4.58.0/docs/data-sources/virtual_network_gateway) | data source |
+
+## Inputs
+
+| Name | Description | Type | Default | Required |
+|------|-------------|------|---------|:--------:|
+| [connection](#input\_connection) | List of Site-to-Site VPN connection objects | list(object({
name = string
location = string
resource_group_name = string
local_gateway_name = string
local_gateway_resource_group_name = string
type = string
gateway_name = string
shared_key = optional(string)
keyvault_secret_name = optional(string)
keyvault_vault_name = optional(string)
keyvault_vault_rg = optional(string)
virtual_network_gateway_id = optional(string)
local_network_gateway_id = optional(string)
connection_protocol = optional(string)
routing_weight = optional(number)
authorization_key = optional(string)
express_route_circuit_id = optional(string)
peer_virtual_network_gateway_id = optional(string)
use_policy_based_traffic_selectors = optional(bool)
express_route_gateway_bypass = optional(bool)
dpd_timeout_seconds = optional(number)
connection_mode = optional(string)
tags_from_rg = optional(bool)
egress_nat_rule_ids = optional(list(string))
ingress_nat_rule_ids = optional(list(string))
local_azure_ip_address_enabled = optional(bool)
tags = optional(map(string))
ipsec_policy = optional(object({
dh_group = string
ike_encryption = string
ike_integrity = string
ipsec_encryption = string
ipsec_integrity = string
pfs_group = string
sa_lifetime = number
sa_datasize = number
}))
})) | `[]` | no |
+
+## Outputs
+
+No outputs.
+
+## Examples
+
+For detailed examples, refer to the [module examples](https://github.com/prefapp/tfm/tree/main/modules/azure-vnet-gateway-connection/_examples):
+
+- [s2s\_basic](https://github.com/prefapp/tfm/tree/main/modules/azure-vnet-gateway-connection/_examples/s2s\_basic) - Basic Site-to-Site connection example.
+- [with\_nat\_rules](https://github.com/prefapp/tfm/tree/main/modules/azure-vnet-gateway-connection/_examples/with\_nat\_rules) - Example with ingress/egress NAT rules.
+- [with\_keyvault](https://github.com/prefapp/tfm/tree/main/modules/azure-vnet-gateway-connection/_examples/with\_keyvault) - Example using Azure Key Vault for shared key management.
+
+## Remote resources
+
+- **Azure Virtual Network Gateway Connection**: [azurerm\_virtual\_network\_gateway\_connection documentation](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_network_gateway_connection)
+- **Azure Key Vault Secret**: [azurerm\_key\_vault\_secret documentation](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault_secret)
+- **Terraform Azure Provider**: [Terraform Provider documentation](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs)
+
+## Support
+
+For issues, questions, or contributions related to this module, please visit the [repository's issue tracker](https://github.com/prefapp/tfm/issues).
+
\ No newline at end of file
diff --git a/modules/azure-vnet-gateway-connection/_examples/s2s_basic/example.tf b/modules/azure-vnet-gateway-connection/_examples/s2s_basic/example.tf
new file mode 100644
index 000000000..92c2f1f36
--- /dev/null
+++ b/modules/azure-vnet-gateway-connection/_examples/s2s_basic/example.tf
@@ -0,0 +1,40 @@
+module "vnet_gateway_connection" {
+ source = "../../"
+ connection = [{
+ name = "example-connection"
+ location = "westeurope"
+ resource_group_name = "example-rg"
+ gateway_name = "example-vnet-gw"
+ local_gateway_name = "example-local-gw"
+ local_gateway_resource_group_name = "example-local-rg"
+ keyvault_vault_name = "example-kv"
+ keyvault_vault_rg = "example-kv-rg"
+ keyvault_secret_name = "vpn-shared-key"
+ type = "IPsec"
+ connection_mode = "InitiatorOnly"
+ connection_protocol = "IKEv2"
+ enable_bgp = false
+ express_route_gateway_bypass = false
+ dpd_timeout_seconds = 30
+ routing_weight = 0
+ use_policy_based_traffic_selectors = false
+ ipsec_policy = {
+ dh_group = "DHGroup14"
+ ike_encryption = "AES256"
+ ike_integrity = "SHA256"
+ ipsec_encryption = "AES256"
+ ipsec_integrity = "SHA256"
+ pfs_group = "PFS2"
+ sa_datasize = 0
+ sa_lifetime = 28800
+ }
+ egress_nat_rule_ids = []
+ ingress_nat_rule_ids = []
+ local_azure_ip_address_enabled = false
+ tags_from_rg = true
+ tags = {
+ environment = "dev"
+ application = "example-app"
+ }
+ }]
+}
diff --git a/modules/azure-vnet-gateway-connection/_examples/s2s_basic/example.yaml b/modules/azure-vnet-gateway-connection/_examples/s2s_basic/example.yaml
new file mode 100644
index 000000000..a52958dad
--- /dev/null
+++ b/modules/azure-vnet-gateway-connection/_examples/s2s_basic/example.yaml
@@ -0,0 +1,34 @@
+connection:
+ - name: example-connection
+ location: westeurope
+ resource_group_name: example-rg
+ gateway_name: example-vnet-gw
+ local_gateway_name: example-local-gw
+ local_gateway_resource_group_name: example-local-rg
+ keyvault_vault_name: example-kv
+ keyvault_vault_rg: example-kv-rg
+ keyvault_secret_name: vpn-shared-key
+ type: IPsec
+ connection_mode: InitiatorOnly
+ connection_protocol: IKEv2
+ enable_bgp: false
+ express_route_gateway_bypass: false
+ dpd_timeout_seconds: 30
+ routing_weight: 0
+ use_policy_based_traffic_selectors: false
+ ipsec_policy:
+ dh_group: DHGroup14
+ ike_encryption: AES256
+ ike_integrity: SHA256
+ ipsec_encryption: AES256
+ ipsec_integrity: SHA256
+ pfs_group: PFS2
+ sa_datasize: 0
+ sa_lifetime: 28800
+ egress_nat_rule_ids: []
+ ingress_nat_rule_ids: []
+ local_azure_ip_address_enabled: false
+ tags_from_rg: true
+ tags:
+ environment: dev
+ application: example-app
diff --git a/modules/azure-vnet-gateway-connection/_examples/with_keyvault_shared_key/example.tf b/modules/azure-vnet-gateway-connection/_examples/with_keyvault_shared_key/example.tf
new file mode 100644
index 000000000..bf739db15
--- /dev/null
+++ b/modules/azure-vnet-gateway-connection/_examples/with_keyvault_shared_key/example.tf
@@ -0,0 +1,40 @@
+module "vnet_gateway_connection" {
+ source = "../../"
+ connection = [{
+ name = "keyvault-connection"
+ location = "westeurope"
+ resource_group_name = "example-rg"
+ gateway_name = "example-vnet-gw"
+ local_gateway_name = "example-local-gw"
+ local_gateway_resource_group_name = "example-local-rg"
+ keyvault_vault_name = "example-kv"
+ keyvault_vault_rg = "example-kv-rg"
+ keyvault_secret_name = "vpn-shared-key"
+ type = "IPsec"
+ connection_mode = "InitiatorOnly"
+ connection_protocol = "IKEv2"
+ enable_bgp = false
+ express_route_gateway_bypass = false
+ dpd_timeout_seconds = 30
+ routing_weight = 0
+ use_policy_based_traffic_selectors = false
+ ipsec_policy = {
+ dh_group = "DHGroup14"
+ ike_encryption = "AES256"
+ ike_integrity = "SHA256"
+ ipsec_encryption = "AES256"
+ ipsec_integrity = "SHA256"
+ pfs_group = "PFS2"
+ sa_datasize = 0
+ sa_lifetime = 28800
+ }
+ egress_nat_rule_ids = []
+ ingress_nat_rule_ids = []
+ local_azure_ip_address_enabled = false
+ tags_from_rg = true
+ tags = {
+ environment = "prod"
+ application = "keyvault-app"
+ }
+ }]
+}
diff --git a/modules/azure-vnet-gateway-connection/_examples/with_keyvault_shared_key/example.yaml b/modules/azure-vnet-gateway-connection/_examples/with_keyvault_shared_key/example.yaml
new file mode 100644
index 000000000..abe5f4694
--- /dev/null
+++ b/modules/azure-vnet-gateway-connection/_examples/with_keyvault_shared_key/example.yaml
@@ -0,0 +1,34 @@
+connection:
+ - name: keyvault-connection
+ location: westeurope
+ resource_group_name: example-rg
+ gateway_name: example-vnet-gw
+ local_gateway_name: example-local-gw
+ local_gateway_resource_group_name: example-local-rg
+ keyvault_vault_name: example-kv
+ keyvault_vault_rg: example-kv-rg
+ keyvault_secret_name: vpn-shared-key
+ type: IPsec
+ connection_mode: InitiatorOnly
+ connection_protocol: IKEv2
+ enable_bgp: false
+ express_route_gateway_bypass: false
+ dpd_timeout_seconds: 30
+ routing_weight: 0
+ use_policy_based_traffic_selectors: false
+ ipsec_policy:
+ dh_group: DHGroup14
+ ike_encryption: AES256
+ ike_integrity: SHA256
+ ipsec_encryption: AES256
+ ipsec_integrity: SHA256
+ pfs_group: PFS2
+ sa_datasize: 0
+ sa_lifetime: 28800
+ egress_nat_rule_ids: []
+ ingress_nat_rule_ids: []
+ local_azure_ip_address_enabled: false
+ tags_from_rg: true
+ tags:
+ environment: prod
+ application: keyvault-app
diff --git a/modules/azure-vnet-gateway-connection/_examples/with_nat_rules/example.tf b/modules/azure-vnet-gateway-connection/_examples/with_nat_rules/example.tf
new file mode 100644
index 000000000..003d456d7
--- /dev/null
+++ b/modules/azure-vnet-gateway-connection/_examples/with_nat_rules/example.tf
@@ -0,0 +1,40 @@
+module "vnet_gateway_connection" {
+ source = "../../"
+ connection = [{
+ name = "nat-connection"
+ location = "westeurope"
+ resource_group_name = "example-rg"
+ gateway_name = "example-vnet-gw"
+ local_gateway_name = "example-local-gw"
+ local_gateway_resource_group_name = "example-local-rg"
+ keyvault_vault_name = "example-kv"
+ keyvault_vault_rg = "example-kv-rg"
+ keyvault_secret_name = "vpn-shared-key"
+ type = "IPsec"
+ connection_mode = "InitiatorOnly"
+ connection_protocol = "IKEv2"
+ enable_bgp = false
+ express_route_gateway_bypass = false
+ dpd_timeout_seconds = 30
+ routing_weight = 0
+ use_policy_based_traffic_selectors = false
+ ipsec_policy = {
+ dh_group = "DHGroup14"
+ ike_encryption = "AES256"
+ ike_integrity = "SHA256"
+ ipsec_encryption = "AES256"
+ ipsec_integrity = "SHA256"
+ pfs_group = "PFS2"
+ sa_datasize = 0
+ sa_lifetime = 28800
+ }
+ egress_nat_rule_ids = ["/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example-rg/providers/Microsoft.Network/virtualNetworkGateways/example-vnet-gw/natRules/egress_nat"]
+ ingress_nat_rule_ids = ["/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example-rg/providers/Microsoft.Network/virtualNetworkGateways/example-vnet-gw/natRules/ingress_nat"]
+ local_azure_ip_address_enabled = false
+ tags_from_rg = false
+ tags = {
+ environment = "test"
+ application = "nat-app"
+ }
+ }]
+}
diff --git a/modules/azure-vnet-gateway-connection/_examples/with_nat_rules/example.yaml b/modules/azure-vnet-gateway-connection/_examples/with_nat_rules/example.yaml
new file mode 100644
index 000000000..7b372f0dd
--- /dev/null
+++ b/modules/azure-vnet-gateway-connection/_examples/with_nat_rules/example.yaml
@@ -0,0 +1,36 @@
+connection:
+ - name: nat-connection
+ location: westeurope
+ resource_group_name: example-rg
+ gateway_name: example-vnet-gw
+ local_gateway_name: example-local-gw
+ local_gateway_resource_group_name: example-local-rg
+ keyvault_vault_name: example-kv
+ keyvault_vault_rg: example-kv-rg
+ keyvault_secret_name: vpn-shared-key
+ type: IPsec
+ connection_mode: InitiatorOnly
+ connection_protocol: IKEv2
+ enable_bgp: false
+ express_route_gateway_bypass: false
+ dpd_timeout_seconds: 30
+ routing_weight: 0
+ use_policy_based_traffic_selectors: false
+ ipsec_policy:
+ dh_group: DHGroup14
+ ike_encryption: AES256
+ ike_integrity: SHA256
+ ipsec_encryption: AES256
+ ipsec_integrity: SHA256
+ pfs_group: PFS2
+ sa_datasize: 0
+ sa_lifetime: 28800
+ egress_nat_rule_ids:
+ - /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example-rg/providers/Microsoft.Network/virtualNetworkGateways/example-vnet-gw/natRules/egress_nat
+ ingress_nat_rule_ids:
+ - /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example-rg/providers/Microsoft.Network/virtualNetworkGateways/example-vnet-gw/natRules/ingress_nat
+ local_azure_ip_address_enabled: false
+ tags_from_rg: false
+ tags:
+ environment: test
+ application: nat-app
diff --git a/modules/azure-vnet-gateway-connection/data.tf b/modules/azure-vnet-gateway-connection/data.tf
new file mode 100644
index 000000000..cc555cd97
--- /dev/null
+++ b/modules/azure-vnet-gateway-connection/data.tf
@@ -0,0 +1,35 @@
+## DATA SOURCES SECTION
+
+# https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/resource_group
+data "azurerm_local_network_gateway" "this" {
+ for_each = { for idx, s in var.connection : idx => s }
+ name = each.value.local_gateway_name
+ resource_group_name = each.value.local_gateway_resource_group_name
+}
+
+# https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/virtual_network_gateway
+data "azurerm_resource_group" "this" {
+ for_each = { for idx, s in var.connection : idx => s }
+ name = each.value.resource_group_name
+}
+
+# https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/virtual_network_gateway
+data "azurerm_virtual_network_gateway" "this" {
+ for_each = { for idx, s in var.connection : idx => s }
+ name = each.value.gateway_name
+ resource_group_name = each.value.resource_group_name
+}
+
+# https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/key_vault_secret
+data "azurerm_key_vault_secret" "s2s" {
+ for_each = { for idx, s in var.connection : idx => s if try(s.keyvault_secret_name, null) != null && try(s.keyvault_vault_name, null) != null && try(s.keyvault_vault_rg, null) != null }
+ name = each.value.keyvault_secret_name
+ key_vault_id = data.azurerm_key_vault.s2s[each.key].id
+}
+
+# https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/key_vault
+data "azurerm_key_vault" "s2s" {
+ for_each = { for idx, s in var.connection : idx => s if try(s.keyvault_vault_name, null) != null && try(s.keyvault_vault_rg, null) != null }
+ name = each.value.keyvault_vault_name
+ resource_group_name = each.value.keyvault_vault_rg
+}
diff --git a/modules/azure-vnet-gateway-connection/docs/footer.md b/modules/azure-vnet-gateway-connection/docs/footer.md
new file mode 100644
index 000000000..ae03a3fd1
--- /dev/null
+++ b/modules/azure-vnet-gateway-connection/docs/footer.md
@@ -0,0 +1,17 @@
+## Examples
+
+For detailed examples, refer to the [module examples](https://github.com/prefapp/tfm/tree/main/modules/azure-vnet-gateway-connection/_examples):
+
+- [s2s_basic](https://github.com/prefapp/tfm/tree/main/modules/azure-vnet-gateway-connection/_examples/s2s_basic) - Basic Site-to-Site connection example.
+- [with_nat_rules](https://github.com/prefapp/tfm/tree/main/modules/azure-vnet-gateway-connection/_examples/with_nat_rules) - Example with ingress/egress NAT rules.
+- [with_keyvault](https://github.com/prefapp/tfm/tree/main/modules/azure-vnet-gateway-connection/_examples/with_keyvault) - Example using Azure Key Vault for shared key management.
+
+## Remote resources
+
+- **Azure Virtual Network Gateway Connection**: [azurerm_virtual_network_gateway_connection documentation](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_network_gateway_connection)
+- **Azure Key Vault Secret**: [azurerm_key_vault_secret documentation](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/key_vault_secret)
+- **Terraform Azure Provider**: [Terraform Provider documentation](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs)
+
+## Support
+
+For issues, questions, or contributions related to this module, please visit the [repository's issue tracker](https://github.com/prefapp/tfm/issues).
diff --git a/modules/azure-vnet-gateway-connection/docs/header.md b/modules/azure-vnet-gateway-connection/docs/header.md
new file mode 100644
index 000000000..49162221f
--- /dev/null
+++ b/modules/azure-vnet-gateway-connection/docs/header.md
@@ -0,0 +1,63 @@
+# **Azure Virtual Network Gateway Connection Terraform Module**
+
+## Overview
+
+This module provisions and manages Azure Virtual Network Gateway Connections for Site-to-Site (S2S), VNet-to-VNet, and ExpressRoute VPNs. It supports advanced configuration, including custom IPsec/IKE policies, NAT rules, BGP, and shared key management via Azure Key Vault.
+
+It is suitable for production, staging, and development environments, and can be integrated into larger Terraform projects or used standalone.
+
+## Key Features
+
+- **S2S, VNet-to-VNet, and ExpressRoute Support**: Create connections between Azure VNets, on-premises networks, or ExpressRoute circuits.
+- **Custom IPsec/IKE Policies**: Fine-grained control over encryption, integrity, and key exchange settings.
+- **NAT Rule Integration**: Attach ingress and egress NAT rules to connections.
+- **Key Vault Integration**: Securely manage shared keys using Azure Key Vault.
+- **Tag Inheritance and Customization**: Inherit tags from the resource group or specify custom tags for all resources.
+- **Extensible and Modular**: Designed for easy extension and integration with other Azure network modules.
+
+## Basic Usage
+
+See the main README and the `_examples/` directory for usage examples.
+
+```hcl
+module "vnet_gateway_connection" {
+ source = "./modules/azure-vnet-gateway-connection"
+ connection = [{
+ name = "example-connection"
+ location = "westeurope"
+ resource_group_name = "example-rg"
+ gateway_name = "example-vnet-gw"
+ local_gateway_name = "example-local-gw"
+ local_gateway_resource_group_name = "example-local-rg"
+ keyvault_vault_name = "example-kv"
+ keyvault_vault_rg = "example-kv-rg"
+ keyvault_secret_name = "vpn-shared-key"
+ type = "IPsec"
+ connection_mode = "InitiatorOnly"
+ connection_protocol = "IKEv2"
+ enable_bgp = false
+ express_route_gateway_bypass = false
+ dpd_timeout_seconds = 30
+ routing_weight = 0
+ use_policy_based_traffic_selectors = false
+ ipsec_policy = {
+ dh_group = "DHGroup14"
+ ike_encryption = "AES256"
+ ike_integrity = "SHA256"
+ ipsec_encryption = "AES256"
+ ipsec_integrity = "SHA256"
+ pfs_group = "PFS2"
+ sa_datasize = 0
+ sa_lifetime = 28800
+ }
+ egress_nat_rule_ids = []
+ ingress_nat_rule_ids = []
+ local_azure_ip_address_enabled = false
+ tags_from_rg = true
+ tags = {
+ environment = "dev"
+ application = "example-app"
+ }
+ }]
+}
+```
diff --git a/modules/azure-vnet-gateway-connection/locals.tf b/modules/azure-vnet-gateway-connection/locals.tf
new file mode 100644
index 000000000..4540baa34
--- /dev/null
+++ b/modules/azure-vnet-gateway-connection/locals.tf
@@ -0,0 +1,12 @@
+## LOCALS SECTION
+
+locals {
+ # Handle tags based on whether to use resource group tags or module-defined tags for each connection (key = idx)
+ tags = { for idx, s in var.connection :
+ idx => (
+ coalesce(s.tags_from_rg, false)
+ ? merge(try(data.azurerm_resource_group.this[idx].tags, {}), try(s.tags, {}))
+ : try(s.tags, {})
+ )
+ }
+}
diff --git a/modules/azure-vnet-gateway-connection/main.tf b/modules/azure-vnet-gateway-connection/main.tf
new file mode 100644
index 000000000..628e22256
--- /dev/null
+++ b/modules/azure-vnet-gateway-connection/main.tf
@@ -0,0 +1,51 @@
+## VPN CONNECTION SECTION
+
+# https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_network_gateway_connection
+resource "azurerm_virtual_network_gateway_connection" "this" {
+ for_each = { for idx, s in var.connection : idx => s }
+ name = each.value.name
+ location = each.value.location
+ resource_group_name = each.value.resource_group_name
+ egress_nat_rule_ids = try(each.value.egress_nat_rule_ids, null)
+ ingress_nat_rule_ids = try(each.value.ingress_nat_rule_ids, null)
+ local_azure_ip_address_enabled = try(each.value.local_azure_ip_address_enabled, null)
+ tags = local.tags[each.key]
+ type = each.value.type
+ virtual_network_gateway_id = (
+ try(each.value.virtual_network_gateway_id, null) != null ? each.value.virtual_network_gateway_id : data.azurerm_virtual_network_gateway.this[each.key].id
+ )
+ local_network_gateway_id = (
+ try(each.value.local_network_gateway_id, null) != null ? each.value.local_network_gateway_id : data.azurerm_local_network_gateway.this[each.key].id
+ )
+ shared_key = (
+ try(each.value.shared_key, null) != null ? each.value.shared_key : (
+ try(data.azurerm_key_vault_secret.s2s[each.key].value, null) != null ? data.azurerm_key_vault_secret.s2s[each.key].value : null
+ )
+ )
+ enable_bgp = try(each.value.enable_bgp, null)
+ connection_protocol = try(each.value.connection_protocol, null)
+ routing_weight = try(each.value.routing_weight, null)
+ authorization_key = try(each.value.authorization_key, null)
+ express_route_circuit_id = try(each.value.express_route_circuit_id, null)
+ peer_virtual_network_gateway_id = try(each.value.peer_virtual_network_gateway_id, null)
+ use_policy_based_traffic_selectors = try(each.value.use_policy_based_traffic_selectors, null)
+ express_route_gateway_bypass = try(each.value.express_route_gateway_bypass, null)
+ dpd_timeout_seconds = try(each.value.dpd_timeout_seconds, null)
+ connection_mode = try(each.value.connection_mode, null)
+ dynamic "ipsec_policy" {
+ for_each = try(each.value.ipsec_policy != null, false) ? [each.value.ipsec_policy] : []
+ content {
+ dh_group = ipsec_policy.value.dh_group
+ ike_encryption = ipsec_policy.value.ike_encryption
+ ike_integrity = ipsec_policy.value.ike_integrity
+ ipsec_encryption = ipsec_policy.value.ipsec_encryption
+ ipsec_integrity = ipsec_policy.value.ipsec_integrity
+ pfs_group = ipsec_policy.value.pfs_group
+ sa_lifetime = ipsec_policy.value.sa_lifetime
+ sa_datasize = ipsec_policy.value.sa_datasize
+ }
+ }
+ lifecycle {
+ ignore_changes = [shared_key]
+ }
+}
diff --git a/modules/azure-vnet-gateway-connection/variables.tf b/modules/azure-vnet-gateway-connection/variables.tf
new file mode 100644
index 000000000..aae452cc0
--- /dev/null
+++ b/modules/azure-vnet-gateway-connection/variables.tf
@@ -0,0 +1,47 @@
+## VARIABLES SECTION
+
+variable "connection" {
+ description = "List of Site-to-Site VPN connection objects"
+ type = list(object({
+ name = string
+ location = string
+ resource_group_name = string
+ local_gateway_name = string
+ local_gateway_resource_group_name = string
+ type = string
+ gateway_name = string
+ shared_key = optional(string)
+ keyvault_secret_name = optional(string)
+ keyvault_vault_name = optional(string)
+ keyvault_vault_rg = optional(string)
+ virtual_network_gateway_id = optional(string)
+ local_network_gateway_id = optional(string)
+ connection_protocol = optional(string)
+ routing_weight = optional(number)
+ authorization_key = optional(string)
+ express_route_circuit_id = optional(string)
+ peer_virtual_network_gateway_id = optional(string)
+ use_policy_based_traffic_selectors = optional(bool)
+ express_route_gateway_bypass = optional(bool)
+ dpd_timeout_seconds = optional(number)
+ connection_mode = optional(string)
+ tags_from_rg = optional(bool)
+ egress_nat_rule_ids = optional(list(string))
+ ingress_nat_rule_ids = optional(list(string))
+ local_azure_ip_address_enabled = optional(bool)
+ tags = optional(map(string))
+ ipsec_policy = optional(object({
+ dh_group = string
+ ike_encryption = string
+ ike_integrity = string
+ ipsec_encryption = string
+ ipsec_integrity = string
+ pfs_group = string
+ sa_lifetime = number
+ sa_datasize = number
+ }))
+ }))
+ default = []
+}
+
+
diff --git a/modules/azure-vnet-gateway-connection/versions.tf b/modules/azure-vnet-gateway-connection/versions.tf
new file mode 100644
index 000000000..64c91805b
--- /dev/null
+++ b/modules/azure-vnet-gateway-connection/versions.tf
@@ -0,0 +1,10 @@
+terraform {
+ required_version = ">= 1.7.0"
+
+ required_providers {
+ azurerm = {
+ source = "hashicorp/azurerm"
+ version = "4.58.0"
+ }
+ }
+}
diff --git a/modules/azure-vnet-gateway/.terraform-docs.yml b/modules/azure-vnet-gateway/.terraform-docs.yml
new file mode 100644
index 000000000..3a69365ff
--- /dev/null
+++ b/modules/azure-vnet-gateway/.terraform-docs.yml
@@ -0,0 +1,48 @@
+formatter: "markdown"
+
+version: ""
+
+header-from: docs/header.md
+footer-from: docs/footer.md
+
+recursive:
+ enabled: false
+ path: modules
+ include-main: true
+
+sections:
+ hide: []
+ show: []
+
+content: ""
+
+output:
+ file: "README.md"
+ mode: inject
+ template: |-
+
+ {{ .Content }}
+
+
+output-values:
+ enabled: false
+ from: ""
+
+sort:
+ enabled: true
+ by: name
+
+settings:
+ anchor: true
+ color: true
+ default: true
+ description: false
+ escape: true
+ hide-empty: false
+ html: true
+ indent: 2
+ lockfile: true
+ read-comments: true
+ required: true
+ sensitive: true
+ type: true
diff --git a/modules/azure-vnet-gateway/README.md b/modules/azure-vnet-gateway/README.md
new file mode 100644
index 000000000..a0f4126be
--- /dev/null
+++ b/modules/azure-vnet-gateway/README.md
@@ -0,0 +1,99 @@
+
+# **Azure Virtual Network Gateway Terraform Module**
+
+## Overview
+
+This module provisions and manages an Azure Virtual Network Gateway for VPN connectivity, supporting both Route-based and Policy-based configurations. It is suitable for production, staging, and development environments, and can be integrated into larger Terraform projects or used standalone.
+
+## Key Features
+
+- **Flexible Gateway Deployment**: Supports Route-based and Policy-based VPN gateways, active-active mode, and multiple SKUs.
+- **Custom IP Configuration**: Allows custom public IP, subnet, and private IP allocation.
+- **Advanced VPN Client Support**: Configure VPN client address spaces, protocols, and AAD integration for P2S.
+- **Tag Inheritance and Customization**: Inherit tags from the resource group or specify custom tags for all resources.
+- **Extensible and Modular**: Designed for easy extension and integration with other Azure network modules.
+
+## Basic Usage
+
+See the main README and the `_examples/` directory for usage examples.
+
+```hcl
+module "vnet_gateway" {
+ source = "./modules/azure-vnet-gateway"
+ vpn = {
+ vnet_name = "my-vnet"
+ gateway_subnet_name = "GatewaySubnet"
+ location = "westeurope"
+ resource_group_name = "my-rg"
+ gateway_name = "my-vpn-gw"
+ ip_name = "my-vpn-ip"
+ public_ip_name = "my-vpn-public-ip"
+ ip_allocation_method = "Dynamic"
+ type = "Vpn"
+ vpn_type = "RouteBased"
+ active_active = false
+ enable_bgp = false
+ sku = "VpnGw1"
+ # ...other optional fields...
+ }
+}
+```
+
+## Requirements
+
+| Name | Version |
+|------|---------|
+| [terraform](#requirement\_terraform) | >= 1.7.0 |
+| [azurerm](#requirement\_azurerm) | 4.58.0 |
+
+## Providers
+
+| Name | Version |
+|------|---------|
+| [azurerm](#provider\_azurerm) | 4.58.0 |
+
+## Modules
+
+No modules.
+
+## Resources
+
+| Name | Type |
+|------|------|
+| [azurerm_virtual_network_gateway.this](https://registry.terraform.io/providers/hashicorp/azurerm/4.58.0/docs/resources/virtual_network_gateway) | resource |
+| [azurerm_virtual_network_gateway_nat_rule.this](https://registry.terraform.io/providers/hashicorp/azurerm/4.58.0/docs/resources/virtual_network_gateway_nat_rule) | resource |
+| [azurerm_public_ip.this](https://registry.terraform.io/providers/hashicorp/azurerm/4.58.0/docs/data-sources/public_ip) | data source |
+| [azurerm_resource_group.this](https://registry.terraform.io/providers/hashicorp/azurerm/4.58.0/docs/data-sources/resource_group) | data source |
+| [azurerm_subnet.this](https://registry.terraform.io/providers/hashicorp/azurerm/4.58.0/docs/data-sources/subnet) | data source |
+| [azurerm_virtual_network_gateway.this](https://registry.terraform.io/providers/hashicorp/azurerm/4.58.0/docs/data-sources/virtual_network_gateway) | data source |
+
+## Inputs
+
+| Name | Description | Type | Default | Required |
+|------|-------------|------|---------|:--------:|
+| [nat\_rules](#input\_nat\_rules) | List of NAT rules for the VPN gateway | list(object({
name = string
mode = string
type = string
ip_configuration_id = optional(string)
external_mapping_address_space = string
internal_mapping_address_space = string
})) | `[]` | no |
+| [tags](#input\_tags) | Tags to apply to resources | `map(string)` | `{}` | no |
+| [tags\_from\_rg](#input\_tags\_from\_rg) | Use resource group tags as base for module tags | `bool` | `false` | no |
+| [vpn](#input\_vpn) | VPN Gateway configuration object (includes P2S config) | object({
vnet_name = string
gateway_subnet_name = string
location = string
resource_group_name = string
gateway_name = string
ip_name = string
public_ip_name = string
public_ip_id = optional(string)
ip_allocation_method = string
gateway_subnet_id = optional(string)
type = string
vpn_type = string
active_active = bool
enable_bgp = bool
sku = string
generation = optional(string)
default_local_network_gateway_id = optional(string)
edge_zone = optional(string)
private_ip_address_enabled = optional(bool)
bgp_route_translation_for_nat_enabled = optional(bool)
dns_forwarding_enabled = optional(bool)
ip_sec_replay_protection_enabled = optional(bool)
remote_vnet_traffic_enabled = optional(bool)
virtual_wan_traffic_enabled = optional(bool)
# ip_configuration block fields
private_ip_address_allocation = optional(string)
# custom_route block
custom_route_address_prefixes = optional(list(string), [])
# vpn_client_configuration block
vpn_client_address_space = optional(list(string), [])
vpn_client_protocols = optional(list(string), [])
vpn_client_aad_tenant = optional(string)
vpn_client_aad_audience = optional(string)
vpn_client_aad_issuer = optional(string)
root_certificates = optional(list(object({
name = string
public_cert = optional(string)
public_cert_data = optional(string)
})), [])
revoked_certificates = optional(list(object({
name = string
thumbprint = string
})), [])
vpn_auth_types = optional(list(string), [])
# bgp_settings block
bgp_settings = optional(object({
asn = optional(number)
peer_weight = optional(number)
peering_addresses = optional(list(object({
ip_configuration_name = optional(string)
apipa_addresses = optional(list(string))
})), [])
}))
# timeouts block
timeouts = optional(object({
create = optional(string)
read = optional(string)
update = optional(string)
delete = optional(string)
}))
}) | n/a | yes |
+
+## Outputs
+
+No outputs.
+
+## Examples
+
+For detailed examples, refer to the [module examples](https://github.com/prefapp/tfm/tree/main/modules/azure-vnet-gateway/_examples):
+
+- [basic\_route\_based](https://github.com/prefapp/tfm/tree/main/modules/azure-vnet-gateway/_examples/basic\_route\_based) - Basic RouteBased gateway example.
+- [active\_active\_bgp](https://github.com/prefapp/tfm/tree/main/modules/azure-vnet-gateway/_examples/active\_active\_bgp) - Active-Active gateway with BGP enabled.
+- [vpn\_client\_aad](https://github.com/prefapp/tfm/tree/main/modules/azure-vnet-gateway/_examples/vpn\_client\_aad) - Gateway with VPN Client and Azure AD authentication.
+
+## Remote resources
+
+- **Azure Virtual Network Gateway**: [azurerm\_virtual\_network\_gateway documentation](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_network_gateway)
+- **Terraform Azure Provider**: [Terraform Provider documentation](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs)
+
+## Support
+
+For issues, questions, or contributions related to this module, please visit the [repository's issue tracker](https://github.com/prefapp/tfm/issues).
+
\ No newline at end of file
diff --git a/modules/azure-vnet-gateway/_examples/active_active_bgp/example.tf b/modules/azure-vnet-gateway/_examples/active_active_bgp/example.tf
new file mode 100644
index 000000000..35f82a9bc
--- /dev/null
+++ b/modules/azure-vnet-gateway/_examples/active_active_bgp/example.tf
@@ -0,0 +1,20 @@
+module "vnet_gateway" {
+ source = "../../"
+ vpn = {
+ vnet_name = "example-vnet"
+ gateway_subnet_name = "GatewaySubnet"
+ location = "westeurope"
+ resource_group_name = "example-rg"
+ gateway_name = "example-vpn-gw"
+ ip_name = "example-vpn-ip"
+ public_ip_name = "example-vpn-public-ip"
+ ip_allocation_method = "Dynamic"
+ type = "Vpn"
+ vpn_type = "RouteBased"
+ active_active = true
+ enable_bgp = true
+ sku = "VpnGw2"
+ bgp_route_translation_for_nat_enabled = true
+ tags = { environment = "prod" }
+ }
+}
diff --git a/modules/azure-vnet-gateway/_examples/active_active_bgp/example.yaml b/modules/azure-vnet-gateway/_examples/active_active_bgp/example.yaml
new file mode 100644
index 000000000..c085af599
--- /dev/null
+++ b/modules/azure-vnet-gateway/_examples/active_active_bgp/example.yaml
@@ -0,0 +1,17 @@
+vpn:
+ vnet_name: example-vnet
+ gateway_subnet_name: GatewaySubnet
+ location: westeurope
+ resource_group_name: example-rg
+ gateway_name: example-vpn-gw
+ ip_name: example-vpn-ip
+ public_ip_name: example-vpn-public-ip
+ ip_allocation_method: Dynamic
+ type: Vpn
+ vpn_type: RouteBased
+ active_active: true
+ enable_bgp: true
+ sku: VpnGw2
+ bgp_route_translation_for_nat_enabled: true
+ tags:
+ environment: prod
diff --git a/modules/azure-vnet-gateway/_examples/basic_route_based/example.tf b/modules/azure-vnet-gateway/_examples/basic_route_based/example.tf
new file mode 100644
index 000000000..c12d46377
--- /dev/null
+++ b/modules/azure-vnet-gateway/_examples/basic_route_based/example.tf
@@ -0,0 +1,19 @@
+module "vnet_gateway" {
+ source = "../../"
+ vpn = {
+ vnet_name = "example-vnet"
+ gateway_subnet_name = "GatewaySubnet"
+ location = "westeurope"
+ resource_group_name = "example-rg"
+ gateway_name = "example-vpn-gw"
+ ip_name = "example-vpn-ip"
+ public_ip_name = "example-vpn-public-ip"
+ ip_allocation_method = "Dynamic"
+ type = "Vpn"
+ vpn_type = "RouteBased"
+ active_active = false
+ enable_bgp = false
+ sku = "VpnGw1"
+ tags = { environment = "dev" }
+ }
+}
diff --git a/modules/azure-vnet-gateway/_examples/basic_route_based/example.yaml b/modules/azure-vnet-gateway/_examples/basic_route_based/example.yaml
new file mode 100644
index 000000000..f8b8eead6
--- /dev/null
+++ b/modules/azure-vnet-gateway/_examples/basic_route_based/example.yaml
@@ -0,0 +1,16 @@
+vpn:
+ vnet_name: example-vnet
+ gateway_subnet_name: GatewaySubnet
+ location: westeurope
+ resource_group_name: example-rg
+ gateway_name: example-vpn-gw
+ ip_name: example-vpn-ip
+ public_ip_name: example-vpn-public-ip
+ ip_allocation_method: Dynamic
+ type: Vpn
+ vpn_type: RouteBased
+ active_active: false
+ enable_bgp: false
+ sku: VpnGw1
+ tags:
+ environment: dev
diff --git a/modules/azure-vnet-gateway/_examples/vpn_client_aad/example.tf b/modules/azure-vnet-gateway/_examples/vpn_client_aad/example.tf
new file mode 100644
index 000000000..2e8e1feab
--- /dev/null
+++ b/modules/azure-vnet-gateway/_examples/vpn_client_aad/example.tf
@@ -0,0 +1,22 @@
+module "vnet_gateway" {
+ source = "../../"
+ vpn = {
+ vnet_name = "example-vnet"
+ gateway_subnet_name = "GatewaySubnet"
+ location = "westeurope"
+ resource_group_name = "example-rg"
+ gateway_name = "example-vpn-gw"
+ ip_name = "example-vpn-ip"
+ public_ip_name = "example-vpn-public-ip"
+ ip_allocation_method = "Dynamic"
+ type = "Vpn"
+ vpn_type = "RouteBased"
+ active_active = false
+ enable_bgp = false
+ sku = "VpnGw1"
+ vpn_client_address_space = ["10.10.0.0/24"]
+ vpn_client_protocols = ["IkeV2", "OpenVPN"]
+ vpn_client_aad_tenant = "https://login.microsoftonline.com/