AWS Certificate Manager Commands

Guide to managing SSL/TLS certificates using AWS Certificate Manager (ACM) through AWS CLI.

Prerequisites and Setup

Install AWS CLI

Install and configure AWS CLI:

# Install AWS CLI (macOS)
brew install awscli

# Install AWS CLI (Linux)
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install

# Configure AWS CLI
aws configure
# Enter: AWS Access Key ID, Secret Access Key, Default region, Output format

Set default region

ACM certificates are region-specific:

# Set region for session
export AWS_DEFAULT_REGION=us-east-1

# Or specify region in each command
aws acm list-certificates --region us-east-1

Requesting Certificates

Request public certificate

Request free SSL/TLS certificate from AWS:

# Request certificate for single domain
aws acm request-certificate \
  --domain-name example.com \
  --validation-method DNS

# Request with Subject Alternative Names
aws acm request-certificate \
  --domain-name example.com \
  --subject-alternative-names www.example.com api.example.com \
  --validation-method DNS

# Request wildcard certificate
aws acm request-certificate \
  --domain-name "*.example.com" \
  --subject-alternative-names example.com \
  --validation-method DNS

Email validation method

Use email validation instead of DNS:

aws acm request-certificate \
  --domain-name example.com \
  --validation-method EMAIL

Add tags to certificate

Tag certificates for organization:

aws acm request-certificate \
  --domain-name example.com \
  --validation-method DNS \
  --tags Key=Environment,Value=Production Key=Application,Value=WebServer

Certificate Validation

Get validation records

Retrieve DNS records for validation:

# Get certificate details
aws acm describe-certificate --certificate-arn arn:aws:acm:region:account:certificate/cert-id

# Extract validation records (using jq)
aws acm describe-certificate --certificate-arn arn:aws:acm:region:account:certificate/cert-id \
  | jq -r '.Certificate.DomainValidationOptions[]'

Automated DNS validation with Route53

Script to automatically create validation records:

#!/bin/bash
CERT_ARN="arn:aws:acm:region:account:certificate/cert-id"
HOSTED_ZONE_ID="Z1234567890ABC"

# Get validation records
aws acm describe-certificate --certificate-arn "$CERT_ARN" \
  --query 'Certificate.DomainValidationOptions[].ResourceRecord' \
  --output json | jq -r '.[] | "{\"Name\": \"" + .Name + "\", \"Type\": \"" + .Type + "\", \"Value\": \"" + .Value + "\"}"' | while read record; do

  # Create Route53 record
  aws route53 change-resource-record-sets \
    --hosted-zone-id "$HOSTED_ZONE_ID" \
    --change-batch '{
      "Changes": [{
        "Action": "UPSERT",
        "ResourceRecordSet": {
          "Name": "'$(echo $record | jq -r .Name)'",
          "Type": "'$(echo $record | jq -r .Type)'",
          "TTL": 300,
          "ResourceRecords": [{"Value": "'$(echo $record | jq -r .Value)'"}]
        }
      }]
    }'
done

Listing and Describing Certificates

List all certificates

View all ACM certificates in region:

# List all certificates
aws acm list-certificates

# List with specific status
aws acm list-certificates --certificate-statuses ISSUED

# List expired certificates
aws acm list-certificates --certificate-statuses EXPIRED

# List pending validation
aws acm list-certificates --certificate-statuses PENDING_VALIDATION

Describe certificate details

Get full certificate information:

# Full certificate details
aws acm describe-certificate --certificate-arn arn:aws:acm:region:account:certificate/cert-id

# Get expiration date
aws acm describe-certificate --certificate-arn arn:aws:acm:region:account:certificate/cert-id \
  --query 'Certificate.NotAfter' --output text

# Get domain names
aws acm describe-certificate --certificate-arn arn:aws:acm:region:account:certificate/cert-id \
  --query 'Certificate.SubjectAlternativeNames' --output json

List certificates by tag

Find certificates with specific tags:

# List tags for certificate
aws acm list-tags-for-certificate --certificate-arn arn:aws:acm:region:account:certificate/cert-id

# Find certificates with specific tag (requires scripting)
for cert in $(aws acm list-certificates --query 'CertificateSummaryList[].CertificateArn' --output text); do
  tags=$(aws acm list-tags-for-certificate --certificate-arn $cert --query 'Tags[?Key==`Environment`].Value' --output text)
  if [ "$tags" = "Production" ]; then
    echo $cert
  fi
done

Importing External Certificates

Import third-party certificate

Import certificate from external CA:

# Import certificate with chain
aws acm import-certificate \
  --certificate fileb://certificate.crt \
  --private-key fileb://private-key.pem \
  --certificate-chain fileb://certificate-chain.crt

# Import without chain (self-signed)
aws acm import-certificate \
  --certificate fileb://certificate.crt \
  --private-key fileb://private-key.pem

Reimport/renew imported certificate

Update existing imported certificate:

aws acm import-certificate \
  --certificate-arn arn:aws:acm:region:account:certificate/cert-id \
  --certificate fileb://new-certificate.crt \
  --private-key fileb://private-key.pem \
  --certificate-chain fileb://certificate-chain.crt

Certificate Renewal

Automatic renewal

ACM-issued certificates renew automatically:

# ACM automatically renews certificates if:
# 1. Certificate is associated with AWS resource (ALB, CloudFront, etc.)
# 2. DNS validation records are still in place

# Check renewal eligibility
aws acm describe-certificate --certificate-arn arn:aws:acm:region:account:certificate/cert-id \
  --query 'Certificate.RenewalEligibility' --output text

# Check renewal status
aws acm describe-certificate --certificate-arn arn:aws:acm:region:account:certificate/cert-id \
  --query 'Certificate.RenewalSummary' --output json

Monitor expiring certificates

Check for certificates expiring soon:

#!/bin/bash
# Find certificates expiring in 30 days
THRESHOLD=$(date -d "+30 days" +%s 2>/dev/null || date -v+30d +%s)

aws acm list-certificates --query 'CertificateSummaryList[].CertificateArn' --output text | while read arn; do
  EXPIRY=$(aws acm describe-certificate --certificate-arn $arn --query 'Certificate.NotAfter' --output text)
  EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s 2>/dev/null || date -j -f "%Y-%m-%dT%H:%M:%S" "$EXPIRY" +%s)

  if [ $EXPIRY_EPOCH -lt $THRESHOLD ]; then
    DOMAIN=$(aws acm describe-certificate --certificate-arn $arn --query 'Certificate.DomainName' --output text)
    echo "Certificate for $DOMAIN expires on $EXPIRY"
  fi
done

🔧 Exporting Certificates

Export private certificate

# Export certificate with private key (imported certs only)
aws acm export-certificate \
  --certificate-arn arn:aws:acm:region:account:certificate/cert-id \
  --passphrase $(echo -n "YourStrongPassphrase" | base64)

# Export returns certificate, private key, and chain in JSON
# Extract components using jq
aws acm export-certificate \
  --certificate-arn arn:aws:acm:region:account:certificate/cert-id \
  --passphrase $(echo -n "password" | base64) \
  | jq -r '.Certificate' > certificate.pem

aws acm export-certificate \
  --certificate-arn arn:aws:acm:region:account:certificate/cert-id \
  --passphrase $(echo -n "password" | base64) \
  | jq -r '.PrivateKey' > private-key.pem

aws acm export-certificate \
  --certificate-arn arn:aws:acm:region:account:certificate/cert-id \
  --passphrase $(echo -n "password" | base64) \
  | jq -r '.CertificateChain' > certificate-chain.pem

Note: ACM-issued public certificates cannot be exported. Only imported certificates can be exported.

🔧 Certificate Tagging

Add tags to certificate

# Add single tag
aws acm add-tags-to-certificate \
  --certificate-arn arn:aws:acm:region:account:certificate/cert-id \
  --tags Key=Environment,Value=Production

# Add multiple tags
aws acm add-tags-to-certificate \
  --certificate-arn arn:aws:acm:region:account:certificate/cert-id \
  --tags Key=Environment,Value=Production Key=Application,Value=WebServer Key=Owner,Value=DevOps

Tags help organize and categorize certificates for billing and management.

Remove tags from certificate

# Remove specific tags
aws acm remove-tags-from-certificate \
  --certificate-arn arn:aws:acm:region:account:certificate/cert-id \
  --tags Key=Environment Key=Application

Remove tags by specifying only the Key field.

List certificate tags

# List all tags for certificate
aws acm list-tags-for-certificate \
  --certificate-arn arn:aws:acm:region:account:certificate/cert-id

View all tags associated with a certificate.

🔧 Wildcard Certificates

Request wildcard certificate

# Request wildcard certificate (covers *.example.com but NOT example.com)
aws acm request-certificate \
  --domain-name "*.example.com" \
  --validation-method DNS

# Request wildcard AND apex domain (recommended)
aws acm request-certificate \
  --domain-name "*.example.com" \
  --subject-alternative-names example.com \
  --validation-method DNS

# Request with multiple wildcards
aws acm request-certificate \
  --domain-name "*.example.com" \
  --subject-alternative-names example.com "*.internal.example.com" \
  --validation-method DNS

Important: Wildcard certificates (*.example.com) do NOT cover the root domain (example.com). Always include both as SANs.

Wildcard validation

# Get validation records for wildcard certificate
aws acm describe-certificate \
  --certificate-arn arn:aws:acm:region:account:certificate/cert-id \
  --query 'Certificate.DomainValidationOptions[]' \
  --output json

# Wildcard certificates require only one DNS validation record
# The validation record is: _<token>.example.com (not _<token>.*.example.com)

Wildcard certificates require a single DNS validation record at the apex domain level.

🔧 AWS Private CA (ACM-PCA)

Create private certificate authority

# Create private CA
aws acm-pca create-certificate-authority \
  --certificate-authority-configuration file://ca-config.json \
  --certificate-authority-type ROOT \
  --idempotency-token 12345

# ca-config.json example:
{
  "KeyAlgorithm": "RSA_4096",
  "SigningAlgorithm": "SHA512WITHRSA",
  "Subject": {
    "Country": "US",
    "Organization": "Example Corp",
    "OrganizationalUnit": "IT",
    "State": "California",
    "Locality": "San Francisco",
    "CommonName": "Example Corp Root CA"
  }
}

Create private CA for internal certificate issuance.

Issue private certificate from CA

# Request private certificate from ACM-PCA
aws acm request-certificate \
  --domain-name internal.example.com \
  --certificate-authority-arn arn:aws:acm-pca:region:account:certificate-authority/ca-id

# Issue certificate from PCA (lower-level API)
aws acm-pca issue-certificate \
  --certificate-authority-arn arn:aws:acm-pca:region:account:certificate-authority/ca-id \
  --csr fileb://csr.pem \
  --signing-algorithm SHA256WITHRSA \
  --validity Value=365,Type=DAYS

Issue internal certificates from your private CA for non-public services.

List private CAs

# List all private certificate authorities
aws acm-pca list-certificate-authorities

# Describe specific CA
aws acm-pca describe-certificate-authority \
  --certificate-authority-arn arn:aws:acm-pca:region:account:certificate-authority/ca-id

View private CA configuration and status.

Using Certificates with AWS Services

Attach to Application Load Balancer (ALB)

Configure ALB with ACM certificate:

# Add HTTPS listener to ALB
aws elbv2 create-listener \
  --load-balancer-arn arn:aws:elasticloadbalancing:region:account:loadbalancer/app/my-alb/id \
  --protocol HTTPS \
  --port 443 \
  --certificates CertificateArn=arn:aws:acm:region:account:certificate/cert-id \
  --default-actions Type=forward,TargetGroupArn=arn:aws:elasticloadbalancing:region:account:targetgroup/my-targets/id

# Add multiple certificates (SNI)
aws elbv2 add-listener-certificates \
  --listener-arn arn:aws:elasticloadbalancing:region:account:listener/app/my-alb/id/listener-id \
  --certificates CertificateArn=arn:aws:acm:region:account:certificate/cert-id-2 \
               CertificateArn=arn:aws:acm:region:account:certificate/cert-id-3

# Update existing listener certificate
aws elbv2 modify-listener \
  --listener-arn arn:aws:elasticloadbalancing:region:account:listener/app/my-alb/id/listener-id \
  --certificates CertificateArn=arn:aws:acm:region:account:certificate/new-cert-id

Attach to Network Load Balancer (NLB)

Configure NLB with TLS termination:

# Create TLS listener for NLB
aws elbv2 create-listener \
  --load-balancer-arn arn:aws:elasticloadbalancing:region:account:loadbalancer/net/my-nlb/id \
  --protocol TLS \
  --port 443 \
  --certificates CertificateArn=arn:aws:acm:region:account:certificate/cert-id \
  --ssl-policy ELBSecurityPolicy-TLS-1-2-2017-01 \
  --default-actions Type=forward,TargetGroupArn=arn:aws:elasticloadbalancing:region:account:targetgroup/my-targets/id

Attach to CloudFront distribution

Use ACM certificate with CloudFront (must be in us-east-1):

# CloudFront requires certificate in us-east-1 region
# Create distribution with custom SSL certificate
aws cloudfront create-distribution \
  --distribution-config file://distribution-config.json

# distribution-config.json must include:
{
  "ViewerCertificate": {
    "ACMCertificateArn": "arn:aws:acm:us-east-1:account:certificate/cert-id",
    "SSLSupportMethod": "sni-only",
    "MinimumProtocolVersion": "TLSv1.2_2021"
  }
}

# Update existing CloudFront distribution certificate
aws cloudfront update-distribution \
  --id DISTRIBUTION_ID \
  --distribution-config file://updated-distribution-config.json

Attach to API Gateway

Configure custom domain for API Gateway:

# Create custom domain name
aws apigateway create-domain-name \
  --domain-name api.example.com \
  --regional-certificate-arn arn:aws:acm:region:account:certificate/cert-id \
  --endpoint-configuration types=REGIONAL

# For edge-optimized API Gateway (certificate must be in us-east-1)
aws apigateway create-domain-name \
  --domain-name api.example.com \
  --certificate-arn arn:aws:acm:us-east-1:account:certificate/cert-id \
  --endpoint-configuration types=EDGE

Attach to Elastic Beanstalk

Configure SSL for Elastic Beanstalk environment:

# Update Elastic Beanstalk environment with ACM certificate
aws elasticbeanstalk update-environment \
  --environment-name my-env \
  --option-settings \
    Namespace=aws:elbv2:listener:443,OptionName=Protocol,Value=HTTPS \
    Namespace=aws:elbv2:listener:443,OptionName=SSLCertificateArns,Value=arn:aws:acm:region:account:certificate/cert-id

Deleting Certificates

Delete certificate

Remove certificate from ACM:

# Delete certificate (must not be in use)
aws acm delete-certificate --certificate-arn arn:aws:acm:region:account:certificate/cert-id

# Check if certificate is in use before deletion
aws acm describe-certificate --certificate-arn arn:aws:acm:region:account:certificate/cert-id \
  --query 'Certificate.InUseBy' --output json

See Also

Important Notes

Free Public Certificates:

ACM public certificates are free. You only pay for AWS resources that use them (ALB, CloudFront, etc.). Private CA (ACM-PCA) has separate pricing.

Regional Service:

ACM certificates are region-specific. For CloudFront and edge-optimized API Gateway, certificate MUST be in us-east-1 region. For regional resources (ALB, NLB, regional API Gateway), use same region as resource.

Export Limitations:

ACM-issued public certificates CANNOT be exported with private keys. Only imported certificates can be exported. Use imported certificates if you need exportable keys for non-AWS resources.

Automatic Renewal:

ACM auto-renews public certificates if: (1) certificate is in use by AWS resource, and (2) DNS validation records still exist. Renewal begins 60 days before expiration. Imported certificates must be manually renewed.

Validation Methods:

DNS validation strongly recommended over email. DNS is fully automatable with Route 53, doesn't require manual email approval, and supports automatic renewal. Email validation requires manual action every 825 days.

Wildcard Certificates:

Wildcard certs (*.example.com) cover subdomains but NOT root domain. Always request both *.example.com and example.com as SANs for complete coverage.

Usage Restrictions:

ACM public certificates can only be used with integrated AWS services: ALB, NLB, CloudFront, API Gateway, Elastic Beanstalk, CloudFormation. Cannot be used directly with EC2, RDS, or on-premises servers.

SNI Support:

All supported AWS services use Server Name Indication (SNI) for multiple certificates. CloudFront dedicated IP addresses incur additional charges ($600/month per distribution).

Private CA:

Use ACM Private CA (acm-pca) for internal certificates, non-public domains, or custom CA hierarchies. Charged per CA per month plus per-certificate issuance fees.

Certificate Limits:

Default limits: 2,500 ACM certificates per region per account, 100 ACM Private CAs per region per account. Request limit increases through AWS Support if needed.

Documentation:

AWS ACM docs: docs.aws.amazon.com/acm

AWS CLI ACM reference: docs.aws.amazon.com/cli/latest/reference/acm

ACM Private CA docs: docs.aws.amazon.com/acm-pca