From 9906db9039865b72a68a0a1ac20118e6f53a63b0 Mon Sep 17 00:00:00 2001 From: pedramsafaei <34566793+pedramsafaei@users.noreply.github.com> Date: Mon, 19 Oct 2026 08:08:28 +0000 Subject: [PATCH 1/2] fix(triggers): use region-derived partition in Lambda Function URL ARN The inferred span ARN for Lambda Function URL events hardcoded the "aws" partition. In GovCloud (us-gov-*) and China (cn-*) regions this produced an incorrect ARN, since those regions use the aws-us-gov and aws-cn partitions respectively. Derive the partition from the region with get_aws_partition_by_region, matching the existing API Gateway and SQS trigger implementations. Adds a regression test covering the aws-us-gov and aws-cn partitions, and marks the two get_arn tests #[serial] since they mutate the shared AWS_LAMBDA_FUNCTION_NAME environment variable. --- .../triggers/lambda_function_url_event.rs | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/bottlecap/src/lifecycle/invocation/triggers/lambda_function_url_event.rs b/bottlecap/src/lifecycle/invocation/triggers/lambda_function_url_event.rs index bec439eae..96d953bbc 100644 --- a/bottlecap/src/lifecycle/invocation/triggers/lambda_function_url_event.rs +++ b/bottlecap/src/lifecycle/invocation/triggers/lambda_function_url_event.rs @@ -4,6 +4,7 @@ use libdd_trace_protobuf::pb::Span; use serde::{Deserialize, Serialize}; use serde_json::Value; +use crate::config::aws::get_aws_partition_by_region; use crate::lifecycle::invocation::{ processor::MS_TO_NS, triggers::{ @@ -164,11 +165,10 @@ impl Trigger for LambdaFunctionUrlEvent { } fn get_arn(&self, region: &str) -> String { + let partition = get_aws_partition_by_region(region); let function_name = env::var("AWS_LAMBDA_FUNCTION_NAME").unwrap_or_default(); - format!( - "arn:aws:lambda:{region}:{}:url:{}", - self.request_context.account_id, function_name - ) + let account_id = &self.request_context.account_id; + format!("arn:{partition}:lambda:{region}:{account_id}:url:{function_name}") } fn get_carrier(&self) -> HashMap { @@ -196,6 +196,7 @@ impl ServiceNameResolver for LambdaFunctionUrlEvent { mod tests { use super::*; use crate::lifecycle::invocation::triggers::test_utils::read_json_file; + use serial_test::serial; #[test] fn test_new() { @@ -326,6 +327,7 @@ mod tests { } #[test] + #[serial] // mutates the shared AWS_LAMBDA_FUNCTION_NAME env var fn test_get_arn() { unsafe { env::set_var("AWS_LAMBDA_FUNCTION_NAME", "mock-lambda") }; let json = read_json_file("lambda_function_url_event.json"); @@ -339,6 +341,30 @@ mod tests { unsafe { env::remove_var("AWS_LAMBDA_FUNCTION_NAME") }; } + #[test] + #[serial] // mutates the shared AWS_LAMBDA_FUNCTION_NAME env var + fn test_get_arn_non_default_partitions() { + unsafe { env::set_var("AWS_LAMBDA_FUNCTION_NAME", "mock-lambda") }; + let json = read_json_file("lambda_function_url_event.json"); + let payload = serde_json::from_str(&json).expect("Failed to deserialize into Value"); + let event = LambdaFunctionUrlEvent::new(payload) + .expect("Failed to deserialize LambdaFunctionUrlEvent"); + + // GovCloud regions use the aws-us-gov partition. + assert_eq!( + event.get_arn("us-gov-west-1"), + "arn:aws-us-gov:lambda:us-gov-west-1:601427279990:url:mock-lambda" + ); + + // China regions use the aws-cn partition. + assert_eq!( + event.get_arn("cn-north-1"), + "arn:aws-cn:lambda:cn-north-1:601427279990:url:mock-lambda" + ); + + unsafe { env::remove_var("AWS_LAMBDA_FUNCTION_NAME") }; + } + #[test] fn test_resolve_service_name_with_representation_enabled() { let json = read_json_file("lambda_function_url_event.json"); From e8a3a3d5cd7f12855ac69587f61de2135a2372ab Mon Sep 17 00:00:00 2001 From: pedramsafaei <34566793+pedramsafaei@users.noreply.github.com> Date: Tue, 20 Oct 2026 19:04:16 +0000 Subject: [PATCH 2/2] test(triggers): avoid env mutation in Lambda URL partition test Derive the expected ARN function name from the current AWS_LAMBDA_FUNCTION_NAME value instead of calling set_var/remove_var, removing the unsafe environment mutation whose safety requirement could not be guaranteed against unsynchronized concurrent env readers. The serial attribute is retained so this test still coordinates with test_get_arn, which mutates the shared variable. --- .../triggers/lambda_function_url_event.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/bottlecap/src/lifecycle/invocation/triggers/lambda_function_url_event.rs b/bottlecap/src/lifecycle/invocation/triggers/lambda_function_url_event.rs index 96d953bbc..a7660c46b 100644 --- a/bottlecap/src/lifecycle/invocation/triggers/lambda_function_url_event.rs +++ b/bottlecap/src/lifecycle/invocation/triggers/lambda_function_url_event.rs @@ -342,27 +342,29 @@ mod tests { } #[test] - #[serial] // mutates the shared AWS_LAMBDA_FUNCTION_NAME env var + #[serial] // coordinates with test_get_arn, which mutates AWS_LAMBDA_FUNCTION_NAME fn test_get_arn_non_default_partitions() { - unsafe { env::set_var("AWS_LAMBDA_FUNCTION_NAME", "mock-lambda") }; let json = read_json_file("lambda_function_url_event.json"); let payload = serde_json::from_str(&json).expect("Failed to deserialize into Value"); let event = LambdaFunctionUrlEvent::new(payload) .expect("Failed to deserialize LambdaFunctionUrlEvent"); + // This test only exercises the partition portion of the ARN, so derive the + // expected value from whatever AWS_LAMBDA_FUNCTION_NAME is currently set to + // rather than mutating the shared process environment. + let function_name = env::var("AWS_LAMBDA_FUNCTION_NAME").unwrap_or_default(); + // GovCloud regions use the aws-us-gov partition. assert_eq!( event.get_arn("us-gov-west-1"), - "arn:aws-us-gov:lambda:us-gov-west-1:601427279990:url:mock-lambda" + format!("arn:aws-us-gov:lambda:us-gov-west-1:601427279990:url:{function_name}") ); // China regions use the aws-cn partition. assert_eq!( event.get_arn("cn-north-1"), - "arn:aws-cn:lambda:cn-north-1:601427279990:url:mock-lambda" + format!("arn:aws-cn:lambda:cn-north-1:601427279990:url:{function_name}") ); - - unsafe { env::remove_var("AWS_LAMBDA_FUNCTION_NAME") }; } #[test]