This commit is contained in:
William Brown 2025-04-04 10:49:55 +10:00
parent b27de62f32
commit 8bc9c93ce9
4 changed files with 63 additions and 36 deletions
examples
server
core/src
testkit/tests/testkit

View file

@ -13,16 +13,6 @@ bindaddress = "[::]:443"
# Defaults to "" (disabled)
# ldapbindaddress = "[::]:636"
#
# HTTPS requests can be reverse proxied by a loadbalancer.
# To preserve the original IP of the caller, these systems
# will often add a header such as "Forwarded" or
# "X-Forwarded-For". If set to true, then this header is
# respected as the "authoritative" source of the IP of the
# connected client. If you are not using a load balancer
# then you should leave this value as default.
# Defaults to false
# trust_x_forward_for = false
#
# The path to the kanidm database.
db_path = "/var/lib/private/kanidm/kanidm.db"
#
@ -86,6 +76,30 @@ domain = "idm.example.com"
# origin = "https://idm.example.com"
origin = "https://idm.example.com:8443"
#
# HTTPS requests can be reverse proxied by a loadbalancer.
# To preserve the original IP of the caller, these systems
# will often add a header such as "Forwarded" or
# "X-Forwarded-For". Some other proxies can use the HAProxy
# proxy v2 header.
# This setting allows configuration of the range of trusted
# IPs which can supply this header information, and which
# format the information is provided in.
# Defaults to "none" (no trusted sources)
# [http_client_address_info]
# proxy-v2 = ["127.0.0.1"]
# x-forward-for = ["127.0.0.1"]
# LDAPS requests can be reverse proxied by a loadbalancer.
# To preserve the original IP of the caller, these systems
# will can add a header such as the HAProxy proxy v2 header.
# This setting allows configuration of the range of trusted
# IPs which can supply this header information, and which
# format the information is provided in.
# Defaults to "none" (no trusted sources)
# [ldap_client_address_info]
# proxy-v2 = ["127.0.0.1"]
[online_backup]
# The path to the output folder for online backups
path = "/var/lib/private/kanidm/backups/"

View file

@ -13,16 +13,6 @@ bindaddress = "[::]:8443"
# Defaults to "" (disabled)
# ldapbindaddress = "[::]:3636"
#
# HTTPS requests can be reverse proxied by a loadbalancer.
# To preserve the original IP of the caller, these systems
# will often add a header such as "Forwarded" or
# "X-Forwarded-For". If set to true, then this header is
# respected as the "authoritative" source of the IP of the
# connected client. If you are not using a load balancer
# then you should leave this value as default.
# Defaults to false
# trust_x_forward_for = false
#
# The path to the kanidm database.
db_path = "/data/kanidm.db"
#
@ -85,7 +75,30 @@ domain = "idm.example.com"
# not consistent, the server WILL refuse to start!
# origin = "https://idm.example.com"
origin = "https://idm.example.com:8443"
#
# HTTPS requests can be reverse proxied by a loadbalancer.
# To preserve the original IP of the caller, these systems
# will often add a header such as "Forwarded" or
# "X-Forwarded-For". Some other proxies can use the HAProxy
# proxy v2 header.
# This setting allows configuration of the range of trusted
# IPs which can supply this header information, and which
# format the information is provided in.
# Defaults to "none" (no trusted sources)
# [http_client_address_info]
# proxy-v2 = ["127.0.0.1"]
# x-forward-for = ["127.0.0.1"]
# LDAPS requests can be reverse proxied by a loadbalancer.
# To preserve the original IP of the caller, these systems
# will can add a header such as the HAProxy proxy v2 header.
# This setting allows configuration of the range of trusted
# IPs which can supply this header information, and which
# format the information is provided in.
# Defaults to "none" (no trusted sources)
# [ldap_client_address_info]
# proxy-v2 = ["127.0.0.1"]
[online_backup]
# The path to the output folder for online backups
path = "/data/kanidm/backups/"

View file

@ -105,12 +105,12 @@ pub enum LdapAddressInfo {
#[default]
None,
#[serde(rename = "proxy-v2")]
ProxyV2 { trusted: HashSet<IpAddr> },
ProxyV2(HashSet<IpAddr>),
}
impl LdapAddressInfo {
pub fn trusted_proxy_v2(&self) -> Option<HashSet<IpAddr>> {
if let Self::ProxyV2 { trusted } = self {
if let Self::ProxyV2(trusted) = self {
Some(trusted.clone())
} else {
None
@ -122,7 +122,7 @@ impl Display for LdapAddressInfo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::None => f.write_str("none"),
Self::ProxyV2 { trusted } => {
Self::ProxyV2(trusted) => {
f.write_str("proxy-v2 [ ")?;
for ip in trusted {
write!(f, "{} ", ip)?;
@ -152,24 +152,24 @@ pub enum HttpAddressInfo {
#[default]
None,
#[serde(rename = "x-forward-for")]
XForwardFor { trusted: HashSet<IpAddr> },
XForwardFor(HashSet<IpAddr>),
#[serde(rename = "x-forward-for-all-source-trusted")]
XForwardForAllSourcesTrusted,
#[serde(rename = "proxy-v2")]
ProxyV2 { trusted: HashSet<IpAddr> },
ProxyV2(HashSet<IpAddr>),
}
impl HttpAddressInfo {
pub(crate) fn trusted_x_forward_for(&self) -> Option<AddressRange> {
match self {
Self::XForwardForAllSourcesTrusted => Some(AddressRange::All),
Self::XForwardFor { trusted } => Some(AddressRange::Range(trusted.clone())),
Self::XForwardFor(trusted) => Some(AddressRange::Range(trusted.clone())),
_ => None,
}
}
pub(crate) fn trusted_proxy_v2(&self) -> Option<HashSet<IpAddr>> {
if let Self::ProxyV2 { trusted } = self {
if let Self::ProxyV2(trusted) = self {
Some(trusted.clone())
} else {
None
@ -182,7 +182,7 @@ impl Display for HttpAddressInfo {
match self {
Self::None => f.write_str("none"),
Self::XForwardFor { trusted } => {
Self::XForwardFor(trusted) => {
f.write_str("x-forward-for [ ")?;
for ip in trusted {
write!(f, "{} ", ip)?;
@ -192,7 +192,7 @@ impl Display for HttpAddressInfo {
Self::XForwardForAllSourcesTrusted => {
f.write_str("x-forward-for [ ALL SOURCES TRUSTED ]")
}
Self::ProxyV2 { trusted } => {
Self::ProxyV2(trusted) => {
f.write_str("proxy-v2 [ ")?;
for ip in trusted {
write!(f, "{} ", ip)?;

View file

@ -58,7 +58,7 @@ async fn dont_trust_xff_dont_send_header(rsclient: &KanidmClient) {
// *test where we trust the x-forwarded-for header
#[kanidmd_testkit::test(http_client_address_info = HttpAddressInfo::XForwardFor { trusted: [DEFAULT_IP_ADDRESS].into() })]
#[kanidmd_testkit::test(http_client_address_info = HttpAddressInfo::XForwardFor ( [DEFAULT_IP_ADDRESS].into() ))]
async fn trust_xff_send_invalid_header_single_value(rsclient: &KanidmClient) {
let client = rsclient.client();
@ -78,7 +78,7 @@ async fn trust_xff_send_invalid_header_single_value(rsclient: &KanidmClient) {
// TODO: Right now we reject the request only if the leftmost address is invalid. In the future that could change so we could also have a test
// with a valid leftmost address and an invalid address later in the list. Right now it wouldn't work.
//
#[kanidmd_testkit::test(http_client_address_info = HttpAddressInfo::XForwardFor { trusted: [DEFAULT_IP_ADDRESS].into() })]
#[kanidmd_testkit::test(http_client_address_info = HttpAddressInfo::XForwardFor ( [DEFAULT_IP_ADDRESS].into() ))]
async fn trust_xff_send_invalid_header_multiple_values(rsclient: &KanidmClient) {
let client = rsclient.client();
@ -95,7 +95,7 @@ async fn trust_xff_send_invalid_header_multiple_values(rsclient: &KanidmClient)
assert_eq!(res.status(), 400);
}
#[kanidmd_testkit::test(http_client_address_info = HttpAddressInfo::XForwardFor { trusted: [DEFAULT_IP_ADDRESS].into() })]
#[kanidmd_testkit::test(http_client_address_info = HttpAddressInfo::XForwardFor ( [DEFAULT_IP_ADDRESS].into() ))]
async fn trust_xff_send_valid_header_single_ipv4_address(rsclient: &KanidmClient) {
let ip_addr = "2001:db8:85a3:8d3:1319:8a2e:370:7348";
@ -115,7 +115,7 @@ async fn trust_xff_send_valid_header_single_ipv4_address(rsclient: &KanidmClient
assert_eq!(ip_res, IpAddr::from_str(ip_addr).unwrap());
}
#[kanidmd_testkit::test(http_client_address_info = HttpAddressInfo::XForwardFor { trusted: [DEFAULT_IP_ADDRESS].into() })]
#[kanidmd_testkit::test(http_client_address_info = HttpAddressInfo::XForwardFor ( [DEFAULT_IP_ADDRESS].into() ))]
async fn trust_xff_send_valid_header_single_ipv6_address(rsclient: &KanidmClient) {
let ip_addr = "203.0.113.195";
@ -135,7 +135,7 @@ async fn trust_xff_send_valid_header_single_ipv6_address(rsclient: &KanidmClient
assert_eq!(ip_res, IpAddr::from_str(ip_addr).unwrap());
}
#[kanidmd_testkit::test(http_client_address_info = HttpAddressInfo::XForwardFor { trusted: [DEFAULT_IP_ADDRESS].into() })]
#[kanidmd_testkit::test(http_client_address_info = HttpAddressInfo::XForwardFor ( [DEFAULT_IP_ADDRESS].into() ))]
async fn trust_xff_send_valid_header_multiple_address(rsclient: &KanidmClient) {
let first_ip_addr = "203.0.113.195, 2001:db8:85a3:8d3:1319:8a2e:370:7348";
@ -176,7 +176,7 @@ async fn trust_xff_send_valid_header_multiple_address(rsclient: &KanidmClient) {
);
}
#[kanidmd_testkit::test(http_client_address_info = HttpAddressInfo::XForwardFor { trusted: [DEFAULT_IP_ADDRESS].into() })]
#[kanidmd_testkit::test(http_client_address_info = HttpAddressInfo::XForwardFor ( [DEFAULT_IP_ADDRESS].into() ))]
async fn trust_xff_dont_send_header(rsclient: &KanidmClient) {
let client = rsclient.client();