Skip to content

Commit 733b842

Browse files
committed
TLS Support
1 parent 78af324 commit 733b842

File tree

11 files changed

+269
-26
lines changed

11 files changed

+269
-26
lines changed

charts/stackrox-mcp/README.md

Lines changed: 97 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,10 @@ The following table lists the configurable parameters of the StackRox MCP chart
126126
| Parameter | Description | Default |
127127
|-----------|-------------|---------|
128128
| `openshift.route.host` | Route hostname | `""` |
129-
| `openshift.route.tls.enabled` | Enable TLS for route | `true` |
130-
| `openshift.route.tls.termination` | TLS termination type | `edge` |
129+
| `openshift.route.TLSEnabled` | Enable TLS for route | `true` |
130+
| `openshift.route.tls.termination` | TLS termination type (auto: reencrypt if TLS enabled) | `reencrypt` |
131131
| `openshift.route.tls.insecureEdgeTerminationPolicy` | Policy for insecure edge traffic | `Redirect` |
132+
| `openshift.route.tls.destinationCACertificate` | CA certificate for pod verification | `""` |
132133

133134
### Scheduling
134135

@@ -170,7 +171,10 @@ The following table lists the configurable parameters of the StackRox MCP chart
170171
| Parameter | Description | Default |
171172
|-----------|-------------|---------|
172173
| `config.server.address` | Server listen address | `0.0.0.0` |
173-
| `config.server.port` | Server listen port | `8080` |
174+
| `config.server.port` | Server listen port | `8443` |
175+
| `config.server.TLSEnabled` | Enable TLS/HTTPS on server | `true` |
176+
| `config.server.TLSCertPath` | Certificate path in container | `/certs/tls.crt` |
177+
| `config.server.TLSKeyPath` | Private key path in container | `/certs/tls.key` |
174178

175179
#### Tools Configuration
176180

@@ -223,6 +227,91 @@ The chart maintains security hardening on OpenShift:
223227

224228
The chart is compatible with the `restricted-v2` SCC on OpenShift.
225229

230+
### End-to-End TLS/HTTPS Configuration
231+
232+
The chart supports end-to-end TLS encryption from client to pod, providing secure communication throughout the entire connection path.
233+
234+
#### Architecture
235+
236+
When TLS is enabled (`config.server.TLSEnabled: true`):
237+
```
238+
Client (HTTPS)
239+
→ LoadBalancer/Route (TLS passthrough/re-encryption)
240+
→ Service (HTTPS port 8443)
241+
→ Pod (HTTPS on port 8443)
242+
```
243+
244+
When TLS is disabled:
245+
```
246+
Client (HTTPS)
247+
→ LoadBalancer/Route (TLS edge termination)
248+
→ Service (HTTP port 8080)
249+
→ Pod (HTTP on port 8080)
250+
```
251+
252+
#### TLS Secret Configuration
253+
254+
The chart provides two ways to configure TLS certificates:
255+
256+
##### Option 1: Generate Secret from Certificate Data (Recommended)
257+
258+
Provide certificate data in values.yaml and the chart will create the secret automatically:
259+
260+
```yaml
261+
tlsSecret:
262+
caCert: |
263+
-----BEGIN CERTIFICATE-----
264+
MIIDXTCCAkWgAwIBAgIJAK...
265+
-----END CERTIFICATE-----
266+
caKey: |
267+
-----BEGIN PRIVATE KEY-----
268+
MIIEvQIBADANBgkqhkiG9w0...
269+
-----END PRIVATE KEY-----
270+
```
271+
272+
Installation:
273+
```bash
274+
helm install stackrox-mcp charts/stackrox-mcp \
275+
--namespace stackrox-mcp \
276+
--create-namespace \
277+
--set-file tlsSecret.caCert=/path/to/tls.crt \
278+
--set-file tlsSecret.caKey=/path/to/tls.key \
279+
--set-file openshift.route.tls.destinationCACertificate=/path/to/tls.crt
280+
```
281+
282+
The chart creates a secret named `<release-name>-stackrox-mcp-tls` automatically.
283+
284+
##### Option 2: Use Existing Secret
285+
286+
Reference an existing Kubernetes TLS secret:
287+
288+
```yaml
289+
tlsSecret:
290+
existingSecretName: "my-existing-tls-secret"
291+
```
292+
293+
Prerequisites:
294+
```bash
295+
kubectl create secret tls my-existing-tls-secret \
296+
--cert=/path/to/tls.crt \
297+
--key=/path/to/tls.key \
298+
--namespace stackrox-mcp
299+
```
300+
301+
**Important Notes:**
302+
- When `tlsSecret.existingSecretName` is set, `tlsSecret.caCert` and `tlsSecret.caKey` are ignored
303+
- Both `caCert` and `caKey` must be provided together
304+
- Use `--set-file` to load certificates from files (recommended over embedding in values)
305+
- Never commit certificate data to version control
306+
307+
##### Generating Self-Signed Certificates
308+
309+
For testing purposes, you can create a self-signed certificate:
310+
311+
```bash
312+
openssl req -x509 -newkey rsa:2048 -days 365 -keyout tls.key -out tls.crt -nodes
313+
```
314+
226315
### High Availability Setup
227316

228317
For high availability with multiple replicas:
@@ -298,8 +387,13 @@ Common issues:
298387
Test the health endpoint:
299388

300389
```bash
390+
# For HTTP (TLS disabled)
301391
kubectl run -i --tty --rm debug --image=curlimages/curl --restart=Never -- \
302392
curl http://stackrox-mcp.stackrox-mcp:8080/health
393+
394+
# For HTTPS (TLS enabled)
395+
kubectl run -i --tty --rm debug --image=curlimages/curl --restart=Never -- \
396+
curl -k https://stackrox-mcp.stackrox-mcp.svc.cluster.local:8443/health
303397
```
304398

305399
Expected response: `{"status":"ok"}`

charts/stackrox-mcp/templates/NOTES.txt

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,25 @@ StackRox MCP Server Configuration:
2424

2525
To test connectivity:
2626
$ kubectl run -i --tty --rm debug --image=curlimages/curl --restart=Never -- \
27-
curl http://{{ include "stackrox-mcp.fullname" . }}.{{ .Release.Namespace }}:{{ .Values.service.port }}/health
27+
curl -h {{ include "stackrox-mcp.portName" . }}://{{ include "stackrox-mcp.fullname" . }}.{{ .Release.Namespace }}:{{ .Values.service.port }}/health
28+
29+
{{- if and (eq (include "stackrox-mcp.isOpenshift" .) "true") .Values.config.server.TLSEnabled (ne .Values.openshift.route.tls.termination "reencrypt") }}
30+
WARN: OpenShift route TLS termination should be set to "reencrypt" if TLS encryption is enabled. You should set ".openshift.route.tls.termination" to "reencrypt".
31+
{{- end }}
32+
33+
{{- if .Values.config.server.TLSEnabled }}
34+
35+
TLS Configuration:
36+
Secret Name: {{ include "stackrox-mcp.tlsSecretName" . }}
37+
{{- if .Values.tlsSecret.existingSecretName }}
38+
Status: Using existing secret "{{ .Values.tlsSecret.existingSecretName }}"
39+
{{- else if and .Values.tlsSecret.caCert .Values.tlsSecret.caKey }}
40+
Status: Generated secret with provided certificates
41+
{{- else }}
42+
43+
WARNING: TLS is enabled but no certificate configuration found!
44+
Please provide either:
45+
- tlsSecret.existingSecretName (to use existing secret)
46+
- tlsSecret.caCert and tlsSecret.caKey (to generate secret)
47+
{{- end }}
48+
{{- end }}

charts/stackrox-mcp/templates/_helpers.tpl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,21 @@ Detect if running on OpenShift
6262
{{- define "stackrox-mcp.isOpenshift" -}}
6363
{{- .Capabilities.APIVersions.Has "route.openshift.io/v1" -}}
6464
{{- end }}
65+
66+
{{/*
67+
Define application port name
68+
*/}}
69+
{{- define "stackrox-mcp.portName" -}}
70+
{{ if .Values.config.server.TLSEnabled }}https{{ else }}http{{ end }}
71+
{{- end }}
72+
73+
{{/*
74+
TLS Secret name - returns existingSecretName if set, otherwise generates name
75+
*/}}
76+
{{- define "stackrox-mcp.tlsSecretName" -}}
77+
{{- if .Values.tlsSecret.existingSecretName }}
78+
{{- .Values.tlsSecret.existingSecretName }}
79+
{{- else }}
80+
{{- include "stackrox-mcp.fullname" . }}-tls
81+
{{- end }}
82+
{{- end }}

charts/stackrox-mcp/templates/configmap.yaml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,18 @@ data:
2222
global:
2323
read_only_tools: {{ .Values.config.global.readOnlyTools }}
2424
25-
# HTTP server configuration
25+
# HTTP/HTTPS server configuration
2626
server:
2727
type: "streamable-http"
2828
address: {{ .Values.config.server.address | quote }}
2929
port: {{ .Values.config.server.port }}
30+
{{- if .Values.config.server.TLSEnabled }}
31+
tls_enabled: true
32+
tls_cert_path: {{ .Values.config.server.TLSCertPath | quote }}
33+
tls_key_path: {{ .Values.config.server.TLSKeyPath | quote }}
34+
{{- else }}
35+
tls_enabled: false
36+
{{- end }}
3037
3138
# MCP tools configuration
3239
{{- if not (or .Values.config.tools.vulnerability.enabled .Values.config.tools.configManager.enabled) }}

charts/stackrox-mcp/templates/deployment.yaml

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ spec:
6565
- --config
6666
- /config/config.yaml
6767
ports:
68-
- name: http
68+
- name: {{ include "stackrox-mcp.portName" . }}
6969
containerPort: {{ .Values.config.server.port }}
7070
protocol: TCP
7171
{{- with .Values.extraEnv }}
@@ -74,22 +74,53 @@ spec:
7474
{{- end }}
7575
{{- if .Values.livenessProbe.enabled }}
7676
livenessProbe:
77-
{{- omit .Values.livenessProbe "enabled" | toYaml | nindent 10 }}
77+
httpGet:
78+
path: /health
79+
port: {{ include "stackrox-mcp.portName" . }}
80+
{{- if .Values.config.server.TLSEnabled }}
81+
scheme: HTTPS
82+
{{- end }}
83+
initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }}
84+
periodSeconds: {{ .Values.livenessProbe.periodSeconds }}
85+
timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }}
86+
successThreshold: {{ .Values.livenessProbe.successThreshold }}
87+
failureThreshold: {{ .Values.livenessProbe.failureThreshold }}
7888
{{- end }}
7989
{{- if .Values.readinessProbe.enabled }}
8090
readinessProbe:
81-
{{- omit .Values.readinessProbe "enabled" | toYaml | nindent 10 }}
91+
httpGet:
92+
path: /health
93+
port: {{ include "stackrox-mcp.portName" . }}
94+
{{- if .Values.config.server.TLSEnabled }}
95+
scheme: HTTPS
96+
{{- end }}
97+
initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }}
98+
periodSeconds: {{ .Values.readinessProbe.periodSeconds }}
99+
timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }}
100+
successThreshold: {{ .Values.readinessProbe.successThreshold }}
101+
failureThreshold: {{ .Values.readinessProbe.failureThreshold }}
82102
{{- end }}
83103
resources:
84104
{{- toYaml .Values.resources | nindent 10 }}
85105
volumeMounts:
86106
- name: config
87107
mountPath: /config
88108
readOnly: true
109+
{{- if .Values.config.server.TLSEnabled }}
110+
- name: tls-certs
111+
mountPath: /certs
112+
readOnly: true
113+
{{- end }}
89114
volumes:
90115
- name: config
91116
configMap:
92117
name: {{ include "stackrox-mcp.configMapName" . }}
118+
{{- if .Values.config.server.TLSEnabled }}
119+
- name: tls-certs
120+
secret:
121+
secretName: {{ include "stackrox-mcp.tlsSecretName" . }}
122+
defaultMode: 0440
123+
{{- end }}
93124
{{- with .Values.nodeSelector }}
94125
nodeSelector:
95126
{{- toYaml . | nindent 8 }}

charts/stackrox-mcp/templates/route.yaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,13 @@ spec:
2020
kind: Service
2121
name: {{ include "stackrox-mcp.fullname" . }}
2222
port:
23-
targetPort: http
23+
targetPort: {{ include "stackrox-mcp.portName" . }}
2424
{{- if .Values.openshift.route.tls.enabled }}
2525
tls:
2626
termination: {{ .Values.openshift.route.tls.termination }}
2727
insecureEdgeTerminationPolicy: {{ .Values.openshift.route.tls.insecureEdgeTerminationPolicy }}
28+
{{- if and .Values.config.server.TLSEnabled .Values.openshift.route.tls.destinationCACertificate }}
29+
destinationCACertificate: {{ .Values.openshift.route.tls.destinationCACertificate | quote }}
30+
{{- end }}
2831
{{- end }}
2932
{{- end }}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{{- if and .Values.config.server.TLSEnabled (not .Values.tlsSecret.existingSecretName) }}
2+
{{- if not (and .Values.tlsSecret.caCert .Values.tlsSecret.caKey) }}
3+
{{- fail "Both tlsSecret.caCert and tlsSecret.caKey must be provided together" }}
4+
{{- end }}
5+
apiVersion: v1
6+
kind: Secret
7+
metadata:
8+
name: {{ include "stackrox-mcp.tlsSecretName" . }}
9+
namespace: {{ .Release.Namespace }}
10+
labels:
11+
{{- include "stackrox-mcp.labels" . | nindent 4 }}
12+
type: kubernetes.io/tls
13+
data:
14+
tls.crt: {{ .Values.tlsSecret.caCert | b64enc }}
15+
tls.key: {{ .Values.tlsSecret.caKey | b64enc }}
16+
{{- end }}

charts/stackrox-mcp/templates/service.yaml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,13 @@ metadata:
1111
{{- end }}
1212
spec:
1313
type: {{ .Values.service.type }}
14+
{{- if eq .Values.service.type "LoadBalancer" }}
15+
sessionAffinity: ClientIP
16+
{{- end }}
1417
ports:
1518
- port: {{ .Values.service.port }}
16-
targetPort: {{ .Values.service.targetPort }}
19+
targetPort: {{ include "stackrox-mcp.portName" . }}
1720
protocol: TCP
18-
name: http
21+
name: {{ include "stackrox-mcp.portName" . }}
1922
selector:
2023
{{- include "stackrox-mcp.selectorLabels" . | nindent 4 }}

charts/stackrox-mcp/values.yaml

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,19 @@ securityContext:
5656

5757
# Service configuration
5858
service:
59-
type: ClusterIP
59+
type: LoadBalancer
6060
port: 8080
61-
targetPort: 8080
6261
annotations: {}
6362

63+
# TLS Secret configuration
64+
tlsSecret:
65+
# Existing secret name can be provided if already existing secret with certificate and key is used
66+
existingSecretName: ""
67+
# CA Certificate
68+
caCert: ""
69+
# CA Key
70+
caKey: ""
71+
6472
# Resource limits and requests
6573
resources:
6674
limits:
@@ -73,9 +81,6 @@ resources:
7381
# Liveness probe configuration
7482
livenessProbe:
7583
enabled: true
76-
httpGet:
77-
path: /health
78-
port: http
7984
initialDelaySeconds: 10
8085
periodSeconds: 10
8186
timeoutSeconds: 5
@@ -85,9 +90,6 @@ livenessProbe:
8590
# Readiness probe configuration
8691
readinessProbe:
8792
enabled: true
88-
httpGet:
89-
path: /health
90-
port: http
9193
initialDelaySeconds: 5
9294
periodSeconds: 5
9395
timeoutSeconds: 3
@@ -113,9 +115,16 @@ openshift:
113115
host: ""
114116
tls:
115117
enabled: true
116-
termination: edge
118+
119+
# Termination type: 'reencrypt' for end-to-end TLS, 'edge' for TLS termination at router
120+
termination: reencrypt
117121
insecureEdgeTerminationPolicy: Redirect
118122

123+
# Destination CA certificate (optional)
124+
# This is the CA that signed the pod's certificate
125+
# If not provided, router will use its own CA bundle to verify pod certificate
126+
destinationCACertificate: ""
127+
119128
# StackRox MCP Configuration
120129
config:
121130
# Central connection configuration
@@ -148,13 +157,21 @@ config:
148157
# Allow only read-only MCP tools (default: true)
149158
readOnlyTools: true
150159

151-
# HTTP server configuration
160+
# HTTP/HTTPS server configuration
152161
server:
153162
# Server listen address (default: 0.0.0.0)
154163
address: "0.0.0.0"
155164

156-
# Server listen port (1-65535, default: 8080)
157-
port: 8080
165+
# Server listen port (1-65535, default: 8443 for HTTPS, 8080 for HTTP)
166+
port: 8443
167+
168+
# Enable TLS/HTTPS on the application server (default: true)
169+
# When enabled, provides end-to-end encryption from client to pod
170+
TLSEnabled: true
171+
172+
# Mount paths for certificates inside the container
173+
TLSCertPath: "/certs/tls.crt"
174+
TLSKeyPath: "/certs/tls.key"
158175

159176
# MCP tools configuration
160177
# At least one tool must be enabled

0 commit comments

Comments
 (0)