Repository navigation
T114 — Steer a dns box's store-rule authorities to the proxy - #2822
norrietaylor merged 2 commits into
Conversation
Creation puts each accepted [secret-store-rules] upstream into the credentialed-upstream declaration beside its grants (BEP-062). The field is skipped when empty, so a policy without store references reads as before.
The steered set of a dns or both box is now the GitHub module's hosts and the store-rule upstream hosts its policy carries (BEP-062).
|
Important Review skippedBot user detected. To trigger a single review, invoke the
|
|
Approved: no findings at Nothing to do. Verdict APPROVE, posted as a comment: the App cannot review its own pull request; the check and the label carry it. Clobber: none seen. |
There was a problem hiding this comment.
arch-review: PASS · the full ruling
The change conforms to §5.3 line 151 and §5.4 line 169. A dns or both box resolves its credentialed hostnames to the proxy. Gatehouse §6.10 line 834 puts the [secret-store-rules] authorities in that credentialed set. The set comes from the operator's accepted rules, not from the spec, as §5.4 line 157 requires. The gate still refuses a name outside the egress allow-list before it steers. The new test pins SERVFAIL while the proxy is down.
Ruled at 5be5fd6 against gominimal/arch@8640f85e193d by claude-opus-5-5.
There was a problem hiding this comment.
Approving at 5be5fd6. A dns or both box now steers the host of each accepted [secret-store-rules] upstream to the proxy, beside the GitHub hosts.
How the names stay bounded:
put_store_upstreamsfillsstore_upstreamsonly from the rulesaccept_store_referencesaccepted for this box.steered_hosts(policy)reads them per box, infor_session_steered.- They share
answer_steeredwith the GitHub hosts: the proxy address while the listener is live, SERVFAIL while it is down. AAAA, HTTPS and SVCB get NODATA. - REFUSED and NXDOMAIN still run first, so steering never bypasses the allow-list.
- Mixed case and a trailing dot are normalised on both sides.
Admission is unchanged, so dns stays refused as #2797 left it, and the path is reached through both on the VM host. Arch: local review and the minimal-arch check both PASS.
Non-blocking: store_authority_of_a_dns_box_resolves_to_the_proxy runs with the default (dns) steering. The gate branches only on needs_resolver(), so it still proves the gate, but a Steering::Both case would pin the configuration that reaches it.
T114 — Steer a dns box's store-rule authorities to the proxy
slice: S16
kind: task
covers: BEP-062
size: M
est: 140 code, 180 8000 tests
executor: agent
difficulty: needs care
model: standard
diagnostics: a
dns-steered box with a store reference resolves its rule's upstream, such as api.openai.com, to the proxy's address while the proxy listens, and gets SERVFAIL while it does not, pinned by store_authority_of_a_dns_box_resolves_to_the_proxyobservability: the gate's existing debug line for a steered answer names the box and the steered name
layers:
- policy:
- crates/boxes/src/lib.rs:
CredentialedUpstreamcarries the upstream authorities of the store rules the creation accepted, written only when the box has one, so a daemon that predates the field still reads a policy without store references- crates/minimal/src/cmd/boxes/create.rs: creation puts each accepted store rule's
upstreaminto the box's policy beside its grants (#2575)test: cargo nextest run -p minimal accepted_store_rule_authorities_reach_the_box_policy
- gate:
- crates/minimald/src/net/switch.rs: the steered set of a
dnsorbothbox is the GitHub module's hosts and the store-rule authorities its policy carries, in place ofcredential_module_hosts()alone; the full literals ofCredentialedUpstreamin this file's tests gain the field- crates/minimald/src/net/dns_gate.rs: the full literals of
CredentialedUpstreamin this file's tests gain the field- crates/minimald/src/box_manager/tests.rs: the full literals of
CredentialedUpstreamgain the fieldtest: cargo nextest run -p minimald store_authority_of_a_dns_box_resolves_to_the_proxy
produces: none
consumes: none
proof: A dns-steered box that references a stored key resolves its rule's upstream to the proxy, and the request carries the stored key while the key never enters the box.
depends on:
- blocked by #2523
- blocked by #2525
Original issue text
Residual from T58 #2567, arch C1 (ruling), epic #1501.
Networking §5.3 line 151 steers every declared credentialed hostname of a
dnsorbothbox to the Box Egress Proxy. The spec counts[secret-store-rules]authorities among those names (BEP-013, BEP-029).credential_module_hostsincrates/minimald/src/net/switch.rssteers onlybep::module::GITHUB.No box reaches the gap today: admission refuses
dnssteering for any box with a broker grant (BEP-017,refusalsincrates/boxes/src/core/bep.rs,!host.box_zone_resolver). Once that refusal lifts, a store authority underdnssteering would resolve through real DNS, which BEP-062 forbids.What closes this
[secret-store-rules]register for the box's store references, besidebep::module::GITHUB.credential_module_hostslinks this issue until then.dnsbox resolves to the proxy address.Generated by Claude Code
Proof
A dns- or both-steered box whose store reference a [secret-store-rules] rule accepted now carries that rule's upstream in its policy (credentialed_upstream.store_upstreams). Its lookup of the upstream host, such as api.openai.com, resolves to the Box Egress Proxy's address while the proxy listens, and gets SERVFAIL while it does not. The GitHub hosts stay steered too. So the box's request for that host goes to the proxy, and the proxy injects the stored key that the box never holds. This branch proves the DNS steering and the policy field. The key injection itself comes from the existing store-handle mint and the proxy, which this task does not change.
Notes from the agent: The new field is CredentialedUpstream.store_upstreams (Vec, authorities as
hostorhost:port). It is skipped when empty, so a policy without store references serializes as before. CredentialedUpstream::store_upstream_hosts() removes the port before the gate matches names. crates/minimald/src/box_manager/tests.rs needed no change: its one literal already ends in..Default::default(). The other literals outside the layers (box_runtime.rs, minvmd, dash) also use Default, so no file outside the layers changed. clippy -p boxes -p minimal -p minimald --all-targets is clean. The existing steered-answer debug line names the switch address and the name. The SERVFAIL warning names session_id and the name, and the new test pins that for api.openai.com.Tests
cargo nextest run -p minimal accepted_store_rule_authorities_reach_the_box_policycargo nextest run -p minimald store_authority_of_a_dns_box_resolves_to_the_proxyVerify
min task run agent-verifyexited 100 under rustc 1.99.0, which the repository does not pin (1.99.1 in rust-toolchain.toml); the PR is not a draft on that alone — CI, which honours the pin, is the gate.Closes #2575