pub struct UrlPolicy {
pub allowed_schemes: Vec<String>,
pub allow_private_networks: bool,
pub allowed_hosts: Vec<String>,
}Expand description
What a party is willing to send a request to.
OCPI hands a server URLs that it is then expected to call: Credentials.url,
Endpoint.url, and every response_url in the Commands and Charging Profiles modules. A
party that fetches those without checking is a server-side request forgery proxy for anyone
it has registered with. The specification says nothing about this, so this crate ships a
default that says no to the things a CPO never legitimately needs to call.
§What this does not do
A UrlPolicy inspects the URL, and only the URL. It cannot see where a host name
resolves, so https://ptp.example.com/cb passes even when that name has an A record for
169.254.169.254, and a name that resolves differently between the check and the connection
defeats it outright (a DNS rebind). Closing that needs a resolver in the connection path,
which belongs to whatever HTTP client is doing the fetching rather than to a URL type.
So treat this as the first of two layers, not as the whole defence. In production, pair it
with with_allowed_hosts — an explicit list per peer is not
subject to either problem — and with an egress policy on the network that refuses the link-
local and private ranges outright. The literal-IP rules below are what stops the careless
cases; the allow-list is what stops the deliberate ones.
use ocpi_kit::types::{Url, UrlPolicy};
let policy = UrlPolicy::default();
assert!(policy.check(&Url::new("https://msp.example.com/cb/1").unwrap()).is_ok());
assert!(policy.check(&Url::new("http://msp.example.com/cb/1").unwrap()).is_err()); // not TLS
assert!(policy.check(&Url::new("https://127.0.0.1/cb").unwrap()).is_err()); // loopback
assert!(policy.check(&Url::new("file:///etc/passwd").unwrap()).is_err()); // schemeFields§
§allowed_schemes: Vec<String>Schemes that may be used. Defaults to https only.
allow_private_networks: boolWhether loopback, link-local, private and unspecified addresses may be targeted.
Defaults to false. Set to true for local development and integration tests.
allowed_hosts: Vec<String>When non-empty, only these hosts (matched case-insensitively, plus their subdomains) may be targeted.
Implementations§
Source§impl UrlPolicy
impl UrlPolicy
Sourcepub fn permissive() -> Self
pub fn permissive() -> Self
A policy that permits anything, for tests and for talking to a peer over plain HTTP on a trusted network.
Sourcepub fn with_allowed_hosts<I, S>(self, hosts: I) -> Self
pub fn with_allowed_hosts<I, S>(self, hosts: I) -> Self
Restricts this policy to hosts and their subdomains.
Sourcepub fn allowing_http(self) -> Self
pub fn allowing_http(self) -> Self
Allows plain http in addition to whatever is already allowed.
Sourcepub fn allowing_private_networks(self) -> Self
pub fn allowing_private_networks(self) -> Self
Allows targets on private and loopback networks.