@@ -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_APPSEC_ENABLED is set (to true) and when that is the case,
296+ // redirects `AWS_LAMBDA_RUNTIME_API` to the agent extension, and turns on universal
297+ // instrumentation unless it was already configured by the customer, so that the HTTP
298+ // constext (invocation details span tags) is avaialble on AppSec traces.
299+ func setupAppSec () {
300+ const DDAppSecEnabledEnvVar = "DD_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 (DDAppSecEnabledEnvVar ); 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