0.29.7
This commit is contained in:
1 parent
ad95bfb050
commit
1431dd47f0
62 files changed
+1360
-198
No files matched your search
@@ -57,6 +57,10 @@ pub fn compile_with_active(
|
||||
}
|
||||
ensure!(config.web_services.len() <= 128, "too many Web Services (max 128)");
|
||||
let mut web_services = HashMap::new();
|
||||
// PHP-FPM can retain FastCGI PHP_VALUE/PHP_ADMIN_VALUE directives in reused
|
||||
// workers. Different directive sets on one socket can leak to the next vhost.
|
||||
// Report unsafe legacy configurations but keep them loadable for migration.
|
||||
let mut php_endpoint_policies: HashMap<String, (String, std::collections::BTreeMap<String, String>, std::collections::BTreeMap<String, String>)> = HashMap::new();
|
||||
for service in &mut config.web_services {
|
||||
service.validate().with_context(|| format!("Web Service {}", service.id))?;
|
||||
// A profile changes effective runtime settings, not the saved standalone
|
||||
@@ -68,6 +72,21 @@ pub fn compile_with_active(
|
||||
})?.clone();
|
||||
effective.validate().with_context(|| format!("Web Service {} PHP-FPM profile {}", service.id, id))?;
|
||||
}
|
||||
if effective.php.enabled {
|
||||
let php = &effective.php;
|
||||
if let Some((owner, values, admin_values)) = php_endpoint_policies.get(&php.endpoint) {
|
||||
if values != &php.php_values || admin_values != &php.php_admin_values {
|
||||
tracing::warn!(
|
||||
service = %effective.id, other_service = %owner, endpoint = %php.endpoint,
|
||||
"PHP-FPM endpoint is shared by Web Services with different PHP_VALUE/PHP_ADMIN_VALUE settings; FPM worker settings can leak across requests. Use distinct PHP-FPM pools/sockets (especially for open_basedir)."
|
||||
);
|
||||
}
|
||||
} else {
|
||||
php_endpoint_policies.insert(php.endpoint.clone(), (
|
||||
effective.id.clone(), php.php_values.clone(), php.php_admin_values.clone(),
|
||||
));
|
||||
}
|
||||
}
|
||||
let compiled = Arc::new(effective.compile().with_context(|| format!("Web Service {}", service.id))?);
|
||||
ensure!(web_services.insert(service.id.clone(), compiled).is_none(), "duplicate Web Service id");
|
||||
}
|
||||
|
||||
@@ -122,7 +122,10 @@ fn compile_routing(
|
||||
// Blank health-check Host means the first exact DNS name of the vhost.
|
||||
// This is important when the backend URL is an IP shared by several vhosts.
|
||||
if pool_settings.health_check.host.is_none()
|
||||
&& pool_settings.health_check.mode == crate::balance::HealthMode::Http
|
||||
&& (pool_settings.health_check.mode == crate::balance::HealthMode::Http
|
||||
|| host.backends.iter().any(|member| member.health_check.as_ref()
|
||||
.is_some_and(|health| health.mode == crate::balance::HealthMode::Http
|
||||
&& health.host.is_none())))
|
||||
{
|
||||
pool_settings.health_check.host = host
|
||||
.frontend
|
||||
|
||||
@@ -6,6 +6,19 @@ fn path_boundaries() {
|
||||
assert!(prefix_matches("/", "/anything"));
|
||||
}
|
||||
#[test]
|
||||
fn invalid_per_backend_health_policy_rejected_without_global_override() {
|
||||
let mut c = demo_config("127.0.0.1:9000".parse().unwrap());
|
||||
c.vhosts[0].backends[0].health_check = Some(crate::balance::HealthCheck {
|
||||
mode: crate::balance::HealthMode::Http,
|
||||
interval_ms: 300,
|
||||
timeout_ms: 400,
|
||||
..Default::default()
|
||||
});
|
||||
assert!(compile(c.clone(), 1, &policy()).is_err());
|
||||
c.vhosts[0].backends[0].health_check.as_mut().unwrap().timeout_ms = 200;
|
||||
assert!(compile(c, 1, &policy()).is_ok());
|
||||
}
|
||||
#[test]
|
||||
fn private_requires_opt_in_and_metadata_always_denied() {
|
||||
let mut c = demo_config("127.0.0.1:9000".parse().unwrap());
|
||||
assert!(compile(c.clone(), 1, &policy()).is_ok());
|
||||
@@ -279,6 +292,18 @@ fn http_health_check_defaults_host_to_first_exact_vhost_dns_name() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn per_member_http_health_inherits_vhost_dns_even_when_global_health_is_tcp() {
|
||||
let mut c = demo_config("127.0.0.1:9000".parse().unwrap());
|
||||
c.vhosts[0].frontend.hosts = vec!["app.example.test".into()];
|
||||
assert_eq!(c.vhosts[0].load_balancing.health_check.mode, crate::balance::HealthMode::Tcp);
|
||||
c.vhosts[0].backends[0].health_check = Some(crate::balance::HealthCheck {
|
||||
mode: crate::balance::HealthMode::Http, path: "/healthz".into(), ..Default::default()
|
||||
});
|
||||
let snapshot = compile(c, 1, &policy()).unwrap();
|
||||
let pool = &snapshot.pools[0];
|
||||
assert_eq!(pool.settings.health_for(&pool.members[0].definition).host.as_deref(), Some("app.example.test"));
|
||||
}
|
||||
#[test]
|
||||
fn explicit_http_health_check_host_override_wins_over_vhost_hostname() {
|
||||
let mut c = demo_config("127.0.0.1:9000".parse().unwrap());
|
||||
|
||||
Reference in new issue
Block a user