Skip to content

Commit 0e6eaf6

Browse files
gnufedeYun-KimKyle-VerhoogP403n1x87avara1986
committed
refactor(appsec): rename appsec submodules to make them private (#6861)
Refactors AppSec submodules to make them private: - ddtrace.appsec.ddwaf -> ddtrace.appsec._ddwaf - ddtrace.appsec.handlers -> ddtrace.appsec._handlers - ddtrace.appsec.iast -> ddtrace.appsec._iast - ddtrace.appsec.processor -> ddtrace.appsec._processor - ddtrace.appsec.trace_utils -> ddtrace.appsec._trace_utils - ddtrace.appsec.utils -> ddtrace.appsec._utils Exports public functions as they were before: - ddtrace.appsec.iast: - ddtrace_iast_flask_patch - ddtrace.appsec.trace_utils: - block_request - block_request_if_user_blocked - should_block_user - track_custom_event - track_user_login_failure_event - track_user_login_success_event - track_user_signup_event - [x] Change(s) are motivated and described in the PR description. - [x] Testing strategy is described if automated tests are not included in the PR. - [x] Risk is outlined (performance impact, potential for breakage, maintainability, etc). - [x] Change is maintainable (easy to change, telemetry, documentation). - [x] [Library release note guidelines](https://ddtrace.readthedocs.io/en/stable/releasenotes.html) are followed. If no release note is required, add label `changelog/no-changelog`. - [x] Documentation is included (in-code, generated user docs, [public corp docs](https://github.com/DataDog/documentation/)). - [x] Backport labels are set (if [applicable](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting)) - [x] Title is accurate. - [x] No unnecessary changes are introduced. - [x] Description motivates each change. - [x] Avoids breaking [API](https://ddtrace.readthedocs.io/en/stable/versioning.html#interfaces) changes unless absolutely necessary. - [x] Testing strategy adequately addresses listed risk(s). - [x] Change is maintainable (easy to change, telemetry, documentation). - [x] Release note makes sense to a user of the library. - [x] Reviewer has explicitly acknowledged and discussed the performance implications of this PR as reported in the benchmarks PR comment. - [x] Backport labels are set in a manner that is consistent with the [release branch maintenance policy](https://ddtrace.readthedocs.io/en/latest/contributing.html#backporting) - [x] If this PR touches code that signs or publishes builds or packages, or handles credentials of any kind, I've requested a review from `@DataDog/security-design-and-guidance`. - [x] This PR doesn't touch any of that. --------- Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: Yun Kim <[email protected]> Co-authored-by: Yun Kim <[email protected]> Co-authored-by: Kyle Verhoog <[email protected]> Co-authored-by: Gabriele N. Tornetta <[email protected]> Co-authored-by: Alberto Vara <[email protected]> Co-authored-by: Nir Rattner <[email protected]> Co-authored-by: ZStriker19 <[email protected]> Co-authored-by: Zachary Groves <[email protected]> Co-authored-by: Munir Abdinur <[email protected]> Co-authored-by: Emmett Butler <[email protected]> Co-authored-by: Emmett Butler <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Christophe Papazian <[email protected]> Co-authored-by: Teague Bick <[email protected]> Co-authored-by: Tahir H. Butt <[email protected]> Co-authored-by: Juanjo Alvarez Martinez <[email protected]>
1 parent 763842b commit 0e6eaf6

File tree

200 files changed

+496
-487
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

200 files changed

+496
-487
lines changed

.gitignore

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ ddtrace/internal/_tagset.c
2525
ddtrace/**/*.html
2626

2727
# Dynamic binary libraries
28-
ddtrace/appsec/ddwaf/libddwaf/
28+
ddtrace/appsec/_ddwaf/libddwaf/
2929
libddwaf*.sha256
3030
ddtrace/internal/datadog/profiling/libdatadog/
3131

@@ -138,9 +138,9 @@ ddtrace/_version.py
138138
artifacts/
139139

140140
# IAST cpp
141-
ddtrace/appsec/iast/_taint_tracking/cmake-build-debug/*
142-
ddtrace/appsec/iast/_taint_tracking/_deps/*
143-
ddtrace/appsec/iast/_taint_tracking/CMakeFiles/*
141+
ddtrace/appsec/_iast/_taint_tracking/cmake-build-debug/*
142+
ddtrace/appsec/_iast/_taint_tracking/_deps/*
143+
ddtrace/appsec/_iast/_taint_tracking/CMakeFiles/*
144144

145145
# CircleCI generated config
146146
.circleci/config.gen.yml

benchmarks/appsec_iast_propagation/scenario.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22

33
import bm
44

5-
from ddtrace.appsec.iast._taint_tracking import OriginType
6-
from ddtrace.appsec.iast._taint_tracking import Source
7-
from ddtrace.appsec.iast._taint_tracking import TaintRange
8-
from ddtrace.appsec.iast._taint_tracking import create_context
9-
from ddtrace.appsec.iast._taint_tracking import reset_context
10-
from ddtrace.appsec.iast._taint_tracking import set_ranges
11-
from ddtrace.appsec.iast._taint_tracking.aspects import add_aspect
12-
from ddtrace.appsec.iast._taint_tracking.aspects import join_aspect
5+
from ddtrace.appsec._iast._taint_tracking import OriginType
6+
from ddtrace.appsec._iast._taint_tracking import Source
7+
from ddtrace.appsec._iast._taint_tracking import TaintRange
8+
from ddtrace.appsec._iast._taint_tracking import create_context
9+
from ddtrace.appsec._iast._taint_tracking import reset_context
10+
from ddtrace.appsec._iast._taint_tracking import set_ranges
11+
from ddtrace.appsec._iast._taint_tracking.aspects import add_aspect
12+
from ddtrace.appsec._iast._taint_tracking.aspects import join_aspect
1313

1414

1515
TAINT_ORIGIN = Source(name="sample_name", value="sample_value", origin=OriginType.PARAMETER)

ddtrace/_monkey.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ def patch_all(**patch_modules):
210210

211211
patch(raise_errors=False, **modules)
212212
if config._iast_enabled:
213-
from ddtrace.appsec.iast._patch_modules import patch_iast
213+
from ddtrace.appsec._iast._patch_modules import patch_iast
214214

215215
patch_iast()
216216

ddtrace/appsec/_api_security/api_manager.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
from ddtrace import config
88
from ddtrace._tracing._limits import MAX_SPAN_META_VALUE_LEN
9-
from ddtrace.appsec import processor as appsec_processor
9+
from ddtrace.appsec import _processor as appsec_processor
1010
from ddtrace.appsec._asm_request_context import _WAF_RESULTS
1111
from ddtrace.appsec._asm_request_context import add_context_callback
1212
from ddtrace.appsec._asm_request_context import call_waf_callback

ddtrace/appsec/_asm_request_context.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
from typing import TYPE_CHECKING
44

55
from ddtrace import config
6-
from ddtrace.appsec import handlers
6+
from ddtrace.appsec import _handlers
77
from ddtrace.appsec._constants import SPAN_DATA_NAMES
88
from ddtrace.appsec._constants import WAF_CONTEXT_NAMES
9-
from ddtrace.appsec.iast._utils import _is_iast_enabled
9+
from ddtrace.appsec._iast._utils import _is_iast_enabled
1010
from ddtrace.internal import core
1111
from ddtrace.internal.compat import parse
1212
from ddtrace.internal.constants import REQUEST_PATH_PARAMS
@@ -153,7 +153,7 @@ def set_headers_response(headers): # type: (Any) -> None
153153

154154
def set_body_response(body_response):
155155
# local import to avoid circular import
156-
from ddtrace.appsec.utils import parse_response_body
156+
from ddtrace.appsec._utils import parse_response_body
157157

158158
parsed_body = parse_response_body(body_response)
159159

@@ -338,7 +338,7 @@ def _start_context(remote_ip, headers, headers_case_sensitive, block_request_cal
338338
if config._appsec_enabled:
339339
resources = _DataHandler()
340340
asm_request_context_set(remote_ip, headers, headers_case_sensitive, block_request_callable)
341-
handlers.listen()
341+
_handlers.listen()
342342
listen_context_handlers()
343343
return resources
344344

@@ -382,8 +382,8 @@ def _on_wrapped_view(kwargs):
382382

383383
# If IAST is enabled, taint the Flask function kwargs (path parameters)
384384
if _is_iast_enabled() and kwargs:
385-
from ddtrace.appsec.iast._taint_tracking import OriginType
386-
from ddtrace.appsec.iast._taint_tracking import taint_pyobject
385+
from ddtrace.appsec._iast._taint_tracking import OriginType
386+
from ddtrace.appsec._iast._taint_tracking import taint_pyobject
387387

388388
_kwargs = {}
389389
for k, v in kwargs.items():
@@ -396,9 +396,9 @@ def _on_wrapped_view(kwargs):
396396

397397
def _on_set_request_tags(request, span, flask_config):
398398
if _is_iast_enabled():
399-
from ddtrace.appsec.iast._metrics import _set_metric_iast_instrumented_source
400-
from ddtrace.appsec.iast._taint_tracking import OriginType
401-
from ddtrace.appsec.iast._taint_utils import LazyTaintDict
399+
from ddtrace.appsec._iast._metrics import _set_metric_iast_instrumented_source
400+
from ddtrace.appsec._iast._taint_tracking import OriginType
401+
from ddtrace.appsec._iast._taint_utils import LazyTaintDict
402402

403403
_set_metric_iast_instrumented_source(OriginType.COOKIE_NAME)
404404
_set_metric_iast_instrumented_source(OriginType.COOKIE)

ddtrace/appsec/_capabilities.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
from ddtrace import Tracer
77
from ddtrace import config as ddconfig
8-
from ddtrace.appsec.utils import _appsec_rc_features_is_enabled
8+
from ddtrace.appsec._utils import _appsec_rc_features_is_enabled
99
from ddtrace.internal.compat import to_bytes_py2
1010

1111

File renamed without changes.
File renamed without changes.

ddtrace/appsec/handlers.py renamed to ddtrace/appsec/_handlers.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
import xmltodict
66

77
from ddtrace import config
8-
from ddtrace.appsec.iast._patch import if_iast_taint_returned_object_for
9-
from ddtrace.appsec.iast._patch import if_iast_taint_yield_tuple_for
10-
from ddtrace.appsec.iast._utils import _is_iast_enabled
8+
from ddtrace.appsec._iast._patch import if_iast_taint_returned_object_for
9+
from ddtrace.appsec._iast._patch import if_iast_taint_yield_tuple_for
10+
from ddtrace.appsec._iast._utils import _is_iast_enabled
1111
from ddtrace.contrib import trace_utils
1212
from ddtrace.internal import core
1313
from ddtrace.internal.constants import HTTP_REQUEST_BLOCKED
@@ -83,9 +83,9 @@ def _on_request_init(wrapped, instance, args, kwargs):
8383
wrapped(*args, **kwargs)
8484
if _is_iast_enabled():
8585
try:
86-
from ddtrace.appsec.iast._metrics import _set_metric_iast_instrumented_source
87-
from ddtrace.appsec.iast._taint_tracking import OriginType
88-
from ddtrace.appsec.iast._taint_tracking import taint_pyobject
86+
from ddtrace.appsec._iast._metrics import _set_metric_iast_instrumented_source
87+
from ddtrace.appsec._iast._taint_tracking import OriginType
88+
from ddtrace.appsec._iast._taint_tracking import taint_pyobject
8989

9090
# TODO: instance.query_string = ??
9191
instance.query_string = taint_pyobject(
@@ -109,8 +109,8 @@ def _on_request_init(wrapped, instance, args, kwargs):
109109
def _on_flask_patch(flask_version):
110110
if _is_iast_enabled():
111111
try:
112-
from ddtrace.appsec.iast._metrics import _set_metric_iast_instrumented_source
113-
from ddtrace.appsec.iast._taint_tracking import OriginType
112+
from ddtrace.appsec._iast._metrics import _set_metric_iast_instrumented_source
113+
from ddtrace.appsec._iast._taint_tracking import OriginType
114114

115115
_w(
116116
"werkzeug.datastructures",
@@ -161,10 +161,10 @@ def _on_django_func_wrapped(fn_args, fn_kwargs, first_arg_expected_type):
161161
# If IAST is enabled and we're wrapping a Django view call, taint the kwargs (view's
162162
# path parameters)
163163
if _is_iast_enabled() and fn_args and isinstance(fn_args[0], first_arg_expected_type):
164-
from ddtrace.appsec.iast._taint_tracking import OriginType # noqa: F401
165-
from ddtrace.appsec.iast._taint_tracking import is_pyobject_tainted
166-
from ddtrace.appsec.iast._taint_tracking import taint_pyobject
167-
from ddtrace.appsec.iast._taint_utils import LazyTaintDict
164+
from ddtrace.appsec._iast._taint_tracking import OriginType # noqa: F401
165+
from ddtrace.appsec._iast._taint_tracking import is_pyobject_tainted
166+
from ddtrace.appsec._iast._taint_tracking import taint_pyobject
167+
from ddtrace.appsec._iast._taint_utils import LazyTaintDict
168168

169169
http_req = fn_args[0]
170170

@@ -216,9 +216,9 @@ def _on_wsgi_environ(wrapped, _instance, args, kwargs):
216216
if not args:
217217
return wrapped(*args, **kwargs)
218218

219-
from ddtrace.appsec.iast._metrics import _set_metric_iast_instrumented_source
220-
from ddtrace.appsec.iast._taint_tracking import OriginType # noqa: F401
221-
from ddtrace.appsec.iast._taint_utils import LazyTaintDict
219+
from ddtrace.appsec._iast._metrics import _set_metric_iast_instrumented_source
220+
from ddtrace.appsec._iast._taint_tracking import OriginType # noqa: F401
221+
from ddtrace.appsec._iast._taint_utils import LazyTaintDict
222222

223223
_set_metric_iast_instrumented_source(OriginType.HEADER_NAME)
224224
_set_metric_iast_instrumented_source(OriginType.HEADER)
@@ -240,7 +240,7 @@ def _on_wsgi_environ(wrapped, _instance, args, kwargs):
240240

241241
def _on_django_patch():
242242
try:
243-
from ddtrace.appsec.iast._taint_tracking import OriginType # noqa: F401
243+
from ddtrace.appsec._iast._taint_tracking import OriginType # noqa: F401
244244

245245
when_imported("django.http.request")(
246246
lambda m: trace_utils.wrap(

ddtrace/appsec/_iast/__init__.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
"""IAST (interactive application security testing) analyzes code for security vulnerabilities.
2+
3+
To add new vulnerabilities analyzers (Taint sink) we should update `IAST_PATCH` in
4+
`ddtrace/appsec/iast/_patch_modules.py`
5+
6+
Create new file with the same name: `ddtrace/appsec/iast/taint_sinks/[my_new_vulnerability].py`
7+
8+
Then, implement the `patch()` function and its wrappers.
9+
10+
In order to have the better performance, the Overhead control engine (OCE) helps us to control the overhead of our
11+
wrapped functions. We should create a class that inherit from `ddtrace.appsec._iast.taint_sinks._base.VulnerabilityBase`
12+
and register with `ddtrace.appsec._iast.oce`.
13+
14+
@oce.register
15+
class MyVulnerability(VulnerabilityBase):
16+
vulnerability_type = "MyVulnerability"
17+
evidence_type = "kind_of_Vulnerability"
18+
19+
Before that, we should decorate our wrappers with `wrap` method and
20+
report the vulnerabilities with `report` method. OCE will manage the number of requests, number of vulnerabilities
21+
to reduce the overhead.
22+
23+
@WeakHash.wrap
24+
def wrapped_function(wrapped, instance, args, kwargs):
25+
# type: (Callable, str, Any, Any, Any) -> Any
26+
WeakHash.report(
27+
evidence_value=evidence,
28+
)
29+
return wrapped(*args, **kwargs)
30+
""" # noqa: RST201, RST213, RST210
31+
import inspect
32+
import sys
33+
34+
from ddtrace.internal.logger import get_logger
35+
36+
from ._ast.ast_patching import astpatch_module
37+
from ._overhead_control_engine import OverheadControl
38+
from ._utils import _is_iast_enabled
39+
40+
41+
log = get_logger(__name__)
42+
43+
oce = OverheadControl()
44+
45+
46+
def ddtrace_iast_flask_patch():
47+
"""
48+
Patch the code inside the Flask main app source code file (typically "app.py") so
49+
IAST/Custom Code propagation works also for the functions and methods defined inside it.
50+
This must be called on the top level or inside the `if __name__ == "__main__"`
51+
and must be before the `app.run()` call. It also requires `DD_IAST_ENABLED` to be
52+
activated.
53+
"""
54+
if not _is_iast_enabled():
55+
return
56+
57+
module_name = inspect.currentframe().f_back.f_globals["__name__"]
58+
module = sys.modules[module_name]
59+
try:
60+
module_path, patched_ast = astpatch_module(module, remove_flask_run=True)
61+
except Exception:
62+
log.debug("Unexpected exception while AST patching", exc_info=True)
63+
return
64+
65+
compiled_code = compile(patched_ast, module_path, "exec")
66+
exec(compiled_code, module.__dict__) # nosec B102
67+
sys.modules[module_name] = compiled_code
68+
69+
70+
__all__ = [
71+
"oce",
72+
"ddtrace_iast_flask_patch",
73+
]

0 commit comments

Comments
 (0)