Skip to content

docs(dstack-ingress): correct what delegation does about CAA - #112

Merged
kvinwang merged 1 commit into
mainfrom
docs/ingress-delegation-caa-row
Jul 29, 2026
Merged

docs(dstack-ingress): correct what delegation does about CAA#112
kvinwang merged 1 commit into
mainfrom
docs/ingress-delegation-caa-row

Conversation

@kvinwang

Copy link
Copy Markdown
Collaborator

TESTING.md describes the pre-#108 delegation design in two places. Docs only — no behaviour change.

#677599f removed the fail-closed CAA gate, with sound reasoning: once the container publishes the delegated CAA itself, an absent record means "not published yet" rather than "nobody can create it", so check_caa follows RFC 8659 here as it does everywhere else. That commit updated the README and left TESTING.md behind.

What was wrong

The negative table promised:

| Delegation with no CAA record at all | Blocked — unlike normal issuance, where "no CAA" means unrestricted and passes |

A 2.3 run reports the opposite on every delegation first pass — necessarily so, since the CAA names the ACME account and the account has to exist first:

[dns-check #1] OK   CAA v23e.kvin.wang: ok (no CAA record set; issuance is unrestricted)

This reads as a security regression to anyone testing against the doc. It isn't, but the doc is what makes it look like one.

The walkthrough still told the tester to create the CAA by hand and said the container blocks until they do. It publishes the record itself:

Adding CAA record for v23e.kvin.wang.v23z.kvin.wang with tag issue and value letsencrypt.org;validationmethods=dns-01;accounturi=…
Successfully set CAA record for v23e.kvin.wang.v23z.kvin.wang

What this changes

  • The table row says what happens, and points at the explanation.
  • A short paragraph explains why the gate went away, so the next reader does not re-derive it as a bug — and points at the row that does carry the weight: a delegated CAA forbidding the CA does block before any ACME attempt, which is what proves the published record is reachable through the operator's CNAME.
  • The walkthrough describes the container publishing the CAA, and says to verify it through the CNAME (dig +short CAA <domain> @<ns>) rather than create it.
  • The dnsman.py set_caa snippet is kept but repurposed for the negative case — it is still the only convenient way to write a structured CAA through Cloudflare's API.

Verified against a real run

Both behaviours were observed while testing dstacktee/dstack-ingress:2.3 against Let's Encrypt staging and a real Cloudflare zone:

  • plain and wildcard delegation both published their own CAA (issue / issuewild on the base), and the challenge TXT was cleaned up afterwards;
  • a delegated CAA changed to forbid the CA blocked before any ACME attempt, quoting issue allows 'example.com', not letsencrypt.org.

677599f removed the fail-closed CAA gate -- once the container publishes
the delegated CAA itself, an absent record means "not published yet"
rather than "nobody can create it", so check_caa follows RFC 8659 here
as it does everywhere else. That commit updated the README and left
TESTING.md describing the old design, in two places:

- the negative table still promised "delegation with no CAA record at
  all: blocked". A 2.3 test run reports the opposite on every first
  pass, which is the documented behaviour and not a defect.

- the walkthrough still told the tester to create the CAA by hand and
  said the container blocks until they do. It publishes the record
  itself; there is nothing to wait for.

Both now say what the code does, with the reasoning for the change kept
so the next reader does not re-derive it as a bug -- and the row that
does carry the weight, a delegated CAA forbidding the CA, is called out
as the one that proves reachability through the operator's CNAME.

The dnsman.py set_caa snippet is kept, repurposed for planting a CAA by
hand in the negative case, which is still the only convenient way to
write a structured CAA through Cloudflare's API.
Copilot AI review requested due to automatic review settings July 29, 2026 04:23

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@kvinwang
kvinwang merged commit 88c639e into main Jul 29, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants