Skip to content

GovTechSG/terraform-aws-firewall

Repository files navigation

terraform-aws-firewall

Terraform module to create an AWS Network Firewall with advanced rule management and automatic threat intelligence integration.

Features

  • 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

Usage

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"
    }
  }
}

Gitsir Integration

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

Requirements

Name Version
terraform >= 0.13

Providers

Name Version
aws n/a
http n/a
random n/a
terraform n/a

Modules

No modules.

Resources

Name Type
aws_cloudwatch_log_group.main resource
aws_cloudwatch_log_subscription_filter.main resource
aws_kms_alias.main resource
aws_kms_key.main resource
aws_networkfirewall_firewall.main resource
aws_networkfirewall_firewall_policy.main resource
aws_networkfirewall_logging_configuration.main resource
aws_networkfirewall_rule_group.allow-outgoing-http resource
aws_networkfirewall_rule_group.allow-outgoing-tcp resource
aws_networkfirewall_rule_group.block-all-outgoing resource
aws_networkfirewall_rule_group.block-domains resource
aws_networkfirewall_rule_group.block-ips resource
aws_networkfirewall_rule_group.gitsir-domain resource
aws_networkfirewall_rule_group.gitsir-ip resource
aws_networkfirewall_rule_group.pretend-to-block-all-outgoing resource
random_id.sid resource
terraform_data.gitsir_blocklist_ip resource
aws_caller_identity.current data source
http_http.gitsir_blocklist_domain data source
http_http.gitsir_blocklist_ip data source
http_http.gitsir_blocklist_packages data source

Inputs

Name Description Type Default Required
alert_outgoing n/a
map(object({
protocol = string
port = number
message = string
}))
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({
capacity = number
domains = list(string)
}))
{} 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({
capacity = number
ips = list(string)
}))
{} 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({
naming_suffix = string
role_arn = string
filter_pattern = string
destination_arn = string
distribution = string
}))
{} 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({
name = string
capacity = number
port = number
ips = list(string)
domains = list(string)
})))
{} no

Outputs

Name Description
firewall n/a
firewall_policy_arn n/a

About

Terraform module to create an AWS Network Firewall

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages