@@ -14,7 +14,6 @@ import (
14
14
"fmt"
15
15
"net/http"
16
16
"os"
17
- "os/exec"
18
17
"strconv"
19
18
"strings"
20
19
"time"
@@ -102,16 +101,16 @@ const (
102
101
// WrapLambdaHandlerInterface is used to instrument your lambda functions.
103
102
// It returns a modified handler that can be passed directly to the lambda.StartHandler function from aws-lambda-go.
104
103
func WrapLambdaHandlerInterface (handler lambda.Handler , cfg * Config ) lambda.Handler {
104
+ setupAppSec ()
105
105
listeners := initializeListeners (cfg )
106
- applyLambdaExecWrapperConfiguration ()
107
106
return wrapper .WrapHandlerInterfaceWithListeners (handler , listeners ... )
108
107
}
109
108
110
109
// WrapFunction is used to instrument your lambda functions.
111
110
// It returns a modified handler that can be passed directly to the lambda.Start function from aws-lambda-go.
112
111
func WrapFunction (handler interface {}, cfg * Config ) interface {} {
112
+ setupAppSec ()
113
113
listeners := initializeListeners (cfg )
114
- applyLambdaExecWrapperConfiguration ()
115
114
return wrapper .WrapHandlerWithListeners (handler , listeners ... )
116
115
}
117
116
@@ -293,63 +292,29 @@ func (cfg *Config) toMetricsConfig(isExtensionRunning bool) metrics.Config {
293
292
return mc
294
293
}
295
294
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
+ }
314
309
}
315
310
316
- script := os .Getenv (AwsLambdaExecWrapperEnvVar )
317
- if script == "" {
318
- // Nothing to do
311
+ if ! enabled {
319
312
return
320
313
}
321
314
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 )
324
316
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" )
354
319
}
355
320
}
0 commit comments