@@ -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+ } ;
2023use warp:: http:: HeaderMap ;
2124
2225use 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