Secure Your AWS Infrastructure: Automating Private Zones and TLS Certificates with Terraform

Secure AWS Infrastructure Deployment with Terraform: A Complete Guide to Self-Signed Certificates and VPC Configuration

Introduction

In today’s digital landscape, where cyber threats are ever-present and data breaches can be catastrophic, securing your cloud infrastructure is not just a best practice—it’s a necessity. As organizations increasingly migrate their operations to the cloud, particularly to platforms like Amazon Web Services (AWS), the need for robust, scalable, and automated security measures has never been more critical.

Secure infrastructure is the bedrock of digital trust. It protects sensitive data, ensures the integrity of communications, and safeguards against unauthorized access. In the context of cloud computing, where resources are distributed and accessible over networks, the importance of security multiplies. Properly secured infrastructure not only protects your organization from potential threats but also ensures compliance with various regulatory standards, maintains customer trust, and can significantly reduce the risk of costly data breaches.

This blog post introduces a quick and simple Terraform module designed to automate the creation and management of secure, private network environments within AWS. Our solution leverages key AWS services such as Certificate Manager (ACM), Private Certificate Authority (PCA), Route 53, and Virtual Private Cloud (VPC) to enable in-transit encryption. By using Terraform, we ensure that this secure environment can be consistently deployed, easily version-controlled, and effortlessly replicated across multiple projects or environments.

Technical Architecture Overview

This architecture creates a complete private PKI solution, allowing for secure internal communications with custom domain names and certificates issued by a trusted private authority.

  1. Route53: A private hosted zone is created in Amazon Route53 for the specified domain name. This zone is associated with the provided VPC, allowing internal DNS resolution.
  2. Private Root CA: If self-signed certificates are not provided, a private root Certificate Authority (CA) is created using AWS Certificate Manager Private Certificate Authority (ACM PCA). The root CA is configured with the specified organization details and uses RSA 2048-bit keys with SHA256 signing.
  3. Private CA Certificate: The root CA certificate is generated and managed by ACM PCA. This certificate serves as the trust anchor for all certificates issued within the private PKI.
  4. Certificate Manager to Request End-Entity Certificates: AWS Certificate Manager (ACM) is used to request and manage end-entity certificates. These certificates are issued by the private CA and can be used for various AWS services.
  5. Usage on a Load Balancer: The end-entity certificates can be attached to AWS resources like Application Load Balancers (ALBs) or API Gateways. This enables secure HTTPS communication within the private network, with clients trusting the private CA.

Infrastructure as Code with Terraform

Prerequisites

Terraform is an open-source Infrastructure as Code (IaC) tool developed by HashiCorp. It allows you to define, manage, and provision infrastructure resources across various cloud providers and services using a declarative language. If you don’t have Terraform installed on your local machine yet, please refer to Install Terraform

AWS CLI (Amazon Web Services Command Line Interface) is a unified tool developed by Amazon to manage your AWS services from the command line. It provides a way to interact with AWS services directly from your terminal or command prompt, allowing you to automate tasks, manage resources, and perform various operations without using the AWS Management Console. If you don’t have AWS CLI installed on your local machine yet, please refer to Installing or updating to the latest version of the AWS CLI

You need AWS credentials for programmatic access created on the AWS account and configured on your local machine. For ways to create and configure them, see Setting up the AWS CLI.

Download and change parameters

Download

Download the code using git clone.

ShellScript
git clone https://github.com/lgdantas/Terraform-AWS-Private-Zone-and-TLS-Certificates.git

Another option is to download the zip file from GitHub, save and unzip the source.

Configure parameters

On terraform.tfvars file

  • Set the vpc id with your actual data.
  • Choose the private domain name.
  • If you want to provision a Private Certification Authority
    • Let the self_signed parameters commented.
    • Replace the Private CA parameters (country, organization etc) with the actual data.
  • If you are in an non-production environment and this is only a leraning experience you can provide your Self signed certificate parameters
# Required variables
vpc_id      = "vpc-xxxxxxxxxxxxxxxxx" # Replace with your VPC ID
domain_name = "sample.aws"            # Replace with your domain name

# Optional: Uncomment and modify if using self-signed certificates
# self_signed_cert = {
#  cert_file  = "cert/sample_pvtc.pem"
#  key_file   = "cert/sample_pvtk.pem"
#  chain_file = "cert/chain.pem"  # Optional
# }

# Optional: CA certificate details (used only if self_signed_cert is not provided)
ca_country             = "BR"
ca_organization        = "SAMPLE"
ca_organizational_unit = "IT"
ca_state               = "SP"
ca_locality            = "Sao Paulo"

Create the infrastructure

Once you have the parameters defined it is time to open the terminal in the terraform project root folder and initialize it.

ShellScript
terraform init

Terraform will display its output message.

ShellScript
Initializing the backend...

Initializing provider plugins...
- Finding hashicorp/aws versions matching "~> 5.0"...
- Installing hashicorp/aws v5.83.1...
- Installed hashicorp/aws v5.83.1 (signed by HashiCorp)

Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

Make sure that AWS CLI is connected to the right account and use terraform plan to predict what changes will be made on your AWS account.

ShellScript
terraform plan

Terraform will display all changes to be made.

ShellScript
...
Plan: 5 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + certificate_arn           = (known after apply)
  + certificate_authority_arn = (known after apply)
  + private_zone_id           = (known after apply)
  + private_zone_name_servers = (known after apply)

───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.
Terraform-AWS-Private-Zone-and-TLS-Certificates % 

Use terraform apply to provision the infrastructure.

ShellScript
terraform apply -auto-approve

Terraform will display its outputs.

ShellScript
...
Apply complete! Resources: 5 added, 0 changed, 0 destroyed.

Outputs:

certificate_arn = "arn:aws:acm:us-east-1:XXXXXXXXXXX:certificate/xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
certificate_authority_arn = "arn:aws:acm-pca:us-east-1:XXXXXXXXXXX:certificate-authority/xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx"
private_zone_id = "AAAAAAAAAAAAAAAAAAAAA"
private_zone_name_servers = tolist([
  "ns-0.awsdns-00.com.",
  "ns-1024.awsdns-00.org.",
  "ns-1536.awsdns-00.co.uk.",
  "ns-512.awsdns-00.net.",

Troubleshooting

You may see a message like this when you try to run Terraform without being connected to your account (AWS CLI):

ShellScript
Terraform-AWS-Private-Zone-and-TLS-Certificates % terraform plan

Planning failed. Terraform encountered an error while generating this plan.


 Error: Retrieving AWS account details: validating provider credentials: retrieving caller identity from STS: operation error STS: GetCallerIdentity, https response error StatusCode: 403, RequestID: ea442dc7-c067-428a-a45a-ae8fe17d8ba2, api error InvalidClientTokenId: The security token included in the request is invalid.
 
   with provider["registry.terraform.io/hashicorp/aws"],
   on main.tf line 11, in provider "aws":
   11: provider "aws" {
 

Terraform-AWS-Private-Zone-and-TLS-Certificates % 

Verify the infrastructure using the console

Open the Route53 console to check the Private Hosted Zone.

Open the AWS Private Certificate Authority console and ensure that the right region is selected to see your root private certificate authority.

Open the AWS Certificate Manager (ACM) console and ensure that the right region is selected to see your domain’s certificate.

The AWS Region can be selected or changed in the top-right corner of the AWS console.

Decomission

Use terraform destroy when you don’t need this infrastructure anymore.

ShellScript
terraform destroy -auto-approve

Terraform will display its outputs.

ShellScript
aws_acmpca_certificate_authority.ca[0]: Destruction complete after 0s
aws_route53_zone.private: Still destroying... [id=AAAAAAAAAAAAAAAAAAAAA, 10s elapsed]
aws_route53_zone.private: Still destroying... [id=AAAAAAAAAAAAAAAAAAAAA, 20s elapsed]
aws_route53_zone.private: Still destroying... [id=AAAAAAAAAAAAAAAAAAAAA, 30s elapsed]
aws_route53_zone.private: Still destroying... [id=AAAAAAAAAAAAAAAAAAAAA, 40s elapsed]
aws_route53_zone.private: Still destroying... [id=AAAAAAAAAAAAAAAAAAAAA, 50s elapsed]
aws_route53_zone.private: Still destroying... [id=AAAAAAAAAAAAAAAAAAAAA, 1m0s elapsed]
aws_route53_zone.private: Destruction complete after 1m5s

Destroy complete! Resources: 5 destroyed.
Terraform-AWS-Private-Zone-and-TLS-Certificates % 

Leave a Reply