Expand description
Fetch, validate, and cache OAuth Client ID Metadata Documents (CIMD).
Split into independently testable layers:
ssrf::validate_url_shape— static URL checks, no network (tested in isolation incimd::ssrf).resolve_and_validate_address— real DNS resolution, bounded by a timeout, rejecting the whole resolved-address set if any address is private. Tested with literal loopback/private hostnames — no real network access needed to prove a rejection; a real “successful public resolution” is not unit-tested here (see the plan’s Global Constraints for why: no network access in CI).fetch_via_pinned_address/fetch_document_at— given an ALREADY resolved+validated address, builds a pinned/no-proxy/ no-redirect client and does the GET + peer-recheck + streaming-cap + parse + validate. Tested against a localwiremockserver by pointing the pin directly at its real bound address — this deliberately bypasses DNS resolution (same as production code does once step 2 has already resolved+validated an address), so it needs no network and no HTTPS certificate.
fetch_and_validate_client_metadata composes all three for the real
production path, with per-key single-flight coordination and a short
negative-result cooldown for cached failures — the mechanism mirrors
crate::upstream::cache::OauthClientCache’s build_locks pattern, but
unlike that cache’s (upstream_name, subject) key (bounded by operator
config and authenticated sessions, not attacker-controlled), client_id
here is an anonymous, attacker-controlled URL — see DocumentCache’s
own doc for how that difference is handled.
Structs§
- Client
Metadata Document - Document
Cache - Single-flight, TTL-and-negative-cached store for fetched CIMD documents,
keyed by the requested URL. Mirrors
crate::upstream::cache::OauthClientCache’sbuild_lockspattern: concurrent callers for the same never-cached (or just-expired) URL serialize on a per-key lock so only one of them actually performs the DNS resolution + fetch; the rest wait for and reuse that result.
Enums§
Functions§
- fetch_
and_ validate_ client_ metadata - Production entry point: single-flight-locked cache lookup (including a
short negative-result cooldown for cached failures), else SSRF-validate
the URL shape, resolve+validate DNS (for domain hosts) or use the
already-validated IP literal directly, fetch via
fetch_via_pinned_address, and cache the result either way. - is_
cimd_ client_ id - Cheap detection heuristic: a CIMD
client_idis anhttps://URL. soma-auth’s own DCR-issuedclient_ids are opaque base64url tokens (random_token(18)inauthorize::register_client) and can never start withhttps://. - resolve_
and_ validate_ address - Resolve
host:portvia DNS (bounded byDNS_TIMEOUT) and return the first resolved address, rejecting the entire result set if any resolved address is private/loopback/etc — a hostname resolving to a mix of public and private addresses is treated as untrusted outright rather than cherry-picking a public one, since DNS load-balancing could non-deterministically prefer the private one on a subsequent lookup even though this specific call pins one address.