How to set up a secure Terraform backend using Amazon S3 + DynamoDB
Introduction
- Managing infrastructure as code is crucial for modern DevOps practices, and Terraform has emerged as a powerful tool for achieving this. In this technical guide, we will delve into the best practices for configuring a Terraform backend using Amazon Web Services’ S3 bucket and associated resources.
- Our aim is to equip you with the skills needed to establish a production-ready environment with sensible defaults.
Prerequisites and Setup
Installing Terraform and Managing Versions
Terraform versions can be efficiently managed using
tfenv
. This tool allows for the installation of multiple versions and can automatically install a specified version using a.terraform-version
file.Alternatively, you can download Terraform directly from the official website. After downloading, unzip the file and place the binary in your system’s path.
To verify your Terraform installation, use the command:
$ terraform version
Authenticating with AWS
Before diving into Terraform, ensure you have AWS credentials configured. You can set up your credentials using the AWS CLI with:
$ aws configure
Terraform Configuration
File Structure
Organize your Terraform code with logical separations in different
.tf
files. This enhances clarity and maintainability.Provider Configuration (main.tf)
Define the AWS provider and its version in a main.tf file. Specify the desired region for resource provisioning.
terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 3.0" } } } provider "aws" { region = "us-east-1" }
Setting Up the Backend
State Resources Configuration (state.tf)
KMS Key and Alias
Create a KMS key and an alias for encryption purposes. This ensures the security of your Terraform state.
resource "aws_kms_key" "terraform-bucket-key" { description = "This key is used to encrypt bucket objects" deletion_window_in_days = 10 enable_key_rotation = true } resource "aws_kms_alias" "key-alias" { name = "alias/terraform-bucket-key" target_key_id = aws_kms_key.terraform-bucket-key.key_id }
S3 Bucket
Set up a secure S3 bucket for storing the Terraform state file. Enable versioning and server-side encryption using the KMS key created earlier.
resource "aws_s3_bucket" "terraform-state" { bucket = "<BUCKET_NAME>" acl = "private" versioning { enabled = true } server_side_encryption_configuration { rule { apply_server_side_encryption_by_default { kms_master_key_id = aws_kms_key.terraform-bucket-key.arn sse_algorithm = "aws:kms" } } } }
S3 Bucket Public Access Block
Prevent public access to the S3 bucket using a public access block.
resource "aws_s3_bucket_public_access_block" "block" { bucket = aws_s3_bucket.terraform-state.id block_public_acls = true block_public_policy = true ignore_public_acls = true restrict_public_buckets = true }
DynamoDB Table
Implement a DynamoDB table for state locking to prevent concurrent writes.
resource "aws_dynamodb_table" "terraform-state" { name = "terraform-state" read_capacity = 20 write_capacity = 20 hash_key = "LockID" attribute { name = "LockID" type = "S" } }
Backend Configuration (state.tf)
Configuring the S3 Backend
Specify the S3 bucket as the backend for Terraform state storage. Include the necessary configurations, such as encryption and DynamoDB table.
terraform { backend "s3" { bucket = "<BUCKET_NAME>" key = "state/terraform.tfstate" region = "us-east-1" encrypt = true kms_key_id = "alias/terraform-bucket-key" dynamodb_table = "terraform-state" } }
Applying Terraform Configuration
Initializing and Applying Resources
After configuring the backend, initialize and apply your Terraform configuration.
$ terraform init $ terraform apply
Review the output to ensure you’re comfortable with the planned changes.
Migrating to the S3 Backend
Updating the Backend
With your state resources in place, migrate to the S3 backend.
$ terraform init
Terraform will prompt you to copy the existing state to the new backend. Respond with “yes” to complete the migration.
Validating Changes
After the migration, verify your resources using:
$ terraform plan
Conclusion
- By following these best practices, you have successfully configured a production-ready Terraform backend using AWS S3 and associated resources.
- This approach ensures secure state management, robust locking, and efficient infrastructure provisioning.
- You are now equipped to manage your infrastructure with confidence and maintain optimal DevOps practices.