@@ -14,7 +14,6 @@ import (
1414	"fmt" 
1515	"net/http" 
1616	"os" 
17- 	"os/exec" 
1817	"strconv" 
1918	"strings" 
2019	"time" 
@@ -102,16 +101,16 @@ const (
102101// WrapLambdaHandlerInterface is used to instrument your lambda functions. 
103102// It returns a modified handler that can be passed directly to the lambda.StartHandler function from aws-lambda-go. 
104103func  WrapLambdaHandlerInterface (handler  lambda.Handler , cfg  * Config ) lambda.Handler  {
104+ 	setupAppSec ()
105105	listeners  :=  initializeListeners (cfg )
106- 	applyLambdaExecWrapperConfiguration ()
107106	return  wrapper .WrapHandlerInterfaceWithListeners (handler , listeners ... )
108107}
109108
110109// WrapFunction is used to instrument your lambda functions. 
111110// It returns a modified handler that can be passed directly to the lambda.Start function from aws-lambda-go. 
112111func  WrapFunction (handler  interface {}, cfg  * Config ) interface {} {
112+ 	setupAppSec ()
113113	listeners  :=  initializeListeners (cfg )
114- 	applyLambdaExecWrapperConfiguration ()
115114	return  wrapper .WrapHandlerWithListeners (handler , listeners ... )
116115}
117116
@@ -293,63 +292,29 @@ func (cfg *Config) toMetricsConfig(isExtensionRunning bool) metrics.Config {
293292	return  mc 
294293}
295294
296- // applyLambdaExecWrapperConfiguration applies environment variables set by the wrapper configured in the 
297- // `AWS_LAMBDA_EXEC_WRAPPER` environment variable if present. This is done here because the AWS Lambda runtimes used by 
298- // go applications (`go1.x` and `provided.al2`) do not honor this setting, while other runtimes do. This assumes the 
299- // wrapper script does nothing other than setting environment variables, and will only honor environment variables with 
300- // names starting with `DD_` or `AWS_LAMBDA_`. In particular, `AWS_LAMBDA_RUNTIME_API` is used to re-route the Lambda 
301- // control flow API through a proxy, which is used by ASM. 
302- // 
303- // See: https://docs.aws.amazon.com/lambda/latest/dg/runtimes-modify.html#runtime-wrapper. 
304- // See: https://github.com/DataDog/datadog-lambda-extension/blob/main/scripts/datadog_wrapper. 
305- func  applyLambdaExecWrapperConfiguration () {
306- 	const  AwsExecutionEnvEnvVar  =  "AWS_EXECUTION_ENV" 
307- 	const  AwsLambdaExecWrapperEnvVar  =  "AWS_LAMBDA_EXEC_WRAPPER" 
308- 
309- 	// Only perform this operation if the Lambda runtime doesn't do it by itself, meaning we only do something for 
310- 	// provided runtimes (in which `AWS_EXECUTION_ENV` is not set) and `go1.x`. 
311- 	if  env  :=  os .Getenv (AwsExecutionEnvEnvVar ); env  !=  ""  &&  env  !=  "AWS_Lambda_go1.x"  {
312- 		logger .Debug (fmt .Sprintf ("Skipping applyLambdaExecWrapperConfiguration, runtime is %s" , env ))
313- 		return 
295+ // setupAppSec checks if DD_SERVERLESS_APPSEC_ENABLED is set (to true) and when that 
296+ // is the case, redirects `AWS_LAMBDA_RUNTIME_API` to the agent extension, and turns 
297+ // on universal instrumentation unless it was already configured by the customer, so 
298+ // that the HTTP constext (invocation details span tags) is avaialble on AppSec traces. 
299+ func  setupAppSec () {
300+ 	const  ServerlessAppSSecEnabledEnvVar  =  "DD_SERVERLESS_APPSEC_ENABLED" 
301+ 	const  AwsLambdaRuntimeApiEnvVar  =  "AWS_LAMBDA_RUNTIME_API" 
302+ 	const  DatadogAgentUrl  =  "127.0.0.1:9000" 
303+ 
304+ 	enabled  :=  false 
305+ 	if  env  :=  os .Getenv (ServerlessAppSSecEnabledEnvVar ); env  !=  ""  {
306+ 		if  on , err  :=  strconv .ParseBool (env ); err  ==  nil  {
307+ 			enabled  =  on 
308+ 		}
314309	}
315310
316- 	script  :=  os .Getenv (AwsLambdaExecWrapperEnvVar )
317- 	if  script  ==  ""  {
318- 		// Nothing to do 
311+ 	if  ! enabled  {
319312		return 
320313	}
321314
322- 	cmd  :=  exec .Command ("env" , "-u" , AwsLambdaExecWrapperEnvVar , script , "sh" , "-c" , "env" )
323- 	logger .Debug (fmt .Sprintf ("[%s] Command: %s" , AwsLambdaExecWrapperEnvVar , cmd .String ()))
315+ 	_  =  os .Setenv (AwsLambdaRuntimeApiEnvVar , DatadogAgentUrl )
324316
325- 	if  stdout , err  :=  cmd .Output (); err  !=  nil  {
326- 		logger .Debug (fmt .Sprintf ("[%s] Failed to run: %s" , AwsLambdaExecWrapperEnvVar , err ))
327- 	} else  {
328- 		for  _ , line  :=  range  strings .Split (string (stdout ), "\n " ) {
329- 			parts  :=  strings .SplitN (line , "=" , 2 )
330- 			if  len (parts ) !=  2  {
331- 				// Forward what the wrapper script prints to the standard output... 
332- 				fmt .Println (line )
333- 				continue 
334- 			}
335- 			name  :=  parts [0 ]
336- 			val  :=  parts [1 ]
337- 
338- 			if  os .Getenv (name ) ==  val  {
339- 				// Not changed, nothing to do. 
340- 				continue 
341- 			}
342- 
343- 			if  ! strings .HasPrefix (name , "DD_" ) &&  ! strings .HasPrefix (name , "AWS_LAMBDA_" ) {
344- 				logger .Debug (fmt .Sprintf ("[%s] Skip %s=<redacted>" , AwsLambdaExecWrapperEnvVar , name ))
345- 				continue 
346- 			}
347- 
348- 			if  err  :=  os .Setenv (name , val ); err  !=  nil  {
349- 				logger .Debug (fmt .Sprintf ("[%s] Failed %s=%s: %s" , AwsLambdaExecWrapperEnvVar , name , val , err ))
350- 			} else  {
351- 				logger .Debug (fmt .Sprintf ("[%s] Set %s=%s" , AwsLambdaExecWrapperEnvVar , name , val ))
352- 			}
353- 		}
317+ 	if  val  :=  os .Getenv (UniversalInstrumentation ); val  ==  ""  {
318+ 		_  =  os .Setenv (UniversalInstrumentation , "1" )
354319	}
355320}
0 commit comments