Skip to content

Commit 7fb22d0

Browse files
committed
protect reserved fields
1 parent f1b829b commit 7fb22d0

1 file changed

Lines changed: 92 additions & 12 deletions

File tree

src/sources/http_server.rs

Lines changed: 92 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,13 @@ use vector_lib::{
1313
},
1414
config::{DataType, LegacyKey, LogNamespace},
1515
configurable::configurable_component,
16-
lookup::{lookup_v2::OptionalValuePath, owned_value_path, path},
16+
lookup::{PathPrefix, lookup_v2::OptionalValuePath, owned_value_path, path},
1717
schema::Definition,
1818
};
19-
use vrl::value::{Kind, ObjectMap, kind::Collection};
19+
use vrl::{
20+
path::ValuePath as _,
21+
value::{Kind, ObjectMap, kind::Collection},
22+
};
2023
use warp::http::HeaderMap;
2124

2225
use crate::{
@@ -523,19 +526,29 @@ impl HttpSource for SimpleHttpSource {
523526
}
524527

525528
/// Injects `%field` enrichment from a `custom` auth VRL program into events.
526-
/// Legacy namespace: inserted into the event body (no-op if key already exists).
529+
/// Both namespaces use insert-if-empty semantics so auth enrichment never
530+
/// overwrites built-in source metadata (`path`, `host`, `headers`, …) that
531+
/// `enrich_events` already populated.
532+
/// Legacy namespace: inserted into the event body.
527533
/// Vector namespace: inserted into event metadata under `http_server.<field>`.
528534
fn inject_auth_enrichment(&self, events: &mut [Event], enrichment: ObjectMap) {
529535
for event in events.iter_mut() {
530536
if let Event::Log(log) = event {
531537
for (key, value) in &enrichment {
532-
self.log_namespace.insert_source_metadata(
533-
SimpleHttpConfig::NAME,
534-
log,
535-
Some(LegacyKey::InsertIfEmpty(path!(key.as_str()))),
536-
path!(key.as_str()),
537-
value.clone(),
538-
);
538+
match self.log_namespace {
539+
LogNamespace::Vector => {
540+
log.try_insert(
541+
(
542+
PathPrefix::Metadata,
543+
path!(SimpleHttpConfig::NAME).concat(path!(key.as_str())),
544+
),
545+
value.clone(),
546+
);
547+
}
548+
LogNamespace::Legacy => {
549+
log.try_insert((PathPrefix::Event, path!(key.as_str())), value.clone());
550+
}
551+
}
539552
}
540553
}
541554
}
@@ -562,11 +575,15 @@ mod tests {
562575
config::LogNamespace,
563576
event::LogEvent,
564577
lookup::{
565-
OwnedTargetPath, PathPrefix, event_path, lookup_v2::OptionalValuePath, owned_value_path,
578+
OwnedTargetPath, PathPrefix, event_path, lookup_v2::OptionalValuePath,
579+
owned_value_path, path,
566580
},
567581
schema::Definition,
568582
};
569-
use vrl::value::{Kind, ObjectMap, kind::Collection};
583+
use vrl::{
584+
path::ValuePath as _,
585+
value::{Kind, ObjectMap, kind::Collection},
586+
};
570587

571588
use super::{SimpleHttpConfig, remove_duplicates};
572589
use crate::{
@@ -1744,6 +1761,69 @@ mod tests {
17441761
}
17451762
}
17461763

1764+
#[test]
1765+
fn inject_auth_enrichment_does_not_clobber_vector_namespace_builtin_fields() {
1766+
use crate::{codecs::DecodingConfig, sources::util::HttpSource as _};
1767+
use vector_lib::codecs::BytesDeserializerConfig;
1768+
use vrl::value::KeyString;
1769+
1770+
let decoder = DecodingConfig::new(
1771+
BytesDecoderConfig::new().into(),
1772+
BytesDeserializerConfig::new().into(),
1773+
LogNamespace::Vector,
1774+
)
1775+
.build()
1776+
.unwrap()
1777+
.with_log_namespace(LogNamespace::Vector);
1778+
1779+
let source = super::SimpleHttpSource {
1780+
headers: vec![],
1781+
query_parameters: vec![],
1782+
path_key: OptionalValuePath::none(),
1783+
host_key: OptionalValuePath::none(),
1784+
decoder,
1785+
log_namespace: LogNamespace::Vector,
1786+
};
1787+
1788+
let mut log = LogEvent::default();
1789+
// Pre-populate %http_server.path as enrich_events would.
1790+
log.insert(
1791+
(
1792+
PathPrefix::Metadata,
1793+
path!(SimpleHttpConfig::NAME).concat(path!("path")),
1794+
),
1795+
"/real/path",
1796+
);
1797+
1798+
let mut events = vec![Event::Log(log)];
1799+
let mut enrichment = ObjectMap::new();
1800+
// Attempt to clobber the built-in `path` field and inject a new field.
1801+
enrichment.insert(KeyString::from("path"), Value::from("/clobbered"));
1802+
enrichment.insert(KeyString::from("tenant_id"), Value::from("t-123"));
1803+
1804+
source.inject_auth_enrichment(&mut events, enrichment);
1805+
1806+
let Event::Log(log) = &events[0] else {
1807+
panic!("expected log event");
1808+
};
1809+
assert_eq!(
1810+
log.get((
1811+
PathPrefix::Metadata,
1812+
path!(SimpleHttpConfig::NAME).concat(path!("path")),
1813+
)),
1814+
Some(&Value::from("/real/path")),
1815+
"auth enrichment must not overwrite built-in source metadata"
1816+
);
1817+
assert_eq!(
1818+
log.get((
1819+
PathPrefix::Metadata,
1820+
path!(SimpleHttpConfig::NAME).concat(path!("tenant_id")),
1821+
)),
1822+
Some(&Value::from("t-123")),
1823+
"new auth enrichment field must be injected"
1824+
);
1825+
}
1826+
17471827
impl ValidatableComponent for SimpleHttpConfig {
17481828
fn validation_configuration() -> ValidationConfiguration {
17491829
let config = Self {

0 commit comments

Comments
 (0)