Skip to content

[ASM] Blocking a request on .NET Core#3066

Merged
anna-git merged 25 commits into
masterfrom
anna/asm/blocking-request
Aug 31, 2022
Merged

[ASM] Blocking a request on .NET Core#3066
anna-git merged 25 commits into
masterfrom
anna/asm/blocking-request

Conversation

@anna-git

@anna-git anna-git commented Aug 9, 2022

Copy link
Copy Markdown
Contributor

Summary of changes

This PR is part of a set of ASM PRs to implement blocking in conjunction with remote config to activate ASM and configure security rules remotely.

It only implements the blocking mechanism that will be used in NET Core subsequently. For now, it's testable on a dummy rule which will be replaced with the waf update and remote config available

Reason for change

Implementing actual blocking

Implementation details

We report everything before blocking and finally throw an exception to stop the request thread from continuing.
Waf is ran multiple times during the request, as data becomes more and more available (request headers and url, path paramters, body..)
Blocking templates are configurable for json and html for now.
Adding address to the waf http.client_ip for later when waf is updated in subsequent PR

Test coverage

Tests will be implemented in conjunction with the new waf's version.

Other details

@andrewlock

This comment has been minimized.

@andrewlock

This comment has been minimized.

@anna-git
anna-git force-pushed the anna/asm/blocking-request branch 2 times, most recently from be51f16 to 5cffe62 Compare August 12, 2022 09:55
@andrewlock

This comment has been minimized.

@anna-git
anna-git force-pushed the anna/asm/blocking-request branch from 5cffe62 to 4352d8d Compare August 22, 2022 09:18
@andrewlock

This comment has been minimized.

@anna-git
anna-git force-pushed the anna/asm/blocking-request branch from 4352d8d to c35bd44 Compare August 22, 2022 14:49
@andrewlock

This comment has been minimized.

@andrewlock

This comment has been minimized.

@anna-git
anna-git force-pushed the anna/asm/blocking-request branch from 6afb73c to 1cd9af9 Compare August 23, 2022 13:29
@andrewlock

This comment has been minimized.

@anna-git
anna-git force-pushed the anna/asm/blocking-request branch from 1cd9af9 to aec6ec6 Compare August 23, 2022 14:53
@andrewlock

This comment has been minimized.

@andrewlock

This comment has been minimized.

@andrewlock

This comment has been minimized.

@andrewlock

This comment has been minimized.

@anna-git
anna-git force-pushed the anna/asm/blocking-request branch from 2d57db2 to eba9d56 Compare August 24, 2022 14:58
@anna-git anna-git changed the title [ASM] Anna/asm/blocking request [ASM] Blocking a request on .NET Core Aug 24, 2022
@andrewlock

This comment has been minimized.

@andrewlock

This comment has been minimized.

@anna-git
anna-git force-pushed the anna/asm/blocking-request branch from b637e1b to f24f19b Compare August 25, 2022 13:10
@andrewlock

This comment has been minimized.

@anna-git
anna-git force-pushed the anna/asm/blocking-request branch from fa2b1d0 to 9da4752 Compare August 25, 2022 14:49
@andrewlock

This comment has been minimized.

@andrewlock

This comment has been minimized.

@anna-git
anna-git force-pushed the anna/asm/blocking-request branch from e48152f to b4a80ef Compare August 26, 2022 08:49
@anna-git
anna-git marked this pull request as ready for review August 26, 2022 08:50
@anna-git
anna-git requested a review from a team as a code owner August 26, 2022 08:50
@anna-git
anna-git force-pushed the anna/asm/blocking-request branch from af3f957 to f437137 Compare August 31, 2022 08:48
@andrewlock

Copy link
Copy Markdown
Member

Benchmarks Report 🐌

Benchmarks for #3066 compared to master:

  • All benchmarks have the same speed
  • All benchmarks have the same allocations

The following thresholds were used for comparing the benchmark speeds:

  • Mann–Whitney U test with statistical test for significance of 5%
  • Only results indicating a difference greater than 10% and 0.3 ns are considered.

Allocation changes below 0.5% are ignored.

Benchmark details

Benchmarks.Trace.AgentWriterBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master WriteAndFlushEnrichedTraces net472 712μs 241ns 932ns 0.374 0 0 3.18 KB
master WriteAndFlushEnrichedTraces netcoreapp3.1 451μs 177ns 662ns 0 0 0 2.58 KB
#3066 WriteAndFlushEnrichedTraces net472 716μs 447ns 1.73μs 0.353 0 0 3.18 KB
#3066 WriteAndFlushEnrichedTraces netcoreapp3.1 468μs 198ns 741ns 0 0 0 2.58 KB
Benchmarks.Trace.AppSecBodyBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master AllCycleSimpleBody net472 198ns 0.881ns 3.41ns 0.0675 0 0 425 B
master AllCycleSimpleBody netcoreapp3.1 248ns 0.762ns 2.95ns 0.0058 0 0 424 B
master AllCycleMoreComplexBody net472 193ns 0.788ns 3.05ns 0.0637 0 0 401 B
master AllCycleMoreComplexBody netcoreapp3.1 241ns 0.848ns 3.29ns 0.00539 0 0 400 B
master BodyExtractorSimpleBody net472 274ns 1.26ns 4.89ns 0.0574 0 0 361 B
master BodyExtractorSimpleBody netcoreapp3.1 242ns 0.776ns 3.01ns 0.00366 0 0 272 B
master BodyExtractorMoreComplexBody net472 14.7μs 53.5ns 207ns 1.2 0.0219 0 7.62 KB
master BodyExtractorMoreComplexBody netcoreapp3.1 12.6μs 55.6ns 215ns 0.0923 0 0 6.75 KB
#3066 AllCycleSimpleBody net472 191ns 0.645ns 2.5ns 0.0675 0 0 425 B
#3066 AllCycleSimpleBody netcoreapp3.1 246ns 0.849ns 3.29ns 0.00573 0 0 424 B
#3066 AllCycleMoreComplexBody net472 194ns 0.857ns 3.32ns 0.0637 0 0 401 B
#3066 AllCycleMoreComplexBody netcoreapp3.1 239ns 0.807ns 3.12ns 0.00541 0 0 400 B
#3066 BodyExtractorSimpleBody net472 265ns 1.07ns 4.13ns 0.0573 0 0 361 B
#3066 BodyExtractorSimpleBody netcoreapp3.1 225ns 0.645ns 2.5ns 0.00366 0 0 272 B
#3066 BodyExtractorMoreComplexBody net472 15μs 54.7ns 212ns 1.21 0.0149 0 7.62 KB
#3066 BodyExtractorMoreComplexBody netcoreapp3.1 12.8μs 46.6ns 180ns 0.0941 0 0 6.75 KB
Benchmarks.Trace.AspNetCoreBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master SendRequest net472 0ns 0ns 0ns 0 0 0 0 b
master SendRequest netcoreapp3.1 181μs 182ns 705ns 0.271 0 0 20.57 KB
#3066 SendRequest net472 0ns 0ns 0ns 0 0 0 0 b
#3066 SendRequest netcoreapp3.1 180μs 115ns 447ns 0.181 0 0 20.57 KB
Benchmarks.Trace.DbCommandBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master ExecuteNonQuery net472 1.83μs 0.401ns 1.5ns 0.15 0.000916 0 947 B
master ExecuteNonQuery netcoreapp3.1 1.45μs 0.768ns 2.98ns 0.0123 0 0 936 B
#3066 ExecuteNonQuery net472 1.86μs 0.812ns 3.04ns 0.15 0.00093 0 947 B
#3066 ExecuteNonQuery netcoreapp3.1 1.5μs 11.4ns 107ns 0.0127 0 0 936 B
Benchmarks.Trace.ElasticsearchBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master CallElasticsearch net472 2.49μs 1.05ns 3.94ns 0.184 0 0 1.16 KB
master CallElasticsearch netcoreapp3.1 1.49μs 0.428ns 1.6ns 0.0149 0 0 1.1 KB
master CallElasticsearchAsync net472 2.67μs 0.832ns 3.22ns 0.205 0 0 1.29 KB
master CallElasticsearchAsync netcoreapp3.1 1.62μs 0.442ns 1.65ns 0.0162 0 0 1.22 KB
#3066 CallElasticsearch net472 2.59μs 0.846ns 3.28ns 0.183 0 0 1.16 KB
#3066 CallElasticsearch netcoreapp3.1 1.57μs 0.55ns 2.13ns 0.0148 0 0 1.1 KB
#3066 CallElasticsearchAsync net472 2.61μs 0.636ns 2.46ns 0.205 0 0 1.29 KB
#3066 CallElasticsearchAsync netcoreapp3.1 1.64μs 2.09ns 8.09ns 0.016 0 0 1.22 KB
Benchmarks.Trace.GraphQLBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master ExecuteAsync net472 2.65μs 4.98ns 19.3ns 0.224 0 0 1.41 KB
master ExecuteAsync netcoreapp3.1 1.62μs 2.5ns 9.67ns 0.0181 0 0 1.34 KB
#3066 ExecuteAsync net472 2.63μs 6.24ns 24.2ns 0.224 0 0 1.41 KB
#3066 ExecuteAsync netcoreapp3.1 1.68μs 2.52ns 9.78ns 0.0187 0 0 1.34 KB
Benchmarks.Trace.HttpClientBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master SendAsync net472 5.66μs 8.67ns 32.4ns 0.439 0 0 2.77 KB
master SendAsync netcoreapp3.1 3.57μs 7.69ns 29.8ns 0.0348 0 0 2.6 KB
#3066 SendAsync net472 5.67μs 17.3ns 67.1ns 0.438 0 0 2.77 KB
#3066 SendAsync netcoreapp3.1 3.63μs 8.65ns 33.5ns 0.0342 0 0 2.6 KB
Benchmarks.Trace.ILoggerBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EnrichedLog net472 3.21μs 2.06ns 7.72ns 0.287 0 0 1.81 KB
master EnrichedLog netcoreapp3.1 2.46μs 1.34ns 4.83ns 0.0245 0 0 1.85 KB
#3066 EnrichedLog net472 3.05μs 3.12ns 11.7ns 0.287 0 0 1.81 KB
#3066 EnrichedLog netcoreapp3.1 2.65μs 0.817ns 3.06ns 0.0253 0 0 1.85 KB
Benchmarks.Trace.Log4netBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EnrichedLog net472 149μs 91.4ns 354ns 0.671 0.224 0 4.65 KB
master EnrichedLog netcoreapp3.1 115μs 124ns 481ns 0 0 0 4.49 KB
#3066 EnrichedLog net472 151μs 110ns 427ns 0.683 0.228 0 4.65 KB
#3066 EnrichedLog netcoreapp3.1 116μs 209ns 808ns 0.0579 0 0 4.49 KB
Benchmarks.Trace.NLogBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EnrichedLog net472 5.6μs 12.4ns 47.9ns 0.569 0.00279 0 3.59 KB
master EnrichedLog netcoreapp3.1 4.37μs 12.8ns 49.6ns 0.0541 0 0 3.91 KB
#3066 EnrichedLog net472 5.49μs 8.94ns 32.2ns 0.568 0.00278 0 3.59 KB
#3066 EnrichedLog netcoreapp3.1 4.37μs 11.2ns 43.5ns 0.052 0 0 3.91 KB
Benchmarks.Trace.RedisBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master SendReceive net472 2.31μs 1.13ns 4.21ns 0.218 0 0 1.37 KB
master SendReceive netcoreapp3.1 1.82μs 0.519ns 1.94ns 0.0182 0 0 1.32 KB
#3066 SendReceive net472 2.22μs 1.05ns 3.64ns 0.218 0 0 1.37 KB
#3066 SendReceive netcoreapp3.1 1.85μs 0.687ns 2.48ns 0.0177 0 0 1.32 KB
Benchmarks.Trace.SerilogBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master EnrichedLog net472 5.04μs 1.76ns 6.83ns 0.353 0 0 2.23 KB
master EnrichedLog netcoreapp3.1 4.28μs 1.83ns 6.83ns 0.0234 0 0 1.8 KB
#3066 EnrichedLog net472 5.03μs 1.57ns 5.87ns 0.352 0 0 2.23 KB
#3066 EnrichedLog netcoreapp3.1 4.38μs 1.01ns 3.9ns 0.0241 0 0 1.8 KB
Benchmarks.Trace.SpanBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master StartFinishSpan net472 1.11μs 0.332ns 1.28ns 0.128 0 0 810 B
master StartFinishSpan netcoreapp3.1 893ns 0.371ns 1.39ns 0.0103 0 0 760 B
master StartFinishScope net472 1.35μs 0.91ns 3.4ns 0.141 0 0 891 B
master StartFinishScope netcoreapp3.1 1.06μs 1.13ns 4.39ns 0.0121 0 0 880 B
#3066 StartFinishSpan net472 1.2μs 0.445ns 1.72ns 0.129 0 0 810 B
#3066 StartFinishSpan netcoreapp3.1 957ns 0.46ns 1.72ns 0.01 0 0 760 B
#3066 StartFinishScope net472 1.37μs 0.965ns 3.61ns 0.141 0 0 891 B
#3066 StartFinishScope netcoreapp3.1 1.13μs 0.499ns 1.93ns 0.0119 0 0 880 B
Benchmarks.Trace.TraceAnnotationsBenchmark - Same speed ✔️ Same allocations ✔️

Raw results

Branch Method Toolchain Mean StdError StdDev Gen 0 Gen 1 Gen 2 Allocated
master RunOnMethodBegin net472 1.48μs 0.658ns 2.55ns 0.141 0 0 891 B
master RunOnMethodBegin netcoreapp3.1 1.17μs 0.726ns 2.72ns 0.0118 0 0 880 B
#3066 RunOnMethodBegin net472 1.45μs 0.896ns 3.47ns 0.141 0 0 891 B
#3066 RunOnMethodBegin netcoreapp3.1 1.15μs 0.302ns 1.13ns 0.0116 0 0 880 B

@andrewlock

Copy link
Copy Markdown
Member

Code Coverage Report 📊

✔️ Merging #3066 into master will not change line coverage
✔️ Merging #3066 into master will not change branch coverage
⛔ Merging #3066 into master will will increase complexity by 45

master #3066 Change
Lines 17259 / 23585 17344 / 23659
Lines % 73% 73% 0% ✔️
Branches 10242 / 14548 10288 / 14578
Branches % 70% 71% 0% ✔️
Complexity 15670 15715 45

View the full report for further details:

Datadog.Trace Breakdown ✔️

master #3066 Change
Lines % 73% 73% 0% ✔️
Branches % 70% 71% 0% ✔️
Complexity 15670 15715 45

The following classes have significant coverage changes.

File Line coverage change Branch coverage change Complexity change
Datadog.Trace.AppSec.SecuritySettings 2% ✔️ 6% ✔️ 8
Datadog.Trace.Ci.CIVisibility 5% ✔️ 6% ✔️ 0 ✔️
Datadog.Trace.AppSec.Transports.Http.HttpTransport 7% ✔️ -30% 11
Datadog.Trace.DiagnosticListeners.DiagnosticObserver 7% ✔️ 0% ✔️ 0 ✔️
Datadog.Trace.Telemetry.Transports.JsonTelemetryTransport 9% ✔️ 17% ✔️ 0 ✔️
Datadog.Trace.Agent.Transports.HttpStreamRequestFactory 12% ✔️ 0% ✔️ 0 ✔️

The following classes were added in #3066:

File Line coverage Branch coverage Complexity
Datadog.Trace.AppSec.BlockException 25% 100% 4
Datadog.Trace.AppSec.InstrumentationGatewayBlockingEventArgs 100% 100% 5

View the full reports for further details:

@anna-git
anna-git merged commit 318b512 into master Aug 31, 2022
@anna-git
anna-git deleted the anna/asm/blocking-request branch August 31, 2022 10:29
@github-actions github-actions Bot added this to the vNext milestone Aug 31, 2022

@andrewlock andrewlock left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, I have a few concerns about the use of the synchronous APIs, but otherwise looks good. Either way, I'm apparently too slow as this is merged 😂

Comment on lines +59 to +60
httpResponse.Clear();
httpResponse.Headers.Clear();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, this may throw if the response is already streaming

Comment on lines +70 to +78
if (_context.Request.Headers["Accept"] == "application/json")
{
httpResponse.ContentType = "application/json";
}
else
{
httpResponse.ContentType = "text/html";
template = templateHtml;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I would probably reverse this condition and use "contains" e.g. if the Accept header contains "text/html", use that, otherwise return json. Otherwise, if they're using a json derivative (e.g. applicataion/hal+json) we incorrectly send them text/html.

if (syncIOFeature != null)
{
// allow synchronous operatoin for net core >=3.1 otherwise invalidoperation exception
syncIOFeature.AllowSynchronousIO = true;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is kinda horrible, is there no way we can make this async up the stack? 🙁 Last thing we really want is thread starvation and hangs 😬

Comment on lines -890 to +911
span.SetHeaderTags(new HeadersCollectionAdapter(httpContext.Response.Headers), tracer.Settings.HeaderTags, defaultTagPrefix: SpanContextPropagator.HttpResponseHeadersTagPrefix);
scope.Dispose();
DoBeforeRequestStops(httpContext, scope, tracer.Settings);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK, this code is called even when there's an exception, so I don't think you need to call this function everywhere 🤔

@@ -1,4 +1,5 @@
Microsoft.AspNetCore.Http.Abstractions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60
Microsoft.AspNetCore.Http.Extensions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😬 Do we have to add this? We generally don't want to add references (we really need to look at removing these in future if anything)

http.request.headers.host: localhost:00000,
http.request.headers.user-agent: Mistake Not...,
http.request.headers.x-forwarded: 86.242.244.246,
http.response.headers.content-length: 0,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this correct? You send content when blocking don't you, so this shouldn't be 0?

robertpi added a commit that referenced this pull request Sep 29, 2022
## Summary of changes

This builds on #3066 to bring blocking capabilities to the .NET Framework as well as core. 

This provides the ability to block a request but is not linked to any real mechanism to block requests, only test blocking rules exist for now.

## Reason for change

We want to support blocking on both .NET Framework and Core.

## Implementation details

Most of the blocking mechanism was put in place in #3066, this just fills in the missing parts for .NET Framework.

## Test coverage

Covered by integration tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants