use openmoat_core::{Decision, Permit, Verdict};
use super::{Broker, Channel};
pub const RULE_SECRET_ROUTE: &str = "proxy-secret-route";
impl Broker {
pub(crate) fn admit(
&self,
host: &str,
channel: Channel,
head: &[u8],
) -> Result<Vec<String>, Decision> {
let refuse = |why: String| Decision::single(Verdict::Deny, RULE_SECRET_ROUTE, why);
let injecting: Vec<_> = self
.held
.iter()
.filter(|h| h.injects(host, channel))
.collect();
if injecting.iter().all(|h| h.secret.allow.is_empty()) {
return Ok(Vec::new());
}
let mut headers = [httparse::EMPTY_HEADER; crate::request::MAX_HEADERS + 2];
let mut request = httparse::Request::new(&mut headers);
let (Ok(httparse::Status::Complete(_)), Some(method), Some(target)) =
(request.parse(head), request.method, request.path)
else {
return Err(refuse(format!(
"the request to {host} could not be read again to check its secrets' rules"
)));
};
let names: Vec<&str> = request.headers.iter().map(|h| h.name).collect();
let mut matched = Vec::new();
for held in injecting {
match held.secret.permit(method, target, &names) {
Permit::Unrestricted => {}
Permit::Rule(rule) => matched.push(format!(
"secret `{}` goes in: the request matches `{rule}`",
held.secret.id
)),
Permit::Refused(why) => return Err(refuse(why)),
_ => {
return Err(refuse(format!(
"{method} request to {host}: secret `{}` gave an answer the proxy \
does not know",
held.secret.id
)));
}
}
}
Ok(matched)
}
}