Terraform module to create an AWS Network Firewall with advanced rule management and automatic threat intelligence integration.
- Automated Gitsir Integration: Automatically pulls and applies IP and domain blocklists from Gitsir threat intelligence
- Flexible Rule Management: Support for custom IP blocks, domain blocks, and whitelisting
- AWS Managed Rules: Integration with AWS managed threat signature rules
- Configurable Actions: Support for strict/established drop and alert modes
- CloudWatch Integration: Comprehensive logging with configurable retention
module "firewall" {
name = "my-firewall"
description = "my firewall for this vpc"
# Cannot use vpc dependency as vpc will also depend on this
subnet_ids = [
"subnet-1a",
"subnet-1b",
"subnet-1c"
]
vpc_id = "vpc-xx"
# Enable automatic Gitsir threat intelligence (requires GitLab credentials)
enable_gitsir_ip_list = true
ci_api_v4_url = var.ci_api_v4_url # Set via TF_VAR_ci_api_v4_url
project_access_token = var.project_access_token # Set via TF_VAR_project_access_token
# Custom IP blocks - key names must be numeric for SID generation
blocked_ips = {
"1001" = {
capacity = 100
ips = ["192.168.1.100/32", "10.0.0.50/32"]
}
}
# Custom domain blocks
blocked_domains = {
"1002" = {
capacity = 50
domains = ["malicious-site.com", "spam-domain.org"]
}
}
# Whitelist outgoing traffic (HTTP/HTTPS and custom TCP)
whitelist_outgoing = {
http = {
"1003" = {
name = "allowed-web-traffic"
capacity = 100
port = 443
ips = []
domains = ["api.example.com", "cdn.example.com"]
}
}
tcp = {
"1004" = {
name = "custom-service"
capacity = 50
port = 8443
ips = ["203.0.113.10/32"]
domains = ["secure-service.example.com"]
}
}
}
# Alert rules for monitoring
alert_outgoing = {
"1005" = {
protocol = "tcp"
port = 22
message = "SSH outbound connection detected"
}
}
# Firewall behavior configuration
default_action = ["aws:alert_established"] # Options: aws:drop_strict, aws:drop_established, aws:alert_strict, aws:alert_established
enable_block_everything_by_default = false
# CloudWatch log group subscriptions
lg_filters = {
"gcsoc" = {
naming_suffix = "gcsoc-lg-filter"
role_arn = "arn:aws:iam::${get_aws_account_id()}:role/central-logging-cloudwatch-firehose-role"
filter_pattern = ""
destination_arn = "arn:aws:firehose:${local.common_vars.region}:${get_aws_account_id()}:deliverystream/clm-central-logging-firehose"
distribution = "ByLogStream"
}
}
}
The module automatically integrates with Gitsir threat intelligence to pull the latest IP and domain blocklists. This feature is controlled by the enable_gitsir_ip_list
variable and requires GitLab API credentials.
Required Environment Variables for Gitsir:
export TF_VAR_ci_api_v4_url="https://sgts.gitlab-dedicated.com/api/v4"
export TF_VAR_project_access_token="your-gitlab-project-access-token"
The token requires:
read_api
scope- At least
Reporter
role on the Gitsir project
Name | Version |
---|---|
terraform | >= 0.13 |
Name | Version |
---|---|
aws | n/a |
http | n/a |
random | n/a |
terraform | n/a |
No modules.
Name | Description | Type | Default | Required |
---|---|---|---|---|
alert_outgoing | n/a | map(object({ |
n/a | yes |
aws_region | Region which resources will be created in | string |
"ap-southeast-1" |
no |
blocked_domains | Domains to block (both ingress & egress), maximum capacity across all rules is 30000 | map(object({ |
{} |
no |
blocked_ips | Block all traffic from/to specific IPs, note that keys can only be numeric, and maximum capacity across all rules is 30000 | map(object({ |
{} |
no |
ci_api_v4_url | GitLab API v4 root URL. To supply to Terraform, set the environment variable TF_VAR_ci_api_v4_url to the value of the predefined CI/CD variable CI_API_V4_URL. See .gitlab-ci-example.yml for an example. Hardcoding this value is also possible as it is unlikely to change, but not recommended. |
string |
n/a | yes |
cloudwatch_log_retention_in_days | Specifies the number of days you want to retain log events in the specified log group. Possible values are: 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653, and 0. If you select 0, the events in the log group are always retained and never expire. | number |
180 |
no |
create_network_firewall | toggle for creation of network firewall, set to false if you only want to create the firewall policy with this module | bool |
true |
no |
default_action | Pick option(s) from aws:drop_strict , aws:drop_established , aws:alert_strict , aws:alert_established . Default to []. |
set(string) |
[] |
no |
delete_protection | Toggle to enable or disable deletion protection | bool |
true |
no |
enable_block_everything_by_default | Creates rule that will block all traffic by default, and you will have to whitelist routes specifically to allow internet traffic | bool |
false |
no |
enable_gitsir_ip_list | Toggle to enable retrieval of gitsir IP list. | bool |
false |
no |
lg_filters | Log group filters for Network Firewall | map(object({ |
{} |
no |
name | The name of the network firewall | string |
n/a | yes |
project_access_token | Your GitLab project access token (create if needed). It requires the read_api scope and at least the Reporter role. |
string |
n/a | yes |
subnet_ids | Subnets used to create network firewall. | set(string) |
[] |
no |
tags | A map of tags to add to all resources | map(any) |
{} |
no |
vpc_id | n/a | string |
"" |
no |
whitelist_outgoing | IPs to allow (egress), note that keys can only be numeric, and maximum capacity across all rules is 30000, protocol can be IP/dns/http/etc. | map(map(object({ |
{} |
no |
Name | Description |
---|---|
firewall | n/a |
firewall_policy_arn | n/a |