Skip to main content
emnode / learn
Compliance

Use ACM certificates on Classic Load Balancers

Security Hub ELB.2 — a Classic Load Balancer terminating HTTPS with a hand-managed certificate is one expired cert away from an outage; move it to ACM so renewal is automatic.

12 min·10 sections·AWS

Last reviewed

Remediates AWS Security Hub: ELB.2

ACM certificates on Classic Load Balancers: the basics

Why a self-managed SSL certificate on a CLB is a latent outage

A Classic Load Balancer (CLB) with an HTTPS or SSL listener has to present a TLS certificate to every client that connects. AWS gives you two ways to supply that certificate: import one into AWS Certificate Manager (ACM), or upload a hand-managed certificate into IAM (the old aws iam upload-server-certificate path). Security Hub control ELB.2 checks which one you used. It fails the CLB if a HTTPS/SSL listener is serving a certificate that did not come from ACM.

The reason ACM is preferred is renewal. Certificates expire — typically every 13 months for a public cert. An ACM-issued certificate that's actually attached to a load balancer renews itself automatically before it lapses, with no human in the loop. A certificate you uploaded to IAM does not: someone has to remember the expiry date, generate a new cert, re-upload it, and re-point the listener. That "someone remembers" step is exactly what fails at 2 a.m. on a holiday weekend.

It's flagged at Medium severity because the failure mode is a hard, total outage, not a slow degradation. When the cert expires, every browser and API client gets a TLS error and the service is effectively down until someone rotates it. ELB.2 is AWS pointing at the load balancers where that clock is ticking and nobody has wired up the automatic renewal that would stop it.

In this lesson you'll learn why a Classic Load Balancer's HTTPS listener needs a certificate, the difference between an ACM-managed certificate and a legacy IAM-uploaded one, and why ELB.2 cares which you use. You'll see the AWS CLI commands to find non-compliant CLBs and the source of their listener certificates, the safe path to move a listener onto an ACM certificate without dropping connections, and the gotchas — automatic renewal only fires when the cert is actually in use, in-region ACM requirements for CLBs, and what happens to imported (versus AWS-issued) certificates.

Fun fact

The certificate that took down a whole platform

Expired-certificate outages are common enough that they have a folklore. In one widely reported case, a major communications provider's voice service went down for hours because a single TLS certificate lapsed — no breach, no attack, just a date that passed with nobody watching. The pattern repeats across the industry every year: the certificate is valid, the renewal is owned by someone who changed teams, and the calendar reminder lives in a spreadsheet nobody opens. ELB.2 exists precisely because AWS can remove this entire failure class with one setting — an ACM-issued certificate that's in active use renews itself automatically, turning a recurring manual deadline into a non-event.

Moving a Classic Load Balancer to an ACM certificate in action

Dev is the platform engineer on call when the weekly Security Hub digest lands. ELB.2 is failing on legacy-api-clb, a Classic Load Balancer fronting an internal-but-important billing API. It still has plenty of traffic, so retiring it isn't an option this quarter — the certificate just needs to move to ACM.

He checks the listener and sees the SSL certificate ARN points at arn:aws:iam::...:server-certificate/... — the legacy IAM-uploaded path, which is exactly why ELB.2 fails. He looks up the existing certificate's domain, then checks ACM in the same region and finds an AWS-issued certificate for the same domain already exists (it was provisioned for the new ALB migration that never finished).

Rather than re-pointing the live listener blind, Dev confirms the ACM cert covers the right domain and is in ISSUED status, then swaps the listener's certificate to the ACM ARN with a single CLI call. The change is non-disruptive — existing connections drain, new TLS handshakes use the ACM cert immediately. ELB.2 flips to PASSED on the next evaluation, and because the cert is now ACM-managed and in use, its renewal is automatic from here on.

First, find which HTTPS/SSL listeners on your Classic Load Balancers are serving a non-ACM certificate. An IAM server-certificate ARN is the tell.

$ aws elb describe-load-balancers --query 'LoadBalancerDescriptions[].{Name:LoadBalancerName,Listeners:ListenerDescriptions[].Listener.SSLCertificateId}' --output table
-----------------------------------------------------------------------------------
| DescribeLoadBalancers |
+------------------+--------------------------------------------------------------+
| Name | Listeners |
+------------------+--------------------------------------------------------------+
| legacy-api-clb | arn:aws:iam::111122223333:server-certificate/legacy-api-2024 |
| checkout-clb | arn:aws:iam::111122223333:server-certificate/checkout-old |
| internal-tools | arn:aws:acm:us-east-1:111122223333:certificate/9f1c-... |
+------------------+--------------------------------------------------------------+
# IAM server-certificate ARNs fail ELB.2; the acm:...:certificate ARN passes.

Listener certificate source per CLB — IAM ARNs are the ones ELB.2 flags.

Confirm an ACM certificate exists for the same domain in this region and is ISSUED, then point the listener at it. This swap is non-disruptive to in-flight connections.

$ aws elb set-load-balancer-listener-ssl-certificate --load-balancer-name legacy-api-clb --load-balancer-port 443 --ssl-certificate-id arn:aws:acm:us-east-1:111122223333:certificate/9f1c2d34-5678-90ab-cdef-EXAMPLE11111
# (no output on success — verify the listener now reports the ACM ARN)
$ aws elb describe-load-balancers --load-balancer-names legacy-api-clb \
--query 'LoadBalancerDescriptions[0].ListenerDescriptions[].Listener.SSLCertificateId'
[
"arn:aws:acm:us-east-1:111122223333:certificate/9f1c2d34-..."
]
# Listener now serves the ACM cert — renewal is automatic while it stays in use.

Re-point the HTTPS listener to the ACM certificate ARN; ELB.2 passes on the next evaluation.

ELB.2 and ACM under the hooddeep dive

ELB.2 maps to the AWS Config managed rule elb-acm-certificate-required, evaluated change-triggered against the AWS::ElasticLoadBalancing::LoadBalancer resource type (the v1 Classic Load Balancer, not the v2 ALB/NLB). The rule inspects each HTTPS/SSL listener's SSLCertificateId. If that ARN is in the acm service namespace (arn:aws:acm:...:certificate/...) the listener passes; if it's an iam server-certificate ARN (arn:aws:iam::...:server-certificate/...), the control reports FAILED. A CLB with no HTTPS/SSL listener at all is out of scope for ELB.2 — there's no certificate to check.

The operational payoff of ACM is managed renewal, but there's a critical condition: ACM only renews a certificate automatically while it is associated with an in-use AWS resource such as a load balancer. An ACM certificate that's issued but attached to nothing will not auto-renew. That's why the fix isn't "create an ACM cert" — it's "attach the ACM cert to the listener," which both clears ELB.2 and enables the renewal that makes it worthwhile. Note also that for Classic and Application Load Balancers the ACM certificate must live in the same Region as the load balancer.

There's a distinction between AWS-issued and imported ACM certificates. ACM auto-renews certificates it issued itself (via DNS or email validation). Certificates you import into ACM from an external CA still satisfy ELB.2 — they came from ACM — but ACM cannot renew them automatically; you get expiry notifications and must re-import. So passing ELB.2 with an imported cert removes the IAM-upload problem but not the manual-renewal one. The fully automatic outcome requires an ACM-issued certificate with DNS validation on a Route 53 (or otherwise automatable) zone.

# List ACM certificates in this region and their status before re-pointing a listener.
aws acm list-certificates \
  --query 'CertificateSummaryList[].{Domain:DomainName,Arn:CertificateArn}' \
  --output table

# Inspect a specific cert: type (AMAZON_ISSUED vs IMPORTED), status, and renewal eligibility.
aws acm describe-certificate \
  --certificate-arn arn:aws:acm:us-east-1:111122223333:certificate/9f1c2d34-5678-90ab-cdef-EXAMPLE11111 \
  --query 'Certificate.{Status:Status,Type:Type,RenewalEligibility:RenewalEligibility,NotAfter:NotAfter}'

# AMAZON_ISSUED + ISSUED + ELIGIBLE means it will auto-renew once attached to the listener.

What is the impact of a non-ACM certificate on a Classic Load Balancer?

The headline impact is outage risk, and it's binary. A TLS certificate is either valid or expired — there's no graceful degradation. The moment a manually managed certificate on a CLB lapses, every HTTPS client gets a certificate error and the service behind that listener is effectively offline until someone generates, uploads, and re-points a new certificate. For a public API or customer-facing site, that's a full outage with a recovery time bounded only by how fast a human notices and acts.

The second-order impact is operational fragility. A manually uploaded IAM certificate has an owner who has to remember its expiry, hold the private key and renewal process, and execute the swap correctly under time pressure. That knowledge is rarely documented and frequently walks out the door when someone changes teams. The result is a load balancer where nobody is confidently accountable for an event that is guaranteed to happen on a known schedule — the worst combination of certain and unowned.

There's a compliance and audit dimension too. ELB.2 maps to NIST 800-53 and 800-171 encryption-in-transit controls. A FAILED finding is a standing item on every audit and security review until it's resolved — recurring overhead in meetings and remediation tracking that is wholly avoidable. Unlike many findings, this one has a clean, permanent fix rather than an ongoing tuning exercise.

What's notably absent from the impact list is cost. ACM-issued certificates are free, and so are most IAM-uploaded ones, so there's no spend delta to recover here. That's why this finding is best understood as risk remediation, not cost optimisation: the value is the outage you don't have, the audit item you close permanently, and the manual deadline you delete from a human's plate.

How do you remediate ELB.2 safely?

Remediation is a short, low-risk loop: find the non-ACM listeners, get an ACM certificate for the same domain in the same region, re-point the listener, and verify renewal is enabled. The swap itself is non-disruptive to live connections.

1. Inventory the non-compliant CLBs and their certificate source

List every Classic Load Balancer and the SSLCertificateId on each HTTPS/SSL listener. Any ARN in the iam namespace (...:server-certificate/...) fails ELB.2; ACM ARNs (...:acm:...:certificate/...) pass. Record the domain each listener serves and how business-critical the fronted service is — that ordering drives which you fix first.

2. Get an ACM certificate for the same domain, in the same region

Check ACM in the load balancer's region for an existing AWS-issued certificate covering the domain. If none exists, request one (aws acm request-certificate) and validate it — DNS validation via Route 53 is preferred because it makes future renewal fully automatic. The certificate must be in the same Region as the CLB and in ISSUED status before you attach it. Importing an external certificate also passes ELB.2, but it will not auto-renew, so prefer an AWS-issued cert where you can.

3. Re-point the listener to the ACM certificate

Use set-load-balancer-listener-ssl-certificate to swap the listener's certificate to the ACM ARN. This is non-disruptive: in-flight connections drain on the old cert and new TLS handshakes use the ACM cert immediately. Verify with describe-load-balancers that the listener now reports the ACM ARN, and confirm ELB.2 flips to PASSED on the next Config evaluation.

4. Confirm auto-renewal and prevent recurrence

Auto-renewal only fires while the certificate is attached to an in-use resource — re-pointing the listener satisfies that. Confirm the cert shows Type: AMAZON_ISSUED and RenewalEligibility: ELIGIBLE. To stop new offenders appearing, make ACM the default in your IaC templates, keep the elb-acm-certificate-required Config rule active, and treat any new IAM-uploaded listener cert as a build-time failure rather than a quarterly audit finding.

# Request an AWS-issued, DNS-validated cert in the load balancer's region (skip if one exists).
aws acm request-certificate \
  --domain-name api.example.com \
  --validation-method DNS \
  --region us-east-1

# After the cert reaches ISSUED, re-point the CLB's HTTPS listener to it.
aws elb set-load-balancer-listener-ssl-certificate \
  --load-balancer-name legacy-api-clb \
  --load-balancer-port 443 \
  --ssl-certificate-id arn:aws:acm:us-east-1:111122223333:certificate/9f1c2d34-5678-90ab-cdef-EXAMPLE11111

# Verify the listener now serves the ACM ARN.
aws elb describe-load-balancers --load-balancer-names legacy-api-clb \
  --query 'LoadBalancerDescriptions[0].ListenerDescriptions[].Listener.SSLCertificateId'

Quick quiz

Question 1 of 5

A Classic Load Balancer fails ELB.2 because its HTTPS listener uses an IAM-uploaded server certificate. You request an AWS-issued ACM certificate for the same domain and region but never attach it to the listener. What's the result?

Keep learning

Go deeper on the ELB.2 control, ACM-managed renewal, and associating certificates with Classic Load Balancers.

You've completed Use ACM certificates on Classic Load Balancers. You now know why ELB.2 flags a CLB whose HTTPS listener uses a hand-managed IAM certificate, the binary outage risk an expired cert creates, and the safe non-disruptive path to move the listener onto an ACM certificate so renewal becomes automatic. You also know the catch — ACM only auto-renews a cert that's actually attached to a live resource. Next time ELB.2 fails, you have a clean, permanent fix.

Back to the library