Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion core/src/config/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use serde::Deserialize;
/// assert!(admin.verbose);
/// ```
#[derive(Debug, Clone, Default, Deserialize)]
#[serde(default)]
#[serde(default, deny_unknown_fields)]
pub struct AdminConfig {
/// Admin endpoint bind address.
pub address: Option<String>,
Expand Down
2 changes: 1 addition & 1 deletion core/src/config/body_limits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use serde::Deserialize;
/// assert_eq!(limits.max_response_bytes, Some(5_242_880));
/// ```
#[derive(Debug, Clone, Default, Deserialize)]
#[serde(default)]
#[serde(default, deny_unknown_fields)]
pub struct BodyLimitsConfig {
/// Maximum request body size in bytes.
pub max_request_bytes: Option<usize>,
Expand Down
1 change: 1 addition & 0 deletions core/src/config/cluster/health_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ impl fmt::Display for HealthCheckType {
/// assert_eq!(hc.interval_ms, 5000);
/// ```
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct HealthCheckConfig {
/// Probe type: [`Http`], [`Tcp`], or [`Grpc`].
///
Expand Down
1 change: 1 addition & 0 deletions core/src/config/cluster/load_balancer_strategy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ pub enum ParameterisedStrategy {

/// Options for the `consistent_hash` load-balancing strategy.
#[derive(Debug, Clone, Default, Deserialize, PartialEq, Eq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ConsistentHashOpts {
/// Name of the request header to use as the hash key.
///
Expand Down
1 change: 1 addition & 0 deletions core/src/config/cluster/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ use serde::{Deserialize, Serialize};
/// assert!(cluster.tls.is_none());
/// ```
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Cluster {
/// Unique name for the cluster.
pub name: Arc<str>,
Expand Down
1 change: 1 addition & 0 deletions core/src/config/condition/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pub use response::{ResponseCondition, ResponseConditionMatch};
macro_rules! impl_condition_deserialize {
($cond:ident, $match_:ty, $label:expr) => {
#[derive(serde::Deserialize)]
#[serde(deny_unknown_fields)]
struct ConditionDeserHelper {
/// The `when` predicate, if present.
#[serde(default)]
Expand Down
1 change: 1 addition & 0 deletions core/src/config/condition/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ impl_condition_deserialize!(Condition, ConditionMatch, "condition");
/// assert_eq!(m.methods.as_ref().unwrap().len(), 2);
/// ```
#[derive(Debug, Clone, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ConditionMatch {
/// Request URI must match this exact path.
#[serde(default)]
Expand Down
1 change: 1 addition & 0 deletions core/src/config/condition/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ impl_condition_deserialize!(ResponseCondition, ResponseConditionMatch, "response
/// assert_eq!(m.status.as_ref().unwrap(), &[200, 201]);
/// ```
#[derive(Debug, Clone, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct ResponseConditionMatch {
/// Response status code must be one of these.
#[serde(default)]
Expand Down
1 change: 1 addition & 0 deletions core/src/config/filters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use super::{Condition, ResponseCondition};
/// assert_eq!(chain.filters.len(), 2);
/// ```
#[derive(Debug, Clone, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct FilterChainConfig {
/// Unique name for this filter chain.
pub name: String,
Expand Down
2 changes: 1 addition & 1 deletion core/src/config/insecure_options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ use serde::Deserialize;
/// ```
#[allow(clippy::struct_excessive_bools, reason = "security override flags")]
#[derive(Debug, Clone, Default, Deserialize)]
#[serde(default)]
#[serde(default, deny_unknown_fields)]
pub struct InsecureOptions {
/// Allow running as root (UID 0).
pub allow_root: bool,
Expand Down
1 change: 1 addition & 0 deletions core/src/config/listener.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use serde::Deserialize;
/// assert!(listener.tls.is_none());
/// ```
#[derive(Debug, Clone, Deserialize, serde::Serialize)]
#[serde(deny_unknown_fields)]
pub struct Listener {
/// Unique name for this listener.
pub name: String,
Expand Down
11 changes: 11 additions & 0 deletions core/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ pub use validate::{MAX_BRANCH_DEPTH, MAX_ITERATIONS_CEILING};
/// assert_eq!(config.listeners[0].address, "127.0.0.1:8080");
/// ```
#[derive(Debug, Clone, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Config {
/// Admin endpoint settings (address and verbosity).
#[serde(default)]
Expand Down Expand Up @@ -565,6 +566,16 @@ filter_chains:
assert!(!config.admin.verbose, "admin verbose should default to false");
}

#[test]
fn reject_unrecognized_top_level_key() {
let yaml = format!("{VALID_YAML}\nunrecognized_key: true\n");
let err = Config::from_yaml(&yaml).unwrap_err();
assert!(
err.to_string().contains("unrecognized_key"),
"error should name the unknown field"
);
}

// -------------------------------------------------------------------------
// Test Utilities
// -------------------------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions core/src/config/route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use serde::{Deserialize, Serialize};
/// assert!(route.headers.is_none());
/// ```
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Route {
/// Path prefix to match. The longest matching prefix wins.
pub path_prefix: String,
Expand Down
1 change: 1 addition & 0 deletions core/src/config/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use serde::Deserialize;
/// assert!(cfg.work_stealing);
/// ```
#[derive(Debug, Clone, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct RuntimeConfig {
/// Number of worker threads per service.
///
Expand Down
1 change: 1 addition & 0 deletions filter/src/builtins/http/observability/request_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const DEFAULT_HEADER_NAME: &str = "X-Request-ID";

/// Configuration for the request ID propagation filter.
#[derive(Debug, Default, Deserialize)]
#[serde(deny_unknown_fields)]
struct RequestIdFilterConfig {
/// Name of the header to read, generate, and forward. Defaults to `X-Request-ID`.
#[serde(default)]
Expand Down
2 changes: 2 additions & 0 deletions filter/src/builtins/http/payload_processing/compression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use crate::{

/// Per-algorithm YAML configuration.
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
struct AlgorithmConfig {
/// Whether this algorithm is enabled.
#[serde(default = "default_true")]
Expand All @@ -32,6 +33,7 @@ struct AlgorithmConfig {

/// YAML configuration for the compression filter.
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
struct CompressionFilterConfig {
/// Default compression level for all algorithms (1..=12).
#[serde(default = "default_level")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub(super) const DEFAULT_MAX_BODY_BYTES: usize = 10_485_760;

/// A single field-to-header mapping used in the `fields` list.
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub(super) struct JsonBodyFieldMapping {
/// Top-level JSON field name to extract.
pub field: String,
Expand All @@ -39,6 +40,7 @@ pub(super) struct JsonBodyFieldMapping {
///
/// [`JsonBodyFieldFilter`]: super::JsonBodyFieldFilter
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub(super) struct JsonBodyFieldConfig {
/// Single-field: top-level JSON field name to extract.
pub field: Option<String>,
Expand Down
1 change: 1 addition & 0 deletions filter/src/builtins/http/security/cors/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use serde::Deserialize;
/// Deserialized YAML config for the CORS filter.
#[allow(clippy::struct_excessive_bools, reason = "CORS spec flags")]
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub(super) struct CorsConfig {
/// Allowed origins. Use `["*"]` for any origin.
pub allow_origins: Vec<String>,
Expand Down
1 change: 1 addition & 0 deletions filter/src/builtins/http/security/forwarded_headers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use crate::{

/// Deserialized YAML config for the forwarded headers filter.
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
struct ForwardedHeadersConfig {
/// CIDR ranges of trusted proxies whose existing
/// X-Forwarded-For values are preserved (appended to).
Expand Down
2 changes: 2 additions & 0 deletions filter/src/builtins/http/security/guardrails/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ pub enum GuardrailsAction {

/// Deserialized YAML config for a single guardrail rule.
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub(super) struct RuleConfig {
/// Header name (required when `target` is `"header"`).
pub name: Option<String>,
Expand All @@ -81,6 +82,7 @@ pub(super) struct RuleConfig {

/// Deserialized YAML config for the guardrails filter.
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub(super) struct GuardrailsConfig {
/// What to do when a rule matches (default: reject).
#[serde(default)]
Expand Down
1 change: 1 addition & 0 deletions filter/src/builtins/http/security/ip_acl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use crate::{
// -----------------------------------------------------------------------------

#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
/// Deserialized YAML config for the IP ACL filter.
struct IpAclConfig {
/// IPs/CIDRs to allow. If non-empty, only these are permitted.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ pub struct LoadBalancerFilter {

/// Deserialization wrapper for the load balancer's YAML config.
#[derive(serde::Deserialize)]
#[serde(deny_unknown_fields)]
struct LoadBalancerConfig {
/// Cluster definitions.
#[serde(default)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use serde::Deserialize;

/// Deserialized YAML config for the rate limit filter.
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub(super) struct RateLimitConfig {
/// `"per_ip"` or `"global"`.
pub mode: String,
Expand Down
1 change: 1 addition & 0 deletions filter/src/builtins/http/traffic_management/redirect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const VALID_STATUSES: [u16; 4] = [301, 302, 307, 308];

/// Deserialized YAML config for the redirect filter.
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
struct RedirectConfig {
/// HTTP redirect status code (301, 302, 307, or 308).
#[serde(default = "default_status")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use serde::Deserialize;

/// Deserialization wrapper for the router's YAML config.
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
pub(super) struct RouterConfig {
/// Route table entries.
#[serde(default)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ struct StaticResponseConfig {

/// A name/value header pair in the static response config.
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
struct HeaderEntry {
/// Header field name.
name: String,
Expand Down
1 change: 1 addition & 0 deletions filter/src/builtins/http/traffic_management/timeout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use crate::{

/// Configuration for the timeout filter.
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
struct TimeoutFilterConfig {
/// Maximum allowed elapsed time from request receipt to response headers,
/// in milliseconds. Requests that exceed this limit receive a 504.
Expand Down
2 changes: 2 additions & 0 deletions filter/src/builtins/http/transformation/header/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ use crate::{

/// Configuration for the header manipulation filter.
#[derive(Debug, Default, Deserialize)]
#[serde(deny_unknown_fields)]
pub(crate) struct HeaderFilterConfig {
/// Headers to append to the upstream request.
#[serde(default)]
Expand All @@ -56,6 +57,7 @@ pub(crate) struct HeaderFilterConfig {

/// A name/value pair used in header add/set/remove config.
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub(crate) struct HeaderPair {
/// Header field name.
pub(crate) name: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use serde::Deserialize;
///
/// Exactly one operation must be specified.
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub(super) struct PathRewriteConfig {
/// Remove this prefix from the request path.
#[serde(default)]
Expand Down Expand Up @@ -41,6 +42,7 @@ pub(super) struct PathRewriteConfig {

/// Regex find/replace configuration.
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
pub(super) struct ReplaceConfig {
/// Regex pattern to match.
pub pattern: String,
Expand Down
1 change: 1 addition & 0 deletions filter/src/builtins/http/transformation/url_rewrite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ const QUERY_VALUE_ENCODE_SET: &AsciiSet = &CONTROLS.add(b' ').add(b'"').add(b'#'
/// assert_eq!(filter.name(), "url_rewrite");
/// ```
#[derive(Debug, Deserialize)]
#[serde(deny_unknown_fields)]
struct UrlRewriteConfig {
/// Ordered list of rewrite operations to apply.
#[serde(default)]
Expand Down
2 changes: 2 additions & 0 deletions filter/src/builtins/tcp/traffic_management/sni_router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ struct WildcardRoute {

/// YAML configuration for the SNI router filter.
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
struct SniRouterConfig {
/// Fallback upstream when no route matches.
#[serde(default)]
Expand All @@ -167,6 +168,7 @@ struct SniRouterConfig {

/// A single SNI route entry.
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
struct SniRouteEntry {
/// Server name patterns (exact or wildcard like `*.example.com`).
server_names: Vec<String>,
Expand Down
2 changes: 2 additions & 0 deletions tls/src/config/certs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ use crate::TlsError;
/// assert!(pair.validate().is_ok());
/// ```
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct CertKeyPair {
/// Path to the PEM certificate file.
pub cert_path: String,
Expand Down Expand Up @@ -86,6 +87,7 @@ impl CertKeyPair {
/// assert_eq!(ca.ca_path, "/etc/ssl/ca.pem");
/// ```
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct CaConfig {
/// Path to the PEM CA certificate file.
pub ca_path: String,
Expand Down
1 change: 1 addition & 0 deletions tls/src/config/cluster.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ pub struct ClusterTls {

/// Raw deserialization helper for [`ClusterTls`].
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
struct ClusterTlsRaw {
/// Custom CA.
#[serde(default)]
Expand Down
1 change: 1 addition & 0 deletions tls/src/config/listener.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ pub struct ListenerTls {

/// Raw deserialization helper for [`ListenerTls`].
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
struct ListenerTlsRaw {
/// Server certificates.
certificates: Vec<CertKeyPair>,
Expand Down
Loading