Orchestrating AWS Certificate Manager Certificates with Terraform: A Comprehensive Guide

AWS Certificate Manager (ACM) provides SSL/TLS certificates for securing applications, serving as a critical component of modern web infrastructure. Every public-facing service requires HTTPS, and ACM offers public certificates for integrated AWS services at no additional cost, with automatic renewal capabilities. However, the validation process presents specific nuances that often complicate infrastructure provisioning when using Infrastructure as Code (IaC) tools like Terraform. This guide details the technical mechanisms for requesting ACM certificates, automating Domain Name System (DNS) validation, handling wildcard certificates, and addressing regional constraints that affect services such as CloudFront and Application Load Balancers (ALB). By leveraging Terraform, organizations can move away from manual certificate management toward a fully automated, reproducible, and auditable deployment model that ensures zero-downtime certificate rotations and secure traffic distribution.

Requesting and Configuring ACM Certificates

The foundation of any secure deployment begins with the certificate request. ACM supports two primary validation methods: DNS and email. While email validation exists, DNS validation is strongly preferred in automated environments because it can be fully integrated with Terraform and Route 53 without human intervention. The aws_acm_certificate resource in Terraform allows users to define the certificate parameters, including the domain name, validation method, and subject alternative names. A critical aspect of certificate management is the lifecycle of the certificate itself. When certificates expire or when domains change, Terraform must manage the transition between the old and new certificates to prevent service interruption.

The create_before_destroy lifecycle rule is essential for this purpose. Without this rule, Terraform would destroy the existing certificate before creating the new one, causing immediate downtime for any services currently referencing the old certificate ARN. By instructing Terraform to create the new certificate before destroying the old one, infrastructure teams ensure that the application load balancers and other dependent resources maintain a valid SSL/TLS endpoint throughout the rotation process. Additionally, enabling certificate transparency logging is a best practice for security and compliance, allowing for the auditing of certificate issuance.

Below is a comprehensive Terraform configuration that demonstrates how to request a public certificate with DNS validation, subject alternative names, and the necessary lifecycle settings to ensure high availability.

```hcl

Public Certificate Resource

resource "awsacmcertificate" "main" {
domainname = var.domainname
validationmethod = "DNS"
subject
alternativenames = var.subjectalternative_names

options {
certificatetransparencylogging_preference = "ENABLED"
}

lifecycle {
createbeforedestroy = true
}

tags = merge(
var.tags,
{
Name = var.domain_name
}
)
}
```

In the configuration above, the subject_alternative_names argument allows for the inclusion of additional domains or subdomains covered by the certificate, which is particularly useful for wildcard certificates or multi-domain setups. The tags block provides metadata for cost allocation and management. The lifecycle block explicitly sets create_before_destroy to true, ensuring that the new certificate is issued and validated before the previous one is revoked or removed.

Automating DNS Validation with Route 53

To complete DNS validation, specific DNS records must be created to prove domain ownership. These records are derived from the domain_validation_options output of the aws_acm_certificate resource. This block contains the resource record name, type, and value required for validation. If the domain is hosted in Route 53, these records can be created programmatically using the aws_route53_record resource. This eliminates the manual step of logging into the Route 53 console and entering CNAME or TXT records.

The aws_route53_record resource requires the zone_id of the hosted zone where the domain is registered. The record type, name, and value are extracted directly from the certificate resource. It is crucial to handle multiple validation options correctly, especially when using wildcard certificates or subject alternative names. In such cases, the domain_validation_options block is a list of objects, and Terraform must iterate through these options or select the correct index if only one record is needed. For wildcard certificates, ACM provides two validation options, one for the base domain and one for the wildcard subdomain. Validating both is often recommended to ensure robustness.

The following code snippet illustrates the creation of the DNS validation record. Note the use of tolist to handle the list nature of the domain_validation_options attribute, ensuring compatibility with Terraform's type system.

hcl resource "aws_route53_record" "site_cert_dns" { allow_overwrite = true zone_id = aws_route53_zone.domain.zone_id name = tolist(aws_acm_certificate.site_cert.domain_validation_options)[0].resource_record_name records = [tolist(aws_acm_certificate.site_cert.domain_validation_options)[0].resource_record_value] type = tolist(aws_acm_certificate.site_cert.domain_validation_options)[0].resource_record_type ttl = 60 }

The allow_overwrite attribute is set to true to permit the Terraform provider to overwrite existing records of the same name and type, preventing conflicts if a record already exists. The ttl is set to a low value (60 seconds) to ensure that DNS changes propagate quickly during validation and subsequent rotations.

The Validation Resource and State Management

Once the DNS records are created, the certificate must be formally validated. This is handled by the aws_acm_certificate_validation resource. This resource does not create a new certificate but rather instructs ACM to verify that the DNS records match the validation options provided in the certificate request. It takes the certificate_arn from the aws_acm_certificate resource and the validation_record_fqdns from the aws_route53_record resource.

The aws_acm_certificate_validation resource acts as a dependency gate. Terraform will wait until the certificate status changes to ISSUED before allowing subsequent resources to proceed. This ensures that any resources referencing the certificate, such as an ALB listener or a CloudFront distribution, only attempt to use the certificate once it is fully validated and active. If the DNS records are not correctly created or if there is a delay in DNS propagation, this resource will time out, providing a clear signal that the validation process has failed.

hcl resource "aws_acm_certificate_validation" "site_cert_validation" { certificate_arn = aws_acm_certificate.site_cert.arn validation_record_fqdns = [aws_route53_record.site_cert_dns.fqdn] }

In environments where the DNS records are managed outside of Terraform or in a separate hosted zone, the validation_record_fqdns can be supplied manually or retrieved from external data sources. However, when using Route 53, the integration is seamless. The FQDN (Fully Qualified Domain Name) of the created record is used as the identifier for the validation process.

Regional Constraints and CloudFront Integration

A significant constraint in ACM certificate management is regionality. ACM certificates are region-specific. While a certificate issued in one region can be used by resources in that same region, CloudFront requires certificates to be issued in the us-east-1 region, regardless of where the origin server is located. This creates a dependency where the certificate provider must be configured specifically for us-east-1 if the certificate is intended for use with CloudFront.

To manage this, Terraform providers can be aliased. This allows a single Terraform configuration to interact with multiple AWS regions. For example, a deployment might use resources in eu-west-1 for compute and us-east-1 for the ACM certificate and CloudFront distribution. The provider block is used to define the default region and any aliased regions.

```hcl
provider "aws" {
region = "eu-west-1"
}

provider "aws" {
alias = "us-east-1"
region = "us-east-1"
}
```

When referencing the certificate in a resource that resides in a different region, the provider alias must be explicitly assigned. For instance, if the ALB is in eu-west-1 but the certificate must be in us-east-1 for CloudFront, the ALB listener would actually need to reference a certificate in us-east-1 if it is being distributed via CloudFront, or a certificate in the same region if it is directly accessing the ALB. In the case of CloudFront, the certificate ARN is taken from the us-east-1 provider.

The aws_acm_certificate resource can be assigned the us-east-1 provider alias to ensure it is created in the correct region.

```hcl
resource "awsacmcertificate" "sitecert" {
provider = aws.us-east-1
domain
name = var.domainname
validation
method = "DNS"

lifecycle {
createbeforedestroy = true
}
}
```

This approach ensures that the certificate is available to CloudFront and any other global service that requires the certificate to be in us-east-1.

Utilizing Certificates in AWS Resources

Once the certificate is validated, it can be referenced in other AWS resources. The most common use case is configuring an HTTPS listener on an Application Load Balancer. The certificate_arn argument of the aws_lb_listener resource requires the ARN of the certificate. It is important to reference the ARN from the aws_acm_certificate_validation resource or the aws_acm_certificate resource, ensuring that the reference points to the validated and active certificate.

```hcl
resource "awslblistener" "https" {
loadbalancerarn = awslb.main.arn
port = 443
protocol = "HTTPS"
ssl
policy = "ELBSecurityPolicy-TLS13-1-2-2021-06"
certificatearn = awsacmcertificatevalidation.sitecertvalidation.certificate_arn

defaultaction {
type = "forward"
target
grouparn = awslbtargetgroup.app.arn
}
}
```

In the example above, the certificate_arn is taken from the aws_acm_certificate_validation resource. This is often preferred over referencing the aws_acm_certificate resource directly because the validation resource ensures that the certificate is in an ISSUED state before the listener is created. The ssl_policy is set to a modern TLS policy, ensuring secure communication. The default_action forwards traffic to the target group, which can contain ECS tasks, EKS pods, or Elastic Beanstalk instances.

Data Sources for Existing Certificates

In scenarios where certificates are managed outside of Terraform or need to be referenced for read-only purposes, the aws_acm_certificate data source can be used. This data source provides details about a specific ACM certificate without creating a new one. It is useful for retrieving the ARN of an existing certificate to use in other resources, such as an S3 bucket policy or an API Gateway configuration.

The data source requires specific arguments to identify the certificate, such as the domain name and the region. Refer to the Terraform Registry documentation for all available arguments and filters.

hcl data "aws_acm_certificate" "example" { domain_name = "example.com" statuses = ["ISSUED"] }

This allows Terraform to integrate with existing certificate management practices, ensuring that infrastructure changes do not disrupt manually managed certificates while still maintaining declarative control over dependent resources.

Architecture and Project Structure

A robust Terraform project for ACM certificate management typically follows a modular structure. This allows for reusability and clarity. A common project structure includes a root module that orchestrates the certificate management, DNS, and dependent services, and a dedicated acm module that encapsulates the certificate logic.

text terraform-acm/ ├── main.tf ├── variables.tf ├── outputs.tf ├── modules/ │ └── acm/ │ ├── main.tf │ ├── variables.tf │ └── outputs.tf └── config/ └── domains.json

The modules/acm/main.tf file contains the resource definitions for the certificate, DNS record, and validation resource. The variables.tf file defines inputs such as domain_name and subject_alternative_names. The outputs.tf file exposes the certificate_arn for use by other modules. This modular approach supports the architecture where ACM is used for public certificates, Private CA for internal certificates, and Route 53 for DNS validation. The integration with other AWS services, such as ECS, EKS, and Elastic Beanstalk, is facilitated by the reference of the certificate ARN in the load balancer and distribution configurations.

Best Practices and Operational Considerations

Managing ACM certificates with Terraform requires attention to several operational details. First, state management is critical. Using an S3 backend with DynamoDB locking ensures that state files are stored securely and that concurrent Terraform runs do not corrupt the state. The backend configuration includes the region, bucket, key, and DynamoDB table for locking.

hcl terraform { backend "s3" { region = "eu-west-1" bucket = "_insert_bucket_name_" key = "domain-r53-acm.tfstate" dynamodb_table = "_insert_dynamodb_lock_table_name_" encrypt = true } }

Second, monitoring and logging should be enabled. ACM logs certificate issuance and renewal events to CloudWatch Logs. Integrating these logs with an alerting system ensures that any validation failures or renewal issues are detected promptly. Third, testing the certificate expiration and renewal process in a staging environment is recommended. By simulating an expiration, teams can verify that the create_before_destroy logic works as expected and that dependent services automatically pick up the new certificate ARN without manual intervention.

Finally, it is important to consider the cost implications of domain registration and hosted zone maintenance. While ACM certificates are free for public use with integrated services, Route 53 hosted zones incur a monthly fee, and domain registration has annual costs. These costs should be factored into the total cost of ownership of the infrastructure.

Conclusion

The integration of AWS Certificate Manager with Terraform represents a mature and essential practice in modern DevOps and cloud infrastructure management. By automating the certificate request, DNS validation, and renewal processes, teams can eliminate manual errors, reduce operational overhead, and ensure continuous compliance with security standards. The ability to handle regional constraints through provider aliasing and to manage zero-downtime rotations through lifecycle rules makes Terraform a powerful tool for orchestrating SSL/TLS certificates in complex multi-service architectures. Whether deploying a simple web application behind an ALB or a global distribution via CloudFront, the principles of automated certificate management remain consistent. Understanding the nuances of DNS validation, the importance of the aws_acm_certificate_validation resource, and the strategic use of Terraform's data sources and providers enables engineers to build secure, scalable, and resilient infrastructure. As cloud ecosystems evolve, the role of Infrastructure as Code in managing cryptographic assets will only become more central, making proficiency in this area a critical skill for cloud engineers.

Sources

  1. AWS Fundamentals
  2. The Cloud Panda
  3. OneUptime
  4. Head for the Cloud

Related Posts