pub struct ProxyAccessConfig {
pub cors: CorsConfig,
pub api_key: Option<String>,
pub api_key_source: ApiKeySource,
pub allowed_hosts: Vec<String>,
pub remote: Option<Arc<dyn RemoteGatewayPort>>,
}Expand description
Who may reach the proxy, and how they prove it.
Two independent gates that happen to travel together, because both are decided at bind time and both are needed by the same layer of the router:
api_keyis opt-in.Noneleaves the endpoint exactly as it behaved before authentication existed.allowed_hostsis always enforced. It is the DNS-rebinding defence, and it does not depend on a token being set.
Fields§
§cors: CorsConfigWhich origins the CORS layer accepts.
api_key: Option<String>Bearer token required on /v1/* and /mcp. None disables the check.
api_key_source: ApiKeySourceWhere api_key came from, which decides whether it may
later be replaced by a settings write. A flag or environment value
outranks the stored setting, so it must not be overridden by one; every
other source is the stored setting, or absent, and tracks it.
allowed_hosts: Vec<String>Host-header values accepted in addition to loopback, normalized to
lowercase with any port stripped. Loopback is always accepted and is
deliberately not listed here — it is a predicate
(is_loopback_host), so 127.0.0.2 and ::1 are covered without
anyone having to enumerate them.
remote: Option<Arc<dyn RemoteGatewayPort>>The remote tunnel’s owner, when this proxy may be reached through one
(ADR 0012). Travels with the access policy because it is one: it
decides whether a request that arrived through the tunnel may reach
/mcp.
None for an embedded server or a test, where nothing is listening
for the answers.
Implementations§
Source§impl ProxyAccessConfig
impl ProxyAccessConfig
Sourcepub fn new(
cors: CorsConfig,
api_key: Option<String>,
bind_host: &str,
extra_hosts: Vec<String>,
) -> Self
pub fn new( cors: CorsConfig, api_key: Option<String>, bind_host: &str, extra_hosts: Vec<String>, ) -> Self
Build the access policy for a proxy about to bind bind_host.
The bound address joins the allowlist automatically when it is a
concrete non-loopback address: someone who asked to bind 192.168.1.5
plainly intends to be reached at 192.168.1.5, and making them repeat
it as --allowed-host would be a rule with no purpose.
A wildcard bind (0.0.0.0 / ::) gets no such inference. It names no
reachable address, so there is nothing to infer, and guessing the
machine’s interface addresses would re-open exactly the hole the
allowlist exists to close. Those deployments must name their hostname
with --allowed-host.
Sourcepub fn with_remote(self, remote: Option<Arc<dyn RemoteGatewayPort>>) -> Self
pub fn with_remote(self, remote: Option<Arc<dyn RemoteGatewayPort>>) -> Self
Attach the remote tunnel’s owner.
Separate from new for the reason
with_key_source is: only the supervisor has
one to attach, and every other construction site means “no tunnel”.
Sourcepub const fn with_key_source(self, source: ApiKeySource) -> Self
pub const fn with_key_source(self, source: ApiKeySource) -> Self
Record where the token came from.
Separate from new so that adding it did not change a
signature every caller spells out; the supervisor is the only layer
that knows the answer, and every other construction site means
ApiKeySource::None.
Sourcepub fn host_allowed(&self, host_header: &str) -> bool
pub fn host_allowed(&self, host_header: &str) -> bool
Whether a request carrying this Host header may proceed.
This is the DNS-rebinding guard. A rebound page reaches the loopback
socket but still asks for the attacker’s hostname, so a Host that is
neither loopback nor explicitly allowed did not come from anyone who
knows where this proxy actually lives.
An absent or unparseable Host is rejected: HTTP/1.1 requires the
header, and a request that omits it has no claim to check.
Trait Implementations§
Source§impl Clone for ProxyAccessConfig
impl Clone for ProxyAccessConfig
Source§fn clone(&self) -> ProxyAccessConfig
fn clone(&self) -> ProxyAccessConfig
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for ProxyAccessConfig
impl Debug for ProxyAccessConfig
Source§impl Default for ProxyAccessConfig
impl Default for ProxyAccessConfig
Source§fn default() -> ProxyAccessConfig
fn default() -> ProxyAccessConfig
Source§impl PartialEq for ProxyAccessConfig
Equality is over the policy — CORS, token, source, hosts — and not
over remote, which is a live object rather
than a value. Two configs that differ only in whether a tunnel owner is
attached describe the same access rules.
impl PartialEq for ProxyAccessConfig
Equality is over the policy — CORS, token, source, hosts — and not
over remote, which is a live object rather
than a value. Two configs that differ only in whether a tunnel owner is
attached describe the same access rules.