Skip to content

Commit 5b1d31b

Browse files
committed
added hostname mismatch tests
1 parent 4e3b299 commit 5b1d31b

5 files changed

Lines changed: 121 additions & 2 deletions

File tree

docker-compose-library.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ services:
125125
ports:
126126
- "8443:8443"
127127
- "8444:8444"
128+
- "8445:8445"
128129
networks:
129130
- lightspeednet
130131
volumes:

docker-compose.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ services:
153153
ports:
154154
- "8443:8443"
155155
- "8444:8444"
156+
- "8445:8445"
156157
networks:
157158
- lightspeednet
158159
volumes:

tests/e2e/features/steps/tls.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,67 @@ def configure_mtls_expired_client_cert(context: Context) -> None:
250250
_write_config(config, _LLAMA_STACK_CONFIG)
251251

252252

253+
@given("Llama Stack is configured with CA certificate and hostname mismatch server")
254+
def configure_tls_hostname_mismatch(context: Context) -> None:
255+
"""Configure run.yaml to connect to the hostname-mismatch TLS server.
256+
257+
The mock server on port 8445 presents a certificate issued for
258+
"wrong-hostname.example.com", but the client connects to
259+
"mock-tls-inference", causing a hostname verification failure.
260+
261+
Parameters:
262+
context: Behave test context.
263+
"""
264+
config, provider = _prepare_tls_provider()
265+
provider["config"]["base_url"] = "https://mock-tls-inference:8445/v1"
266+
provider["config"]["network"]["tls"] = {"verify": "/certs/ca.crt"}
267+
_write_config(config, _LLAMA_STACK_CONFIG)
268+
269+
270+
@given(
271+
"Llama Stack is configured with mutual TLS and hostname mismatch server"
272+
)
273+
def configure_mtls_hostname_mismatch(context: Context) -> None:
274+
"""Configure run.yaml for mTLS against the hostname-mismatch TLS server.
275+
276+
The mock server on port 8445 presents a certificate issued for
277+
"wrong-hostname.example.com". Even though client certs are provided,
278+
the hostname mismatch should cause the connection to fail.
279+
280+
Parameters:
281+
context: Behave test context.
282+
"""
283+
config, provider = _prepare_tls_provider()
284+
provider["config"]["base_url"] = "https://mock-tls-inference:8445/v1"
285+
provider["config"]["network"]["tls"] = {
286+
"verify": "/certs/ca.crt",
287+
"client_cert": "/certs/client.crt",
288+
"client_key": "/certs/client.key",
289+
}
290+
_write_config(config, _LLAMA_STACK_CONFIG)
291+
292+
293+
@given(
294+
'Llama Stack is configured with TLS minimum version "{version}" and hostname mismatch server'
295+
)
296+
def configure_tls_min_version_hostname_mismatch(
297+
context: Context, version: str
298+
) -> None:
299+
"""Configure run.yaml with TLS min version against the hostname-mismatch server.
300+
301+
Parameters:
302+
context: Behave test context.
303+
version: The TLS version (e.g., "TLSv1.2", "TLSv1.3").
304+
"""
305+
config, provider = _prepare_tls_provider()
306+
provider["config"]["base_url"] = "https://mock-tls-inference:8445/v1"
307+
provider["config"]["network"]["tls"] = {
308+
"verify": "/certs/ca.crt",
309+
"min_version": version,
310+
}
311+
_write_config(config, _LLAMA_STACK_CONFIG)
312+
313+
253314
@given(
254315
'Llama Stack is configured with TLS minimum version "{version}" and CA certificate path "{path}"'
255316
)

tests/e2e/features/tls.feature

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,28 @@ Feature: TLS configuration for remote inference providers
116116
Then The status code of the response is 500
117117
And The body of the response does not contain Hello from the TLS mock inference server
118118

119+
Scenario: Inference fails with CA certificate verification and hostname mismatch
120+
Given Llama Stack is configured with CA certificate and hostname mismatch server
121+
And Llama Stack is restarted
122+
And Lightspeed Stack is restarted
123+
When I use "query" to ask question
124+
"""
125+
{"query": "Say hello", "model": "mock-tls-model", "provider": "tls-openai"}
126+
"""
127+
Then The status code of the response is 500
128+
And The body of the response does not contain Hello from the TLS mock inference server
129+
130+
Scenario: Inference fails with mutual TLS and hostname mismatch
131+
Given Llama Stack is configured with mutual TLS and hostname mismatch server
132+
And Llama Stack is restarted
133+
And Lightspeed Stack is restarted
134+
When I use "query" to ask question
135+
"""
136+
{"query": "Say hello", "model": "mock-tls-model", "provider": "tls-openai"}
137+
"""
138+
Then The status code of the response is 500
139+
And The body of the response does not contain Hello from the TLS mock inference server
140+
119141
Scenario: Inference succeeds with TLS minimum version TLSv1.3
120142
Given Llama Stack is configured with TLS minimum version "TLSv1.3" and CA certificate path "/certs/ca.crt"
121143
And Llama Stack is restarted
@@ -137,6 +159,17 @@ Feature: TLS configuration for remote inference providers
137159
Then The status code of the response is 500
138160
And The body of the response does not contain Hello from the TLS mock inference server
139161

162+
Scenario: Inference fails with TLS minimum version TLSv1.3 and hostname mismatch
163+
Given Llama Stack is configured with TLS minimum version "TLSv1.3" and hostname mismatch server
164+
And Llama Stack is restarted
165+
And Lightspeed Stack is restarted
166+
When I use "query" to ask question
167+
"""
168+
{"query": "Say hello", "model": "mock-tls-model", "provider": "tls-openai"}
169+
"""
170+
Then The status code of the response is 500
171+
And The body of the response does not contain Hello from the TLS mock inference server
172+
140173
Scenario: Inference fails with TLS minimum version TLSv1.3 and expired CA certificate
141174
Given Llama Stack is configured with TLS minimum version "TLSv1.3" and CA certificate path "/certs/expired-ca.crt"
142175
And Llama Stack is restarted

tests/e2e/mock_tls_inference_server/server.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,10 +253,17 @@ def main() -> None:
253253
_export_expired_client_cert(ca, client_cert, certs_dir / "expired-client.crt")
254254
print(f" Expired client cert: {certs_dir / 'expired-client.crt'}")
255255

256+
# Issue a server cert with a hostname that does NOT match the Docker service
257+
# name ("mock-tls-inference") — used to test hostname-mismatch rejection.
258+
hostname_mismatch_cert = ca.issue_cert("wrong-hostname.example.com")
259+
print(" Hostname-mismatch server cert: wrong-hostname.example.com (port 8445)")
260+
256261
print("=" * 60)
257262
print("Starting servers...")
258263
print("=" * 60)
259264

265+
hostname_mismatch_port = int(sys.argv[3]) if len(sys.argv) > 3 else 8445
266+
260267
# Create TLS server (no client cert required)
261268
tls_server = ThreadingHTTPServer(("", tls_port), OpenAIHandler)
262269
tls_ctx = _make_tls_context(ca, server_cert, require_client_cert=False)
@@ -267,17 +274,33 @@ def main() -> None:
267274
mtls_ctx = _make_tls_context(ca, server_cert, require_client_cert=True)
268275
mtls_server.socket = mtls_ctx.wrap_socket(mtls_server.socket, server_side=True)
269276

277+
# Create hostname-mismatch TLS server (cert SAN ≠ connecting hostname)
278+
mismatch_server = ThreadingHTTPServer(
279+
("", hostname_mismatch_port), OpenAIHandler
280+
)
281+
mismatch_ctx = _make_tls_context(
282+
ca, hostname_mismatch_cert, require_client_cert=False
283+
)
284+
mismatch_server.socket = mismatch_ctx.wrap_socket(
285+
mismatch_server.socket, server_side=True
286+
)
287+
270288
print("=" * 60)
271289
print("Mock TLS Inference Server")
272290
print("=" * 60)
273-
print(f" TLS : https://localhost:{tls_port} (no client cert)")
274-
print(f" mTLS : https://localhost:{mtls_port} (client cert required)")
291+
print(f" TLS : https://localhost:{tls_port} (no client cert)")
292+
print(f" mTLS : https://localhost:{mtls_port} (client cert required)")
293+
print(
294+
f" Mismatch : https://localhost:{hostname_mismatch_port}"
295+
" (hostname-mismatch cert)"
296+
)
275297
print(f" Model: {MODEL_ID}")
276298
print("=" * 60)
277299

278300
for srv, label in [
279301
(tls_server, f"TLS :{tls_port}"),
280302
(mtls_server, f"mTLS :{mtls_port}"),
303+
(mismatch_server, f"Mismatch :{hostname_mismatch_port}"),
281304
]:
282305
t = threading.Thread(target=_run_server, args=(srv, label), daemon=True)
283306
t.start()

0 commit comments

Comments
 (0)