Skip to main content

UrlPolicy

Struct UrlPolicy 

Source
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());          // scheme

Fields§

§allowed_schemes: Vec<String>

Schemes that may be used. Defaults to https only.

§allow_private_networks: bool

Whether 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

Source

pub fn permissive() -> Self

A policy that permits anything, for tests and for talking to a peer over plain HTTP on a trusted network.

Source

pub fn with_allowed_hosts<I, S>(self, hosts: I) -> Self
where I: IntoIterator<Item = S>, S: Into<String>,

Restricts this policy to hosts and their subdomains.

Source

pub fn allowing_http(self) -> Self

Allows plain http in addition to whatever is already allowed.

Source

pub fn allowing_private_networks(self) -> Self

Allows targets on private and loopback networks.

Source

pub fn check(&self, url: &Url) -> Result<(), UrlRefused>

Checks url against this policy.

§Errors

Returns UrlRefused naming the rule that rejected the URL.

Trait Implementations§

Source§

impl Clone for UrlPolicy

Source§

fn clone(&self) -> UrlPolicy

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for UrlPolicy

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for UrlPolicy

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more