From 9d6d68f545773b8071028b54499c0e1cca33aeb1 Mon Sep 17 00:00:00 2001 From: Byron Wolfman Date: Fri, 6 Jun 2025 16:02:59 -0400 Subject: [PATCH 1/4] feat(sources) add access to URL path in custom VRL auth --- src/common/http/server_auth.rs | 49 ++++++++++++++++++++++++------ src/sinks/websocket_server/sink.rs | 2 +- src/sources/util/http/prelude.rs | 6 +++- 3 files changed, 46 insertions(+), 11 deletions(-) diff --git a/src/common/http/server_auth.rs b/src/common/http/server_auth.rs index fda8ccdbf82eb..b3155f5781206 100644 --- a/src/common/http/server_auth.rs +++ b/src/common/http/server_auth.rs @@ -198,6 +198,7 @@ impl HttpServerAuthMatcher { &self, address: Option<&SocketAddr>, headers: &HeaderMap, + path: &str, ) -> Result<(), ErrorMessage> { match self { HttpServerAuthMatcher::AuthHeader(expected, err_message) => { @@ -218,7 +219,7 @@ impl HttpServerAuthMatcher { } } HttpServerAuthMatcher::Vrl { program } => { - self.handle_vrl_auth(address, headers, program) + self.handle_vrl_auth(address, headers, path, program) } } } @@ -227,6 +228,7 @@ impl HttpServerAuthMatcher { &self, address: Option<&SocketAddr>, headers: &HeaderMap, + path: &str, program: &Program, ) -> Result<(), ErrorMessage> { let mut target = VrlTarget::new( @@ -250,6 +252,7 @@ impl HttpServerAuthMatcher { "address".into(), address.map_or(Value::Null, |a| Value::from(a.ip().to_string())), ), + ("path".into(), Value::from(path.to_owned())), ]), Default::default(), )), @@ -439,7 +442,7 @@ mod tests { let matcher = basic_auth.build(&Default::default()).unwrap(); - let result = matcher.handle_auth(Some(&next_addr()), &HeaderMap::new()); + let result = matcher.handle_auth(Some(&next_addr()), &HeaderMap::new(), "/"); assert!(result.is_err()); let error = result.unwrap_err(); @@ -458,7 +461,7 @@ mod tests { let mut headers = HeaderMap::new(); headers.insert(AUTHORIZATION, HeaderValue::from_static("Basic wrong")); - let result = matcher.handle_auth(Some(&next_addr()), &headers); + let result = matcher.handle_auth(Some(&next_addr()), &headers, "/"); assert!(result.is_err()); let error = result.unwrap_err(); @@ -482,7 +485,7 @@ mod tests { AUTHORIZATION, Authorization::basic(&username, &password).0.encode(), ); - let result = matcher.handle_auth(Some(&next_addr()), &headers); + let result = matcher.handle_auth(Some(&next_addr()), &headers, "/"); assert!(result.is_ok()); } @@ -497,7 +500,7 @@ mod tests { let mut headers = HeaderMap::new(); headers.insert(AUTHORIZATION, HeaderValue::from_static("test")); - let result = matcher.handle_auth(Some(&next_addr()), &headers); + let result = matcher.handle_auth(Some(&next_addr()), &headers, "/"); assert!(result.is_ok()); } @@ -513,7 +516,7 @@ mod tests { let matcher = custom_auth.build(&Default::default()).unwrap(); let headers = HeaderMap::new(); - let result = matcher.handle_auth(Some(&next_addr()), &headers); + let result = matcher.handle_auth(Some(&next_addr()), &headers, "/"); assert!(result.is_ok()); } @@ -529,7 +532,35 @@ mod tests { let matcher = custom_auth.build(&Default::default()).unwrap(); let headers = HeaderMap::new(); - let result = matcher.handle_auth(None, &headers); + let result = matcher.handle_auth(None, &headers, "/"); + + assert!(result.is_err()); + } + + #[test] + fn custom_auth_matcher_should_be_able_to_check_path() { + let custom_auth = HttpServerAuthConfig::Custom { + source: r#".path == "/ok""#.to_string(), + }; + + let matcher = custom_auth.build(&Default::default()).unwrap(); + + let headers = HeaderMap::new(); + let result = matcher.handle_auth(Some(&next_addr()), &headers, "/ok"); + + assert!(result.is_ok()); + } + + #[test] + fn custom_auth_matcher_should_return_401_with_wrong_path() { + let custom_auth = HttpServerAuthConfig::Custom { + source: r#".path == "/ok""#.to_string(), + }; + + let matcher = custom_auth.build(&Default::default()).unwrap(); + + let headers = HeaderMap::new(); + let result = matcher.handle_auth(Some(&next_addr()), &headers, "/bad"); assert!(result.is_err()); } @@ -544,7 +575,7 @@ mod tests { let mut headers = HeaderMap::new(); headers.insert(AUTHORIZATION, HeaderValue::from_static("wrong value")); - let result = matcher.handle_auth(Some(&next_addr()), &headers); + let result = matcher.handle_auth(Some(&next_addr()), &headers, "/"); assert!(result.is_err()); let error = result.unwrap_err(); @@ -562,7 +593,7 @@ mod tests { let mut headers = HeaderMap::new(); headers.insert(AUTHORIZATION, HeaderValue::from_static("test")); - let result = matcher.handle_auth(Some(&next_addr()), &headers); + let result = matcher.handle_auth(Some(&next_addr()), &headers, "/"); assert!(result.is_err()); let error = result.unwrap_err(); diff --git a/src/sinks/websocket_server/sink.rs b/src/sinks/websocket_server/sink.rs index 62da60bd1740a..f8ab7ebab45b9 100644 --- a/src/sinks/websocket_server/sink.rs +++ b/src/sinks/websocket_server/sink.rs @@ -214,7 +214,7 @@ impl WebSocketListenerSink { )); return Ok(response); }; - match auth.handle_auth(Some(&addr), req.headers()) { + match auth.handle_auth(Some(&addr), req.headers(), req.uri().path()) { Ok(_) => { extra_tags.append(&mut Self::extract_extra_tags( &extra_tags_config, diff --git a/src/sources/util/http/prelude.rs b/src/sources/util/http/prelude.rs index 15f7a23b1c0f5..b6310ec2c2c75 100644 --- a/src/sources/util/http/prelude.rs +++ b/src/sources/util/http/prelude.rs @@ -133,7 +133,11 @@ pub trait HttpSource: Clone + Send + Sync + 'static { let events = auth_matcher .as_ref() .map_or(Ok(()), |a| { - a.handle_auth(addr.as_ref().map(|a| a.0).as_ref(), &headers) + a.handle_auth( + addr.as_ref().map(|a| a.0).as_ref(), + &headers, + path.as_str(), + ) }) .and_then(|()| self.decode(encoding_header.as_deref(), body)) .and_then(|body| { From a4a44a30d5f0e0596afa42722e364f0e7f27e08b Mon Sep 17 00:00:00 2001 From: Byron Wolfman Date: Fri, 6 Jun 2025 16:04:53 -0400 Subject: [PATCH 2/4] update website docs for VRL custom auth --- website/cue/reference/components.cue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/cue/reference/components.cue b/website/cue/reference/components.cue index 11fbc0a3f34f9..1a04b3c06ffc9 100644 --- a/website/cue/reference/components.cue +++ b/website/cue/reference/components.cue @@ -1289,8 +1289,8 @@ components: { authorization code using VRL. Here is an example that looks up the token in an enrichment table backed by a CSV file. - Currently custom VRL auth has access to `headers` and `address` (IP address of the - client). + Currently custom VRL auth has access to `headers`, `path`, and `address` (IP + address of the client). ```yaml \(kind)s: From cd2d4ccaf12b8f301f1f426075b38d292ec92993 Mon Sep 17 00:00:00 2001 From: Byron Wolfman Date: Fri, 6 Jun 2025 16:22:06 -0400 Subject: [PATCH 3/4] format components.cue (tabs vs spaces) --- website/cue/reference/components.cue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/cue/reference/components.cue b/website/cue/reference/components.cue index 1a04b3c06ffc9..46ac8ddc97bf9 100644 --- a/website/cue/reference/components.cue +++ b/website/cue/reference/components.cue @@ -1290,7 +1290,7 @@ components: { enrichment table backed by a CSV file. Currently custom VRL auth has access to `headers`, `path`, and `address` (IP - address of the client). + address of the client). ```yaml \(kind)s: From 8d0af47dbbf2d78876dd80b66202f2df8937517b Mon Sep 17 00:00:00 2001 From: Byron Wolfman Date: Fri, 6 Jun 2025 16:23:20 -0400 Subject: [PATCH 4/4] Add changelog entry --- changelog.d/23165_custom_auth_path_access.feature.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/23165_custom_auth_path_access.feature.md diff --git a/changelog.d/23165_custom_auth_path_access.feature.md b/changelog.d/23165_custom_auth_path_access.feature.md new file mode 100644 index 0000000000000..91cbd40e07779 --- /dev/null +++ b/changelog.d/23165_custom_auth_path_access.feature.md @@ -0,0 +1 @@ +Enabled URL path access in VRL scripts of custom auth strategy for server components.