carlos / platform Public

edge: e2e — a non-home edge answers the validation, and the name mints

The automated shadow of the dev proof that failed as #277: one bucket,
two edges, and the host in exactly ONE box's registry. Edge B — the box
DNS points at, homing nothing for the name — answers the CA out of the
bucket, edge A mints, and the certificate reaches B's mirror and serves a
real handshake. The tls-alpn-01 half is proved at the same seam the unit
tests use, since the fake CA offers http-01 only, together with its #180
twin: a label under the mirrored catch-all is still refused a token cert.

Without the widening this test fails the way production did — "no viable
challenge type found" for the domain, after the CA burned an
authorization against the box that refused it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Paul Campbell pushed by paul@keymail.dev 3d2c8bf76d218f14df8f51ac88f38b04dd2bb31c parent 0d0d02f
1 file changed, +124 −0
  • internal/edge/certsync_e2e_test.go +124 −0
diff --git a/internal/edge/certsync_e2e_test.go b/internal/edge/certsync_e2e_test.go
index e7f538956..7eef19508 100644
--- a/internal/edge/certsync_e2e_test.go
+++ b/internal/edge/certsync_e2e_test.go
@@ -1155,3 +1155,127 @@ func TestCertSyncE2EConcurrentRefreshIsRaceFree(t *testing.T) {
t.Fatalf("account key seeding raced: %q, %v", got, err)
}
}
+
+// ---- #277: the non-home edge answers, and the home-boxed name mints ---------
+
+// e2eRemoteHomedHost is homed on edge A and absent from edge B's registry —
+// the shape the original scenario deliberately did not have (there, B carried
+// every host in its own route table).
+const e2eRemoteHomedHost = "remote.bab.example.test"
+
+// The automated shadow of the dev proof that failed as #277: a member points
+// a custom domain's A record at edge B, which homes nothing for that name. B
+// backhauls to A, A (the issuer) sees the hello and orders, and the CA then
+// validates against B — the box whose registry has never heard of the host.
+// Before the widening, B refused the challenge, every authorization failed,
+// and the name's Let's Encrypt budget went in minutes. After it, B answers
+// out of the bucket, A mints, and the certificate reaches B's mirror.
+//
+// The backhaul leg itself is not re-proved here (homemap_test.go owns it);
+// what this pins is that everything CERT-side works with the host in ONE
+// box's registry and the other box's home map.
+func TestNonHomeEdgeAnswersValidationForRemoteHomedHost(t *testing.T) {
+ e2eQuietLogs(t)
+ bucket := t.TempDir()
+ ca := newFakeACME(t)
+
+ // Edge B: no routes at all for the name — this is the box DNS points at.
+ edgeB := newE2EEdge(t, bucket, false, ca.directoryURL())
+ ca.validateAgainst(edgeB.serveHTTP(t))
+ if edgeB.edge.Allowed(e2eRemoteHomedHost) {
+ t.Fatal("test bug: edge B must not carry the host in its own registry")
+ }
+
+ // ...but it mirrors the deployment's edges files, in which edge A homes
+ // the name exactly. That, and only that, is what admits the validation.
+ homes := newHomeMap(release.NewDirStore(bucket), "edge-b")
+ homedOn(t, homes, "edge-a", "203.0.113.10", e2eRemoteHomedHost, "*.other.example.test")
+ edgeB.edge.homes.Store(homes)
+
+ // Edge A: the housekeeper, and the box that homes the route. Its own :80
+ // chain is served purely so "the CA never reached the issuer" is an
+ // assertion rather than an assumption.
+ edgeA := newE2EEdge(t, bucket, true, ca.directoryURL(), e2eRemoteHomedHost)
+ edgeA.serveHTTP(t)
+
+ lnB := edgeB.serveTLS(t)
+ if _, err := e2eDial(lnB, e2eRemoteHomedHost, ca.rootPool()); err == nil {
+ t.Fatal("edge B answered a handshake for a certificate that does not exist yet")
+ }
+
+ // The mint, on edge A — exactly what a backhauled hello triggers there.
+ minted, err := edgeA.getCert(ecdsaHello(e2eRemoteHomedHost))
+ if err != nil {
+ t.Fatalf("the issuer failed to mint a host it homes: %v", err)
+ }
+ ca.checkFaults(t)
+ if minted.Leaf == nil || minted.Leaf.VerifyHostname(e2eRemoteHomedHost) != nil {
+ t.Fatalf("minted cert does not cover %s", e2eRemoteHomedHost)
+ }
+
+ t.Run("the validation was answered by the box that homes nothing", func(t *testing.T) {
+ v, ok := ca.lastValidation()
+ if !ok {
+ t.Fatal("the CA never validated anything")
+ }
+ if !v.ok || v.host != e2eRemoteHomedHost {
+ t.Fatalf("validation of %q ok=%v — the body B served was not the key authorization", v.host, v.ok)
+ }
+ if n := edgeB.hits.Load(); n == 0 {
+ t.Fatal("edge B's :80 chain was never reached")
+ }
+ if n := edgeA.hits.Load(); n != 0 {
+ t.Fatalf("edge A's :80 chain served %d request(s) — the CA must never have reached the issuer", n)
+ }
+ // It came out of the bucket, live: B never polled, and its own
+ // autocert handler is shut for this name by the issuer gate.
+ if n := len(edgeB.mirror.snapshot().entries); n != 0 {
+ t.Fatalf("edge B's mirror holds %d entry/entries — the read-through is not what was tested", n)
+ }
+ if err := edgeB.edge.issuerHostPolicy()(context.Background(), e2eRemoteHomedHost); !errors.Is(err, errNotIssuer) {
+ t.Fatalf("edge B's HostPolicy = %v, want errNotIssuer — a non-issuer orders nothing, however it is named", err)
+ }
+ want := certKey(v.token + httpTokenSuffix)
+ reads, _ := edgeB.store.snapshot()
+ if !slices.Contains(reads, want) {
+ t.Fatalf("edge B read %v, want a live read of %q", reads, want)
+ }
+ })
+
+ t.Run("the tls-alpn-01 twin is admitted for the same name", func(t *testing.T) {
+ // The fake CA offers http-01 only (its doc says why), so the ALPN half
+ // is proved at the same seam the unit tests use: a token cert in the
+ // bucket, an acme-tls/1 hello at edge B for a name only edge A homes.
+ // Written through a THIRD handle on the bucket, standing in for the
+ // issuer's publishingCache: edge B's own handle must stay write-free,
+ // which the last subtest asserts.
+ putBucket(t, release.NewDirStore(bucket), e2eRemoteHomedHost+alpnTokenSuffix,
+ hostCertPEM(t, e2eRemoteHomedHost, time.Now().Add(24*time.Hour)))
+ if c := edgeB.mirror.alpnTokenCert(context.Background(), e2eRemoteHomedHost); c == nil {
+ t.Fatal("edge B refused a tls-alpn-01 validation for a host edge A homes")
+ }
+ // And the label under the mirrored catch-all is still refused (#180).
+ if c := edgeB.mirror.alpnTokenCert(context.Background(), "invented.other.example.test"); c != nil {
+ t.Fatal("a label under a mirrored catch-all was served a token cert")
+ }
+ })
+
+ t.Run("the minted cert reaches the non-home edge", func(t *testing.T) {
+ if err := edgeB.mirror.Refresh(context.Background()); err != nil {
+ t.Fatalf("one refresh must be enough: %v", err)
+ }
+ state, err := e2eDial(lnB, e2eRemoteHomedHost, ca.rootPool())
+ if err != nil {
+ t.Fatalf("edge B must serve the certificate edge A minted: %v", err)
+ }
+ if len(state.PeerCertificates) == 0 || !bytes.Equal(state.PeerCertificates[0].Raw, minted.Leaf.Raw) {
+ t.Fatal("edge B served a certificate that is not the one edge A minted")
+ }
+ _, wrote := edgeB.store.snapshot()
+ if len(wrote) != 0 {
+ t.Fatalf("a gated edge wrote %v to the control bucket — only the issuer may", wrote)
+ }
+ })
+
+ ca.checkFaults(t)
+}