Terraform module to create firewall resource on AZURE.
We eat, drink, sleep and most importantly love DevOps. We are working towards strategies for standardizing architecture while ensuring security for the infrastructure. We are strong believer of the philosophy Bigger problems are always solved by breaking them into smaller manageable problems. Resonating with microservices architecture, it is considered best-practice to run database, cluster, storage in smaller connected yet manageable pieces within the infrastructure.
This module is basically combination of Terraform open source and includes automatation tests and examples. It also helps to create and improve your infrastructure with minimalistic code instead of maintaining the whole infrastructure code yourself.
We have fifty plus terraform modules. A few of them are comepleted and are available for open source usage while a few others are in progress.
This module has a few dependencies:
IMPORTANT: Since the master
branch used in source
varies based on new modifications, we suggest that you use the release versions here.
Here is an example of how you can use this module in your inventory structure:
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.specific_subnet_id[0]
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[1] //Public ip associated with firewall. Here index 1 indicates 'vnet ip' (from public_ip_names = ["ingress" , "vnet"])
},
{
name = "https"
protocols = ["TCP"]
destination_ports = ["443"]
source_addresses = ["*"]
translated_port = "443"
translated_address = "X.X.X.X" #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 = "X.X.X.X" #provide private ip address to translate
destination_address = module.firewall.public_ip_address[0] //Public ip associated with firewall.Here index 0 indicates 'ingress ip' (from public_ip_names = ["ingress" , "vnet"])
},
{
name = "https"
protocols = ["TCP"]
source_addresses = ["*"] // ["X.X.X.X"]
destination_ports = ["443"]
translated_port = "443"
translated_address = "X.X.X.X" #provide private ip address to translate
destination_address = module.firewall.public_ip_address[0] //Public ip associated with firewall
}
]
}
]
}
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.specific_subnet_id[0]
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. Here index 1 indicates 'vnet ip' (from public_ip_names = ["ingress" , "vnet"])
},
{
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.Here index 0 indicates 'ingress ip' (from public_ip_names = ["ingress" , "vnet"])
},
{
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
}
]
}
]
}
Name | Description | Type | Default | Required |
---|---|---|---|---|
additional_public_ips | List of additional public ips' ids to attach to the firewall. | list(object({ |
[] |
no |
app_policy_collection_group | (optional) Name of app policy group | string |
"DefaultApplicationRuleCollectionGroup" |
no |
application_rule_collection | One or more application_rule_collection blocks as defined below.. | map |
{} |
no |
days | Number of days to create retension policies for te diagnosys setting. | number |
365 |
no |
dnat-destination_ip | Variable to specify that you have destination ip to attach to policy or not.(Destination ip is public ip that is attached to firewall) | bool |
true |
no |
dns_servers | DNS Servers to use with Azure Firewall. Using this also activate DNS Proxy. | list(string) |
null |
no |
enable_diagnostic | Set to false to prevent the module from creating the diagnosys setting for the NSG Resource.. | bool |
false |
no |
enable_ip_subnet | Should subnet id be attached to first public ip name specified in public ip names variable. To be true when there is no individual public ip. | bool |
true |
no |
enable_prefix_subnet | Should subnet id be attached to first public ip name specified in public ip prefix name varible. To be true when there is no individual public ip. | bool |
false |
no |
enabled | Set to false to prevent the module from creating any resources. | bool |
true |
no |
environment | Environment (e.g. prod , dev , staging ). |
string |
"" |
no |
eventhub_authorization_rule_id | Eventhub authorization rule id to pass it to destination details of diagnosys setting of NSG. | string |
null |
no |
eventhub_name | Eventhub Name to pass it to destination details of diagnosys setting of NSG. | string |
null |
no |
firewall_enable | n/a | bool |
false |
no |
firewall_policy_id | The ID of the Firewall Policy. | string |
null |
no |
firewall_private_ip_ranges | A list of SNAT private CIDR IP ranges, or the special string IANAPrivateRanges , which indicates Azure Firewall does not SNAT when the destination IP address is a private range per IANA RFC 1918. |
list(string) |
null |
no |
identity_type | Specifies the type of Managed Service Identity that should be configured on this Storage Account. Possible values are SystemAssigned , UserAssigned , SystemAssigned, UserAssigned (to enable both). |
string |
"UserAssigned" |
no |
label_order | Label order, e.g. sequence of application name and environment name ,environment ,'attribute' [webserver ,qa ,devops ,public ,] . |
list(any) |
[ |
no |
location | The location/region where the virtual network is created. Changing this forces a new resource to be created. | string |
"" |
no |
log_analytics_workspace_id | log analytics workspace id to pass it to destination details of diagnosys setting of NSG. | string |
null |
no |
managedby | ManagedBy, eg ''. | string |
"" |
no |
name | Name (e.g. app or cluster ). |
string |
"" |
no |
nat_policy_collection_group | (optional) Name of nat policy group | string |
"DefaultDnatRuleCollectionGroup" |
no |
nat_rule_collection | One or more nat_rule_collection blocks as defined below. | map |
{} |
no |
net_policy_collection_group | (optional) Name of network policy group | string |
"DefaultNetworkRuleCollectionGroup" |
no |
network_rule_collection | One or more network_rule_collection blocks as defined below. | map |
{} |
no |
policy_rule_enabled | Flag used to control creation of policy rules. | bool |
false |
no |
prefix_public_ip_allocation_method | n/a | string |
"Static" |
no |
prefix_public_ip_names | Name of prefix public ips. | list(string) |
[] |
no |
prefix_public_ip_sku | n/a | string |
"Standard" |
no |
public_ip_allocation_method | Defines the allocation method for this IP address. Possible values are Static or Dynamic | string |
"Static" |
no |
public_ip_names | n/a | list(string) |
[] |
no |
public_ip_prefix_enable | Flag to control creation of public ip prefix resource. | bool |
false |
no |
public_ip_prefix_ip_version | The IP Version to use, IPv6 or IPv4. Changing this forces a new resource to be created. Default is IPv4 | string |
"IPv4" |
no |
public_ip_prefix_length | Specifies the number of bits of the prefix. The value can be set between 0 (4,294,967,296 addresses) and 31 (2 addresses). Defaults to 28(16 addresses). Changing this forces a new resource to be created. | number |
31 |
no |
public_ip_prefix_sku | SKU for public ip prefix. Default to standard. | string |
"Standard" |
no |
public_ip_sku | The SKU of the Public IP. Accepted values are Basic and Standard. Defaults to Basic | string |
"Standard" |
no |
repository | Terraform current module repo | string |
"" |
no |
resource_group_name | A container that holds related resources for an Azure solution | string |
"" |
no |
retention_policy_enabled | Set to false to prevent the module from creating retension policy for the diagnosys setting. | bool |
false |
no |
sku_name | (optional) describe your variable | string |
"AZFW_VNet" |
no |
sku_policy | Specifies the firewall-policy sku | string |
"Standard" |
no |
sku_tier | Specifies the firewall sku tier | string |
"Standard" |
no |
storage_account_id | Storage account id to pass it to destination details of diagnosys setting of NSG. | string |
null |
no |
subnet_id | Subnet ID | string |
"" |
no |
tags | A map of tags to add to all resources | map(string) |
{} |
no |
threat_intel_mode | (Optional) The operation mode for threat intelligence-based filtering. Possible values are: Off, Alert, Deny. Defaults to Alert. | string |
"Alert" |
no |
Name | Description |
---|---|
firewall_id | Firewall generated id |
firewall_name | Firewall name |
firewall_policy_id | n/a |
prefix_public_ip_address | n/a |
prefix_public_ip_id | n/a |
private_ip_address | Firewall private IP |
public_ip_address | n/a |
public_ip_id | n/a |
public_ip_prefix_id | n/a |
In this module testing is performed with terratest and it creates a small piece of infrastructure, matches the output like ARN, ID and Tags name etc and destroy infrastructure in your AWS account. This testing is written in GO, so you need a GO environment in your system.
You need to run the following command in the testing folder:
go test -run Test
If you come accross a bug or have any feedback, please log it in our issue tracker, or feel free to drop us an email at [email protected].
If you have found it worth your time, go ahead and give us a ★ on our GitHub!
At CloudDrove, we offer expert guidance, implementation support and services to help organisations accelerate their journey to the cloud. Our services include docker and container orchestration, cloud migration and adoption, infrastructure automation, application modernisation and remediation, and performance engineering.
We are The Cloud Experts!
We ❤️ Open Source and you can check out our other modules to get help with your new Cloud ideas.