{"id":19107223,"url":"https://github.com/govtechsg/terraform-aws-firewall","last_synced_at":"2026-05-16T00:07:29.781Z","repository":{"id":39342596,"uuid":"386133392","full_name":"GovTechSG/terraform-aws-firewall","owner":"GovTechSG","description":"Terraform module to create an AWS Network Firewall","archived":false,"fork":false,"pushed_at":"2025-08-26T13:39:44.000Z","size":46,"stargazers_count":0,"open_issues_count":3,"forks_count":0,"subscribers_count":55,"default_branch":"master","last_synced_at":"2025-08-26T18:35:28.305Z","etag":null,"topics":["aws","terraform","terraform-module","terraform-modules"],"latest_commit_sha":null,"homepage":"","language":"HCL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GovTechSG.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-07-15T02:10:46.000Z","updated_at":"2025-03-18T01:11:36.000Z","dependencies_parsed_at":"2025-07-14T11:07:29.705Z","dependency_job_id":"a4a8b5bb-4c89-4232-8309-77b80a3b56fd","html_url":"https://github.com/GovTechSG/terraform-aws-firewall","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/GovTechSG/terraform-aws-firewall","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GovTechSG%2Fterraform-aws-firewall","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GovTechSG%2Fterraform-aws-firewall/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GovTechSG%2Fterraform-aws-firewall/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GovTechSG%2Fterraform-aws-firewall/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GovTechSG","download_url":"https://codeload.github.com/GovTechSG/terraform-aws-firewall/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GovTechSG%2Fterraform-aws-firewall/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33085111,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-15T20:25:35.270Z","status":"ssl_error","status_checked_at":"2026-05-15T20:25:34.732Z","response_time":103,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","terraform","terraform-module","terraform-modules"],"created_at":"2024-11-09T04:11:41.019Z","updated_at":"2026-05-16T00:07:29.776Z","avatar_url":"https://github.com/GovTechSG.png","language":"HCL","funding_links":[],"categories":[],"sub_categories":[],"readme":"# terraform-aws-firewall\nTerraform module to create an AWS Network Firewall with advanced rule management and automatic threat intelligence integration.\n\n## Features\n\n- **Automated Gitsir Integration**: Automatically pulls and applies IP and domain blocklists from Gitsir threat intelligence\n- **Flexible Rule Management**: Support for custom IP blocks, domain blocks, and whitelisting\n- **AWS Managed Rules**: Integration with AWS managed threat signature rules\n- **Configurable Actions**: Support for strict/established drop and alert modes\n- **CloudWatch Integration**: Comprehensive logging with configurable retention\n\n## Usage\n\n```hcl\nmodule \"firewall\" {\n  name        = \"my-firewall\"\n  description = \"my firewall for this vpc\"\n\n  # Cannot use vpc dependency as vpc will also depend on this\n  subnet_ids = [\n   \"subnet-1a\",\n   \"subnet-1b\",\n   \"subnet-1c\"\n  ]\n\n  vpc_id = \"vpc-xx\"\n\n  # Enable automatic Gitsir threat intelligence (requires GitLab credentials)\n  enable_gitsir_ip_list = true\n  ci_api_v4_url        = var.ci_api_v4_url        # Set via TF_VAR_ci_api_v4_url\n  project_access_token = var.project_access_token # Set via TF_VAR_project_access_token\n\n  # Custom IP blocks - key names must be numeric for SID generation\n  blocked_ips = {\n    \"1001\" = {\n      capacity = 100\n      ips      = [\"192.168.1.100/32\", \"10.0.0.50/32\"]\n    }\n  }\n\n  # Custom domain blocks\n  blocked_domains = {\n    \"1002\" = {\n      capacity = 50\n      domains  = [\"malicious-site.com\", \"spam-domain.org\"]\n    }\n  }\n\n  # Whitelist outgoing traffic (HTTP/HTTPS and custom TCP)\n  whitelist_outgoing = {\n    http = {\n      \"1003\" = {\n        name     = \"allowed-web-traffic\"\n        capacity = 100\n        port     = 443\n        ips      = []\n        domains  = [\"api.example.com\", \"cdn.example.com\"]\n      }\n    }\n    tcp = {\n      \"1004\" = {\n        name     = \"custom-service\"\n        capacity = 50\n        port     = 8443\n        ips      = [\"203.0.113.10/32\"]\n        domains  = [\"secure-service.example.com\"]\n      }\n    }\n  }\n\n  # Alert rules for monitoring\n  alert_outgoing = {\n    \"1005\" = {\n      protocol = \"tcp\"\n      port     = 22\n      message  = \"SSH outbound connection detected\"\n    }\n  }\n\n  # Firewall behavior configuration\n  default_action = [\"aws:alert_established\"] # Options: aws:drop_strict, aws:drop_established, aws:alert_strict, aws:alert_established\n  enable_block_everything_by_default = false\n\n  # CloudWatch log group subscriptions\n  lg_filters = {\n    \"gcsoc\" = {\n      naming_suffix   = \"gcsoc-lg-filter\"\n      role_arn        = \"arn:aws:iam::${get_aws_account_id()}:role/central-logging-cloudwatch-firehose-role\"\n      filter_pattern  = \"\"\n      destination_arn = \"arn:aws:firehose:${local.common_vars.region}:${get_aws_account_id()}:deliverystream/clm-central-logging-firehose\"\n      distribution    = \"ByLogStream\"\n    }\n  }\n}\n```\n\n### Gitsir Integration\n\nThe 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.\n\n**Required Environment Variables for Gitsir:**\n```bash\nexport TF_VAR_ci_api_v4_url=\"https://sgts.gitlab-dedicated.com/api/v4\"\nexport TF_VAR_project_access_token=\"your-gitlab-project-access-token\"\n```\n\nThe token requires:\n- `read_api` scope\n- At least `Reporter` role on the Gitsir project\n\n## Requirements\n\n| Name | Version |\n|------|---------|\n| \u003ca name=\"requirement_terraform\"\u003e\u003c/a\u003e [terraform](#requirement\\_terraform) | \u003e= 0.13 |\n\n## Providers\n\n| Name | Version |\n|------|---------|\n| \u003ca name=\"provider_aws\"\u003e\u003c/a\u003e [aws](#provider\\_aws) | n/a |\n| \u003ca name=\"provider_http\"\u003e\u003c/a\u003e [http](#provider\\_http) | n/a |\n| \u003ca name=\"provider_random\"\u003e\u003c/a\u003e [random](#provider\\_random) | n/a |\n| \u003ca name=\"provider_terraform\"\u003e\u003c/a\u003e [terraform](#provider\\_terraform) | n/a |\n\n## Modules\n\nNo modules.\n\n## Resources\n\n| Name | Type |\n|------|------|\n| [aws_cloudwatch_log_group.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource |\n| [aws_cloudwatch_log_subscription_filter.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_subscription_filter) | resource |\n| [aws_kms_alias.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_alias) | resource |\n| [aws_kms_key.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource |\n| [aws_networkfirewall_firewall.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkfirewall_firewall) | resource |\n| [aws_networkfirewall_firewall_policy.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkfirewall_firewall_policy) | resource |\n| [aws_networkfirewall_logging_configuration.main](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkfirewall_logging_configuration) | resource |\n| [aws_networkfirewall_rule_group.allow-outgoing-http](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkfirewall_rule_group) | resource |\n| [aws_networkfirewall_rule_group.allow-outgoing-tcp](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkfirewall_rule_group) | resource |\n| [aws_networkfirewall_rule_group.block-all-outgoing](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkfirewall_rule_group) | resource |\n| [aws_networkfirewall_rule_group.block-domains](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkfirewall_rule_group) | resource |\n| [aws_networkfirewall_rule_group.block-ips](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkfirewall_rule_group) | resource |\n| [aws_networkfirewall_rule_group.gitsir-domain](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkfirewall_rule_group) | resource |\n| [aws_networkfirewall_rule_group.gitsir-ip](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkfirewall_rule_group) | resource |\n| [aws_networkfirewall_rule_group.pretend-to-block-all-outgoing](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkfirewall_rule_group) | resource |\n| [random_id.sid](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource |\n| [terraform_data.gitsir_blocklist_ip](https://registry.terraform.io/providers/hashicorp/terraform/latest/docs/resources/data) | resource |\n| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source |\n| [http_http.gitsir_blocklist_domain](https://registry.terraform.io/providers/hashicorp/http/latest/docs/data-sources/http) | data source |\n| [http_http.gitsir_blocklist_ip](https://registry.terraform.io/providers/hashicorp/http/latest/docs/data-sources/http) | data source |\n| [http_http.gitsir_blocklist_packages](https://registry.terraform.io/providers/hashicorp/http/latest/docs/data-sources/http) | data source |\n\n## Inputs\n\n| Name | Description | Type | Default | Required |\n|------|-------------|------|---------|:--------:|\n| \u003ca name=\"input_alert_outgoing\"\u003e\u003c/a\u003e [alert\\_outgoing](#input\\_alert\\_outgoing) | n/a | \u003cpre\u003emap(object({\u003cbr\u003e    protocol = string\u003cbr\u003e    port     = number\u003cbr\u003e    message  = string\u003cbr\u003e  }))\u003c/pre\u003e | n/a | yes |\n| \u003ca name=\"input_aws_region\"\u003e\u003c/a\u003e [aws\\_region](#input\\_aws\\_region) | Region which resources will be created in | `string` | `\"ap-southeast-1\"` | no |\n| \u003ca name=\"input_blocked_domains\"\u003e\u003c/a\u003e [blocked\\_domains](#input\\_blocked\\_domains) | Domains to block (both ingress \u0026 egress), maximum capacity across all rules is 30000 | \u003cpre\u003emap(object({\u003cbr\u003e    capacity = number\u003cbr\u003e    domains  = list(string)\u003cbr\u003e  }))\u003c/pre\u003e | `{}` | no |\n| \u003ca name=\"input_blocked_ips\"\u003e\u003c/a\u003e [blocked\\_ips](#input\\_blocked\\_ips) | Block all traffic from/to specific IPs, note that keys can only be numeric, and maximum capacity across all rules is 30000 | \u003cpre\u003emap(object({\u003cbr\u003e    capacity = number\u003cbr\u003e    ips      = list(string)\u003cbr\u003e  }))\u003c/pre\u003e | `{}` | no |\n| \u003ca name=\"input_ci_api_v4_url\"\u003e\u003c/a\u003e [ci\\_api\\_v4\\_url](#input\\_ci\\_api\\_v4\\_url) | GitLab API v4 root URL.\u003cbr\u003eTo supply to Terraform, set the environment variable TF\\_VAR\\_ci\\_api\\_v4\\_url\u003cbr\u003eto the value of the predefined CI/CD variable CI\\_API\\_V4\\_URL.\u003cbr\u003eSee .gitlab-ci-example.yml for an example.\u003cbr\u003eHardcoding this value is also possible as it is unlikely to change, but not recommended. | `string` | n/a | yes |\n| \u003ca name=\"input_cloudwatch_log_retention_in_days\"\u003e\u003c/a\u003e [cloudwatch\\_log\\_retention\\_in\\_days](#input\\_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 |\n| \u003ca name=\"input_create_network_firewall\"\u003e\u003c/a\u003e [create\\_network\\_firewall](#input\\_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 |\n| \u003ca name=\"input_default_action\"\u003e\u003c/a\u003e [default\\_action](#input\\_default\\_action) | Pick option(s) from `aws:drop_strict`, `aws:drop_established`, `aws:alert_strict`, `aws:alert_established`. Default to []. | `set(string)` | `[]` | no |\n| \u003ca name=\"input_delete_protection\"\u003e\u003c/a\u003e [delete\\_protection](#input\\_delete\\_protection) | Toggle to enable or disable deletion protection | `bool` | `true` | no |\n| \u003ca name=\"input_enable_block_everything_by_default\"\u003e\u003c/a\u003e [enable\\_block\\_everything\\_by\\_default](#input\\_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 |\n| \u003ca name=\"input_enable_gitsir_ip_list\"\u003e\u003c/a\u003e [enable\\_gitsir\\_ip\\_list](#input\\_enable\\_gitsir\\_ip\\_list) | Toggle to enable retrieval of gitsir IP list. | `bool` | `false` | no |\n| \u003ca name=\"input_lg_filters\"\u003e\u003c/a\u003e [lg\\_filters](#input\\_lg\\_filters) | Log group filters for Network Firewall | \u003cpre\u003emap(object({\u003cbr\u003e    naming_suffix   = string\u003cbr\u003e    role_arn        = string\u003cbr\u003e    filter_pattern  = string\u003cbr\u003e    destination_arn = string\u003cbr\u003e    distribution    = string\u003cbr\u003e  }))\u003c/pre\u003e | `{}` | no |\n| \u003ca name=\"input_name\"\u003e\u003c/a\u003e [name](#input\\_name) | The name of the network firewall | `string` | n/a | yes |\n| \u003ca name=\"input_project_access_token\"\u003e\u003c/a\u003e [project\\_access\\_token](#input\\_project\\_access\\_token) | Your GitLab project access token (create if needed).\u003cbr\u003eIt requires the read\\_api scope and at least the Reporter role. | `string` | n/a | yes |\n| \u003ca name=\"input_subnet_ids\"\u003e\u003c/a\u003e [subnet\\_ids](#input\\_subnet\\_ids) | Subnets used to create network firewall. | `set(string)` | `[]` | no |\n| \u003ca name=\"input_tags\"\u003e\u003c/a\u003e [tags](#input\\_tags) | A map of tags to add to all resources | `map(any)` | `{}` | no |\n| \u003ca name=\"input_vpc_id\"\u003e\u003c/a\u003e [vpc\\_id](#input\\_vpc\\_id) | n/a | `string` | `\"\"` | no |\n| \u003ca name=\"input_whitelist_outgoing\"\u003e\u003c/a\u003e [whitelist\\_outgoing](#input\\_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. | \u003cpre\u003emap(map(object({\u003cbr\u003e    name     = string\u003cbr\u003e    capacity = number\u003cbr\u003e    port     = number\u003cbr\u003e    ips      = list(string)\u003cbr\u003e    domains  = list(string)\u003cbr\u003e  })))\u003c/pre\u003e | `{}` | no |\n\n## Outputs\n\n| Name | Description |\n|------|-------------|\n| \u003ca name=\"output_firewall\"\u003e\u003c/a\u003e [firewall](#output\\_firewall) | n/a |\n| \u003ca name=\"output_firewall_policy_arn\"\u003e\u003c/a\u003e [firewall\\_policy\\_arn](#output\\_firewall\\_policy\\_arn) | n/a |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgovtechsg%2Fterraform-aws-firewall","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgovtechsg%2Fterraform-aws-firewall","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgovtechsg%2Fterraform-aws-firewall/lists"}