Nothing in AWS Tells You www Is Missing
The first one took one DNS record. The certificate
already covered www, CloudFront already accepted it, and the only thing missing was
the record pointing the name at the distribution.
I assumed that was luck — that past me had gotten most of the way through one setup and stalled at the last step. So I went through the other four expecting to find real work: a certificate to re-issue here, an alternate domain name to add there.
There wasn't any. Four for four, the fix was DNS and nothing else.
The sweep
apresapply.com, unpivot-sql.com, thomasrones.com, fxf.social. Every one of them
had the same shape as csv-helper.com:
- The CloudFront distribution already listed
www.<domain>in its alternate domain names. - The distribution already had IPv6 enabled.
- The certificate already covered
www.
And on every one, www returned NXDOMAIN.
The certificates are the part that convinced me this wasn't carelessness at the last
step. They were issued months earlier — April, May, July — and two of them aren't even
www-specific:
$ for d in csv-helper.com apresapply.com unpivot-sql.com thomasrones.com fxf.social; do
openssl s_client -connect $d:443 -servername $d </dev/null 2>/dev/null \
| openssl x509 -noout -ext subjectAltName | tail -1
done
csv-helper.com, www.csv-helper.com
apresapply.com, *.apresapply.com
unpivot-sql.com, www.unpivot-sql.com
thomasrones.com, www.thomasrones.com
fxf.social, *.fxf.social
apresapply.com and fxf.social have wildcard certificates. There was never a
decision to make about www on those two — a wildcard covers it automatically, along
with every other label. The TLS layer was ready for a hostname that did not exist, and
had been for months.
So the certificate was never the blocker on any of the five. Neither was CloudFront. The entire outage, across five domains and an unknown number of months, was a missing row in a DNS zone.
What varied was which record was missing
The one thing that wasn't uniform is the interesting one.
fxf.social had an AAAA alias on the apex but no www record of any kind. The others
had an A alias on the apex and nothing else — no apex AAAA, no www in either
family. So the gaps didn't line up.
If these zones had come out of a template, the same records would be present and the same ones absent every time. They don't, which means each was typed by hand, on a different day, stopping wherever it looked finished. That's the actual root cause: not a wrong decision repeated five times, but five separate sessions of manual data entry with no definition of done.
Why nothing reported it
This is the part worth keeping, because it generalises past www and past AWS.
Three services were involved and each did its job correctly:
- ACM issued a certificate covering
www.<domain>. It has no way to know whether anything resolves there. A certificate is a statement about names you may serve, not names you do serve, so an unused SAN isn't an error — it's the normal state of a wildcard. - CloudFront accepted
www.<domain>as an alternate domain name. It validates that your certificate covers the name, because that's a constraint it can check locally. It does not check DNS. A distribution configured for a hostname nobody points at is perfectly valid — that's exactly what a migration looks like halfway through. - Route 53 served the records in the zone. It has no opinion about what CloudFront expects, because it's a DNS server, not an integration test.
Nobody is wrong. There's just no service whose job is the join, and the failure only exists in the join.
Monitoring doesn't catch it either, and the reason is worth stating plainly: you cannot alert on a hostname you never configured. A health check watches an endpoint you told it about. There's no error rate, no elevated latency, no expiring certificate, no failed deploy. A name that doesn't exist produces no telemetry at all, because nothing is running there to produce any.
The only signal is a person typing the habitual www. and quietly deciding you're down.
And the check that finds it is embarrassingly cheap:
$ dig +short www.example.com
One command per domain, and I'd never run it — because there was nothing prompting me to. Every dashboard I own was green, and every one of them was right.
The one I skipped
talktop.us already had www, and it's the only one of the six not behind CloudFront —
it resolves to a single origin IP rather than a CDN edge. Different hosting, different
shape, different failure mode. It's missing IPv6, which I've left alone because the whole
thing is getting redeployed shortly and fixing infrastructure you're about to replace is
just a slower way of deleting it.
Worth noting as the counter-example, though. The five that shared the bug also shared a setup process. The one that didn't share the process didn't have the bug.
What I broke by fixing it
Being honest about the state I've actually left things in:
$ for h in ... ; do curl -sSo /dev/null -w '%{http_code} %{redirect_url}\n' https://$h/; done
200
200 # www
All five domains, both hostnames, 200 with no redirect and no <link rel="canonical">.
That's the third case in the taxonomy I set out to measure — apex and www both serving
identical content with nothing declaring which is real. Before this week, four of those
five had an unambiguous canonical form for the stupidest possible reason: only one of the
two names existed. I fixed the outage and created a duplicate-content problem in the same
motion.
It's a much smaller problem than the one it replaced, and it's the right order to fix them in — a name that doesn't resolve fails for everyone, while duplicate content is a ranking-signal inefficiency. But it's the kind of thing that stays "temporary" for two years if you don't write it down, so: it's written down.
One of them is staying broken on purpose. csv-helper.com is a fixture for the scanner
this all leads to, parked in the both-serve-200 state so I can assert the classifier
recognises the case where nothing is failing. The other four just need a redirect.
The general version
Everything above is one instance of a shape worth recognising: a system composed of services that are each individually correct, failing in the gaps between them, silently, because no component can see the whole.
The fix is never the hard part. The hard part is that nothing tells you.
Comments
No comments yet. Be the first!