# terraform-aws-secure-baseline hardens an AWS account in one apply

> This Terraform module applies a hardened account configuration across every region: CloudTrail, GuardDuty, Config, SecurityHub, a root account audit, and the removal of the default VPC's permissive rules. Most of its settings map to CIS AWS Foundations and AWS Foundational Security Best Practices, and the module is published on the Terraform Registry.

**nozaq/terraform-aws-secure-baseline** — Terraform module to set up your AWS account with the secure baseline configuration based on CIS Amazon Web Services Foundations and AWS Foundational Security Best Practices.

- Repository: https://github.com/nozaq/terraform-aws-secure-baseline
- Stars: 1,202 · Forks: 381
- Language: HCL
- License: MIT
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/nozaq-terraform-aws-secure-baseline

## What the baseline actually turns on

The feature list is organised in three groups, and it is worth reading each line because the module is opinionated about defaults. Under identity and access management it sets an IAM password policy, creates an IAM role for contacting AWS support during incident handling, enables AWS Config rules to audit root account status, enables IAM Access Analyzer in each region, and turns on the S3 account level Public Access Block. Under logging and monitoring it enables CloudTrail in all regions with delivery to CloudWatch Logs, encrypts CloudTrail logs with AWS Key Management Service, stores logs in an S3 bucket with access logging enabled, archives them into Amazon Glacier after a given period that defaults to 90 days, enables CloudTrail Insights event logging by default, and sets up CloudWatch alarms for critical changes. It also enables AWS Config in each region to record configuration state automatically, SecurityHub with the available standards subscribed, and GuardDuty in each region.

## The default VPC gets its permissive rules removed

The networking and computing group contains the change that will surprise you most. The module removes all rules associated with default route tables, default network ACLs and default security groups in the default VPC in all regions. That is a destructive operation on resources AWS creates for you automatically and that many applications quietly depend on. The same group disables automatic public IP assignment in default subnets, enables VPC Flow Logs with the default VPC in all regions, enables default EBS encryption for newly created volumes, and enables AWS Config rules to audit unrestricted common ports in security group rules. A module that deletes default security group rules is not a background hardening layer. It is a change to network reachability, and it belongs in a review, not in a maintenance window you run unattended.

## You must pass a provider for every region, and that is a real cost

The usage section in the README makes an unusual demand. You define a provider per AWS region and pass them all into the module, and the README calls this the recommended way to handle multiple regions in one module. The example passes seventeen regional providers alongside the default one. The module then uses the region input for global resources and fans the regional configuration out across the providers you pass in. The practical consequence is that the provider list in your root module becomes a long maintenance item. A new region in the account means a new provider block and a new entry in that map, and the module does not discover regions on its own. An example directory named select-region exists in the repository, which suggests there is a lighter path worth looking at before you copy the full provider map into production code.

## A first apply: the module call and its four required inputs

The module is registered on the Terraform Registry, so the source is a registry reference rather than a git path. The call below is the documented usage, with the provider map trimmed to a few regions for readability; the full example in the README lists all of them.

```hcl
module "secure_baseline" {
  source = "nozaq/secure-baseline/aws"

  audit_log_bucket_name           = "YOUR_BUCKET_NAME"
  aws_account_id                  = data.aws_caller_identity.current.account_id
  region                          = data.aws_region.current.name
  support_iam_role_principal_arns = ["YOUR_IAM_USER"]
}
```

The inputs table lists four of them as required. The bucket name is the S3 bucket that will hold the various audit logs, and the account ID and region identify where the global resources are set up, while the support role principal ARNs list the IAM principals allowed to assume the role for contacting AWS support. The two data sources at the top of the example supply the account ID and the region name so you do not hardcode them.

## Where the logs go, and the option to send them elsewhere

Log placement is a first class decision in this module rather than an afterthought. A new S3 bucket to store audit logs is created by default, and the CloudTrail logs are encrypted with Key Management Service, with access logging enabled on the bucket and automatic archival into Glacier after the configured period, which defaults to 90 days. You can instead point the module at an external bucket, and the README says that this is useful when you already have a centralised S3 bucket for all logs, with an example directory named external-bucket for the detail. There is a second dimension of log placement too, in the account structure. When several accounts sit in an AWS Organization, the module configures a separated environment for each account, and you can change that behaviour to manage security information and audit logs centrally from one master account, with an organization example directory showing how.

## Eleven submodules you can use on their own

The package is not a monolith. The module is composed of several submodules, each of which can be used independently, and eleven of them are listed. The alarm submodule covers the CloudWatch alarms for critical account changes, the analyzer submodule the IAM Access Analyzer setup, the cloudtrail submodule the trail and its delivery, the config submodule the AWS Config rules and recorded configuration state, the ebs submodule default volume encryption, the guardduty submodule the detector per region, the iam submodule the password policy and the support role, the s3 submodule the bucket and public access block settings, the securityhub submodule the security service and standards, the vpc submodule the network changes, and secure-bucket is the shared bucket resource. This is the most useful thing about the layout if you are not ready for the whole baseline, because you can adopt one area, for example logging, without taking the default VPC rule removal with it.

## Provider version floors, and a release history that stopped in 2022

The compatibility section is unusually explicit about version requirements across the module's history. Starting from v1.0 the module requires the AWS Terraform provider at 4.0 or later, with an upgrade guide in the docs directory describing the recommended procedure for that step. Starting from v0.20 it required provider 3.0 or later, and you should use v0.19 if you need the 2.x provider or earlier. Starting from v0.10 it required Terraform 0.12 or later. The current requirements table asks for Terraform 1.1.4 or later and the AWS provider at 4.3 or later. The release history is where the caution comes from. The tags are v2.1.0 from 2022-12-03, v2.0.0 from 2022-06-05 and v1.1.0 from 2022-04-17, yet the repository is not archived and the last push was on 2026-09-13. So there is recent work on the code with no new release for a long stretch, which means the version you pin from the Registry may lag the repository you see. The module is MIT licensed, and the repository includes a CHANGELOG.md and a .chglog directory for changelog generation, a .tflint.hcl for linting, and a .terraform-docs.yml that generates the tables in the README.

## Conclusion

terraform-aws-secure-baseline suits a team setting up a new AWS account, or an existing one that has no logging at all, and who want hardening expressed as reviewable Terraform rather than console clicks. It does not suit a production account that already has CloudTrail or GuardDuty, since the module creates and manages those resources itself and will collide with what is already there. Before you apply it, read the compliance.md file in the repository to see which benchmark items the module actually covers, and check the provider version floor, because the module requires the AWS provider at 4.3 or later and Terraform at 1.1.4 or later.

## FAQ

### How do I use the terraform-aws-secure-baseline module?

The module is published on the Terraform Registry with the source `nozaq/secure-baseline/aws`, and you pass in a provider for each AWS region along with the required inputs for the log bucket name, account ID, region and support role principal ARNs. The README shows the full call in its usage section.

### What does the module do to the default VPC?

It removes all rules associated with default route tables, default network ACLs and default security groups in the default VPC in all regions, disables automatic public IP assignment in default subnets, and enables VPC Flow Logs for the default VPC. Those are reachability changes, not just logging changes.

### Can I use an existing S3 bucket for the audit logs?

Yes. A new S3 bucket is created by default, but an external bucket can be specified, which the README says is useful when you already have a centralized S3 bucket for all logs. There is an external-bucket example directory in the repository.

### Can I use individual parts of the module instead of the whole baseline?

Yes. The module is composed of several submodules, each of which can be used independently, and the README lists eleven of them, including alarm, analyzer, cloudtrail, config, ebs, guardduty, iam, s3, securityhub, vpc and secure-bucket.

### Which Terraform and AWS provider versions does the module need?

The requirements table asks for Terraform 1.1.4 or later and the AWS provider at 4.3 or later. The compatibility section adds that v1.0 required provider 4.0 or later, v0.20 required provider 3.0 or later, and v0.10 required Terraform 0.12 or later.

### How do I check which benchmark items the module covers?

The README points to a compliance document in the repository root, described as a place to check which items in various benchmarks are covered. Most configurations are based on CIS Amazon Web Services Foundations v1.4.0 and AWS Foundational Security Best Practices v1.0.0.

## Sources

- [Issues](https://github.com/nozaq/terraform-aws-secure-baseline/issues)
- [License: MIT](https://github.com/nozaq/terraform-aws-secure-baseline/blob/main/LICENSE)
- [nozaq/terraform-aws-secure-baseline on GitHub](https://github.com/nozaq/terraform-aws-secure-baseline)
- [README](https://github.com/nozaq/terraform-aws-secure-baseline/blob/main/README.md)
- [Releases](https://github.com/nozaq/terraform-aws-secure-baseline/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/nozaq-terraform-aws-secure-baseline
