Skip to content
Open
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 docs/understand/scenarios/ai_guard.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ The scenario sets the following environment variables on the weblog:

| Variable | Value | Description |
|---|---|---|
| `DD_APPSEC_ENABLED` | `false` | Explicitly disables AppSec so AI Guard client IP coverage does not rely on ASM behavior |
| `DD_AI_GUARD_ENABLED` | `true` | Enables the AI Guard SDK |
| `DD_AI_GUARD_ENDPOINT` | `http://vcr_cassettes:<port>/vcr/aiguard` | Points to VCR container instead of real API |
| `DD_API_KEY` | `mock_api_key` | Mock key (real key not needed with VCR) |
Expand Down
1 change: 1 addition & 0 deletions manifests/cpp_httpd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# use `>1.0.0` to indicate that requirement.
manifest:
tests/ai_guard/test_ai_guard_sdk.py::Test_AIGuardEvent_Tag: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_ClientIPTagsCollected: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_ContentParts: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_Evaluation: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_Full_Response_And_Tags: missing_feature
Expand Down
1 change: 1 addition & 0 deletions manifests/cpp_nginx.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
# use `>1.0.0` to indicate that requirement.
manifest:
tests/ai_guard/test_ai_guard_sdk.py::Test_AIGuardEvent_Tag: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_ClientIPTagsCollected: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_ContentParts: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_Evaluation: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_Full_Response_And_Tags: missing_feature
Expand Down
1 change: 1 addition & 0 deletions manifests/dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
---
manifest:
tests/ai_guard/test_ai_guard_sdk.py::Test_AIGuardEvent_Tag: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_ClientIPTagsCollected: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_ContentParts: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_Evaluation: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_Full_Response_And_Tags: missing_feature
Expand Down
1 change: 1 addition & 0 deletions manifests/golang.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
---
manifest:
tests/ai_guard/test_ai_guard_sdk.py::Test_AIGuardEvent_Tag: missing_feature (APPSEC-62216)
tests/ai_guard/test_ai_guard_sdk.py::Test_ClientIPTagsCollected: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_ContentParts: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_Evaluation: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_Full_Response_And_Tags: missing_feature
Expand Down
4 changes: 4 additions & 0 deletions manifests/java.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
---
manifest:
tests/ai_guard/test_ai_guard_sdk.py::Test_AIGuardEvent_Tag: missing_feature (APPSEC-62215)
tests/ai_guard/test_ai_guard_sdk.py::Test_ClientIPTagsCollected:
- weblog_declaration:
"*": irrelevant (just one weblog is enough to test the SDK)
"spring-boot": missing_feature (APPSEC-62199)
tests/ai_guard/test_ai_guard_sdk.py::Test_ContentParts:
- 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 @@ -91,6 +91,10 @@ refs:
- &ref_6_0_0 '>=6.0.0-pre'
manifest:
tests/ai_guard/test_ai_guard_sdk.py::Test_AIGuardEvent_Tag: missing_feature (APPSEC-62217)
tests/ai_guard/test_ai_guard_sdk.py::Test_ClientIPTagsCollected:
- weblog_declaration:
"*": irrelevant (just one weblog is enough to test the SDK)
express4: missing_feature (APPSEC-62202)
tests/ai_guard/test_ai_guard_sdk.py::Test_ContentParts:
- 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 @@ -2,6 +2,7 @@
---
manifest:
tests/ai_guard/test_ai_guard_sdk.py::Test_AIGuardEvent_Tag: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_ClientIPTagsCollected: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_ContentParts: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_Evaluation: missing_feature
tests/ai_guard/test_ai_guard_sdk.py::Test_Full_Response_And_Tags: missing_feature
Expand Down
4 changes: 4 additions & 0 deletions manifests/python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ manifest:
- weblog_declaration:
tornado: v4.4.0-rc2
tests/ai_guard/test_ai_guard_sdk.py::Test_AIGuardEvent_Tag: missing_feature (APPSEC-62216)
tests/ai_guard/test_ai_guard_sdk.py::Test_ClientIPTagsCollected:
- weblog_declaration:
"*": irrelevant (just one weblog is enough to test the SDK)
"flask-poc": missing_feature (APPSEC-62201)
tests/ai_guard/test_ai_guard_sdk.py::Test_ContentParts:
- 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 @@ -2,6 +2,16 @@
---
manifest:
tests/ai_guard/test_ai_guard_sdk.py::Test_AIGuardEvent_Tag: missing_feature (APPSEC-62218)
tests/ai_guard/test_ai_guard_sdk.py::Test_ClientIPTagsCollected:
- weblog_declaration:
"*": missing_feature (APPSEC-62200)
rails42: irrelevant
rack: irrelevant
sinatra14: irrelevant
sinatra22: irrelevant
sinatra32: irrelevant
sinatra41: irrelevant
uds-sinatra: irrelevant
tests/ai_guard/test_ai_guard_sdk.py::Test_ContentParts:
- weblog_declaration:
"*": v2.31.0-dev
Expand Down
37 changes: 36 additions & 1 deletion tests/ai_guard/test_ai_guard_sdk.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import json
import math

from utils import context, interfaces, scenarios, weblog, features
from utils import context, interfaces, scenarios, weblog, features, rfc
from utils.dd_constants import SamplingMechanism, SamplingPriority
from utils.dd_types import DataDogLibrarySpan, DataDogLibraryTrace, is_same_boolean

Expand Down Expand Up @@ -225,6 +225,41 @@ def test_root_span_user_keep(self):
)


@rfc("https://datadoghq.atlassian.net/wiki/x/x4DVhAE")
@features.ai_guard
@scenarios.ai_guard
class Test_ClientIPTagsCollected:
PUBLIC_IP = "5.6.7.9"

def setup_client_ip_tags(self):
self.r = weblog.post(
"/ai_guard/evaluate",
headers={"X-Forwarded-For": self.PUBLIC_IP},
json=MESSAGES["ALLOW"],
)

def test_client_ip_tags(self):
"""Test AI Guard collects client IP tags on the local root span with AppSec disabled."""
assert self.r.status_code == 200

spans = [span for _, _, span in interfaces.library.get_spans(request=self.r, full_trace=True)]
assert any(span.get("resource") == "ai_guard" for span in spans), "No ai_guard span found in the trace"

span = interfaces.library.get_root_span(self.r)
assert span
meta = span.get("meta", {})
assert meta
assert "network.client.ip" in meta
network_client_ip = meta["network.client.ip"]
assert network_client_ip
assert network_client_ip != self.PUBLIC_IP

http_client_ip = meta.get("http.client_ip")
assert http_client_ip
assert http_client_ip == self.PUBLIC_IP
assert network_client_ip != http_client_ip


@features.ai_guard
@scenarios.ai_guard
class Test_Full_Response_And_Tags:
Expand Down
2 changes: 2 additions & 0 deletions utils/_context/_scenarios/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1235,7 +1235,9 @@ class _Scenarios:
ai_guard = AIGuardScenario(
"AI_GUARD",
other_weblog_containers=(VCRCassettesContainer,),
appsec_enabled=False,
weblog_env={
"DD_APPSEC_ENABLED": "false",
"DD_AI_GUARD_ENABLED": "true",
"DD_AI_GUARD_ENDPOINT": f"http://vcr_cassettes:{ContainerPorts.vcr_cassettes}/vcr/aiguard",
"DD_API_KEY": "mock_api_key",
Expand Down
Loading