feat(aap): In App WAF support#744
Conversation
a9a47e9 to
a79197a
Compare
|
| if (!this.tracerWrapper.currentSpan) return false; | ||
| this.wrappedCurrentSpan = new SpanWrapper(this.tracerWrapper.currentSpan, {}); | ||
|
|
||
| processAppsecRequest(event, this.tracerWrapper.currentSpan); |
There was a problem hiding this comment.
Should this happen at the beginning of the invocation? I'm wondering if this should be moved to onStartInvocation.
There was a problem hiding this comment.
Good catch. processAppsecRequest ran after the handler, too late to ever support blocking. Moved it to onRequestStart, called right before the handler runs, once the span is active. Couldnt be onStartInvocation itself since the span doesnt exist yet there.
| * @param event | ||
| */ | ||
| public onRequestStart(event: any): void { | ||
| processAppsecRequest(event, this.tracerWrapper.currentSpan); |
There was a problem hiding this comment.
Is there a reason we can't just put this into onStartInvocation?
There was a problem hiding this comment.
Yes, there is. onStartInvocation runs before onWrap even creates the span (tracer.wrap() activates it later, wrapping the handler invocation itself), so currentSpan would be null there. onRequestStart is the earliest point where the span is guaranteed active, right before the handler runs.
| } | ||
|
|
||
| public async onStartInvocation(event: any, context: Context) { | ||
| initAppsec(); |
There was a problem hiding this comment.
Looks like there's a this.config object available. Makes sense to add the appsec enabled check to the config.
There was a problem hiding this comment.
Added appsecEnabled to TraceConfig, resolved from DD_APPSEC_ENABLED in getConfig() like every other flag.
a2945c1 to
fde79ca
Compare
| } | ||
| const responseStatusCode = result?.statusCode?.toString(); | ||
| const responseHeaders = result?.headers as Record<string, string> | undefined; | ||
| processAppsecResponse(this.tracerWrapper.currentSpan, responseStatusCode, responseHeaders); |
There was a problem hiding this comment.
Can we move the is appsec enabled check to wrap this new block? That way none of it will execute if appsec isn't enabled. It will also make it easier to see on a quick read that this section is skipped in most cases.
There was a problem hiding this comment.
nit. I would make the signature of this method like
processAppsecResponse(this.tracerWrapper.currentSpan, result)Do the extraction of the status code and headers inside the function, rather than before it. That keeps this already long onEndInvocation method neater and puts the extraction of the data closer to where you'll use it.
| } | ||
|
|
||
| public async onStartInvocation(event: any, context: Context) { | ||
| initAppsec(this.config.appsecEnabled); |
There was a problem hiding this comment.
This doesn't seem necessary anymore now that we've moved the bool to the config. We should just use this.config.appsecEnabled around the processAppsecRequest and processAppsecResponse methods directly.
| let enabled = false; | ||
|
|
||
| export function initAppsec(appsecEnabled: boolean): void { | ||
| enabled = appsecEnabled; | ||
| } |
There was a problem hiding this comment.
I think these lines can be removed as long as we do the appsec enabled check just before each process call.
purple4reina
left a comment
There was a problem hiding this comment.
Just a couple of small nitpicks. Otherwise, everything looks great.
|
Next steps to merge:
|
What does this PR do?
Adds AppSec support to the Lambda layer by extracting HTTP data from Lambda events and publishing it to diagnostic channels consumed by dd-trace-js's AppSec subsystem.
Changes:
move_ddtrace_dependency.jsnow reads@datadog/native-appsecfrom dd-trace'soptionalDependenciesand promotes it to a direct dependency so it survives--ignore-optional. The Dockerfile runs the script beforerm -rf node_modulesand strips unused native prebuilds (non-Linux-glibc platforms)src/appsec/event-data-extractor.ts): Parses API Gateway v1/v2, ALB, and Lambda Function URL events, extracting headers, method, path, query, body, client IP, path params, cookies, and routesrc/appsec/index.ts): ChecksDD_APPSEC_ENABLEDand publishes extracted data todatadog:lambda:start-invocation/datadog:lambda:end-invocationdiagnostic channelsinitAppsec()called inonStartInvocation,processAppSecRequestandprocessAppSecResponsecalled inonEndingInvocationMotivation
Porting the In-App WAF security product to AWS Lambda for the Node.js runtime. The Lambda layer extracts HTTP data and dispatches it to the tracer for WAF execution and reporting.
The layer is intentionally kept thin, only extracting and publishing data. All security logic (WAF, reporting, trace keeping) lives in dd-trace-js.
Testing Guidelines
Additional Notes
@datadog/native-appsecis NOT added to this repo'spackage.json. The version is read dynamically from dd-trace'soptionalDependenciesat build time, so dd-trace-js remains the single owner of the native module version.DD_APPSEC_ENABLED.Types of Changes
Check all that apply
APPSEC-60752