AWS ACM Certificate Expiry Alerts Beyond Default
AWS Certificate Manager (ACM) is a fantastic service. It simplifies the provisioning, management, and deployment of SSL/TLS certificates for your AWS services like Elastic Load Balancers (ELBs), CloudFront distributions, and API Gateways. For AWS-issued certificates, ACM even handles automatic renewal, often without you needing to lift a finger. It's magic, right?
Well, mostly.
While ACM's automatic renewal is a huge win, relying solely on its default notifications can leave critical blind spots in your infrastructure. As engineers, we know that "mostly" isn't good enough when it comes to security and uptime. Unexpected certificate expiry is a classic cause of production outages, user trust issues, and frantic, late-night fixes. This article will explore why the default ACM alerts might not be sufficient for your needs and how you can build a more robust, proactive monitoring strategy.
The AWS ACM Default Renewal Process (and its Blind Spots)
For certificates issued by ACM, the service attempts to renew them automatically, typically 45 days before expiry. This process usually works seamlessly if your validation methods (DNS or email) remain intact.
- DNS Validation: If you use DNS validation, ACM looks for the CNAME record it provided in your DNS configuration. As long as this record exists and is resolvable, ACM can re-validate domain ownership and renew the certificate.
- Email Validation: For email-validated certificates, ACM sends renewal notices to the domain's WHOIS contact email addresses, or a set of common administrative addresses (e.g., admin@, hostmaster@). Someone needs to click a link in that email to approve the renewal.
However, this "set it and forget it" model has critical blind spots:
- Imported Certificates: This is the big one. If you've imported a certificate into ACM (e.g., a wildcard certificate from a third-party CA, or one you manage via ACME clients), ACM will never automatically renew it. You are solely responsible for monitoring its expiry and importing a new certificate well in advance. The default notifications for imported certs are often too close to expiry to allow for proper renewal and deployment.
- Broken DNS Validation: Accidental deletion or modification of the ACM CNAME record in your DNS provider can silently break the automatic renewal process. ACM won't be able to validate ownership, and the certificate will eventually expire.
- Failed Email Validation: If the email addresses used for validation are no longer monitored, or if your mail server blocks ACM's renewal emails, the renewal process will stall, leading to expiry.
- Unused or Forgotten Resources: Certificates might be attached to old Load Balancers, CloudFront distributions, or API Gateways that are no longer actively managed but haven't been decommissioned. These can expire and cause issues if they're still in use by some obscure legacy system or if they block new deployments.
- The 45-Day Window: For complex environments with change control processes, multiple teams, and cross-region deployments, 45 days isn't always enough lead time. You might need 60, 90, or even 120 days to ensure a smooth, risk-free renewal.
Why Default Alerts Aren't Enough for Engineers
The default ACM notifications are often just emails sent to the root account or specific contacts. While better than nothing, they fall short for several reasons:
- Lack of Centralization: Alerts are often siloed within email inboxes, easily missed amidst other notifications.
- Insufficient Lead Time: As mentioned, 45 days can be too short for critical production systems that require extensive testing and deployment windows.
- No Aggregation: If you manage hundreds of certificates across multiple AWS accounts and regions, you'll get a flood of individual emails, making it hard to prioritize and track.
- Limited Integration: Default alerts don't easily integrate with your existing incident management tools (Slack, PagerDuty, Jira).
- Actionability: The alerts often just state "certificate expiring" without providing immediate context on which service it's attached to, who owns it, or what the next steps are.
The goal isn't just to be notified of an impending expiry, but to be alerted proactively and actionably with enough time to prevent an incident.
Building Your Own Proactive ACM Expiry Monitoring (The DIY Approach)
If the default alerts aren't cutting it, you can build your own monitoring solution. This typically involves scripting or using AWS services in conjunction.
Option 1: AWS CLI/SDK Scripting for Early Detection
You can periodically poll ACM using the AWS CLI or SDK to get a comprehensive list of your certificates and their expiry dates. This approach gives you granular control.
Here's a simple Python script snippet that lists certificates nearing expiry. You'd typically run this from a Lambda function, EC2 instance, or CI/CD pipeline.
import boto3
from datetime import datetime, timedelta, timezone
def check_acm_certificates(days_threshold=60):
client = boto3.client('acm')
expiring_certificates = []
paginator = client.get_paginator('list_certificates')
for page in paginator.paginate(CertificateStatuses=['ISSUED', 'PENDING_VALIDATION']):
for cert_summary in page['CertificateSummaryList']:
cert_arn = cert_summary['CertificateArn']
cert_description = client.describe_certificate(CertificateArn=cert_arn)['Certificate']
not_after = cert_description['NotAfter'] # This is a datetime object
# Convert 'not_after' to a timezone-aware datetime if it's not already
# AWS usually returns timezone-aware datetime objects, but it's good practice to ensure.
if not_after.tzinfo is None:
not_after = not_after.replace(tzinfo=timezone.utc)
# Get current time, also timezone-aware
now = datetime.now(timezone.utc)
time_until_expiry = not_after - now
if time_until_expiry < timedelta(days=days_threshold):
cert_info = {
'DomainName': cert_description.get('DomainName', 'N/A'),
'CertificateArn': cert_arn,
'NotAfter': not_after.isoformat(),
'Status': cert_description.get('Status', 'N/A'),
'Type': cert_description.get('Type', 'N/A'), # 'IMPORTED' vs 'AMAZON_ISSUED'
'DaysUntilExpiry': time_until_expiry.days
}
expiring_certificates.append(cert_info)
return expiring_certificates
if __name__ == "__main__":
threshold = 90 # Alert for certificates expiring in the next 90 days
expiring_certs = check_acm_certificates(threshold)
if expiring_certs:
print(f"Found {len(expiring_certs)} certificates expiring within {threshold} days:")
for cert in expiring_certs:
print(f"- Domain: {cert['DomainName']}, ARN: {cert['CertificateArn']}, Type: {cert['Type']}, Expires: {cert['NotAfter']} ({cert['DaysUntilExpiry']} days left)")
# Here you would integrate with SNS, Slack, PagerDuty, etc.
else:
print(f"No certificates expiring within {threshold} days found.")
This script allows you to:
* Define a custom days_threshold (e.g., 90 or 120 days) for earlier alerts.
* Identify Type: IMPORTED certificates specifically, which require manual intervention.
* Integrate with AWS SNS, Slack webhooks, or other alert systems once a certificate is detected as expiring.
Option 2: AWS Config Rules
AWS Config offers a managed rule called acm-certificate-expiration-check. This rule evaluates if your ACM certificates are expiring within a specified number of days (default 45).
You can enable it via the AWS Config console or CLI:
aws configservice put-config-rule \
--config-rule-name acm-certificate-expiration-check \
--source Owner=AWS,SourceIdentifier=ACM_CERTIFICATE_EXPIRATION_CHECK \
--input-parameters '{"daysToExpiration":"60"}' \
--description "Checks if ACM certificates are expiring within 60 days."
Caveat: This rule only works for AWS-issued certificates. It will not detect imported certificate expirations. For imported certificates