mirror of https://github.com/linkerd/linkerd2.git
Parse probe paths as URI (#10934)
Fixes #10877 Linkerd reads the list of container readiness and liveness probes for a pod in order to generate authorizations which allow probes by default. However, when reading the `path` field of a probe, we interpret this field literally rather than parsing it as a URI. This means that any non-path parts of the URI (such as URI params) will attempt to match against the path of a probe request, causing these authorizations to fail. Instead, we parse this field as a URI and only use the path part for path matching. Invalid URIs are skipped and a warning is logged. Signed-off-by: Alex Leong <alex@buoyant.io>
This commit is contained in:
parent
cc6c0fc4bb
commit
5309789f35
|
|
@ -1334,6 +1334,7 @@ dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
"futures",
|
"futures",
|
||||||
|
"http",
|
||||||
"k8s-gateway-api",
|
"k8s-gateway-api",
|
||||||
"kubert",
|
"kubert",
|
||||||
"linkerd-policy-controller-core",
|
"linkerd-policy-controller-core",
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ publish = false
|
||||||
ahash = "0.8"
|
ahash = "0.8"
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
futures = { version = "0.3", default-features = false }
|
futures = { version = "0.3", default-features = false }
|
||||||
|
http = "0.2"
|
||||||
k8s-gateway-api = "0.11"
|
k8s-gateway-api = "0.11"
|
||||||
kubert = { version = "0.16", default-features = false, features = ["index"] }
|
kubert = { version = "0.16", default-features = false, features = ["index"] }
|
||||||
linkerd-policy-controller-core = { path = "../../core" }
|
linkerd-policy-controller-core = { path = "../../core" }
|
||||||
|
|
|
||||||
|
|
@ -74,8 +74,14 @@ fn container_http_probe_paths(
|
||||||
.filter_map(|p| {
|
.filter_map(|p| {
|
||||||
let probe = p.http_get.as_ref()?;
|
let probe = p.http_get.as_ref()?;
|
||||||
let port = get_port(&probe.port, container)?;
|
let port = get_port(&probe.port, container)?;
|
||||||
let path = probe.path.clone().unwrap_or_else(|| "/".to_string());
|
let path = probe.path.as_deref().unwrap_or("/");
|
||||||
Some((port, path))
|
match http::Uri::try_from(path) {
|
||||||
|
Ok(uri) => Some((port, uri.path().to_string())),
|
||||||
|
Err(error) => {
|
||||||
|
tracing::warn!(%error, path, "invalid probe path");
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -313,4 +319,27 @@ mod tests {
|
||||||
assert_eq!(paths.len(), 1);
|
assert_eq!(paths.len(), 1);
|
||||||
assert_eq!(paths.iter().next().unwrap(), "/");
|
assert_eq!(paths.iter().next().unwrap(), "/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn probe_with_params() {
|
||||||
|
let probes = pod_http_probes(&k8s::PodSpec {
|
||||||
|
containers: vec![k8s::Container {
|
||||||
|
liveness_probe: Some(k8s::Probe {
|
||||||
|
http_get: Some(k8s::HTTPGetAction {
|
||||||
|
path: Some("/liveness-container-1?foo=bar".to_string()),
|
||||||
|
port: k8s::IntOrString::Int(5432),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
}],
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(probes.len(), 1);
|
||||||
|
let paths = probes.get(&5432.try_into().unwrap()).unwrap();
|
||||||
|
assert_eq!(paths.len(), 1);
|
||||||
|
assert_eq!(paths.iter().next().unwrap(), "/liveness-container-1");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue