Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions manifests/cpp_httpd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ manifest:
tests/ai_guard/test_ai_guard_sdk.py::Test_Full_Response_And_Tags: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_RootSpanUserKeep: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_SDK_Disabled: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_SDS_Findings_In_SDK_Response: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_SensitiveDataScanning: missing_feature
tests/apm_tracing_e2e/: missing_feature (missing /e2e_otel_span endpoint on weblog)
tests/appsec/: irrelevant (ASM is not implemented in C++)
Expand Down
1 change: 1 addition & 0 deletions manifests/cpp_nginx.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ manifest:
tests/ai_guard/test_ai_guard_sdk.py::Test_Full_Response_And_Tags: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_RootSpanUserKeep: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_SDK_Disabled: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_SDS_Findings_In_SDK_Response: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_SensitiveDataScanning: missing_feature
tests/apm_tracing_e2e/test_otel.py::Test_Otel_Span: missing_feature (missing /e2e_otel_span endpoint on weblog)
tests/apm_tracing_e2e/test_otel.py::Test_Otel_Span::test_distributed_otel_trace: irrelevant (Golang specific test with OTel Go contrib package)
Expand Down
1 change: 1 addition & 0 deletions manifests/dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ manifest:
tests/ai_guard/test_ai_guard_sdk.py::Test_Full_Response_And_Tags: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_RootSpanUserKeep: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_SDK_Disabled: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_SDS_Findings_In_SDK_Response: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_SensitiveDataScanning: missing_feature
tests/apm_tracing_e2e/test_otel.py::Test_Otel_Span: missing_feature (missing /e2e_otel_span endpoint on weblog)
tests/apm_tracing_e2e/test_otel.py::Test_Otel_Span::test_distributed_otel_trace: irrelevant (Golang specific test with OTel Go contrib package)
Expand Down
1 change: 1 addition & 0 deletions manifests/golang.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ manifest:
tests/ai_guard/test_ai_guard_sdk.py::Test_Full_Response_And_Tags: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_RootSpanUserKeep: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_SDK_Disabled: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_SDS_Findings_In_SDK_Response: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_SensitiveDataScanning: missing_feature
tests/apm_tracing_e2e/test_otel.py::Test_Otel_Span:
- weblog_declaration:
Expand Down
4 changes: 4 additions & 0 deletions manifests/java.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ manifest:
- weblog_declaration:
"*": irrelevant (just one weblog is enough to test the SDK)
"spring-boot": v1.54.0
tests/ai_guard/test_ai_guard_sdk.py::Test_SDS_Findings_In_SDK_Response:
- weblog_declaration:
"*": irrelevant (just one weblog is enough to test the SDK)
"spring-boot": v1.61.0-SNAPSHOT
tests/ai_guard/test_ai_guard_sdk.py::Test_SensitiveDataScanning:
- weblog_declaration:
"*": irrelevant (just one weblog is enough to test the SDK)
Expand Down
4 changes: 4 additions & 0 deletions manifests/nodejs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ manifest:
- weblog_declaration:
"*": irrelevant (just one weblog is enough to test the SDK)
express4: *ref_5_69_0
tests/ai_guard/test_ai_guard_sdk.py::Test_SDS_Findings_In_SDK_Response:
- weblog_declaration:
"*": irrelevant (just one weblog is enough to test the SDK)
express4: *ref_5_90_0
tests/ai_guard/test_ai_guard_sdk.py::Test_SensitiveDataScanning:
- weblog_declaration:
"*": irrelevant (just one weblog is enough to test the SDK)
Expand Down
1 change: 1 addition & 0 deletions manifests/php.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ manifest:
tests/ai_guard/test_ai_guard_sdk.py::Test_Full_Response_And_Tags: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_RootSpanUserKeep: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_SDK_Disabled: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_SDS_Findings_In_SDK_Response: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_SensitiveDataScanning: missing_feature
tests/apm_tracing_e2e/test_otel.py::Test_Otel_Span: missing_feature (missing /e2e_otel_span endpoint on weblog)
tests/apm_tracing_e2e/test_otel.py::Test_Otel_Span::test_distributed_otel_trace: irrelevant (Golang specific test with OTel Go contrib package)
Expand Down
4 changes: 4 additions & 0 deletions manifests/python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ manifest:
- weblog_declaration:
"*": irrelevant (just one weblog is enough to test the SDK)
"flask-poc": v4.0.0
tests/ai_guard/test_ai_guard_sdk.py::Test_SDS_Findings_In_SDK_Response:
- weblog_declaration:
"*": irrelevant (just one weblog is enough to test the SDK)
"flask-poc": v4.7.0-rc1
tests/ai_guard/test_ai_guard_sdk.py::Test_SensitiveDataScanning:
- weblog_declaration:
"*": irrelevant (just one weblog is enough to test the SDK)
Expand Down
10 changes: 10 additions & 0 deletions manifests/ruby.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ manifest:
sinatra32: irrelevant
sinatra41: irrelevant
uds-sinatra: irrelevant
tests/ai_guard/test_ai_guard_sdk.py::Test_SDS_Findings_In_SDK_Response:
- weblog_declaration:
"*": missing_feature
rails42: irrelevant
rack: irrelevant
sinatra14: irrelevant
sinatra22: irrelevant
sinatra32: irrelevant
sinatra41: irrelevant
uds-sinatra: irrelevant
tests/ai_guard/test_ai_guard_sdk.py::Test_SensitiveDataScanning:
- weblog_declaration:
"*": missing_feature
Expand Down
25 changes: 25 additions & 0 deletions tests/ai_guard/test_ai_guard_sdk.py
Original file line number Diff line number Diff line change
Expand Up @@ -369,3 +369,28 @@ def test_sensitive_data(self):
"""
assert self.r.status_code == 200
interfaces.library.validate_one_span(self.r, validator=self._assert_span_with_sensitive_data(), full_trace=True)


@features.ai_guard
@scenarios.ai_guard
class Test_SDS_Findings_In_SDK_Response:
def setup_sds_in_response(self):
self.r = weblog.post("/ai_guard/evaluate", json=MESSAGES["SENSITIVE_DATA"])

def test_sds_in_response(self):
"""Test SDS findings are returned in SDK response.
Verifies that the SDK evaluation response contains sds findings.
"""
assert self.r.status_code == 200
body = json.loads(self.r.text)
sds = _assert_key(body, "sds")
assert len(sds) > 0, f"No SDS findings in SDK response: {body}"
for finding in sds:
assert _assert_key(finding, "rule_display_name")
assert _assert_key(finding, "rule_tag")
assert _assert_key(finding, "category")
assert _assert_key(finding, "matched_text")
location = _assert_key(finding, "location")
assert _assert_key(location, "start_index") is not None
assert _assert_key(location, "end_index_exclusive") is not None
assert _assert_key(location, "path")
7 changes: 6 additions & 1 deletion utils/build/docker/python/flask/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -2194,7 +2194,12 @@ def ai_guard_evaluate():
except Exception as e:
if isinstance(e, AIGuardAbortError):
return jsonify(
{"action": getattr(e, "action", ""), "reason": getattr(e, "reason", ""), "tags": getattr(e, "tags", [])}
{
"action": getattr(e, "action", ""),
"reason": getattr(e, "reason", ""),
"tags": getattr(e, "tags", []),
"sds": getattr(e, "sds", []),
}
), 403
else:
return jsonify({"error": str(e), "type": e.__class__.__name__}), 500
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,18 @@ def evaluate
allow_raise = request.headers['X-AI-Guard-Block']&.downcase == "true"
result = Datadog::AIGuard.evaluate(*messages, allow_raise: allow_raise)

render json: {
response_data = {
action: result.action,
reason: result.reason,
tags: result.tags,
is_blocking_enabled: result.blocking_enabled?
}
response_data[:sds] = result.sds if result.respond_to?(:sds)
render json: response_data
rescue Datadog::AIGuard::AIGuardAbortError => e
render json: { action: e.action, reason: e.reason, tags: e.tags }, status: 403
error_data = { action: e.action, reason: e.reason, tags: e.tags }
error_data[:sds] = e.sds if e.respond_to?(:sds)
render json: error_data, status: 403
rescue => e
render json: {error: e.to_s, type: e.class.name}, status: 500
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,18 @@ def evaluate
allow_raise = request.headers['X-AI-Guard-Block']&.downcase == "true"
result = Datadog::AIGuard.evaluate(*messages, allow_raise: allow_raise)

render json: {
response_data = {
action: result.action,
reason: result.reason,
tags: result.tags,
is_blocking_enabled: result.blocking_enabled?
}
response_data[:sds] = result.sds if result.respond_to?(:sds)
render json: response_data
rescue Datadog::AIGuard::AIGuardAbortError => e
render json: { action: e.action, reason: e.reason, tags: e.tags }, status: 403
error_data = { action: e.action, reason: e.reason, tags: e.tags }
error_data[:sds] = e.sds if e.respond_to?(:sds)
render json: error_data, status: 403
rescue => e
render json: {error: e.to_s, type: e.class.name}, status: 500
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,18 @@ def evaluate
allow_raise = request.headers['X-AI-Guard-Block']&.downcase == "true"
result = Datadog::AIGuard.evaluate(*messages, allow_raise: allow_raise)

render json: {
response_data = {
action: result.action,
reason: result.reason,
tags: result.tags,
is_blocking_enabled: result.blocking_enabled?
}
response_data[:sds] = result.sds if result.respond_to?(:sds)
render json: response_data
rescue Datadog::AIGuard::AIGuardAbortError => e
render json: { action: e.action, reason: e.reason, tags: e.tags }, status: 403
error_data = { action: e.action, reason: e.reason, tags: e.tags }
error_data[:sds] = e.sds if e.respond_to?(:sds)
render json: error_data, status: 403
rescue => e
render json: {error: e.to_s, type: e.class.name}, status: 500
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,18 @@ def evaluate
allow_raise = request.headers['X-AI-Guard-Block']&.downcase == "true"
result = Datadog::AIGuard.evaluate(*messages, allow_raise: allow_raise)

render json: {
response_data = {
action: result.action,
reason: result.reason,
tags: result.tags,
is_blocking_enabled: result.blocking_enabled?
}
response_data[:sds] = result.sds if result.respond_to?(:sds)
render json: response_data
rescue Datadog::AIGuard::AIGuardAbortError => e
render json: { action: e.action, reason: e.reason, tags: e.tags }, status: 403
error_data = { action: e.action, reason: e.reason, tags: e.tags }
error_data[:sds] = e.sds if e.respond_to?(:sds)
render json: error_data, status: 403
rescue => e
render json: {error: e.to_s, type: e.class.name}, status: 500
end
Expand Down
Loading