Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions acm-certificate/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# ACM Certificate

This module provisions an AWS ACM certificate for one or more domains and optionally performs automatic DNS validation
using Route 53.

## Features

- AWS ACM certificate with multi-domain (SAN) support
- Optional automatic DNS validation via Route 53
- Ability to manage DNS validation externally if no hosted zone is provided
- Deterministic primary domain selection
- Safe certificate replacement using `create_before_destroy`
- Resource tagging support

## Usage

See `variables.tf` for the full argument reference.

```hcl
module "acm_certificate" {
source = "github.com/script47/aws-tf-modules/acm-certificate"

domains = [
"example.org",
"www.example.org"
]

zone_id = "Z123456789"

tags = {
Project = "my-project"
Service = "my-service"
Environment = "production"
}

providers = {
aws.default = aws
aws.acm = aws.useast1
}
}
26 changes: 26 additions & 0 deletions acm-certificate/acm.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
locals {
domains = distinct(var.domains)
primary_domain = local.domains[0]
}

resource "aws_acm_certificate" "this" {
domain_name = local.primary_domain
subject_alternative_names = local.domains
validation_method = "DNS"
tags = var.tags

lifecycle {
create_before_destroy = true
}

provider = aws.acm
}

resource "aws_acm_certificate_validation" "this" {
for_each = var.zone_id == null ? {} : { "validation" = true }

certificate_arn = aws_acm_certificate.this.arn
validation_record_fqdns = [for record in aws_route53_record.acm_records : record.fqdn]

provider = aws.acm
}
17 changes: 17 additions & 0 deletions acm-certificate/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
output "arn" {
value = var.zone_id == null ? aws_acm_certificate.this.arn : aws_acm_certificate_validation.this["validation"].certificate_arn
}

output "dns" {
value = {
domains = local.domains
records = {
for dvo in aws_acm_certificate.this.domain_validation_options :
dvo.domain_name => {
type = dvo.resource_record_type
name = dvo.resource_record_name
value = dvo.resource_record_value
}
}
}
}
14 changes: 14 additions & 0 deletions acm-certificate/providers.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
terraform {
required_version = ">= 1.13"

required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6"
configuration_aliases = [
aws.acm,
aws.default,
]
}
}
}
17 changes: 17 additions & 0 deletions acm-certificate/route53.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#############################################
# Validation for the ACM cert
#############################################
resource "aws_route53_record" "acm_records" {
for_each = var.zone_id == null ? {} : {
for o in aws_acm_certificate.this.domain_validation_options : o.domain_name => o
}

zone_id = var.zone_id
type = each.value.resource_record_type
name = each.value.resource_record_name
records = [each.value.resource_record_value]
ttl = 60
allow_overwrite = true

provider = aws.default
}
20 changes: 20 additions & 0 deletions acm-certificate/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
variable "zone_id" {
type = string
description = "The ID of the hosted zone"
default = null
}

variable "domains" {
type = list(string)
description = "List of domain names for your CloudFront distribution. The first domain specified will be classed as the primary domain (used as S3 bucket name, Route53 hosted zone name etc.)"

validation {
condition = length(var.domains) > 0
error_message = "domains requires at least one domain to be specified"
}
}

variable "tags" {
type = map(string)
description = "The tags to apply to all resources created"
}
2 changes: 1 addition & 1 deletion lambda-function/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ This module allows you to setup a Lambda function.
See `variables.tf` for the full argument reference.

```hcl
module "static_site" {
module "lambda_fn" {
source = "github.com/script47/aws-tf-modules/lambda-function"

name = "my-lambda-func"
Expand Down
4 changes: 2 additions & 2 deletions lambda-function/outputs.tf
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
output "lambda" {
output "fn" {
value = {
arn = aws_lambda_function.fn.arn
invoke_arn = aws_lambda_function.fn.invoke_arn
}
}

output "cloudwatch" {
output "log_group" {
value = {
arn = length(aws_cloudwatch_log_group.logs) > 0 ? aws_cloudwatch_log_group.logs[0].arn : null
}
Expand Down
1 change: 1 addition & 0 deletions static-site/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ variable "hosted_zone" {
variable "domains" {
type = list(string)
description = "List of domain names for your CloudFront distribution. The first domain specified will be classed as the primary domain (used as S3 bucket name, Route53 hosted zone name etc.)"

validation {
condition = length(var.domains) > 0
error_message = "domains requires at least one domain to be specified"
Expand Down
Loading