mirror of
https://github.com/kerberos-io/helm-charts.git
synced 2026-11-08 20:50:22 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d4a8479a9b |
@@ -16,7 +16,7 @@ type: application
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 0.176.0
|
||||
version: 0.177.0
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
|
||||
@@ -335,6 +335,34 @@ ownership on existing optional `LOCAL_CACHE_DIRECTORY` mounts. Its liveness
|
||||
endpoint is `GET /api/health`. Wire those settings in the actual Vault deployment
|
||||
only when a compatible image release is selected; no migration is required.
|
||||
|
||||
### MCP
|
||||
|
||||
Deploy a Hub API image supporting MCP, then enable the read-only Streamable HTTP
|
||||
endpoint at `/mcp`:
|
||||
|
||||
```yaml
|
||||
kerberoshub:
|
||||
api:
|
||||
mcp:
|
||||
enabled: true
|
||||
allowedOrigins: []
|
||||
```
|
||||
|
||||
After upgrading the Helm release, an unauthenticated request to `/mcp` should
|
||||
return `401` instead of `404`. Connect using HTTPS and an existing Hub access
|
||||
token in `Authorization: Bearer <token>`; browser-session JWTs and cookies cannot
|
||||
authenticate MCP. Recording tools require `media.read`, device tools require
|
||||
`devices.read`, and both require effective resource grants.
|
||||
|
||||
VS Code and other clients without an `Origin` header need no `allowedOrigins`.
|
||||
For browser MCP clients, list exact origins such as `https://agent.example.com`.
|
||||
Wildcards and trailing slashes are not supported. These origins are independent
|
||||
of REST CORS; frontend and REST origins are not automatically copied into MCP.
|
||||
MCP stays disabled by default, and these settings apply only to Hub API pods
|
||||
in `all` and `ui` modes. The chart does not change the API image tag.
|
||||
|
||||
Validate rendering with `bash scripts/check-hub-mcp.sh` from the repository root.
|
||||
|
||||
### Passkeys
|
||||
|
||||
Users and sub-users can create and manage their own passkeys in **Profile >
|
||||
@@ -697,6 +725,8 @@ kerberospipeline:
|
||||
| `kerberoshub.api.schema` | The protocol to serve the Kerberos Hub API, `'http'` or `'https'`. | `"https"` |
|
||||
| `kerberoshub.api.url` | The Kerberos Hub API ingress to access the API. | `"api.yourdomain.com"` |
|
||||
| `kerberoshub.api.corsAllowedOrigins` | Additional complete HTTP(S) origins allowed to call the Hub API. Configured frontend origins remain allowed automatically. | `[]` |
|
||||
| `kerberoshub.api.mcp.enabled` | Expose the read-only `/mcp` endpoint; sets `MCP_ENABLED`. Requires a compatible Hub API image. | `false` |
|
||||
| `kerberoshub.api.mcp.allowedOrigins` | Exact HTTP(S) origins for browser MCP clients, joined into `MCP_ALLOWED_ORIGINS`. Independent of REST CORS; no wildcards or trailing slash. | `[]` |
|
||||
| `kerberoshub.api.disableAgentHeartbeat` | Temporarily stop serving the polled `GET /devices` list (hub-api returns `204` without database reads). Devices still load once through `/session/bootstrap`; online/offline status stops refreshing. | `false` |
|
||||
| `kerberoshub.api.mediaProxy.enabled` | Serve media through hub-api (`/media/proxy`) instead of handing out Vault/storage URLs, hiding the storage endpoint from clients. | `false` |
|
||||
| `kerberoshub.api.mediaProxy.publicUrl` | Public hub-api base URL used in proxied media URLs. Defaults to `{schema}://{url}`. | `""` |
|
||||
|
||||
@@ -323,6 +323,11 @@ spec:
|
||||
{{- end }}
|
||||
- name: CORS_ALLOWED_ORIGINS
|
||||
value: {{ join "," $corsOrigins | quote }}
|
||||
{{- $mcp := .Values.kerberoshub.api.mcp | default dict }}
|
||||
- name: MCP_ENABLED
|
||||
value: {{ $mcp.enabled | default false | quote }}
|
||||
- name: MCP_ALLOWED_ORIGINS
|
||||
value: {{ join "," ($mcp.allowedOrigins | default list) | quote }}
|
||||
{{ if .Values.isPrivate }}
|
||||
- name: KERBEROS_PRIVATE_CLOUD
|
||||
value: "true"
|
||||
|
||||
@@ -62,6 +62,22 @@
|
||||
"api": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"mcp": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"enabled": {"type": "boolean"},
|
||||
"allowedOrigins": {
|
||||
"type": "array",
|
||||
"uniqueItems": true,
|
||||
"items": {
|
||||
"type": "string",
|
||||
"pattern": "^https?://[^/?#*@,\\s]+$"
|
||||
},
|
||||
"description": "Exact HTTP(S) origins for browser MCP clients, without wildcards, credentials, paths or trailing slashes. Independent of REST CORS."
|
||||
}
|
||||
}
|
||||
},
|
||||
"passkeys": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
|
||||
@@ -370,6 +370,12 @@ kerberoshub:
|
||||
# Additional complete HTTP(S) origins allowed to call the Hub API.
|
||||
# The configured frontend origins remain allowed automatically.
|
||||
corsAllowedOrigins: []
|
||||
# Read-only Streamable HTTP MCP endpoint at /mcp; requires a compatible API image.
|
||||
mcp:
|
||||
enabled: false
|
||||
# Exact HTTP(S) origins for browser MCP clients; no wildcards or trailing slash.
|
||||
# Clients without an Origin header (such as VS Code) need no entries.
|
||||
allowedOrigins: []
|
||||
# Temporarily stop serving the polled GET /devices list: hub-api answers 204
|
||||
# without querying MongoDB. The frontend still loads devices once through
|
||||
# /session/bootstrap, but device online/offline status stops refreshing.
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
CHART_DIR="${1:-charts/hub}"
|
||||
|
||||
extract_mcp() {
|
||||
awk '
|
||||
/^---/ { deployment=0; name=""; variable="" }
|
||||
/^kind: Deployment$/ { deployment=1 }
|
||||
deployment && /^ name:/ { name=$2 }
|
||||
/- name: MCP_/ { variable=$3; next }
|
||||
variable != "" && /value:/ {
|
||||
value=$0
|
||||
sub(/^[[:space:]]*value: /, "", value)
|
||||
print (deployment ? name : "non-deployment"), variable, value
|
||||
variable=""
|
||||
}
|
||||
' | sort
|
||||
}
|
||||
|
||||
assert_mcp() {
|
||||
local rendered="$1" expected="$2" actual
|
||||
actual="$(printf '%s\n' "$rendered" | extract_mcp)"
|
||||
if [[ "$actual" != "$expected" ]]; then
|
||||
printf 'Unexpected MCP environment:\n%s\nExpected:\n%s\n' "$actual" "$expected" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
defaults="$(printf '%s\n' 'hub-api MCP_ALLOWED_ORIGINS ""' 'hub-api MCP_ENABLED "false"')"
|
||||
enabled="$(printf '%s\n' \
|
||||
'hub-api MCP_ALLOWED_ORIGINS "https://agent.example.com,http://localhost:4200"' \
|
||||
'hub-api MCP_ENABLED "true"')"
|
||||
flags=(
|
||||
--set kerberoshub.api.mcp.enabled=true
|
||||
--set-json 'kerberoshub.api.mcp.allowedOrigins=["https://agent.example.com","http://localhost:4200"]'
|
||||
)
|
||||
|
||||
for mode in all ui pipeline; do
|
||||
default_render="$(helm template hub "$CHART_DIR" --set "mode=$mode")"
|
||||
configured_render="$(helm template hub "$CHART_DIR" --set "mode=$mode" "${flags[@]}")"
|
||||
helm lint "$CHART_DIR" --quiet --set "mode=$mode" "${flags[@]}"
|
||||
if [[ "$mode" == pipeline ]]; then
|
||||
assert_mcp "$default_render" ""
|
||||
assert_mcp "$configured_render" ""
|
||||
[[ "$default_render" == "$configured_render" ]]
|
||||
else
|
||||
assert_mcp "$default_render" "$defaults"
|
||||
assert_mcp "$configured_render" "$enabled"
|
||||
rest_default="$(grep -A1 -- '- name: CORS_ALLOWED_ORIGINS' <<< "$default_render")"
|
||||
rest_configured="$(grep -A1 -- '- name: CORS_ALLOWED_ORIGINS' <<< "$configured_render")"
|
||||
[[ "$rest_default" == "$rest_configured" ]]
|
||||
fi
|
||||
echo "OK ($mode): MCP defaults, overrides, API-only environment and REST CORS isolation"
|
||||
done
|
||||
|
||||
assert_mcp "$(helm template hub "$CHART_DIR" --set kerberoshub.api.mcp.enabled=true)" \
|
||||
"$(printf '%s\n' 'hub-api MCP_ALLOWED_ORIGINS ""' 'hub-api MCP_ENABLED "true"')"
|
||||
assert_mcp "$(helm template hub "$CHART_DIR" --set kerberoshub.api.mcp=null)" "$defaults"
|
||||
assert_mcp "$(helm template hub "$CHART_DIR" "${flags[@]}" --set kerberoshub.api.mcp.enabled=false)" \
|
||||
"$(printf '%s\n' 'hub-api MCP_ALLOWED_ORIGINS "https://agent.example.com,http://localhost:4200"' 'hub-api MCP_ENABLED "false"')"
|
||||
|
||||
expect_invalid() {
|
||||
local output
|
||||
if output="$(helm template hub "$CHART_DIR" "$@" 2>&1)"; then
|
||||
echo "Invalid MCP settings unexpectedly rendered: $*" >&2
|
||||
return 1
|
||||
fi
|
||||
if [[ "$output" != *"mcp"* ]]; then
|
||||
printf 'Rendering failed for an unexpected reason:\n%s\n' "$output" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
expect_invalid --set-string kerberoshub.api.mcp.enabled=true
|
||||
expect_invalid --set-string kerberoshub.api.mcp.allowedOrigins=https://agent.example.com
|
||||
expect_invalid --set-string kerberoshub.api.mcp.origin=https://agent.example.com
|
||||
for origin in 'https://*.example.com' 'https://agent.example.com/' \
|
||||
'https://agent.example.com/path' 'https://agent.example.com?query' \
|
||||
'https://agent.example.com#fragment' 'https://user@agent.example.com' \
|
||||
'https://agent.example.com,https://other.example.com' 'https://bad host' 'ftp://agent.example.com'; do
|
||||
expect_invalid --set-json "kerberoshub.api.mcp.allowedOrigins=[\"$origin\"]"
|
||||
done
|
||||
expect_invalid --set-json 'kerberoshub.api.mcp.allowedOrigins=["https://agent.example.com","https://agent.example.com"]'
|
||||
|
||||
echo "All Hub MCP configuration checks passed."
|
||||
Reference in New Issue
Block a user