diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index ddbb1ac..de97c1a 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -44,3 +44,31 @@ updates:
- "Crew"
# Allow up to 3 open pull requests for pip dependencies
open-pull-requests-limit: 3
+
+ - package-ecosystem: "terraform" # See documentation for possible values
+ directory: "/examples/firewall-with-isolated-rules" # Location of package manifests
+ schedule:
+ interval: "daily"
+ # Add assignees
+ assignees:
+ - "clouddrove-ci"
+ # Add reviewer
+ reviewers:
+ - "approvers"
+ - "Crew"
+ # Allow up to 3 open pull requests for pip dependencies
+ open-pull-requests-limit: 3
+
+ - package-ecosystem: "terraform" # See documentation for possible values
+ directory: "/examples/firewall-with-public-ip-prefix" # Location of package manifests
+ schedule:
+ interval: "daily"
+ # Add assignees
+ assignees:
+ - "clouddrove-ci"
+ # Add reviewer
+ reviewers:
+ - "approvers"
+ - "Crew"
+ # Allow up to 3 open pull requests for pip dependencies
+ open-pull-requests-limit: 3
diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml
deleted file mode 100644
index 1ee6f78..0000000
--- a/.github/workflows/changelog.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-name: changelog
-permissions: write-all
-on:
- push:
- tags:
- - "*"
- workflow_dispatch:
-jobs:
- changelog:
- uses: clouddrove/github-shared-workflows/.github/workflows/changelog.yml@master
- secrets: inherit
- with:
- branch: 'master'
diff --git a/.github/workflows/readme.yml b/.github/workflows/readme.yml
deleted file mode 100644
index 444164d..0000000
--- a/.github/workflows/readme.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-name: Readme Workflow
-on:
- push:
- branches:
- - master
- paths-ignore:
- - 'README.md'
- - 'docs/**'
- workflow_dispatch:
-jobs:
- README:
- uses: clouddrove/github-shared-workflows/.github/workflows/readme.yml@master
- secrets:
- TOKEN : ${{ secrets.GITHUB }}
- SLACK_WEBHOOK_TERRAFORM: ${{ secrets.SLACK_WEBHOOK_TERRAFORM }}
\ No newline at end of file
diff --git a/.github/workflows/terraform-diff.yml b/.github/workflows/terraform-diff.yml
index b009b3d..5bf49fc 100644
--- a/.github/workflows/terraform-diff.yml
+++ b/.github/workflows/terraform-diff.yml
@@ -1,4 +1,4 @@
-name: Terraform plan Difference
+name: Terraform Plan Difference
on:
pull_request:
branches:
@@ -12,6 +12,26 @@ jobs:
provider: 'azurerm'
terraform_directory: 'examples/complete'
target_branch: 'master'
+ secrets:
+ AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }}
+ ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }}
+
+ firewall-with-isolated-rules-example:
+ uses: clouddrove/github-shared-workflows/.github/workflows/tf-pr-checks.yaml@master
+ with:
+ provider: 'azurerm'
+ terraform_directory: 'examples/firewall-with-isolated-rules'
+ target_branch: 'master'
+ secrets:
+ AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }}
+ ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }}
+
+ firewall-with-public-ip-prefix-example:
+ uses: clouddrove/github-shared-workflows/.github/workflows/tf-pr-checks.yaml@master
+ with:
+ provider: 'azurerm'
+ terraform_directory: 'examples/firewall-with-public-ip-prefix'
+ target_branch: 'master'
secrets:
AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }}
ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }}
\ No newline at end of file
diff --git a/.github/workflows/tf-checks.yml b/.github/workflows/tf-checks.yml
index 3fcc04e..d4fd5fe 100644
--- a/.github/workflows/tf-checks.yml
+++ b/.github/workflows/tf-checks.yml
@@ -9,8 +9,17 @@ jobs:
complete-example:
uses: clouddrove/github-shared-workflows/.github/workflows/tf-checks.yml@master
with:
- working_directory: './examples/complete/'
+ working_directory: 'examples/complete/'
+
+ firewall-with-isolated-rules-example:
+ uses: clouddrove/github-shared-workflows/.github/workflows/tf-checks.yml@master
+ with:
+ working_directory: 'examples/firewall-with-isolated-rules/'
+ firewall-with-public-ip-prefix-example:
+ uses: clouddrove/github-shared-workflows/.github/workflows/tf-checks.yml@master
+ with:
+ working_directory: 'examples/firewall-with-public-ip-prefix/'
# Seperate Job for TFlint workflow call
tf-lint:
uses: clouddrove/github-shared-workflows/.github/workflows/tf-lint.yml@master
diff --git a/README.md b/README.md
index 03015cf..9ee000a 100644
--- a/README.md
+++ b/README.md
@@ -22,7 +22,6 @@
-
["name","environment", "location"]| no | +| Name | Source | Version | +|------|--------|---------| +| [labels](#module\_labels) | terraform-az-modules/tags/azure | 1.0.0 | -### Outputs - -| Name | Description | -|------|-------------| -| label_order | Label order, e.g. `name`,`application`,`centralus`. | +## Resources +| Name | Type | +|------|------| +| [azurerm_firewall.firewall](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/firewall) | resource | +| [azurerm_firewall_policy.policy](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/firewall_policy) | resource | +| [azurerm_firewall_policy_rule_collection_group.app_policy_rule_collection_group](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/firewall_policy_rule_collection_group) | resource | +| [azurerm_firewall_policy_rule_collection_group.nat_policy_rule_collection_group](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/firewall_policy_rule_collection_group) | resource | +| [azurerm_firewall_policy_rule_collection_group.network_policy_rule_collection_group](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/firewall_policy_rule_collection_group) | resource | +| [azurerm_monitor_diagnostic_setting.firewall_diagnostic_setting](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/monitor_diagnostic_setting) | resource | +| [azurerm_public_ip.primary_public_ip](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/public_ip) | resource | +| [azurerm_public_ip.public_ip](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/public_ip) | resource | +| [azurerm_public_ip_prefix.pip-prefix](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/public_ip_prefix) | resource | +| [azurerm_user_assigned_identity.identity](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/user_assigned_identity) | resource | +## Inputs - +| Name | Description | +|------|-------------| +| [firewall\_id](#output\_firewall\_id) | Firewall ID | +| [firewall\_name](#output\_firewall\_name) | Firewall name | +| [firewall\_policy\_id](#output\_firewall\_policy\_id) | value of firewall policy ID | +| [primary\_public\_ip\_address](#output\_primary\_public\_ip\_address) | Primary public IP address (clean) | +| [primary\_public\_ip\_id](#output\_primary\_public\_ip\_id) | ID of the primary public IP (clean) | +| [primary\_public\_ip\_name](#output\_primary\_public\_ip\_name) | Name of the primary public IP (clean) | +| [public\_ip\_addresses](#output\_public\_ip\_addresses) | value of public IP addresses | +| [public\_ip\_ids](#output\_public\_ip\_ids) | The IDs of all public IPs | +| [public\_ip\_prefix\_id](#output\_public\_ip\_prefix\_id) | value of public IP prefix ID | ## Module Dependencies @@ -107,8 +177,6 @@ This module has dependencies on: Refer [here](CHANGELOG.md). - - ## β¨ Contributors Big thanks to our contributors for elevating our project with their dedication and expertise! But, we do not wish to stop there, would like to invite contributions from the community in improving these projects and making them more versatile for better reach. Remember, every bit of contribution is immensely valuable, as, together, we are moving in only 1 direction, i.e. forward. diff --git a/README.yaml b/README.yaml index e8b3a21..273a829 100644 --- a/README.yaml +++ b/README.yaml @@ -5,13 +5,13 @@ # # Name of this project -name : Terraform Azure Module Template +name: Terraform Azure Firewall Module # License of this project license: "APACHE" # Canonical GitHub repo -github_repo: terraform-az-modules/terraform-module-template +github_repo: terraform-az-modules/terraform-azure-firewall # Badges to display badges: @@ -37,13 +37,267 @@ providers: version: ">= 3.116.0" # description of this project +# description of this project description: |- - Terraform Azure Module Template to create new modules using this as baseline + The Terraform Azure Firewall Module is designed to simplify the deployment and management of Azure Firewall resources. + It provides a comprehensive solution for securing your Azure environment by enabling centralized network security policies, + traffic filtering, and threat protection. This module supports advanced features such as DDoS protection, + firewall policies, rule collections (application, network, and NAT), and diagnostic settings for monitoring and auditing. + + Key Features: + - Deploy Azure Firewall with customizable configurations. + - Manage public IPs and public IP prefixes for scalability. + - Define firewall policies with advanced security features like TLS inspection and IDPS. + - Configure application, network, and NAT rule collections for granular traffic control. + - Enable diagnostic settings for centralized monitoring and troubleshooting. + - Support for tagging to ensure traceability and cost management. + + Use this module to enhance the security posture of your Azure environment while maintaining flexibility and scalability. -# How to use this project # How to use this project usage: |- Here are some examples of how you can use this module in your inventory structure: ```hcl - locals {} - ``` \ No newline at end of file + ### Simple Example + Here is an example of how you can use this module in your inventory structure: + ### Default example + ```hcl + module "firewall" { + depends_on = [module.name_specific_subnet] + source = "clouddrove/firewall/azure" + name = "app" + environment = "test" + resource_group_name = module.resource_group.resource_group_name + location = module.resource_group.resource_group_location + subnet_id = module.name_specific_subnet.subnet_ids["AzureFirewallSubnet"] + public_ip_names = ["ingress", "vnet"] // Name of public ips you want to create. + + # additional_public_ips = [{ + # name = "public-ip_name", + # public_ip_address_id = "public-ip_resource_id" + # } ] + firewall_enable = true + policy_rule_enabled = true + enable_diagnostic = true + log_analytics_workspace_id = module.log-analytics.workspace_id + + application_rule_collection = [ + { + name = "example_app_policy" + priority = 200 + action = "Allow" + rules = [ + { + name = "app_test" + source_addresses = ["*"] // ["X.X.X.X"] + destination_fqdns = ["*"] // ["X.X.X.X"] + protocols = [ + { + port = "443" + type = "Https" + }, + { + port = "80" + type = "Http" + } + ] + } + ] + } + ] + + network_rule_collection = [ + { + name = "example_network_policy" + priority = "100" + action = "Allow" + rules = [ + { + name = "ssh" + protocols = ["TCP"] + source_addresses = ["*"] // ["X.X.X.X"] + destination_addresses = ["*"] // ["X.X.X.X"] + destination_ports = ["22"] + } + + ] + }, + { + name = "example_network_policy-2" + priority = "101" + action = "Allow" + rules = [ + { + name = "smtp" + protocols = ["TCP"] + source_addresses = ["*"] // ["X.X.X.X"] + destination_addresses = ["*"] // ["X.X.X.X"] + destination_ports = ["587"] + } + ] + } + ] + + nat_rule_collection = [ + { + name = "example_nat_policy-1" + priority = "101" + rules = [ + { + name = "http" + protocols = ["TCP"] + source_addresses = ["*"] // ["X.X.X.X"] + destination_ports = ["80"] + source_addresses = ["*"] + translated_port = "80" + translated_address = "X.X.X.X" #provide private ip address to translate + destination_address = module.firewall.public_ip_address //Public ip associated with firewall. + + }, + ] + }, + } + + ``` + ### firewall-with-isolated-rules + ```hcl + module "firewall" { + depends_on = [module.name_specific_subnet] + source = "clouddrove/firewall/azure" + name = "app" + environment = "test" + resource_group_name = module.resource_group.resource_group_name + location = module.resource_group.resource_group_location + subnet_id = module.name_specific_subnet.subnet_ids["AzureFirewallSubnet"] + public_ip_names = ["ingress", "vnet"] // Name of public ips you want to create. + + # additional_public_ips = [{ + # name = "public-ip_name", + # public_ip_address_id = "public-ip_resource_id" + # } ] + firewall_enable = true + enable_diagnostic = true + log_analytics_workspace_id = module.log-analytics.workspace_id + + } + module "firewall-rules" { + depends_on = [module.firewall] + source = "clouddrove/firewall/azure" + name = "app" + environment = "test" + policy_rule_enabled= true + firewall_policy_id = module.firewall.firewall_policy_id + + application_rule_collection = [ + { + name = "example_app_policy" + priority = 200 + action = "Allow" + rules = [ + { + name = "app_test" + source_addresses = ["*"] // ["X.X.X.X"] + destination_fqdns = ["*"] // ["X.X.X.X"] + protocols = [ + { + port = "443" + type = "Https" + }, + { + port = "80" + type = "Http" + } + ] + } + ] + } + ] + + network_rule_collection = [ + { + name = "example_network_policy" + priority = 100 + action = "Allow" + rules = [ + { + name = "ssh" + protocols = ["TCP"] + source_addresses = ["*"] // ["X.X.X.X"] + destination_addresses = ["*"] // ["X.X.X.X"] + destination_ports = ["22"] + } + + ] + }, + { + name = "example_network_policy-2" + priority = "101" + action = "Allow" + rules = [ + { + name = "smtp" + protocols = ["TCP"] + source_addresses = ["*"] // ["X.X.X.X"] + destination_addresses = ["*"] // ["X.X.X.X"] + destination_ports = ["587"] + } + ] + } + ] + + nat_rule_collection = [ + { + name = "example_nat_policy-1" + priority = "101" + rules = [ + { + name = "http" + protocols = ["TCP"] + source_addresses = ["*"] // ["X.X.X.X"] + destination_ports = ["80"] + source_addresses = ["*"] + translated_port = "80" + translated_address = "10.1.1.1" #provide private ip address to translate + destination_address = module.firewall.public_ip_address[1] //Public ip associated with firewall. + }, + { + name = "https" + protocols = ["TCP"] + destination_ports = ["443"] + source_addresses = ["*"] + translated_port = "443" + translated_address = "10.1.1.1" #provide private ip address to translate + destination_address = module.firewall.public_ip_address[1] //Public ip associated with firewall + + } + ] + }, + + { + name = "example-nat-policy-2" + priority = "100" + rules = [ + { + name = "http" + protocols = ["TCP"] + source_addresses = ["*"] // ["X.X.X.X"] + destination_ports = ["80"] + translated_port = "80" + translated_address = "10.1.1.2" #provide private ip address to translate + destination_address = module.firewall.public_ip_address[0] //Public ip associated with firewall + }, + { + name = "https" + protocols = ["TCP"] + source_addresses = ["*"] // ["X.X.X.X"] + destination_ports = ["443"] + translated_port = "443" + translated_address = "10.1.1.2" #provide private ip address to translate + destination_address = module.firewall.public_ip_address[0] //Public ip associated with firewall + } + ] + } + ] + } + + ``` diff --git a/examples/complete/README.md b/examples/complete/README.md index 6dced76..3947e9f 100644 --- a/examples/complete/README.md +++ b/examples/complete/README.md @@ -1,18 +1,17 @@ -# Terraform Azure Module Template +# Terraform Azure Application Insights -This directory contains an example usage of the **terraform-azure-module-template**. It demonstrates how to use the module with default settings or with custom configurations. +This directory contains an example usage of the **terraform-azure-firewall**. It demonstrates how to use the module with default settings or with custom configurations. --- ## π Requirements -| Name | Version | -|-----------|-----------| -| Terraform | >= 1.6.6 | -| Azurerm | >= 3.116.0| - +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.6.6 | +| [azurerm](#requirement\_azurerm) | >=3.116.0 | --- ## π Providers @@ -22,9 +21,13 @@ None specified in this example. --- ## π¦ Modules - -None specified in this example. - +| Name | Source | Version | +|------|--------|---------| +| [firewall](#module\_firewall) | ../.. | n/a | +| [log-analytics](#module\_log-analytics) | terraform-az-modules/log-analytics/azure | 1.0.0 | +| [name\_specific\_subnet](#module\_name\_specific\_subnet) | terraform-az-modules/subnet/azure | 1.0.0 | +| [resource\_group](#module\_resource\_group) | terraform-az-modules/resource-group/azure | 1.0.0 | +| [vnet](#module\_vnet) | terraform-az-modules/vnet/azure | 1.0.0 | --- ## ποΈ Resources @@ -41,6 +44,12 @@ No input variables are defined in this example. ## π€ Outputs -No outputs are defined in this example. +| Name | Description | +|------|-------------| +| [firewall\_id](#output\_firewall\_id) | Firewall generated id | +| [primary\_public\_ip\_address](#output\_primary\_public\_ip\_address) | The Primary public IP address associated with the firewall | +| [primary\_public\_ip\_id](#output\_primary\_public\_ip\_id) | The Primary public IP associated with the firewall | +| [public\_ip\_address](#output\_public\_ip\_address) | The public IP address associated with the firewall | +| [public\_ip\_id](#output\_public\_ip\_id) | The public IP associated with the firewall | diff --git a/examples/complete/example.tf b/examples/complete/example.tf index 773bdbd..f2756b3 100644 --- a/examples/complete/example.tf +++ b/examples/complete/example.tf @@ -2,6 +2,193 @@ provider "azurerm" { features {} } +locals { + name = "app" + environment = "test" + # Define public IPs as a local variable for reusability + public_ip_names = ["vnet", "app"] +} +##----------------------------------------------------------------------------- +## Resource Group module call +## Resource group in which all resources will be deployed. ##----------------------------------------------------------------------------- -## Resources +module "resource_group" { + source = "terraform-az-modules/resource-group/azure" + version = "1.0.0" + name = local.name + environment = local.environment + label_order = ["name", "environment", ] + location = "East US" +} + +##----------------------------------------------------------------------------- +## Virtual Network module call. +## Virtual Network in firewall specific subnet will be created. +##----------------------------------------------------------------------------- +module "vnet" { + depends_on = [module.resource_group] + source = "terraform-az-modules/vnet/azure" + version = "1.0.0" + name = local.name + environment = local.environment + resource_group_name = module.resource_group.resource_group_name + location = module.resource_group.resource_group_location + address_spaces = ["10.0.0.0/16"] +} + +##----------------------------------------------------------------------------- +## Subnet module call. +## Name specific subnet for firewall will be created. +##----------------------------------------------------------------------------- +module "name_specific_subnet" { + depends_on = [module.vnet] + source = "terraform-az-modules/subnet/azure" + version = "1.0.0" + environment = "test" + label_order = ["name", "environment", ] + resource_group_name = module.resource_group.resource_group_name + location = module.resource_group.resource_group_location + virtual_network_name = module.vnet.vnet_name + subnets = [ + { + name = "AzureFirewallSubnet" + subnet_prefixes = ["10.0.1.0/24"] + } + ] + enable_route_table = true + route_tables = [ + { + name = "route-table" + routes = [ + { + name = "route-table" + address_prefix = "0.0.0.0/0" + next_hop_type = "Internet" + } + ] + } + ] +} + +##----------------------------------------------------------------------------- +## Log Analytic Module Call. +## Log Analytic workspace for firerwall diagnostic setting. ##----------------------------------------------------------------------------- +module "log-analytics" { + source = "terraform-az-modules/log-analytics/azure" + version = "1.0.0" + name = local.name + environment = local.environment + label_order = ["name", "environment"] + log_analytics_workspace_sku = "PerGB2018" + resource_group_name = module.resource_group.resource_group_name + location = module.resource_group.resource_group_location +} + +##----------------------------------------------------------------------------- +## Firewall module call. +## All firewall related resources will be deployed from this module, i.e. including firewall and firewall rules. +##----------------------------------------------------------------------------- +module "firewall" { + depends_on = [module.name_specific_subnet] + source = "../.." + name = local.name + environment = local.environment + resource_group_name = module.resource_group.resource_group_name + location = module.resource_group.resource_group_location + subnet_id = module.name_specific_subnet.subnet_ids["AzureFirewallSubnet"] + public_ip_names = local.public_ip_names + firewall_enable = true + public_ip_prefix_enable = true + public_ip_prefix_length = 28 + policy_rule_enabled = true + enable_diagnostic = true + log_analytics_workspace_id = module.log-analytics.workspace_id + logs = [ + { + category = "AzureFirewallApplicationRule" + }, + { + category = "AzureFirewallNetworkRule" + }, + { + category = "AzureFirewallDnsProxy" + }, + ] + + application_rule_collection = [ + { + name = "example_app_policy" + priority = 200 + action = "Allow" + rules = [ + { + name = "app_test" + source_addresses = ["*"] // ["X.X.X.X"] + destination_fqdns = ["*"] // ["X.X.X.X"] + protocols = [ + { + port = "443" + type = "Https" + }, + { + port = "80" + type = "Http" + } + ] + } + ] + } + ] + + network_rule_collection = [ + { + name = "example_network_policy" + priority = 100 + action = "Allow" + rules = [ + { + name = "ssh" + protocols = ["TCP"] + source_addresses = ["*"] // ["X.X.X.X"] + destination_addresses = ["*"] // ["X.X.X.X"] + destination_ports = ["22"] + } + + ] + }, + { + name = "example_network_policy-2" + priority = "101" + action = "Allow" + rules = [ + { + name = "smtp" + protocols = ["TCP"] + source_addresses = ["*"] // ["X.X.X.X"] + destination_addresses = ["*"] // ["X.X.X.X"] + destination_ports = ["587"] + } + ] + } + ] + + nat_rule_collection = [ + { + name = "web_server_nat_policy" + priority = 100 + description = "Redirects external traffic to internal web server" + rules = [ + { + name = "web_server_nat" + protocols = ["TCP"] + source_addresses = ["*"] # Any source + destination_address = module.firewall.public_ip_addresses["vnet"] # Your firewall's PUBLIC IP + destination_ports = ["8080"] # External port + translated_address = "10.0.1.20" # Internal server IP + translated_port = "80" # Internal port + } + ] + } + ] +} diff --git a/examples/complete/outputs.tf b/examples/complete/outputs.tf index 35553e0..ae82a4a 100644 --- a/examples/complete/outputs.tf +++ b/examples/complete/outputs.tf @@ -1,3 +1,13 @@ -##----------------------------------------------------------------------------- -## Outputs -##----------------------------------------------------------------------------- +output "firewall_id" { + description = "Firewall generated id" + value = module.firewall.firewall_id +} +output "public_ip_id" { + value = module.firewall.public_ip_ids + description = "The public IP associated with the firewall" +} + +output "public_ip_address" { + value = module.firewall.public_ip_addresses + description = "The public IP address associated with the firewall" +} diff --git a/examples/complete/variables.tf b/examples/complete/variables.tf deleted file mode 100644 index d5a4b06..0000000 --- a/examples/complete/variables.tf +++ /dev/null @@ -1,3 +0,0 @@ -##----------------------------------------------------------------------------- -## Variables -##----------------------------------------------------------------------------- diff --git a/examples/complete/versions.tf b/examples/complete/version.tf similarity index 100% rename from examples/complete/versions.tf rename to examples/complete/version.tf diff --git a/examples/firewall-with-isolated-rules/README.md b/examples/firewall-with-isolated-rules/README.md new file mode 100644 index 0000000..612f271 --- /dev/null +++ b/examples/firewall-with-isolated-rules/README.md @@ -0,0 +1,60 @@ + + +# Terraform Azure Application Insights + +This directory contains an example usage of the **terraform-azure-firewall**. It demonstrates how to use the module with default settings or with custom configurations. + +--- + +## π Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.6.6 | +| [azurerm](#requirement\_azurerm) | >=3.116.0 | + +--- + +## π Providers + +None specified in this example. + +--- + +## π¦ Modules + +| Name | Source | Version | +|------|--------|---------| +| [firewall](#module\_firewall) | ../.. | n/a | +| [firewall-rules](#module\_firewall-rules) | ../.. | n/a | +| [log-analytics](#module\_log-analytics) | terraform-az-modules/log-analytics/azure | 1.0.0 | +| [name\_specific\_subnet](#module\_name\_specific\_subnet) | terraform-az-modules/subnet/azure | 1.0.0 | +| [resource\_group](#module\_resource\_group) | terraform-az-modules/resource-group/azure | 1.0.0 | +| [vnet](#module\_vnet) | terraform-az-modules/vnet/azure | 1.0.0 | + +--- + +## ποΈ Resources + +No resources are directly created in this example. + +--- + +## π§ Inputs + +No input variables are defined in this example. + +--- + +## π€ Outputs + +| Name | Description | +|------|-------------| +| [firewall\_id](#output\_firewall\_id) | Firewall generated id | +| [firewall\_name](#output\_firewall\_name) | The name of the Firewall | +| [public\_ip\_address](#output\_public\_ip\_address) | value of public IP Addresses | +| [public\_ip\_id](#output\_public\_ip\_id) | value of public IP IDs | + + + + diff --git a/examples/firewall-with-isolated-rules/example.tf b/examples/firewall-with-isolated-rules/example.tf new file mode 100644 index 0000000..9f01c66 --- /dev/null +++ b/examples/firewall-with-isolated-rules/example.tf @@ -0,0 +1,196 @@ +provider "azurerm" { + features {} +} + +locals { + name = "app" + environment = "test" +} + +##----------------------------------------------------------------------------- +## Resource Group module call +## Resource group in which all resources will be deployed. +##----------------------------------------------------------------------------- +module "resource_group" { + source = "../../../terraform-azure-resource-group" #"terraform-az-modules/resource-group/azure" + # version = "1.0.1" + name = local.name + environment = local.environment + label_order = ["name", "environment"] + location = "East US" +} + +##----------------------------------------------------------------------------- +## Virtual Network module call. +## Virtual Network in firewall specific subnet will be created. +##----------------------------------------------------------------------------- +module "vnet" { + depends_on = [module.resource_group] + source = "../../../terraform-azure-vnet" #"terraform-az-modules/vnet/azure" + #version = "1.0.0" + name = local.name + environment = local.environment + resource_group_name = module.resource_group.resource_group_name + location = module.resource_group.resource_group_location + address_spaces = ["10.0.0.0/16"] +} + +##----------------------------------------------------------------------------- +## Subnet module call. +## Name specific subnet for firewall will be created. +##----------------------------------------------------------------------------- +module "name_specific_subnet" { + depends_on = [module.vnet] + source = "../../../terraform-azure-subnet" #"terraform-az-modules/subnet/azure" + #version = "1.0.0" + environment = "test" + label_order = ["name", "environment", ] + resource_group_name = module.resource_group.resource_group_name + location = module.resource_group.resource_group_location + virtual_network_name = module.vnet.vnet_name + subnets = [ + { + name = "AzureFirewallSubnet" + subnet_prefixes = ["10.0.1.0/24"] + } + ] + enable_route_table = true + route_tables = [ + { + name = "route-table" + routes = [ + { + name = "route-table" + address_prefix = "0.0.0.0/0" + next_hop_type = "Internet" + } + ] + } + ] +} + +##----------------------------------------------------------------------------- +## Log Analytic Module Call. +## Log Analytic workspace for firerwall diagnostic setting. +##----------------------------------------------------------------------------- +module "log-analytics" { + source = "../../../terraform-azure-log-analytics" #"terraform-az-modules/log-analytics/azure" + #version = "1.0.0" + name = local.name + environment = local.environment + label_order = ["name", "environment", "location"] + log_analytics_workspace_sku = "PerGB2018" + resource_group_name = module.resource_group.resource_group_name + location = module.resource_group.resource_group_location + +} + + +##----------------------------------------------------------------------------- +## Firewall module call. +## From this module call firewall rules will not be deployed and thus no rule collection group will be created. +##----------------------------------------------------------------------------- +module "firewall" { + depends_on = [module.name_specific_subnet] + source = "../.." + name = local.name + environment = local.environment + resource_group_name = module.resource_group.resource_group_name + location = module.resource_group.resource_group_location + subnet_id = module.name_specific_subnet.subnet_ids["AzureFirewallSubnet"] + public_ip_names = ["ingress", "vnet"] // Name of public ips you want to create. + firewall_enable = true + enable_diagnostic = true + log_analytics_workspace_id = module.log-analytics.workspace_id + logs = [{ + category = "AzureFirewallApplicationRule" + }, + ] + +} + +##----------------------------------------------------------------------------- +## Firewall-Rules module call. +## This is same module as 'firewall module', but from this module only firewall rules and rule collection group will be deployed. +##----------------------------------------------------------------------------- +module "firewall-rules" { + depends_on = [module.firewall] + source = "../.." + name = local.name + environment = local.environment + policy_rule_enabled = true + firewall_policy_id = module.firewall.firewall_policy_id + application_rule_collection = [ + { + name = "example_app_policy" + priority = 200 + action = "Allow" + rules = [ + { + name = "app_test" + source_addresses = ["*"] // ["X.X.X.X"] + destination_fqdns = ["*"] // ["X.X.X.X"] + protocols = [ + { + port = "443" + type = "Https" + }, + { + port = "80" + type = "Http" + } + ] + } + ] + } + ] + network_rule_collection = [ + { + name = "example_network_policy" + priority = "100" + action = "Allow" + rules = [ + { + name = "ssh" + protocols = ["TCP"] + source_addresses = ["*"] // ["X.X.X.X"] + destination_addresses = ["*"] // ["X.X.X.X"] + destination_ports = ["22"] + } + + ] + }, + { + name = "example_network_policy-2" + priority = "101" + action = "Allow" + rules = [ + { + name = "smtp" + protocols = ["TCP"] + source_addresses = ["*"] // ["X.X.X.X"] + destination_addresses = ["*"] // ["X.X.X.X"] + destination_ports = ["587"] + } + ] + } + ] + + nat_rule_collection = [ + { + name = "example_nat_policy-1" + priority = "101" + rules = [ + { + name = "nat_rule_collection1_rule1" + protocols = ["TCP", "UDP"] + source_addresses = ["10.0.0.1", "10.0.0.2"] + destination_address = module.firewall.public_ip_addresses["vnet"] + destination_ports = ["80"] + translated_address = "192.168.0.1" + translated_port = "8080" + }, + ] + }, + ] +} diff --git a/examples/firewall-with-isolated-rules/outputs.tf b/examples/firewall-with-isolated-rules/outputs.tf new file mode 100644 index 0000000..9d05239 --- /dev/null +++ b/examples/firewall-with-isolated-rules/outputs.tf @@ -0,0 +1,20 @@ +output "firewall_id" { + description = "Firewall generated id" + value = module.firewall.firewall_id +} + +output "firewall_name" { + value = module.firewall.firewall_name + description = "The name of the Firewall" + +} + +output "public_ip_id" { + value = module.firewall.public_ip_ids + description = "value of public IP IDs" +} + +output "public_ip_address" { + value = module.firewall.public_ip_addresses + description = "value of public IP Addresses" +} diff --git a/examples/firewall-with-isolated-rules/version.tf b/examples/firewall-with-isolated-rules/version.tf new file mode 100644 index 0000000..e56b7ac --- /dev/null +++ b/examples/firewall-with-isolated-rules/version.tf @@ -0,0 +1,16 @@ +##----------------------------------------------------------------------------- +## Versions +##----------------------------------------------------------------------------- +# Terraform version +terraform { + required_version = ">= 1.6.6" +} + +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = ">=3.116.0" + } + } +} \ No newline at end of file diff --git a/examples/firewall-with-public-ip-prefix/README.md b/examples/firewall-with-public-ip-prefix/README.md new file mode 100644 index 0000000..69876be --- /dev/null +++ b/examples/firewall-with-public-ip-prefix/README.md @@ -0,0 +1,57 @@ + + +# Terraform Azure Application Insights + +This directory contains an example usage of the **terraform-azure-firewall**. It demonstrates how to use the module with default settings or with custom configurations. + +--- + +## π Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.6.6 | +| [azurerm](#requirement\_azurerm) | >=3.116.0 | + +--- + +## π Providers + +None specified in this example. + +--- + +## π¦ Modules + +| Name | Source | Version | +|------|--------|---------| +| [firewall](#module\_firewall) | ../.. | n/a | +| [log-analytics](#module\_log-analytics) | terraform-az-modules/log-analytics/azure | 1.0.0 | +| [name\_specific\_subnet](#module\_name\_specific\_subnet) | terraform-az-modules/subnet/azure | 1.0.0 | +| [resource\_group](#module\_resource\_group) | terraform-az-modules/resource-group/azure | 1.0.0 | +| [vnet](#module\_vnet) | terraform-az-modules/vnet/azure | 1.0.0 | + +--- + +## ποΈ Resources + +No resources are directly created in this example. + +--- + +## π§ Inputs + +No input variables are defined in this example. + +--- + +## π€ Outputs + +| Name | Description | +|------|-------------| +| [firewall\_id](#output\_firewall\_id) | Firewall generated id | +| [firewall\_name](#output\_firewall\_name) | The name of the Firewall | +| [public\_ip\_address](#output\_public\_ip\_address) | value of public IP Addresses | +| [public\_ip\_id](#output\_public\_ip\_id) | value of public IP IDs | + + diff --git a/examples/firewall-with-public-ip-prefix/example.tf b/examples/firewall-with-public-ip-prefix/example.tf new file mode 100644 index 0000000..3448e69 --- /dev/null +++ b/examples/firewall-with-public-ip-prefix/example.tf @@ -0,0 +1,182 @@ +provider "azurerm" { + features {} +} + +locals { + name = "app2-firewall" + environment = "test" +} + +##----------------------------------------------------------------------------- +## Resource Group module call +## Resource group in which all resources will be deployed. +##----------------------------------------------------------------------------- +module "resource_group" { + source = "terraform-az-modules/resource-group/azure" + version = "1.0.0" + name = local.name + environment = local.environment + label_order = ["name", "environment", ] + location = "East US" +} + +##----------------------------------------------------------------------------- +## Virtual Network module call. +## Virtual Network in firewall specific subnet will be created. +##----------------------------------------------------------------------------- +module "vnet" { + depends_on = [module.resource_group] + source = "terraform-azure-vnet" #"terraform-az-modules/vnet/azure" + version = "1.0.0" + name = local.name + environment = local.environment + resource_group_name = module.resource_group.resource_group_name + location = module.resource_group.resource_group_location + address_spaces = ["10.0.0.0/16"] +} + +##----------------------------------------------------------------------------- +## Subnet module call. +## Name specific subnet for firewall will be created. +##----------------------------------------------------------------------------- +module "name_specific_subnet" { + depends_on = [module.vnet] + source = "terraform-az-modules/subnet/azure" + version = "1.0.0" + environment = "test" + label_order = ["name", "environment", "location"] + resource_group_name = module.resource_group.resource_group_name + location = module.resource_group.resource_group_location + virtual_network_name = module.vnet.vnet_name + subnets = [ + { + name = "AzureFirewallSubnet" + subnet_prefixes = ["10.0.1.0/24"] + } + ] + enable_route_table = true + route_tables = [ + { + name = "route-table" + routes = [ + { + name = "route-table" + address_prefix = "0.0.0.0/0" + next_hop_type = "Internet" + } + ] + } + ] +} + +##----------------------------------------------------------------------------- +## Log Analytic Module Call. +## Log Analytic workspace for firerwall diagnostic setting. +##----------------------------------------------------------------------------- +module "log-analytics" { + source = "terraform-az-modules/log-analytics/azure" + version = "1.0.0" + name = local.name + environment = local.environment + label_order = ["name", "environment", "location"] + log_analytics_workspace_sku = "PerGB2018" + resource_group_name = module.resource_group.resource_group_name + location = module.resource_group.resource_group_location +} + + + +##----------------------------------------------------------------------------- +## Firewall module call. +## All firewall related resources will be deployed from this module, i.e. including firewall and firewall rules. +##----------------------------------------------------------------------------- +module "firewall" { + depends_on = [module.name_specific_subnet] + source = "../.." + name = local.name + environment = local.environment + resource_group_name = module.resource_group.resource_group_name + location = module.resource_group.resource_group_location + subnet_id = module.name_specific_subnet.subnet_ids["AzureFirewallSubnet"] + firewall_enable = true + policy_rule_enabled = true + public_ip_names = ["ingress", "vnet", "app", "app-2"] + enable_diagnostic = true + eventhub_name = local.name + public_ip_prefix_enable = true + log_analytics_workspace_id = module.log-analytics.workspace_id + + application_rule_collection = [ + { + name = "example_app_policy" + priority = 200 + action = "Allow" + rules = [ + { + name = "app_test" + source_addresses = ["*"] // ["X.X.X.X"] + destination_fqdns = ["*"] // ["X.X.X.X"] + protocols = [ + { + port = "443" + type = "Https" + }, + { + port = "80" + type = "Http" + } + ] + } + ] + } + ] + network_rule_collection = [ + { + name = "example_network_policy" + priority = "100" + action = "Allow" + rules = [ + { + name = "ssh" + protocols = ["TCP"] + source_addresses = ["*"] // ["X.X.X.X"] + destination_addresses = ["*"] // ["X.X.X.X"] + destination_ports = ["22"] + } + + ] + }, + { + name = "example_network_policy-2" + priority = "101" + action = "Allow" + rules = [ + { + name = "smtp" + protocols = ["TCP"] + source_addresses = ["*"] // ["X.X.X.X"] + destination_addresses = ["*"] // ["X.X.X.X"] + destination_ports = ["587"] + } + ] + } + ] + + nat_rule_collection = [ + { + name = "example_nat_policy-1" + priority = "101" + rules = [ + { + name = "nat_rule_collection1_rule1" + protocols = ["TCP", "UDP"] + source_addresses = ["10.0.0.1", "10.0.0.2"] + destination_ports = ["80"] + destination_address = module.firewall.public_ip_addresses["vnet"] + translated_address = "192.168.0.1" + translated_port = "8080" + }, + ] + }, + ] +} diff --git a/examples/firewall-with-public-ip-prefix/outputs.tf b/examples/firewall-with-public-ip-prefix/outputs.tf new file mode 100644 index 0000000..7d3d57f --- /dev/null +++ b/examples/firewall-with-public-ip-prefix/outputs.tf @@ -0,0 +1,23 @@ +output "firewall_id" { + description = "Firewall generated id" + value = module.firewall.firewall_id + +} + +output "firewall_name" { + value = module.firewall.firewall_name + description = "The name of the Firewall" + + +} + +output "public_ip_id" { + value = module.firewall.public_ip_ids + description = "value of public IP IDs" +} + +output "public_ip_address" { + value = module.firewall.public_ip_addresses + description = "value of public IP Addresses" +} + diff --git a/examples/firewall-with-public-ip-prefix/version.tf b/examples/firewall-with-public-ip-prefix/version.tf new file mode 100644 index 0000000..e56b7ac --- /dev/null +++ b/examples/firewall-with-public-ip-prefix/version.tf @@ -0,0 +1,16 @@ +##----------------------------------------------------------------------------- +## Versions +##----------------------------------------------------------------------------- +# Terraform version +terraform { + required_version = ">= 1.6.6" +} + +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = ">=3.116.0" + } + } +} \ No newline at end of file diff --git a/locals.tf b/locals.tf index 691b39e..699a012 100644 --- a/locals.tf +++ b/locals.tf @@ -1,6 +1,7 @@ + ##----------------------------------------------------------------------------- -## Locals +## Locals declaration for determining the local variables ##----------------------------------------------------------------------------- locals { - label_order = var.label_order -} \ No newline at end of file + name = var.custom_name != null ? var.custom_name : module.labels.id +} diff --git a/main.tf b/main.tf index 22e570c..1a58273 100644 --- a/main.tf +++ b/main.tf @@ -1,3 +1,234 @@ ##----------------------------------------------------------------------------- -## Resources +# Standard Tagging Module β Applies standard tags to all resources for traceability ##----------------------------------------------------------------------------- +module "labels" { + source = "terraform-az-modules/labels/azure" + version = "1.0.0" + name = var.custom_name == null ? var.name : var.custom_name + location = var.location + environment = var.environment + managedby = var.managedby + label_order = var.label_order + repository = var.repository + deployment_mode = var.deployment_mode + extra_tags = var.extra_tags +} + +##----------------------------------------------------------------------------- +# Firewall Public IP Prefix β optional +##----------------------------------------------------------------------------- +resource "azurerm_public_ip_prefix" "pip_prefix" { + count = var.enabled && var.firewall_enable && var.public_ip_prefix_enable ? 1 : 0 + name = format(var.resource_position_prefix ? "public-ip-prefix-%s" : "%s-public-ip-prefix", local.name) + location = var.location + resource_group_name = var.resource_group_name + sku = var.public_ip_prefix_sku + ip_version = var.public_ip_prefix_ip_version + prefix_length = var.public_ip_prefix_length + tags = module.labels.tags +} + +##----------------------------------------------------------------------------- +# Public IPs β one resource, creates all PIPs +##----------------------------------------------------------------------------- +resource "azurerm_public_ip" "public_ip" { + for_each = toset(var.public_ip_names) + name = var.public_ip_prefix_enable ? format(var.resource_position_prefix ? "pip-%s-%s" : "%s-%s-pip", local.name, each.value) : format(var.resource_position_prefix ? "ip-%s-%s" : "%s-%s-ip", local.name, each.value) + location = var.location + resource_group_name = var.resource_group_name + allocation_method = var.public_ip_allocation_method + sku = var.public_ip_sku + public_ip_prefix_id = var.public_ip_prefix_enable ? azurerm_public_ip_prefix.pip_prefix[0].id : null + ddos_protection_mode = "VirtualNetworkInherited" + tags = module.labels.tags + + lifecycle { + create_before_destroy = true + } +} + +##----------------------------------------------------------------------------- +# Azure Firewall +##----------------------------------------------------------------------------- +resource "azurerm_firewall" "firewall" { + depends_on = [azurerm_public_ip.public_ip, azurerm_public_ip_prefix.pip_prefix] + count = var.enabled && var.firewall_enable ? 1 : 0 + name = format(var.resource_position_prefix ? "firewall-%s" : "%s-firewall", local.name) + location = var.location + resource_group_name = var.resource_group_name + threat_intel_mode = var.threat_intel_mode + sku_tier = var.sku_tier + sku_name = var.sku_name + firewall_policy_id = join("", azurerm_firewall_policy.policy.*.id) + tags = module.labels.tags + private_ip_ranges = var.firewall_private_ip_ranges + dns_servers = var.dns_servers + + # Primary ip_configuration (first in the list) + ip_configuration { + name = format(var.resource_position_prefix ? "ipconfig-%s-%s" : "%s-%s-ipconfig", local.name, var.public_ip_names[0]) + subnet_id = var.subnet_id + public_ip_address_id = azurerm_public_ip.public_ip[var.public_ip_names[0]].id + } + + # Additional ip_configurations (skip first one) + dynamic "ip_configuration" { + for_each = length(var.public_ip_names) > 1 ? toset(slice(var.public_ip_names, 1, length(var.public_ip_names))) : [] + content { + name = format(var.resource_position_prefix ? "ipconfig-%s-%s" : "%s-%s-ipconfig", local.name, ip_configuration.value) + public_ip_address_id = azurerm_public_ip.public_ip[ip_configuration.value].id + # subnet_id omitted here! + } + } + + lifecycle { + ignore_changes = [tags] + } +} + +##----------------------------------------------------------------------------- +# Firewall Policy +##----------------------------------------------------------------------------- +resource "azurerm_firewall_policy" "policy" { + count = var.enabled && var.firewall_enable ? 1 : 0 + name = format(var.resource_position_prefix ? "firewall-policy-%s" : "%s-firewall-policy", local.name) + resource_group_name = var.resource_group_name + location = var.location + sku = var.sku_policy + + dynamic "identity" { + for_each = var.identity_type != null && var.sku_policy == "Premium" && var.sku_tier == "Premium" ? [1] : [] + content { + type = var.identity_type + identity_ids = var.identity_type == "UserAssigned" ? [join("", azurerm_user_assigned_identity.identity.*.id)] : null + } + } +} + +##----------------------------------------------------------------------------- +# Firewall Policy Rule Collection Groups +##----------------------------------------------------------------------------- +resource "azurerm_firewall_policy_rule_collection_group" "app_policy" { + depends_on = [azurerm_firewall_policy.policy] + count = var.enabled && var.policy_rule_enabled ? 1 : 0 + name = var.app_policy_collection_group + firewall_policy_id = var.firewall_policy_id == null ? join("", azurerm_firewall_policy.policy.*.id) : var.firewall_policy_id + priority = 300 + + dynamic "application_rule_collection" { + for_each = var.application_rule_collection + content { + name = application_rule_collection.value.name + priority = application_rule_collection.value.priority + action = application_rule_collection.value.action + + dynamic "rule" { + for_each = application_rule_collection.value.rules + content { + name = lookup(rule.value, "name", null) + source_addresses = lookup(rule.value, "source_addresses", null) + source_ip_groups = lookup(rule.value, "source_ip_groups", null) + destination_fqdns = lookup(rule.value, "destination_fqdns", null) + + dynamic "protocols" { + for_each = rule.value.protocols + content { + port = lookup(protocols.value, "port", null) + type = lookup(protocols.value, "type", null) + } + } + } + } + } + } +} + +resource "azurerm_firewall_policy_rule_collection_group" "network_policy" { + depends_on = [azurerm_firewall_policy.policy] + count = var.enabled && var.policy_rule_enabled ? 1 : 0 + name = var.net_policy_collection_group + firewall_policy_id = var.firewall_policy_id == null ? join("", azurerm_firewall_policy.policy.*.id) : var.firewall_policy_id + priority = 200 + + dynamic "network_rule_collection" { + for_each = var.network_rule_collection + content { + name = network_rule_collection.value.name + priority = network_rule_collection.value.priority + action = network_rule_collection.value.action + + dynamic "rule" { + for_each = network_rule_collection.value.rules + content { + name = rule.value.name + protocols = rule.value.protocols + destination_ports = rule.value.destination_ports + source_addresses = lookup(rule.value, "source_addresses", null) + source_ip_groups = lookup(rule.value, "source_ip_groups", null) + destination_addresses = lookup(rule.value, "destination_addresses", null) + destination_ip_groups = lookup(rule.value, "destination_ip_groups", null) + destination_fqdns = lookup(rule.value, "destination_fqdns", null) + } + } + } + } +} + +resource "azurerm_firewall_policy_rule_collection_group" "nat_policy" { + depends_on = [azurerm_firewall_policy.policy] + count = var.enabled && var.policy_rule_enabled ? 1 : 0 + name = var.nat_policy_collection_group + firewall_policy_id = var.firewall_policy_id == null ? join("", azurerm_firewall_policy.policy.*.id) : var.firewall_policy_id + priority = 100 + + dynamic "nat_rule_collection" { + for_each = var.nat_rule_collection + content { + name = nat_rule_collection.value.name + priority = nat_rule_collection.value.priority + action = "Dnat" + + dynamic "rule" { + for_each = nat_rule_collection.value.rules + content { + name = rule.value.name + protocols = rule.value.protocols + destination_ports = rule.value.destination_ports + source_addresses = lookup(rule.value, "source_addresses", null) + destination_address = lookup(rule.value, "destination_address", null) + translated_address = lookup(rule.value, "translated_address", null) + translated_port = lookup(rule.value, "translated_port", null) + } + } + } + } +} + +##----------------------------------------------------------------------------- +# Diagnostics +##----------------------------------------------------------------------------- +resource "azurerm_monitor_diagnostic_setting" "firewall_diagnostic" { + count = var.enabled && var.enable_diagnostic && var.firewall_enable ? 1 : 0 + name = format(var.resource_position_prefix ? "firewall-diagnostic-%s" : "%s-firewall-diagnostic", local.name) + target_resource_id = azurerm_firewall.firewall[0].id + storage_account_id = var.storage_account_id + eventhub_name = var.eventhub_name + eventhub_authorization_rule_id = var.eventhub_authorization_rule_id + log_analytics_workspace_id = var.log_analytics_workspace_id + log_analytics_destination_type = var.log_analytics_destination_type + + dynamic "enabled_metric" { + for_each = var.metric_enabled ? ["AllMetrics"] : [] + content { + category = enabled_metric.value + } + } + + dynamic "enabled_log" { + for_each = var.logs + content { + category_group = lookup(enabled_log.value, "category_group", null) + category = lookup(enabled_log.value, "category", null) + } + } +} diff --git a/outputs.tf b/outputs.tf index e0af9ca..6537015 100644 --- a/outputs.tf +++ b/outputs.tf @@ -1,7 +1,30 @@ -##----------------------------------------------------------------------------- -## Outputs -##----------------------------------------------------------------------------- -output "label_order" { - value = local.label_order - description = "Label order." -} \ No newline at end of file +output "firewall_id" { + description = "Firewall ID" + value = join("", azurerm_firewall.firewall.*.id) +} + +output "firewall_name" { + value = join("", azurerm_firewall.firewall.*.name) + description = "Firewall name" +} + +output "public_ip_ids" { + description = "The IDs of all public IPs" + value = { for k, v in azurerm_public_ip.public_ip : k => v.id } +} + +output "public_ip_addresses" { + description = "value of public IP addresses" + value = { for k, v in azurerm_public_ip.public_ip : k => v.ip_address } +} + +output "firewall_policy_id" { + description = "value of firewall policy ID" + value = join("", azurerm_firewall_policy.policy.*.id) +} + +output "public_ip_prefix_id" { + description = "value of public IP prefix ID" + value = join("", azurerm_public_ip_prefix.pip_prefix.*.id) +} + diff --git a/permissions.tf b/permissions.tf index 0220f63..3bc2652 100644 --- a/permissions.tf +++ b/permissions.tf @@ -1,3 +1,10 @@ -##----------------------------------------------------------------------------- -## Permissions, Roles, and Policies -##----------------------------------------------------------------------------- \ No newline at end of file + +##------------------------------------------------------------------------------------ +# User Assigned Identity β Creates a user assigned identity for Azure Firewall Policy +##------------------------------------------------------------------------------------ +resource "azurerm_user_assigned_identity" "identity" { + count = var.enabled && var.firewall_enable ? 1 : 0 + location = var.location + name = format(var.resource_position_prefix ? "fw-policy-mid-%s" : "%s-fw-policy-mid", local.name) + resource_group_name = var.resource_group_name +} diff --git a/variables.tf b/variables.tf index 5e40885..c76a7bc 100644 --- a/variables.tf +++ b/variables.tf @@ -1,8 +1,376 @@ ##----------------------------------------------------------------------------- -## Variables +## Naming convention ##----------------------------------------------------------------------------- +variable "custom_name" { + type = string + default = null + description = "Override default naming convention" +} + +variable "resource_position_prefix" { + type = bool + default = true + description = <