feat: mount a custom CA certificate into MCP containers and the Obot pod - #7109
Open
jbittner-dimensional wants to merge 2 commits into
Open
feat: mount a custom CA certificate into MCP containers and the Obot pod#7109jbittner-dimensional wants to merge 2 commits into
jbittner-dimensional wants to merge 2 commits into
Conversation
Enterprise/airgapped deployments often front internal services with a private CA that isn't in the default trust store. Add support for mounting a custom PEM CA bundle so Go, Python, and Node.js runtimes in MCP containers (and the Obot pod) trust it. - Docker backend: OBOT_SERVER_MCPCACERT_FILE bind-mounts a PEM file into every MCP container and sets SSL_CERT_FILE / REQUESTS_CA_BUNDLE / NODE_EXTRA_CA_CERTS. - Kubernetes backend: OBOT_SERVER_MCPCACERT_SECRET_NAME / _SECRET_KEY mount a Secret on every MCP container with the same env vars. - Helm: new top-level `mcpCACertificate` section (content / existingSecret / secretKey) that creates the Secret in the release and MCP namespaces and mounts the bundle on the Obot pod. Config keys live in the internal ConfigMap.
Contributor
There was a problem hiding this comment.
Pull request overview
Adds first-class support for supplying a custom PEM CA bundle so MCP workloads (Docker containers or Kubernetes pods) and the Obot pod can trust internal/private TLS CAs in enterprise/airgapped deployments.
Changes:
- Adds new server options/env config for custom CA injection: file bind-mount for Docker runtime, Secret mount for Kubernetes runtime.
- Implements CA bundle mounting + runtime env vars (
SSL_CERT_FILE,REQUESTS_CA_BUNDLE,NODE_EXTRA_CA_CERTS) for MCP deployments (Docker + Kubernetes backends). - Extends the Helm chart with an
mcpCACertificatesection, Secret creation (when inline content is provided), and pod mounts/env wiring.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| pkg/mcp/loader.go | Adds new CLI/env options for CA bundle configuration (file for Docker, Secret name/key for Kubernetes). |
| pkg/mcp/kubernetes.go | Adds Secret-backed CA bundle volume/env injection into generated MCP Deployments. |
| pkg/mcp/docker.go | Adds optional CA bundle bind-mount + env vars for Docker-backed MCP containers, plus startup validation. |
| chart/values.yaml | Documents new mcpCACertificate values and Docker-side CA file setting. |
| chart/templates/mcp-ca-certificate.yaml | Creates the CA bundle Secret(s) when inline PEM content is provided. |
| chart/templates/internal-configmap.yaml | Emits CA Secret name/key into internal config when MCP runtime backend is Kubernetes. |
| chart/templates/deployment.yaml | Mounts CA Secret into Obot pod and sets runtime trust env vars. |
| chart/templates/_helpers.tpl | Adds helper to compute the effective CA Secret name. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+96
to
+100
| {{- if include "obot.mcpCACertificate.secretName" . }} | ||
| - name: mcp-ca-bundle | ||
| mountPath: /etc/ssl/certs/obot-ca-bundle | ||
| readOnly: true | ||
| {{- end }} |
Comment on lines
+172
to
+176
| {{- if include "obot.mcpCACertificate.secretName" . }} | ||
| - name: mcp-ca-bundle | ||
| secret: | ||
| secretName: {{ include "obot.mcpCACertificate.secretName" . }} | ||
| {{- end }} |
Comment on lines
+399
to
+401
| # mcpCACertificate -- Mount a custom PEM CA bundle into the Obot pod and every MCP server pod so they trust TLS certificates issued by an internal CA (airgapped / enterprise deployments). | ||
| # Only used when config.OBOT_SERVER_MCPRUNTIME_BACKEND is "kubernetes". For the Docker backend, use config.OBOT_SERVER_MCPCACERT_FILE. | ||
| # The bundle replaces the default trust store for Go (SSL_CERT_FILE) and Python (REQUESTS_CA_BUNDLE); if public-internet TLS must also work, concatenate your CA with the system bundle before supplying it. |
Comment on lines
+957
to
+960
| Secret: &corev1.SecretVolumeSource{ | ||
| SecretName: k.caCertSecretName, | ||
| }, | ||
| }, |
Comment on lines
+102
to
+106
| if d.caCertFile != "" { | ||
| if _, err := os.Stat(d.caCertFile); err != nil { | ||
| return nil, fmt.Errorf("MCP CA cert file %q not accessible: %w", d.caCertFile, err) | ||
| } | ||
| } |
- deployment.yaml: emit the CA volume + volumeMount whenever mcpCACertificate is set (previously nested under an unrelated persistence/encryption if, so enabling only mcpCACertificate set the trust-store env vars without mounting the Secret). - kubernetes.go: project only the configured secretKey via Items so a wrong key fails fast at mount time instead of pointing SSL_CERT_FILE at a missing path. - docker.go: validate the CA file is a readable regular file at startup. - values.yaml: clarify the Obot pod always mounts the bundle; MCP pods only on the kubernetes backend.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
Enterprise and airgapped deployments frequently front internal services with a private CA that isn't in the default system trust store. MCP containers (and the Obot pod itself) then fail TLS verification when talking to those services. This adds first-class support for mounting a custom PEM CA bundle so Go, Python, and Node.js runtimes all trust it.
What's added
Docker backend
OBOT_SERVER_MCPCACERT_FILE: bind-mounts a PEM file (read-only) into every MCP container and setsSSL_CERT_FILE,REQUESTS_CA_BUNDLE,NODE_EXTRA_CA_CERTS. Validated at startup.Kubernetes backend
OBOT_SERVER_MCPCACERT_SECRET_NAME/OBOT_SERVER_MCPCACERT_SECRET_KEY: mounts the named Secret on every MCP container with the same three env vars. No-op when unset.Helm chart
mcpCACertificatesection (content/existingSecret/secretKey) that creates the Secret in the release and MCP namespaces and mounts the bundle on the Obot pod. Config keys are emitted into the internal ConfigMap.Notes
The bundle replaces the default trust store for Go (
SSL_CERT_FILE) and Python (REQUESTS_CA_BUNDLE); if public-internet TLS must also work, concatenate the custom CA with the system bundle before supplying it (documented invalues.yaml).Testing
go build ./pkg/mcp/...passes.🤖 Generated with Claude Code