Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .ai/spec/what/security.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ The operator enforces security boundaries through RBAC, network policies, pod se
15. MCP server header secrets must contain a specific key `header` (constant `MCPSECRETDATAPATH`) and are mounted read-only at `/etc/mcp/headers/<secretName>/`.

### OpenShift MCP Server Security
16. The shipped OpenShift MCP server runs with the `--read-only` flag and is configured via a TOML config file that blocks access to Secret and RBAC resources, preventing secret data from reaching the LLM.
16. The shipped OpenShift MCP server is configured via a TOML config file (`read_only = false`, denied Secret/RBAC resources) so the LLM can use core write tools (e.g. `resources_create_or_update`) while secret data stays blocked at the server level. The sidecar does not pass `--read-only` on the command line; `read_only = false` in TOML overrides the RHEL image build default of `ReadOnly: true`.
17. The denied resources are configured in the `openshift-mcp-server-config` ConfigMap as a TOML config with entries blocking `core/v1/secrets`, `rbac.authorization.k8s.io/v1/roles`, `rbac.authorization.k8s.io/v1/rolebindings`, `rbac.authorization.k8s.io/v1/clusterroles`, and `rbac.authorization.k8s.io/v1/clusterrolebindings`.
18. User-defined MCP servers (via `spec.mcpServers`) are the user's responsibility to secure.

Expand Down
3 changes: 3 additions & 0 deletions internal/controller/utils/mcp_server_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,14 @@ import (
// Other sensitive resource types (RBAC) are also denied as defense in depth.
// Toolsets are listed explicitly so upstream default changes do not affect OLS; the metrics toolset
// uses in-cluster Thanos Querier and Alertmanager endpoints.
// read_only = false is required: openshift-mcp-server-rhel9 sets ReadOnly=true in build-time defaults;
// omitting this leaves only readOnlyHint tools (no resources_create_or_update, etc.).
const OpenShiftMCPServerConfigTOML = `# Denied resources prevent the MCP server from accessing these Kubernetes resource types.
# This ensures secret data never reaches the LLM through the shipped MCP server.
# User-brought MCP servers (spec.mcpServers) are the user's responsibility to secure.
# Toolsets are pinned explicitly so upstream default changes do not affect OLS.

read_only = false
toolsets = ["core", "config", "helm", "metrics"]

[[denied_resources]]
Expand Down
3 changes: 3 additions & 0 deletions internal/controller/utils/mcp_server_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ func TestOpenShiftMCPServerConfigTOML(t *testing.T) {
t.Error("TOML config should use denied_resources table array syntax")
}

if !strings.Contains(config, "read_only = false") {
t.Error("TOML config must set read_only = false to override openshift-mcp-server-rhel9 build defaults")
}
if !strings.Contains(config, `toolsets = ["core", "config", "helm", "metrics"]`) {
t.Error("TOML config should pin default toolsets explicitly")
}
Expand Down