Skip to content

Commit 88c639e

Browse files
authored
Merge pull request #112 from Dstack-TEE/docs/ingress-delegation-caa-row
docs(dstack-ingress): correct what delegation does about CAA
2 parents dc34a5d + cf40016 commit 88c639e

1 file changed

Lines changed: 38 additions & 8 deletions

File tree

custom-domain/dstack-ingress/TESTING.md

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -229,16 +229,26 @@ watch for: the three records verifying, `Executing (challenge-delegation):` with
229229
cleaned up afterwards (query `_acme-challenge.<domain>.<alias>` at the
230230
authoritative nameserver — it should be gone).
231231

232-
The CAA step comes last, once the ACME account exists and its URI is known. It
233-
blocks until you create the record it prints. Cloudflare's API wants CAA as
234-
structured fields rather than one string, so most quick DNS scripts cannot write
235-
it; the image's own `dnsman.py set_caa` can, and running it in a one-off
236-
container is the easiest way to play the operator here:
232+
The CAA comes last and needs nothing from you: it names the ACME account, so the
233+
account has to exist first, and the container publishes it into the delegation
234+
zone itself once it does. Expect `Adding CAA record for <domain>.<zone> with tag
235+
issue` on the first pass — `issuewild` for a wildcard, on the base name. Confirm
236+
it at the authoritative nameserver, and confirm it resolves *through* the
237+
operator's CNAME, since that is what the CA follows:
238+
239+
```bash
240+
dig +short CAA <domain> @<authoritative-ns>
241+
```
242+
243+
To plant a CAA by hand — for the negative case below, or to check that the
244+
container replaces it — note that Cloudflare's API wants CAA as structured
245+
fields rather than one string, so most quick DNS scripts cannot write it. The
246+
image's own `dnsman.py set_caa` can, in a one-off container:
237247

238248
```bash
239249
docker run --rm --env-file .env --entrypoint dnsman.py <image> \
240-
set_caa --domain svc.example.com --caa-tag issue \
241-
--caa-value 'letsencrypt.org;validationmethods=dns-01;accounturi=<uri>'
250+
set_caa --domain svc.example.com.deleg.example.com --caa-tag issue \
251+
--caa-value 'example.com'
242252
```
243253

244254
**What this does not test.** The whole point of delegation is that a token scoped
@@ -255,7 +265,7 @@ These fail fast and are cheap, so run them on every change:
255265
|---|---|
256266
| tls-alpn-01 + a wildcard domain | Refused before any ACME call, citing RFC 8737 |
257267
| Delegation, CAA in the delegated zone changed to forbid the CA | Blocked before any ACME attempt — proves the published CAA is reachable through the CNAME |
258-
| Delegation with no CAA record at all | Blocked — unlike normal issuance, where "no CAA" means unrestricted and passes |
268+
| Delegation with no CAA record at all | Proceeds, reporting `no CAA record set; issuance is unrestricted` — see below |
259269
| Delegation, later pass, gateway CNAME broken | Renewal proceeds — that record is for serving, and dns-01 does not use it |
260270
| A CAA record with `validationmethods=dns-01`, mode tls-alpn-01 | Blocked with the restriction quoted back |
261271
| TXT holding the wrong value | Reported as `want <x>, saw <y>`, not "missing" |
@@ -264,6 +274,26 @@ These fail fast and are cheap, so run them on every change:
264274
The last one is worth keeping: it is the cross-tenant impersonation defence, and
265275
it is observable rather than merely argued.
266276

277+
**Why "no CAA at all" is not a blocking case.** It used to be. When the operator
278+
had to create the CAA record, its absence was the state that mattered: nothing
279+
then stopped anyone else who could satisfy the delegated challenge, and the
280+
container held no token to create it. Once the container began publishing the
281+
delegated CAA itself, absence stopped meaning that — it means "not published
282+
yet", and the next pass fixes it — so the gate was removed along with
283+
`ALLOW_MISSING_CAA` and dnsguide's `--caa-required`. `check_caa` now follows
284+
RFC 8659 for delegation as it always did elsewhere: an absent CAA record set
285+
forbids nothing.
286+
287+
The neighbouring row still holds, and it is the one that carries the weight: a
288+
CAA in the delegated zone that forbids the CA **does** block, before any ACME
289+
attempt, which is what proves the published record is reachable through the
290+
operator's CNAME. Expect the reason quoted back, e.g. `issue allows
291+
'example.com', not letsencrypt.org`.
292+
293+
Note also that the first pass on a fresh deployment necessarily runs before any
294+
CAA exists: the record names the ACME account, so the account has to exist
295+
first. `process_domain` issues, writes the CAA, then issues again.
296+
267297
## Traps
268298

269299
**Start from a clean zone.** Records left over from an earlier run change which

0 commit comments

Comments
 (0)