Skip to content

Commit 39c3133

Browse files
Add /llm endpoint to flask-poc weblog (#7127)
Co-authored-by: Claude Sonnet 4.6/Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 53b4592 commit 39c3133

12 files changed

Lines changed: 78 additions & 21 deletions

manifests/python.yml

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -95,15 +95,36 @@ manifest:
9595
fastapi: v3.13.0.dev
9696
tests/appsec/api_security/test_endpoint_discovery.py::Test_Endpoint_Discovery::test_optional_type: irrelevant
9797
tests/appsec/api_security/test_endpoint_fallback.py: irrelevant (python weblogs always have http.route)
98-
tests/appsec/api_security/test_endpoints.py::Test_LLM_Endpoint::test_openai_async_chat_completions_create: missing_feature
99-
tests/appsec/api_security/test_endpoints.py::Test_LLM_Endpoint::test_openai_async_completions_create: missing_feature
100-
tests/appsec/api_security/test_endpoints.py::Test_LLM_Endpoint::test_openai_async_responses_create: missing_feature
101-
tests/appsec/api_security/test_endpoints.py::Test_LLM_Endpoint::test_openai_latest_chat_completions_create: missing_feature
102-
tests/appsec/api_security/test_endpoints.py::Test_LLM_Endpoint::test_openai_latest_completions_create: missing_feature
103-
tests/appsec/api_security/test_endpoints.py::Test_LLM_Endpoint::test_openai_latest_responses_create: missing_feature
104-
tests/appsec/api_security/test_endpoints.py::Test_LLM_Endpoint::test_openai_legacy_chat_completions_create: missing_feature
105-
tests/appsec/api_security/test_endpoints.py::Test_LLM_Endpoint::test_openai_legacy_completions_create: missing_feature
106-
tests/appsec/api_security/test_endpoints.py::Test_LLM_Endpoint::test_root_has_no_llm_tags: missing_feature
98+
tests/appsec/api_security/test_endpoints.py::Test_LLM_Endpoint::test_openai_async_chat_completions_create:
99+
- weblog_declaration:
100+
"*": irrelevant (openai instrumentation is framework-independent, only tested on flask-poc)
101+
flask-poc: v4.12.0rc1
102+
tests/appsec/api_security/test_endpoints.py::Test_LLM_Endpoint::test_openai_async_completions_create:
103+
- weblog_declaration:
104+
"*": irrelevant (openai instrumentation is framework-independent, only tested on flask-poc)
105+
flask-poc: v4.12.0rc1
106+
tests/appsec/api_security/test_endpoints.py::Test_LLM_Endpoint::test_openai_async_responses_create:
107+
- weblog_declaration:
108+
"*": irrelevant (openai instrumentation is framework-independent, only tested on flask-poc)
109+
flask-poc: v4.12.0rc1
110+
tests/appsec/api_security/test_endpoints.py::Test_LLM_Endpoint::test_openai_latest_chat_completions_create:
111+
- weblog_declaration:
112+
"*": irrelevant (openai instrumentation is framework-independent, only tested on flask-poc)
113+
flask-poc: v4.12.0rc1
114+
tests/appsec/api_security/test_endpoints.py::Test_LLM_Endpoint::test_openai_latest_completions_create:
115+
- weblog_declaration:
116+
"*": irrelevant (openai instrumentation is framework-independent, only tested on flask-poc)
117+
flask-poc: v4.12.0rc1
118+
tests/appsec/api_security/test_endpoints.py::Test_LLM_Endpoint::test_openai_latest_responses_create:
119+
- weblog_declaration:
120+
"*": irrelevant (openai instrumentation is framework-independent, only tested on flask-poc)
121+
flask-poc: v4.12.0rc1
122+
tests/appsec/api_security/test_endpoints.py::Test_LLM_Endpoint::test_openai_legacy_chat_completions_create: irrelevant (legacy openai API not available in openai >= 1.0)
123+
tests/appsec/api_security/test_endpoints.py::Test_LLM_Endpoint::test_openai_legacy_completions_create: irrelevant (legacy openai API not available in openai >= 1.0)
124+
tests/appsec/api_security/test_endpoints.py::Test_LLM_Endpoint::test_root_has_no_llm_tags:
125+
- weblog_declaration:
126+
"*": irrelevant (openai instrumentation is framework-independent, only tested on flask-poc)
127+
flask-poc: v4.12.0rc1
107128
tests/appsec/api_security/test_schemas.py::Test_Scanners:
108129
- weblog_declaration:
109130
"*": v2.4.0

tests/appsec/api_security/test_endpoints.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def setup_openai_async_completions_create(self):
7171
def test_openai_async_completions_create(self):
7272
assert_llm_span(self.request, self.MODEL)
7373

74-
def setup_root_no_llm(self):
74+
def setup_root_has_no_llm_tags(self):
7575
# Baseline request to root endpoint should not produce LLM tags
7676
self.root_request = weblog.get("/")
7777

utils/build/docker/python/docker-bake.hcl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,13 @@ target "django-poc" {
3939
target "flask-poc" {
4040
context = "."
4141
dockerfile = "utils/build/docker/python/flask-poc.base.Dockerfile"
42-
tags = ["datadog/system-tests:flask-poc.base-v13"]
42+
tags = ["datadog/system-tests:flask-poc.base-v14"]
4343
}
4444

4545
target "uwsgi-poc" {
4646
context = "."
4747
dockerfile = "utils/build/docker/python/uwsgi-poc.base.Dockerfile"
48-
tags = ["datadog/system-tests:uwsgi-poc.base-v9"]
48+
tags = ["datadog/system-tests:uwsgi-poc.base-v10"]
4949
}
5050

5151
target "tornado" {

utils/build/docker/python/fastapi/requirements-fastapi.txt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
PyYAML
2-
fastapi
3-
uvicorn
2+
fastapi==0.135.2
3+
starlette==1.3.1
4+
uvicorn==0.49.0
5+
anyio==4.13.0
6+
pydantic==2.13.4
47
requests
58
cryptography==42.0.8
69
pycryptodome

utils/build/docker/python/flask-poc.Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM datadog/system-tests:flask-poc.base-v13
1+
FROM datadog/system-tests:flask-poc.base-v14
22

33
WORKDIR /app
44

utils/build/docker/python/flask-poc.base.Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,5 @@ RUN apt update && apt install -y pkg-config default-libmysqlclient-dev pkg-confi
2121
COPY utils/build/docker/python/flask/requirements-flask-poc.txt /tmp/flask-requirements.txt
2222
RUN pip install --upgrade pip && pip install -r /tmp/flask-requirements.txt
2323

24-
# docker build --progress=plain -f utils/build/docker/python/flask-poc.base.Dockerfile -t datadog/system-tests:flask-poc.base-v12 .
25-
# docker push datadog/system-tests:flask-poc.base-v12
24+
# docker build --progress=plain -f utils/build/docker/python/flask-poc.base.Dockerfile -t datadog/system-tests:flask-poc.base-v14 .
25+
# docker push datadog/system-tests:flask-poc.base-v14

utils/build/docker/python/flask/app.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
from iast import weak_hash_duplicates
5959
from iast import weak_hash_multiple
6060
from iast import weak_hash_secure_algorithm
61+
import openai
6162
import requests
6263
import stripe
6364
import opentelemetry.baggage
@@ -2252,6 +2253,36 @@ def stripe_webhook():
22522253
return jsonify({"error": str(e)}), 403
22532254

22542255

2256+
@app.route("/llm")
2257+
async def llm():
2258+
model = request.args.get("model", "")
2259+
operation = request.args.get("operation", "")
2260+
if not model or not operation:
2261+
return jsonify({"error": "Missing or empty query parameters: model, operation"}), 400
2262+
try:
2263+
if operation == "openai-latest-responses.create":
2264+
openai.OpenAI(api_key="sk-fake").responses.create(model=model, input="Hello")
2265+
elif operation == "openai-latest-chat.completions.create":
2266+
openai.OpenAI(api_key="sk-fake").chat.completions.create(
2267+
model=model, messages=[{"role": "user", "content": "Hello"}]
2268+
)
2269+
elif operation == "openai-latest-completions.create":
2270+
openai.OpenAI(api_key="sk-fake").completions.create(model=model, prompt="Hello")
2271+
elif operation == "openai-async-responses.create":
2272+
await openai.AsyncOpenAI(api_key="sk-fake").responses.create(model=model, input="Hello")
2273+
elif operation == "openai-async-chat.completions.create":
2274+
await openai.AsyncOpenAI(api_key="sk-fake").chat.completions.create(
2275+
model=model, messages=[{"role": "user", "content": "Hello"}]
2276+
)
2277+
elif operation == "openai-async-completions.create":
2278+
await openai.AsyncOpenAI(api_key="sk-fake").completions.create(model=model, prompt="Hello")
2279+
else:
2280+
return jsonify({"error": f"unknown operation: {operation}"}), 400
2281+
except Exception as e:
2282+
return jsonify({"error": str(e)}), 500
2283+
return jsonify({"model": model, "operation": operation})
2284+
2285+
22552286
@app.route("/sca/vulnerable-call")
22562287
def sca_requests_vulnerable_call():
22572288
"""Trigger a call to requests.sessions.Session.send (CVE-2024-35195 target)."""

utils/build/docker/python/flask/requirements-flask-poc.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@ urllib3==1.26.19
2323
openfeature-sdk==0.8.3
2424
loguru==0.7.3
2525
stripe==12.5.1
26+
openai==2.41.1

utils/build/docker/python/flask/requirements-uwsgi-poc.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@ PyMySQL==1.1.1
2121
openfeature-sdk==0.8.3
2222
loguru==0.7.3
2323
stripe==12.5.1
24+
openai==2.41.1

utils/build/docker/python/uds-flask.Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM datadog/system-tests:flask-poc.base-v13
1+
FROM datadog/system-tests:flask-poc.base-v14
22

33
WORKDIR /app
44

0 commit comments

Comments
 (0)