Skip to content

Commit 7f1a345

Browse files
committed
added expired and untrusted certs
1 parent 6692ec4 commit 7f1a345

File tree

3 files changed

+50
-24
lines changed

3 files changed

+50
-24
lines changed

tests/e2e/features/tls.feature

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,19 @@ Feature: TLS configuration for remote inference providers
2929
"""
3030
Then The status code of the response is 200
3131

32-
Scenario: Inference fails with an invalid CA certificate
33-
Given Llama Stack is configured with CA certificate path "/certs/client.crt"
32+
Scenario: Inference fails with an untrusted CA certificate
33+
Given Llama Stack is configured with CA certificate path "/certs/untrusted-ca.crt"
34+
And Llama Stack is restarted
35+
And Lightspeed Stack is restarted
36+
When I use "query" to ask question
37+
"""
38+
{"query": "Say hello", "model": "mock-tls-model", "provider": "tls-openai"}
39+
"""
40+
Then The status code of the response is 500
41+
And The body of the response does not contain Hello from the TLS mock inference server
42+
43+
Scenario: Inference fails with an expired CA certificate
44+
Given Llama Stack is configured with CA certificate path "/certs/expired-ca.crt"
3445
And Llama Stack is restarted
3546
And Lightspeed Stack is restarted
3647
When I use "query" to ask question

tests/e2e/mock_tls_inference_server/server.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
Certificates are generated on-the-fly using trustme at server startup.
1212
"""
1313

14+
import datetime
1415
import json
1516
import ssl
1617
import sys
@@ -21,6 +22,8 @@
2122
from typing import Any
2223

2324
import trustme
25+
from cryptography.hazmat.primitives import hashes, serialization
26+
from cryptography.x509 import CertificateBuilder, random_serial_number
2427

2528
MODEL_ID = "mock-tls-model"
2629

@@ -105,6 +108,31 @@ def _send_json(self, data: dict | list) -> None:
105108
self.wfile.write(payload)
106109

107110

111+
def _export_expired_ca_cert(ca: trustme.CA, path: Path) -> None:
112+
"""Re-sign a trustme CA certificate with expired validity dates.
113+
114+
Creates a copy of the CA's self-signed certificate but with validity
115+
dates set in the past, making it an expired certificate.
116+
117+
Parameters:
118+
ca: The trustme CA whose certificate and key to use.
119+
path: File path to write the expired CA certificate PEM.
120+
"""
121+
original = ca._certificate # noqa: SLF001
122+
now = datetime.datetime.now(datetime.timezone.utc)
123+
builder = CertificateBuilder()
124+
builder = builder.subject_name(original.subject)
125+
builder = builder.issuer_name(original.issuer)
126+
builder = builder.public_key(original.public_key())
127+
builder = builder.serial_number(random_serial_number())
128+
builder = builder.not_valid_before(now - datetime.timedelta(days=365))
129+
builder = builder.not_valid_after(now - datetime.timedelta(days=1))
130+
for ext in original.extensions:
131+
builder = builder.add_extension(ext.value, ext.critical)
132+
expired_cert = builder.sign(ca._private_key, hashes.SHA256()) # noqa: SLF001
133+
path.write_bytes(expired_cert.public_bytes(serialization.Encoding.PEM))
134+
135+
108136
def _make_tls_context(
109137
ca: trustme.CA,
110138
server_cert: trustme.LeafCert,
@@ -174,6 +202,15 @@ def main() -> None:
174202
print(f" Client cert: {certs_dir / 'client.crt'}")
175203
print(f" Client key: {certs_dir / 'client.key'}")
176204

205+
# Export untrusted CA certificate (from a separate CA that did not sign the server cert)
206+
untrusted_ca = trustme.CA()
207+
untrusted_ca.cert_pem.write_to_path(str(certs_dir / "untrusted-ca.crt"))
208+
print(f" Untrusted CA cert: {certs_dir / 'untrusted-ca.crt'}")
209+
210+
# Export expired CA certificate (re-signed with past validity dates)
211+
_export_expired_ca_cert(ca, certs_dir / "expired-ca.crt")
212+
print(f" Expired CA cert: {certs_dir / 'expired-ca.crt'}")
213+
177214
print("=" * 60)
178215
print("Starting servers...")
179216
print("=" * 60)

tests/e2e/test_list.txt

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1 @@
1-
features/faiss.feature
2-
features/inline_rag.feature
3-
features/smoketests.feature
4-
features/authorized_noop.feature
5-
features/authorized_noop_token.feature
6-
features/authorized_rh_identity.feature
7-
features/rbac.feature
8-
features/conversations.feature
9-
features/conversation_cache_v2.feature
10-
features/feedback.feature
11-
features/health.feature
12-
features/info.feature
13-
features/responses.feature
14-
features/responses_streaming.feature
15-
features/query.feature
16-
features/rlsapi_v1.feature
17-
features/rlsapi_v1_errors.feature
18-
features/streaming_query.feature
19-
features/rest_api.feature
20-
features/mcp.feature
21-
features/models.feature
22-
features/proxy.feature
231
features/tls.feature

0 commit comments

Comments
 (0)