Permit private IPv6 while redacting responses
This commit is contained in:
parent
7bd5316b1b
commit
5cbb0364d2
4 changed files with 47 additions and 3 deletions
|
|
@ -163,7 +163,12 @@ fn is_metadata_capable_space(address: IpAddr) -> bool {
|
|||
|| (first == 169 && second == 254)
|
||||
|| (first == 192 && second == 0 && third == 0)
|
||||
}
|
||||
IpAddr::V6(address) => address.segments()[0] & 0xfe00 == 0xfc00,
|
||||
IpAddr::V6(address) => {
|
||||
let segments = address.segments();
|
||||
(segments[0] == 0xfd00 && segments[1] == 0x0ec2)
|
||||
|| (segments[0] == 0xfd20 && segments[1] == 0x00ce)
|
||||
|| (segments[..4] == [0xfd00, 0x0db8, 0xdeca, 0xdeed])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,12 +32,20 @@ pub struct OutboundRequest {
|
|||
credential_headers: HeaderMap,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OutboundResponse {
|
||||
final_url: CanonicalUrl,
|
||||
response: reqwest::Response,
|
||||
}
|
||||
|
||||
impl fmt::Debug for OutboundResponse {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter
|
||||
.debug_struct("OutboundResponse")
|
||||
.field("status", &self.response.status())
|
||||
.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Resolver> OutboundClient<R> {
|
||||
#[must_use]
|
||||
pub fn builder(resolver: R, policy: OutboundPolicy) -> OutboundClientBuilder<R> {
|
||||
|
|
|
|||
|
|
@ -158,11 +158,14 @@ async fn allowlists_never_override_metadata_denial() {
|
|||
let policy = OutboundPolicyBuilder::new()
|
||||
.allow_non_global("10.0.0.0/8".parse::<IpNet>().expect("network"))
|
||||
.allow_non_global("169.254.0.0/16".parse::<IpNet>().expect("network"))
|
||||
.allow_non_global("fd00::/8".parse::<IpNet>().expect("network"))
|
||||
.allow_non_global("fc00::/7".parse::<IpNet>().expect("network"))
|
||||
.build();
|
||||
authorize_literal(&policy, "10.1.2.3")
|
||||
.await
|
||||
.expect("allowlisted private address");
|
||||
authorize_literal(&policy, "fd12:3456:789a::1")
|
||||
.await
|
||||
.expect("allowlisted ULA address");
|
||||
for address in [
|
||||
"169.254.169.254",
|
||||
"169.254.170.2",
|
||||
|
|
|
|||
|
|
@ -251,6 +251,34 @@ fn request_debug_redacts_url_and_credential_values() {
|
|||
assert!(!debug.contains("synthetic-api-key"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn response_debug_redacts_url_and_response_headers() {
|
||||
let (port, _, server) = serve_http(1, |_| {
|
||||
response(
|
||||
"200 OK",
|
||||
&[("Set-Cookie", "session=synthetic-secret")],
|
||||
"ok",
|
||||
)
|
||||
})
|
||||
.await;
|
||||
let resolver = ScriptedResolver::new([("source.test", vec![vec![ip("127.0.0.1")]])]);
|
||||
let client = OutboundClient::builder(resolver, local_policy(port, 5)).build();
|
||||
let result = client
|
||||
.execute(
|
||||
OutboundRequest::get(&format!(
|
||||
"http://source.test:{port}/sensitive?token=synthetic"
|
||||
))
|
||||
.expect("request"),
|
||||
)
|
||||
.await
|
||||
.expect("response");
|
||||
let debug = format!("{result:?}");
|
||||
assert!(debug.contains("200"));
|
||||
assert!(!debug.contains("sensitive"));
|
||||
assert!(!debug.contains("synthetic-secret"));
|
||||
server.await.expect("server");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn denied_redirect_is_rejected_before_dial() {
|
||||
let (port, _, server) = serve_http(1, |request| {
|
||||
|
|
|
|||
Loading…
Reference in a new issue