Watch
0
0
Fork
You've already forked hyperhive
0

squid blocks a runtime deny list from the controller in every egress mode, ahead of the allow list

This commit is contained in:
atlas 2026-11-04 22:00:42 +01:00 • committed by mara
commit dd5fde848f

View file

@ -1,5 +1,5 @@
//! `/api/egress/allowed-domains` — the destinations the swarm lets agents
//! reach through their hive's egress proxy.
//! `/api/egress/allowed-domains` and `/api/egress/denied-domains` — the destinations the swarm lets
//! agents reach through their hive's egress proxy, and the ones it refuses.
use serde::{Deserialize, Serialize};
@ -33,6 +33,40 @@ pub struct AllowedDomains {
pub entries: Vec<AllowedDomain>,
}
/// One refused destination and who it is refused for.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(utoipa::ToSchema))]
#[serde(deny_unknown_fields)]
pub struct DeniedDomain {
/// A DNS name written as in [`AllowedDomain::domain`]: at least two
/// labels, lower-cased, one leading dot for the name and its subdomains.
#[cfg_attr(feature = "schema", schema(example = ".example.com"))]
pub domain: String,
/// The agent this entry is for. Absent means every agent in the swarm. An
/// agent's entry adds to the swarm-wide ones and never lifts one.
#[serde(default, skip_serializing_if = "Option::is_none")]
#[cfg_attr(feature = "schema", schema(example = "atlas"))]
pub agent: Option<String>,
}
/// The swarm's deny list: every entry, swarm-wide and per agent, sorted, and
/// whether every hive has taken it.
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "schema", derive(utoipa::ToSchema))]
pub struct DeniedDomains {
pub entries: Vec<DeniedDomain>,
/// The revision of the stored list, `0` when nobody has written one. A
/// hive reports the revision it last rendered into its proxy.
#[serde(default)]
pub revision: u64,
/// The hives whose proxy is not known to refuse these names yet: they have
/// not reported the list's revision (a hive that predates the deny list
/// never does, a new one takes a minute or so), or have not reported at
/// all. Empty when the list is empty and no hive reports otherwise.
#[serde(default)]
pub behind: Vec<String>,
}
#[cfg(test)]
mod tests {
use super::*;
@ -60,4 +94,23 @@ mod tests {
);
assert!(serde_json::from_str::<AllowedDomain>(r#"{"domain":"a.io","hive":"x"}"#).is_err());
}
#[test]
fn a_denied_entry_has_no_derived_flag_and_refuses_unknown_fields() {
let swarm_wide = DeniedDomain {
domain: ".example.com".to_owned(),
agent: None,
};
let wire = r#"{"domain":".example.com"}"#;
assert_eq!(serde_json::to_string(&swarm_wide).unwrap(), wire);
assert_eq!(
serde_json::from_str::<DeniedDomain>(wire).unwrap(),
swarm_wide
);
// A deny is never automatic, so the allow list's `derived` is not a field.
assert!(
serde_json::from_str::<DeniedDomain>(r#"{"domain":"a.io","derived":true}"#).is_err()
);
assert!(serde_json::from_str::<DeniedDomain>(r#"{"domain":"a.io","hive":"x"}"#).is_err());
}
}