Files
hncb-fusion-deid-demo/terraform/custom_domain.tf
Conan Scott b5de55d4a6 feat(net): custom domain for the Fusion-facing API
Fusion couldn't resolve the default *.execute-api.amazonaws.com endpoint, so front
the same HTTP API with hncb-deid.apim-apac-demo.com (ACM DNS-validated cert,
apigatewayv2 REGIONAL custom domain, root api mapping, Route53 A ALIAS). Callers
resolve our hostname straight to IPs and never touch an execute-api name; also
survives API-id churn. Point POLICY_SETUP + README demo at the custom URLs.

Verified live: resolves to IPs, 401 unauthenticated, tokenizes with the key.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 11:04:19 +10:00

81 lines
2.9 KiB
HCL

# ---------------------------------------------------------------------------
# Custom domain for the Fusion-facing API. Fusion couldn't resolve the default
# *.execute-api.amazonaws.com hostname, so we front the same HTTP API with a
# stable name in a zone we control and point it with a Route53 ALIAS (A record).
# Callers resolve hncb-deid.apim-apac-demo.com -> IPs directly; they never have to
# resolve an execute-api / amazonaws.com name. Also survives API-id churn.
# ---------------------------------------------------------------------------
locals {
api_fqdn = "hncb-deid.apim-apac-demo.com"
}
data "aws_route53_zone" "api" {
name = "apim-apac-demo.com"
private_zone = false
}
# Regional API Gateway custom domains need the ACM cert in the SAME region.
resource "aws_acm_certificate" "api" {
domain_name = local.api_fqdn
validation_method = "DNS"
tags = local.onprem_tag
lifecycle {
create_before_destroy = true
}
}
resource "aws_route53_record" "api_cert_validation" {
for_each = {
for dvo in aws_acm_certificate.api.domain_validation_options : dvo.domain_name => {
name = dvo.resource_record_name
type = dvo.resource_record_type
record = dvo.resource_record_value
}
}
zone_id = data.aws_route53_zone.api.zone_id
name = each.value.name
type = each.value.type
records = [each.value.record]
ttl = 60
allow_overwrite = true
}
resource "aws_acm_certificate_validation" "api" {
certificate_arn = aws_acm_certificate.api.arn
validation_record_fqdns = [for r in aws_route53_record.api_cert_validation : r.fqdn]
}
resource "aws_apigatewayv2_domain_name" "api" {
domain_name = local.api_fqdn
domain_name_configuration {
certificate_arn = aws_acm_certificate_validation.api.certificate_arn
endpoint_type = "REGIONAL"
security_policy = "TLS_1_2"
}
tags = local.onprem_tag
}
# Map the custom domain at the root to the $default stage (routes: /tokenize, etc.)
resource "aws_apigatewayv2_api_mapping" "api" {
api_id = aws_apigatewayv2_api.gateway.id
domain_name = aws_apigatewayv2_domain_name.api.id
stage = aws_apigatewayv2_stage.default.id
}
# ALIAS (IPv4) -> returns IPs directly, so Fusion never resolves an AWS hostname.
resource "aws_route53_record" "api_alias" {
zone_id = data.aws_route53_zone.api.zone_id
name = local.api_fqdn
type = "A"
alias {
name = aws_apigatewayv2_domain_name.api.domain_name_configuration[0].target_domain_name
zone_id = aws_apigatewayv2_domain_name.api.domain_name_configuration[0].hosted_zone_id
evaluate_target_health = false
}
}
output "tokenize_url_custom" { value = "https://${local.api_fqdn}/tokenize" }
output "restore_url_custom" { value = "https://${local.api_fqdn}/restore" }
output "demo_url_custom" { value = "https://${local.api_fqdn}/demo" }