Prerequisites
Before requesting an ACM certificate:- Domain name: You must own a domain name (e.g.,
example.com) - DNS access: Ability to create DNS records for domain validation
- ALB created: Your Application Load Balancer must exist
ACM certificates are free and automatically renew. You only pay for the resources using them (ALB).
Certificate Strategy
For the ADMA application, request a certificate that covers both your main domain and subdomains:- Primary domain:
example.com(frontend) - API subdomain:
api.example.com(backend) - Short URL subdomain:
go.example.com(redirect domain)
Request ACM Certificate
Use DNS validation for automated renewals. Email validation requires manual intervention every 13 months.
export DOMAIN="example.com" # Replace with your domain
CERT_ARN=$(aws acm request-certificate \
--domain-name $DOMAIN \
--subject-alternative-names "*.$DOMAIN" \
--validation-method DNS \
--region $AWS_REGION \
--query 'CertificateArn' \
--output text)
echo "Certificate ARN: $CERT_ARN"
CERT_ARN=$(aws acm request-certificate \
--domain-name $DOMAIN \
--subject-alternative-names "api.$DOMAIN" "go.$DOMAIN" "www.$DOMAIN" \
--validation-method DNS \
--region $AWS_REGION \
--query 'CertificateArn' \
--output text)
aws acm describe-certificate \
--certificate-arn $CERT_ARN \
--region $AWS_REGION \
--query 'Certificate.DomainValidationOptions[].ResourceRecord' \
--output table
----------------------------------------------------------------------
| DescribeCertificate |
+------------+-------------------------------------------------------+
| Name | _abc123.example.com |
| Type | CNAME |
| Value | _xyz456.acm-validations.aws. |
+------------+-------------------------------------------------------+
DNS Validation
Validate with Route 53 (Automatic)
If your domain uses Route 53, ACM can create validation records automatically:HOSTED_ZONE_ID=$(aws route53 list-hosted-zones \
--query "HostedZones[?Name=='$DOMAIN.'].Id" \
--output text | cut -d'/' -f3)
echo "Hosted Zone ID: $HOSTED_ZONE_ID"
# Get validation record details
VALIDATION_RECORD=$(aws acm describe-certificate \
--certificate-arn $CERT_ARN \
--region $AWS_REGION \
--query 'Certificate.DomainValidationOptions[0].ResourceRecord' \
--output json)
RECORD_NAME=$(echo $VALIDATION_RECORD | jq -r '.Name')
RECORD_VALUE=$(echo $VALIDATION_RECORD | jq -r '.Value')
# Create the CNAME record
aws route53 change-resource-record-sets \
--hosted-zone-id $HOSTED_ZONE_ID \
--change-batch '{
"Changes": [{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "'$RECORD_NAME'",
"Type": "CNAME",
"TTL": 300,
"ResourceRecords": [{"Value": "'$RECORD_VALUE'"}]
}
}]
}'
aws acm describe-certificate \
--certificate-arn $CERT_ARN \
--region $AWS_REGION \
--query 'Certificate.Status' \
--output text
Validate with External DNS Provider
If you use a different DNS provider (Cloudflare, GoDaddy, Namecheap, etc.):aws acm describe-certificate \
--certificate-arn $CERT_ARN \
--region $AWS_REGION \
--query 'Certificate.DomainValidationOptions[].ResourceRecord'
_abc123.example.com (from ACM output)_xyz456.acm-validations.aws. (from ACM output)Some DNS providers require you to enter only the subdomain part (e.g.,
_abc123) without the domain name.Configure ALB to Use Certificate
Update Existing HTTPS Listener
If you created an HTTPS listener without a certificate:Create New HTTPS Listener
If you only have an HTTP listener:Add Routing Rules to HTTPS Listener
Re-create the routing rules if you created a new listener:Configure DNS for Your Domain
Point Domain to ALB
Create DNS records pointing to your ALB:Route 53 Alias records are preferred over CNAME for root domains and provide better performance (no additional DNS lookup).
SSL/TLS Security Policies
Recommended Policy
The default policyELBSecurityPolicy-TLS-1-2-2017-01 supports:
- TLS 1.2 and TLS 1.3
- Modern cipher suites
- Perfect Forward Secrecy (PFS)
Available Policies
List available SSL policies:Stricter Policy (TLS 1.3 Only)
For maximum security:Test HTTPS Configuration
Subject: CN=example.com
Issuer: CN=Amazon, OU=Server CA 1B, O=Amazon, C=US
Verify return code: 0 (ok)
# Test frontend
curl -I https://$DOMAIN
# Test backend API
curl https://api.$DOMAIN/api/stats
# Test short URL
curl -I https://go.$DOMAIN/abc1234
Update Application Configuration
Update environment variables in your ECS task definitions:Backend Task Definition
Update these values ininfrastructure/task-def-backend.json:
Frontend Rebuild
Rebuild and push the frontend with the HTTPS API URL:Certificate Renewal
ACM certificates automatically renew before expiration:- Renewal attempt: 60 days before expiration
- DNS validation: Must remain valid for automatic renewal
- No action required if DNS validation records exist
Monitor Certificate Expiration
Set up a CloudWatch alarm:Troubleshooting
Certificate Stuck in PENDING_VALIDATION
Cause: DNS validation record not found Solution:- Verify the CNAME record is created correctly
- Check DNS propagation:
dig _abc123.example.com CNAME - Ensure you used the exact name and value from ACM
NET::ERR_CERT_COMMON_NAME_INVALID
Cause: Certificate doesn’t cover the domain you’re accessing Solution: Request a new certificate with the correct domain/SANsMixed Content Warnings
Cause: Frontend loading HTTP resources over HTTPS Solution: Ensure all resources (scripts, images) use HTTPS URLs or relative pathsCORS Errors After HTTPS
Cause: CORS configuration still allows HTTP origins Solution: UpdateCORS_ALLOWED_ORIGINS to use HTTPS URLs
Security Best Practices
- ✅ Use TLS 1.2 or higher (disable TLS 1.0/1.1)
- ✅ Enable HTTP Strict Transport Security (HSTS)
- ✅ Use wildcard certificates sparingly
- ✅ Rotate certificates annually (ACM does this automatically)
- ✅ Monitor certificate expiration
- ✅ Test SSL configuration with SSL Labs
Next Steps
With HTTPS configured:- Enable security headers (HSTS, CSP, X-Frame-Options)
- Set up CloudWatch monitoring and alarms
- Configure auto-scaling for ECS services
- Implement CI/CD for automated deployments
- Create production database backups