Expand description
The global IP gate: whitelist, blacklist, and exempt_ips.
This is the Rust family’s minimal port of the reference engine’s global IP
stage (guard-core check_ip_access, frozen by the ecosystem
exempt_ips contract). One call,
IpGateConfig::evaluate, decides a request IP:
if a whitelist is configured and the IP is not on it: deny (not in whitelist)
otherwise, if the IP is on the blacklist: deny (blacklisted)
allowed: is_whitelisted = matched the whitelist
is_exempt = matched exempt_ips§The exempt_ips contract
exempt_ips is the skip-list for known-friendly automation (monitoring
probes, VPN egress, a partner’s server). A match sets the same skip state
a whitelist match sets (IpGateDecision::is_exempt), but it carries no
deny path of its own: exemption can never open the whitelist gate, and an
exempt IP on the blacklist is still denied. whitelist keeps its
allowlist semantics untouched: when it is non-empty, every unlisted IP is
denied exactly as before, exemption included.
Matching semantics are identical for all three lists: an entry is a bare
IP or a CIDR range (host bits are cleared at parse time, so 1.2.3.4/24
and 1.2.3.0/24 are the same network), an IPv4-mapped request address
(::ffff:203.0.113.7) matches its IPv4 canonical form, and families never
cross (an IPv4 entry never matches an unrelated IPv6 address).
Invalid entries are config errors: IpGateConfig::new fails closed, so
an adapter that builds its gate at startup never serves with a broken
list.
§Example
use std::net::IpAddr;
use std::str::FromStr;
use guard_core_engine::ip_gate::{IpGateConfig, IpGateVerdict};
let gate = IpGateConfig::new(
[] as [&str; 0],
["203.0.113.9"],
["198.51.100.7", "198.51.100.16/28"],
)
.expect("valid lists");
// An exempt IP passes with the skip flag set.
let exempt = gate.evaluate(IpAddr::from_str("198.51.100.7").unwrap());
assert!(matches!(exempt, IpGateVerdict::Allowed(decision) if decision.is_exempt));
// A CIDR entry matches the whole range, the flag carried along.
let in_range = gate.evaluate(IpAddr::from_str("198.51.100.20").unwrap());
assert!(matches!(in_range, IpGateVerdict::Allowed(decision) if decision.is_exempt));
// The blacklist wins over exemption: no deny path is added, but none is
// removed either.
assert_eq!(
gate.evaluate(IpAddr::from_str("203.0.113.9").unwrap()),
IpGateVerdict::Denied(guard_core_engine::ip_gate::IpGateDenial::Blacklisted)
);
// Everyone else passes unimpeded: an empty whitelist denies nobody.
let other = gate.evaluate(IpAddr::from_str("192.0.2.1").unwrap());
assert!(matches!(other, IpGateVerdict::Allowed(decision) if !decision.is_exempt));Structs§
- IpGate
Config - The global IP gate: the parsed
whitelist,blacklist, andexempt_ipslists. - IpGate
Decision - The skip state a request carries after it passed the global IP gate.
- IpGate
Error - An invalid list entry: the config error
IpGateConfig::newfails with. - Route
Access - The combined route verdict of
RouteIpGate::evaluate_access: the referencecheck_route_ip_accessresult plus the skip flag the reference derives from the route’s country verdict. - Route
IpGate - The route-level IP gate: a route decorator’s
ip_whitelistandip_blacklist(RouteConfig.ip_whitelist/.ip_blacklist).
Enums§
- IpGate
Denial - Why the global IP gate denied a request.
- IpGate
Verdict - The outcome of the global IP gate for one request IP.
- Route
IpVerdict - The outcome of the route-level IP gate for one request IP
(
check_route_ip_access’s tri-state, the country arms aside; seeRouteIpGate::evaluate_accessfor the combined verdict).