Commit 4ca52b1
feat(core): complete draft-02 flat-FQDN migration across all surfaces
Ships the full draft-mozleywilliams-dnsop-dnsaid-02 wire-format
migration as a single 0.24.0 release.
The bulk of this work was authored by Nick Williams (@nicknacnic) and
is consolidated here from his draft-02 stack so the migration lands as
one reviewable, releasable unit instead of a five-deep PR chain. Full
credit to Nick for the underlying implementation -- see the
Co-authored-by trailer.
## Wire format (-01 -> -02)
- Flat primary owner record at {name}.{domain} -- a valid x.509 SAN
dNSName. The agent protocol no longer travels in the FQDN; it lives
in the SVCB bap SvcParamKey (or alpn when single-protocol). SVCB and
companion TXT are written at the flat owner on every publish.
- Optional walkable AliasMode at {name}._agents.{domain} pointing at
the flat owner. Off by default under -02 to avoid an enumeration
handle (see docs/privacy-considerations.md); opt in per-publish via
publish_walkable_alias=True, the CLI --walkable flag, or the MCP
kwarg.
- Per-call legacy -01 fallback via allow_legacy on discover() /
discover_at_fqdn(); results stamped legacy_resolved=True. The
process-wide DNS_AID_LEGACY_01_FALLBACK=1 env form is preserved and
now logs on each use.
- Single FQDN parser dns_aid.core.fqdn.parse_dnsaid_fqdn recognising
flat, walkable, and legacy shapes; discoverer and telemetry parse
paths are thin projections over it.
## SvcParamKeys
- New well-known SvcParamKey at the project's interim private-use code
point key65409 (final IANA assignment deferred per draft 7.1).
Reconstructed as https://<svcb-target>/.well-known/<value> and
fetched as the capability descriptor; absolute-path values per
Figure 3 are honoured without double-prefixing. validate_well_known_path
constrains the value to a traversal- and injection-safe class on
both publish and discover.
- Scalar bap per draft 5.1: bare (mcp, a2a) or =-versioned (mcp=1.0).
A field validator on both models closes a SvcParam quoting break-out
(a crafted value such as mcp" key65500="x used to inject a sibling
key through to_params()). normalize_bap collapses legacy comma/list
inputs onto the canonical scalar across discoverer, SDK, and indexer.
## Trust path
- JWS record signature binds to (fqdn, target, port, alpn). A valid
signature lifted off one record and pasted onto a spoofed SVCB is
rejected at the binding check. The binding comparison is
DNS-normalized (case-insensitive, trailing-dot-insensitive) so a
legitimately-signed dotted or mixed-case endpoint is not falsely
rejected.
- cap-sha256 mismatch refuses the record (CapDigestMismatchError)
instead of silently downgrading to TXT; cap_sha256_verified marks
when the pin was actually applied.
- DANE score gates on DNSSEC (RFC 6698 10.1): a TLSA record without a
DNSSEC chain no longer credits +15 to security_score.
- TargetName underscore validator rejects underscored endpoint labels
by default (CA/Browser-Forum BR + RFC 5280 dNSName conformance),
with an operator-only bypass requiring both DNS_AID_ALLOW_UNDERSCORE_TARGET=1
and the per-call flag.
## Completion fixes (this consolidation)
- validate_fqdn accepts the flat owner {name}.{domain}. It previously
required a literal _agents label and rejected every flat FQDN, so
the MCP verify_agent_dns tool could not verify a draft-02 agent. It
now validates a well-formed multi-label DNS name (flat, walkable,
legacy, and index shapes all pass) and remains the sole input guard
at the MCP boundary.
- CLI and MCP surfaces emit the flat owner name -- delete/search
output, the MCP unpublish result, and list_agent_index now show
{name}.{domain} instead of the legacy nested name.
- index sync enumerates flat primary owners. It previously discovered
agents only via the walkable AliasMode or legacy shape, so a flat-only
agent (the draft-02 default publish shape) was silently dropped from
the index. It now detects flat owners by their companion TXT record,
reads the protocol off the SVCB SvcParams, and dedups against any
walkable alias for the same agent.
- Discovery reconciles the agent protocol from the SVCB record. The
protocol lives in the record (bap, or alpn) under draft-02, not the
FQDN. The discoverer now stamps the record's true protocol on every
path (discover_at_fqdn, the zone-walk, the HTTP index), so a
default-published a2a/https agent (alpn, no bap) is no longer
mislabeled mcp -- which previously failed the JWS binding check and
picked the wrong handler. The zone-walk dedups by (fqdn, protocol).
- parse_dnsaid_fqdn accepts a flat owner in a two-label zone
(agent.internal) and normalizes case + a trailing dot up front.
- Docs, CHANGELOG, CITATION, and the package version (0.23.0 -> 0.24.0)
updated to the flat shape.
## Production hardening
- SVCB SvcParam injection closed on every free-form field. The bap
validator already blocked quote break-out injection; the same guard
now applies to cap / cap-sha256 / policy / realm / sig / connect-meta /
enroll-uri on both models, so a forged value cannot inject a sibling
SvcParamKey into the authoritative record via the presentation-format
backends.
- JWKS fetch is SSRF-guarded, size-capped (64 KB), redirect-free, and the
per-process cache is bounded. JWS verification pins alg=ES256 (rejects
none/RSA) and the key to a P-256 EC signing key with 32-byte
coordinates -- closing algorithm/curve confusion on the attacker-
influenceable JWKS path.
- The HTTP agent index fetch is bounded in body size (1 MB) and agent
count (500) so a hostile index can't OOM or amplify the per-agent
fan-out.
## Verification
Full local gate run green: ruff, ruff format, mypy (83 source files),
bandit (0 issues), and 1890 unit/integration tests. Verified end to end
across the CLI, MCP, and SDK surfaces against live Route53 and a local
BIND9/DDNS backend (publish -> discover -> verify -> delete round-trips,
flat-owner resolution, protocol reconciliation for a2a/mcp/https,
signature binding, index round-trip); NIOS WAPI lifecycle validated on
the same code paths. The JWKS hardening was validated live over real TLS
sockets and real ES256 crypto: SSRF guard blocks a loopback JWKS, the
full sign -> fetch -> verify chain succeeds, the streaming size cap
rejects an oversized document, and alg/curve confusion is refused.
Breaking changes (strict underscore TargetName validator, scalar bap,
and the -01 -> -02 default flip) are documented with migration notes
in CHANGELOG [0.24.0].
Co-authored-by: Layer8 <NWillAU900@gmail.com>
Signed-off-by: Igor Racic <iracic82@gmail.com>1 parent 5db084f commit 4ca52b1
75 files changed
Lines changed: 6494 additions & 756 deletions
File tree
- docs
- integrations
- rfc
- examples/integration_otel_collector
- scripts
- src/dns_aid
- backends
- infoblox
- cli
- core
- mcp
- sdk
- telemetry
- utils
- tests
- integration
- parity
- testbed
- bind-orga/zones
- bind-orgb/zones
- unit
- core
- sdk
- auth
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
16 | | - | |
17 | | - | |
| 16 | + | |
| 17 | + | |
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | | - | |
13 | | - | |
14 | 12 | | |
15 | 13 | | |
16 | | - | |
| 14 | + | |
17 | 15 | | |
18 | 16 | | |
19 | 17 | | |
20 | | - | |
21 | | - | |
22 | | - | |
23 | | - | |
24 | | - | |
25 | | - | |
26 | | - | |
27 | | - | |
28 | | - | |
29 | | - | |
30 | | - | |
31 | | - | |
32 | | - | |
33 | | - | |
34 | 18 | | |
35 | 19 | | |
36 | 20 | | |
| |||
97 | 81 | | |
98 | 82 | | |
99 | 83 | | |
100 | | - | |
| 84 | + | |
101 | 85 | | |
102 | 86 | | |
103 | 87 | | |
| |||
278 | 262 | | |
279 | 263 | | |
280 | 264 | | |
281 | | - | |
| 265 | + | |
282 | 266 | | |
283 | 267 | | |
284 | 268 | | |
| |||
397 | 381 | | |
398 | 382 | | |
399 | 383 | | |
400 | | - | |
| 384 | + | |
401 | 385 | | |
402 | 386 | | |
403 | 387 | | |
| |||
491 | 475 | | |
492 | 476 | | |
493 | 477 | | |
494 | | - | |
495 | | - | |
| 478 | + | |
| 479 | + | |
496 | 480 | | |
497 | 481 | | |
498 | 482 | | |
499 | 483 | | |
500 | 484 | | |
501 | | - | |
| 485 | + | |
502 | 486 | | |
503 | 487 | | |
504 | 488 | | |
| |||
526 | 510 | | |
527 | 511 | | |
528 | 512 | | |
529 | | - | |
| 513 | + | |
530 | 514 | | |
531 | 515 | | |
532 | 516 | | |
| |||
536 | 520 | | |
537 | 521 | | |
538 | 522 | | |
539 | | - | |
| 523 | + | |
540 | 524 | | |
541 | 525 | | |
542 | 526 | | |
| |||
553 | 537 | | |
554 | 538 | | |
555 | 539 | | |
556 | | - | |
| 540 | + | |
557 | 541 | | |
558 | 542 | | |
559 | 543 | | |
| |||
1025 | 1009 | | |
1026 | 1010 | | |
1027 | 1011 | | |
1028 | | - | |
| 1012 | + | |
| 1013 | + | |
| 1014 | + | |
| 1015 | + | |
| 1016 | + | |
| 1017 | + | |
| 1018 | + | |
| 1019 | + | |
| 1020 | + | |
| 1021 | + | |
| 1022 | + | |
| 1023 | + | |
| 1024 | + | |
| 1025 | + | |
| 1026 | + | |
| 1027 | + | |
| 1028 | + | |
| 1029 | + | |
| 1030 | + | |
| 1031 | + | |
| 1032 | + | |
| 1033 | + | |
| 1034 | + | |
| 1035 | + | |
| 1036 | + | |
| 1037 | + | |
| 1038 | + | |
| 1039 | + | |
| 1040 | + | |
| 1041 | + | |
| 1042 | + | |
| 1043 | + | |
| 1044 | + | |
| 1045 | + | |
| 1046 | + | |
| 1047 | + | |
| 1048 | + | |
| 1049 | + | |
| 1050 | + | |
| 1051 | + | |
| 1052 | + | |
| 1053 | + | |
| 1054 | + | |
| 1055 | + | |
| 1056 | + | |
| 1057 | + | |
| 1058 | + | |
| 1059 | + | |
| 1060 | + | |
| 1061 | + | |
| 1062 | + | |
| 1063 | + | |
| 1064 | + | |
| 1065 | + | |
| 1066 | + | |
| 1067 | + | |
| 1068 | + | |
| 1069 | + | |
| 1070 | + | |
| 1071 | + | |
| 1072 | + | |
| 1073 | + | |
| 1074 | + | |
| 1075 | + | |
| 1076 | + | |
| 1077 | + | |
| 1078 | + | |
| 1079 | + | |
| 1080 | + | |
| 1081 | + | |
| 1082 | + | |
| 1083 | + | |
| 1084 | + | |
1029 | 1085 | | |
1030 | | - | |
| 1086 | + | |
1031 | 1087 | | |
1032 | 1088 | | |
1033 | 1089 | | |
| |||
1076 | 1132 | | |
1077 | 1133 | | |
1078 | 1134 | | |
1079 | | - | |
| 1135 | + | |
1080 | 1136 | | |
1081 | 1137 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
84 | 84 | | |
85 | 85 | | |
86 | 86 | | |
87 | | - | |
| 87 | + | |
88 | 88 | | |
89 | 89 | | |
90 | 90 | | |
| |||
168 | 168 | | |
169 | 169 | | |
170 | 170 | | |
171 | | - | |
172 | | - | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
173 | 174 | | |
174 | 175 | | |
175 | 176 | | |
| |||
305 | 306 | | |
306 | 307 | | |
307 | 308 | | |
308 | | - | |
| 309 | + | |
309 | 310 | | |
310 | 311 | | |
311 | 312 | | |
| |||
316 | 317 | | |
317 | 318 | | |
318 | 319 | | |
319 | | - | |
| 320 | + | |
320 | 321 | | |
321 | 322 | | |
322 | 323 | | |
| |||
332 | 333 | | |
333 | 334 | | |
334 | 335 | | |
335 | | - | |
| 336 | + | |
336 | 337 | | |
337 | 338 | | |
338 | 339 | | |
| |||
580 | 581 | | |
581 | 582 | | |
582 | 583 | | |
583 | | - | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
584 | 587 | | |
585 | 588 | | |
586 | 589 | | |
| |||
767 | 770 | | |
768 | 771 | | |
769 | 772 | | |
770 | | - | |
| 773 | + | |
771 | 774 | | |
772 | 775 | | |
773 | 776 | | |
| |||
933 | 936 | | |
934 | 937 | | |
935 | 938 | | |
936 | | - | |
| 939 | + | |
937 | 940 | | |
938 | 941 | | |
939 | 942 | | |
| |||
1052 | 1055 | | |
1053 | 1056 | | |
1054 | 1057 | | |
1055 | | - | |
| 1058 | + | |
1056 | 1059 | | |
1057 | 1060 | | |
1058 | 1061 | | |
| |||
1076 | 1079 | | |
1077 | 1080 | | |
1078 | 1081 | | |
1079 | | - | |
| 1082 | + | |
1080 | 1083 | | |
1081 | 1084 | | |
1082 | 1085 | | |
| |||
1521 | 1524 | | |
1522 | 1525 | | |
1523 | 1526 | | |
1524 | | - | |
| 1527 | + | |
1525 | 1528 | | |
1526 | 1529 | | |
1527 | 1530 | | |
| |||
1843 | 1846 | | |
1844 | 1847 | | |
1845 | 1848 | | |
1846 | | - | |
| 1849 | + | |
1847 | 1850 | | |
1848 | 1851 | | |
0 commit comments