Skip to content

Commit 4a9a186

Browse files
committed
addressed comments
1 parent 65f7bc0 commit 4a9a186

File tree

5 files changed

+113
-80
lines changed

5 files changed

+113
-80
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: Lightspeed Core Service (LCS)
2+
service:
3+
host: 0.0.0.0
4+
port: 8080
5+
auth_enabled: false
6+
workers: 1
7+
color_log: true
8+
access_log: true
9+
llama_stack:
10+
use_as_library_client: false
11+
url: http://${env.E2E_LLAMA_HOSTNAME}:8321
12+
api_key: xyzzy
13+
user_data_collection:
14+
feedback_enabled: true
15+
feedback_storage: "/tmp/data/feedback"
16+
transcripts_enabled: true
17+
transcripts_storage: "/tmp/data/transcripts"
18+
authentication:
19+
module: "noop"
20+
inference:
21+
default_provider: tls-openai
22+
default_model: mock-tls-model

tests/e2e/features/environment.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -552,14 +552,14 @@ def after_feature(context: Context, feature: Feature) -> None:
552552
restart_container("lightspeed-stack")
553553
remove_config_backup(context.default_config_backup)
554554

555-
# Restore Lightspeed Stack config if TLS Background step switched it
556-
if getattr(context, "tls_config_active", False):
557-
switch_config(context.default_config_backup)
558-
remove_config_backup(context.default_config_backup)
555+
# Restore Lightspeed Stack config if the generic configure_service step switched it
556+
backup_path = "lightspeed-stack.yaml.backup"
557+
if os.path.exists(backup_path):
558+
switch_config(backup_path)
559+
remove_config_backup(backup_path)
559560
if not context.is_library_mode:
560561
restart_container("llama-stack")
561562
restart_container("lightspeed-stack")
562-
context.tls_config_active = False
563563

564564
# Clean up any proxy servers left from the last scenario
565565
if hasattr(context, "tunnel_proxy") or hasattr(context, "interception_proxy"):

tests/e2e/features/steps/tls.py

Lines changed: 52 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -12,43 +12,17 @@
1212
import os
1313
import shutil
1414

15-
import yaml
1615
from behave import given # pyright: ignore[reportAttributeAccessIssue]
1716
from behave.runner import Context
1817

19-
from tests.e2e.utils.utils import (
20-
create_config_backup,
21-
restart_container,
22-
switch_config,
18+
from tests.e2e.features.steps.proxy import (
19+
_LLAMA_STACK_CONFIG,
20+
_load_llama_config,
21+
_write_config,
2322
)
2423

25-
# Llama Stack config — mounted into the container from the host
26-
_LLAMA_STACK_CONFIG = "run.yaml"
2724
_LLAMA_STACK_CONFIG_BACKUP = "run.yaml.tls-backup"
2825

29-
_LIGHTSPEED_STACK_CONFIG = "lightspeed-stack.yaml"
30-
31-
32-
def _load_llama_config() -> dict:
33-
"""Load the base Llama Stack run config.
34-
35-
Returns:
36-
The parsed YAML configuration as a dictionary.
37-
"""
38-
with open(_LLAMA_STACK_CONFIG, encoding="utf-8") as f:
39-
return yaml.safe_load(f)
40-
41-
42-
def _write_config(config: dict, path: str) -> None:
43-
"""Write a YAML config file.
44-
45-
Parameters:
46-
config: The configuration dictionary to write.
47-
path: The file path to write to.
48-
"""
49-
with open(path, "w", encoding="utf-8") as f:
50-
yaml.dump(config, f, default_flow_style=False)
51-
5226

5327
_TLS_PROVIDER_BASE: dict = {
5428
"provider_id": "tls-openai",
@@ -124,28 +98,6 @@ def _prepare_tls_provider() -> tuple[dict, dict]:
12498
# proxy.py and shared across features by behave.
12599

126100

127-
@given("Lightspeed Stack is configured for TLS testing")
128-
def configure_lightspeed_for_tls(context: Context) -> None:
129-
"""Switch lightspeed-stack.yaml to the TLS test configuration.
130-
131-
Backs up the current config and switches to the TLS variant that sets
132-
default_provider to tls-openai and default_model to mock-tls-model.
133-
The backup is restored in after_scenario via the shared restore step.
134-
135-
Parameters:
136-
context: Behave test context.
137-
"""
138-
mode_dir = "library-mode" if context.is_library_mode else "server-mode"
139-
tls_config = f"tests/e2e/configuration/{mode_dir}/lightspeed-stack-tls.yaml"
140-
141-
if not hasattr(context, "default_config_backup"):
142-
context.default_config_backup = create_config_backup(_LIGHTSPEED_STACK_CONFIG)
143-
144-
switch_config(tls_config)
145-
restart_container("lightspeed-stack")
146-
context.tls_config_active = True
147-
148-
149101
# --- TLS Configuration Steps ---
150102

151103

@@ -210,6 +162,54 @@ def configure_tls_mtls(context: Context) -> None:
210162
_write_config(config, _LLAMA_STACK_CONFIG)
211163

212164

165+
@given('Llama Stack is configured with CA certificate path "{path}"')
166+
def configure_tls_verify_ca_path(context: Context, path: str) -> None:
167+
"""Configure run.yaml with TLS verify pointing to a specific CA cert path.
168+
169+
Parameters:
170+
context: Behave test context.
171+
path: Path to the CA certificate file.
172+
"""
173+
config, provider = _prepare_tls_provider()
174+
provider["config"]["network"]["tls"] = {"verify": path}
175+
_write_config(config, _LLAMA_STACK_CONFIG)
176+
177+
178+
@given("Llama Stack is configured for mTLS without client certificate")
179+
def configure_mtls_no_client_cert(context: Context) -> None:
180+
"""Configure run.yaml for mTLS port but without providing client certificate.
181+
182+
This should fail because the mTLS server requires a client certificate.
183+
184+
Parameters:
185+
context: Behave test context.
186+
"""
187+
config, provider = _prepare_tls_provider()
188+
provider["config"]["base_url"] = "https://mock-tls-inference:8444/v1"
189+
provider["config"]["network"]["tls"] = {"verify": "/certs/ca.crt"}
190+
_write_config(config, _LLAMA_STACK_CONFIG)
191+
192+
193+
@given("Llama Stack is configured for mTLS with wrong client certificate")
194+
def configure_mtls_wrong_client_cert(context: Context) -> None:
195+
"""Configure run.yaml for mTLS with a certificate not issued by the server's CA.
196+
197+
Uses the CA cert itself as the client cert, which is not a valid client
198+
identity certificate, causing the mTLS handshake to fail.
199+
200+
Parameters:
201+
context: Behave test context.
202+
"""
203+
config, provider = _prepare_tls_provider()
204+
provider["config"]["base_url"] = "https://mock-tls-inference:8444/v1"
205+
provider["config"]["network"]["tls"] = {
206+
"verify": "/certs/ca.crt",
207+
"client_cert": "/certs/ca.crt",
208+
"client_key": "/certs/client.key",
209+
}
210+
_write_config(config, _LLAMA_STACK_CONFIG)
211+
212+
213213
@given('Llama Stack is configured with TLS minimum version "{version}"')
214214
def configure_tls_min_version(context: Context, version: str) -> None:
215215
"""Configure run.yaml with TLS minimum version.

tests/e2e/features/tls.feature

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Feature: TLS configuration for remote inference providers
66
Background:
77
Given The service is started locally
88
And REST API service prefix is /v1
9-
And Lightspeed Stack is configured for TLS testing
9+
And The service uses the lightspeed-stack-tls.yaml configuration
1010
And The original Llama Stack config is restored if modified
1111

1212
Scenario: Inference succeeds with TLS verification disabled
@@ -50,6 +50,39 @@ Feature: TLS configuration for remote inference providers
5050
"""
5151
Then The status code of the response is 200
5252

53+
Scenario: Inference fails with invalid CA certificate path
54+
Given Llama Stack is configured with CA certificate path "/certs/nonexistent.crt"
55+
And Llama Stack is restarted
56+
And Lightspeed Stack is restarted
57+
When I use "query" to ask question
58+
"""
59+
{"query": "Say hello", "model": "mock-tls-model", "provider": "tls-openai"}
60+
"""
61+
Then The status code of the response is 500
62+
And The body of the response does not contain Hello from the TLS mock inference server
63+
64+
Scenario: Inference fails when mTLS is required but no client certificate is provided
65+
Given Llama Stack is configured for mTLS without client certificate
66+
And Llama Stack is restarted
67+
And Lightspeed Stack is restarted
68+
When I use "query" to ask question
69+
"""
70+
{"query": "Say hello", "model": "mock-tls-model", "provider": "tls-openai"}
71+
"""
72+
Then The status code of the response is 500
73+
And The body of the response does not contain Hello from the TLS mock inference server
74+
75+
Scenario: Inference fails when mTLS is required but wrong client certificate is provided
76+
Given Llama Stack is configured for mTLS with wrong client certificate
77+
And Llama Stack is restarted
78+
And Lightspeed Stack is restarted
79+
When I use "query" to ask question
80+
"""
81+
{"query": "Say hello", "model": "mock-tls-model", "provider": "tls-openai"}
82+
"""
83+
Then The status code of the response is 500
84+
And The body of the response does not contain Hello from the TLS mock inference server
85+
5386
Scenario: Inference succeeds with TLS minimum version TLSv1.3
5487
Given Llama Stack is configured with TLS minimum version "TLSv1.3"
5588
And Llama Stack is restarted

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)