mirror of
https://github.com/kerberos-io/helm-charts.git
synced 2026-10-26 18:48:26 +00:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c42388b96f | ||
|
|
04d6990460 |
@@ -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.166.0
|
||||
version: 0.167.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
|
||||
|
||||
@@ -31,6 +31,61 @@ Uninstall the Kerberos Hub chart
|
||||
|
||||
helm uninstall hub -n kerberos-hub
|
||||
|
||||
### Passkeys
|
||||
|
||||
Users and sub-users can create and manage their own passkeys in **Profile >
|
||||
Passkeys**, then use **Sign in with a passkey** for passwordless authentication
|
||||
with device PIN/biometric verification. Existing password/MFA sign-in remains
|
||||
available. Enrollment and removal require the current password and an
|
||||
authenticator-app code when MFA is enabled.
|
||||
|
||||
Deploy Hub API and frontend images that support passkeys before enabling this
|
||||
configuration; the chart version alone does not update the service image tags.
|
||||
Passkeys are disabled by default. Configure their trust explicitly:
|
||||
|
||||
```yaml
|
||||
kerberoshub:
|
||||
api:
|
||||
passkeys:
|
||||
enabled: true
|
||||
rpId: "hub.example.com"
|
||||
origins:
|
||||
- "https://hub.example.com"
|
||||
rpName: "Kerberos Hub"
|
||||
```
|
||||
|
||||
| Value | Default | Purpose |
|
||||
| --- | --- | --- |
|
||||
| `kerberoshub.api.passkeys.enabled` | `false` | Inject passkey configuration into Hub API pods only |
|
||||
| `kerberoshub.api.passkeys.rpId` | `""` | Required when enabled; sets `PASSKEY_RP_ID` |
|
||||
| `kerberoshub.api.passkeys.origins` | `[]` | Required when enabled; exact trusted frontend origins, joined with commas into `PASSKEY_ORIGINS` |
|
||||
| `kerberoshub.api.passkeys.rpName` | `"Kerberos Hub"` | Display name; sets `PASSKEY_RP_NAME` |
|
||||
|
||||
Use the **frontend's public hostname and origins**, not the API URL. Origins
|
||||
must have no path or trailing slash. Each origin hostname must equal the RP ID
|
||||
or be its subdomain. Include only trusted origins, especially when sharing an
|
||||
RP ID across tenant subdomains. Keep the RP ID stable: changing it makes
|
||||
existing passkeys unusable. The API validates the RP/origin relationship at
|
||||
runtime; missing/invalid configuration makes passkeys unavailable without
|
||||
affecting password/MFA sign-in.
|
||||
|
||||
HTTPS and a compatible browser are required. Local development may use
|
||||
`rpId: "localhost"` with `origins: ["http://localhost:4200"]`.
|
||||
The frontend displays translated cancellation, verification and unavailable
|
||||
messages when a ceremony cannot complete.
|
||||
|
||||
Apply values with a Helm upgrade or GitOps sync; changes trigger an API rollout.
|
||||
If these variables were previously configured through `kerberoshub.extraEnv`,
|
||||
remove those entries when enabling the dedicated settings to avoid duplicate
|
||||
environment variables. Setting `enabled: false` omits the chart-managed
|
||||
variables; any passkey variables supplied through `extraEnv` still take effect.
|
||||
|
||||
The API's MongoDB identity needs reads on `users`, CRUD on `passkeys`, and
|
||||
insert/find-and-delete on `passkey_challenges`. It attempts to create the
|
||||
`passkey_challenge_expiry_ttl` index on `expiresAt` with
|
||||
`expireAfterSeconds: 0`; expiration and single-use enforcement work without the
|
||||
index, but the index is needed for automatic expired-challenge cleanup.
|
||||
|
||||
### Sequence logging
|
||||
|
||||
Set `kerberospipeline.sequence.logLevel` to control the Sequence service's
|
||||
|
||||
@@ -436,6 +436,15 @@ spec:
|
||||
- name: MFA_ISSUER
|
||||
value: "{{ .Values.kerberoshub.api.mfaIssuer }}"
|
||||
|
||||
{{- if .Values.kerberoshub.api.passkeys.enabled }}
|
||||
- name: PASSKEY_RP_ID
|
||||
value: {{ required "kerberoshub.api.passkeys.rpId is required when passkeys are enabled" .Values.kerberoshub.api.passkeys.rpId | quote }}
|
||||
- name: PASSKEY_ORIGINS
|
||||
value: {{ required "kerberoshub.api.passkeys.origins is required when passkeys are enabled" .Values.kerberoshub.api.passkeys.origins | join "," | quote }}
|
||||
- name: PASSKEY_RP_NAME
|
||||
value: {{ .Values.kerberoshub.api.passkeys.rpName | quote }}
|
||||
{{- end }}
|
||||
|
||||
# AWS (Legacy, use Kerberos Vault instead)
|
||||
- name: AWS_REGION
|
||||
value: "{{ .Values.kerberoshub.api.aws.region }}"
|
||||
|
||||
@@ -62,6 +62,38 @@
|
||||
"api": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"passkeys": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"enabled": {"type": "boolean"},
|
||||
"rpId": {
|
||||
"type": "string",
|
||||
"description": "Stable WebAuthn relying-party hostname, without scheme, port or path. Must match each frontend origin's hostname or be its parent domain."
|
||||
},
|
||||
"origins": {
|
||||
"type": "array",
|
||||
"uniqueItems": true,
|
||||
"items": {
|
||||
"type": "string",
|
||||
"pattern": "^https://[^/?#]+$|^http://localhost(:[0-9]+)?$"
|
||||
},
|
||||
"description": "Exact trusted frontend origins, with no path or trailing slash. HTTPS is required except for HTTP localhost development."
|
||||
},
|
||||
"rpName": {"type": "string"}
|
||||
},
|
||||
"if": {
|
||||
"required": ["enabled"],
|
||||
"properties": {"enabled": {"const": true}}
|
||||
},
|
||||
"then": {
|
||||
"required": ["rpId", "origins"],
|
||||
"properties": {
|
||||
"rpId": {"minLength": 1},
|
||||
"origins": {"minItems": 1}
|
||||
}
|
||||
}
|
||||
},
|
||||
"corsAllowedOrigins": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
|
||||
@@ -392,6 +392,13 @@ kerberoshub:
|
||||
|
||||
# MFA issuer name
|
||||
mfaIssuer: "yourdomain.com"
|
||||
# WebAuthn passkeys for users and sub-users; requires compatible API/frontend images.
|
||||
# Use the public frontend hostname/origins, not the API URL. Keep rpId stable.
|
||||
passkeys:
|
||||
enabled: false
|
||||
rpId: "" # e.g. "hub.example.com", without scheme, port or path.
|
||||
origins: [] # e.g. ["https://hub.example.com"]; exact origins, no trailing slash.
|
||||
rpName: "Kerberos Hub"
|
||||
# Admin API's are made available for automation of Kerberos Hub.
|
||||
# To access those API's (e.g. creation of owner users), an API key needs to be provided.
|
||||
apiKey: "a-random-admin-api-key"
|
||||
|
||||
Executable
+98
@@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
CHART_DIR="${1:-charts/hub}"
|
||||
|
||||
extract_passkeys() {
|
||||
awk '
|
||||
/^---/ { deployment=0; name=""; variable="" }
|
||||
/^kind: Deployment$/ { deployment=1 }
|
||||
deployment && /^ name:/ { name=$2 }
|
||||
deployment && /- name: PASSKEY_/ { variable=$3; next }
|
||||
variable != "" && /value:/ {
|
||||
value=$0
|
||||
sub(/^[[:space:]]*value: /, "", value)
|
||||
print name, variable, value
|
||||
variable=""
|
||||
}
|
||||
' | sort
|
||||
}
|
||||
|
||||
assert_passkeys() {
|
||||
local rendered="$1" expected="$2" actual count expected_count
|
||||
actual="$(printf '%s\n' "$rendered" | extract_passkeys)"
|
||||
if [[ "$actual" != "$expected" ]]; then
|
||||
printf 'Unexpected passkey environment:\n%s\nExpected:\n%s\n' "$actual" "$expected" >&2
|
||||
return 1
|
||||
fi
|
||||
count="$(printf '%s\n' "$rendered" | awk '/- name: PASSKEY_/ { count++ } END { print count+0 }')"
|
||||
expected_count="$(printf '%s\n' "$expected" | awk 'NF { count++ } END { print count+0 }')"
|
||||
if [[ "$count" != "$expected_count" ]]; then
|
||||
echo "Passkey variables leaked outside the expected Deployment or were duplicated" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
CONFIGURED_FLAGS=(
|
||||
--set-json kerberoshub.api.passkeys.enabled=true
|
||||
--set-json 'kerberoshub.api.passkeys.rpId="example.com"'
|
||||
--set-json 'kerberoshub.api.passkeys.origins=["https://hub.example.com","https://legacy.example.com:8443"]'
|
||||
--set-json 'kerberoshub.api.passkeys.rpName="Example Hub"'
|
||||
)
|
||||
expected="$(printf '%s\n' \
|
||||
'hub-api PASSKEY_ORIGINS "https://hub.example.com,https://legacy.example.com:8443"' \
|
||||
'hub-api PASSKEY_RP_ID "example.com"' \
|
||||
'hub-api PASSKEY_RP_NAME "Example Hub"' | sort)"
|
||||
|
||||
for mode in all ui pipeline; do
|
||||
default_render="$(helm template hub "$CHART_DIR" --set "mode=$mode")"
|
||||
assert_passkeys "$default_render" ""
|
||||
configured_render="$(helm template hub "$CHART_DIR" --set "mode=$mode" "${CONFIGURED_FLAGS[@]}")"
|
||||
if [[ "$mode" == pipeline ]]; then
|
||||
assert_passkeys "$configured_render" ""
|
||||
else
|
||||
assert_passkeys "$configured_render" "$expected"
|
||||
fi
|
||||
echo "OK ($mode): defaults opt out; enabled settings affect Hub API only"
|
||||
done
|
||||
|
||||
disabled_render="$(helm template hub "$CHART_DIR" "${CONFIGURED_FLAGS[@]}" --set kerberoshub.api.passkeys.enabled=false)"
|
||||
assert_passkeys "$disabled_render" ""
|
||||
|
||||
localhost_render="$(helm template hub "$CHART_DIR" --set mode=ui \
|
||||
--set kerberoshub.api.passkeys.enabled=true \
|
||||
--set-string kerberoshub.api.passkeys.rpId=localhost \
|
||||
--set-json 'kerberoshub.api.passkeys.origins=["http://localhost:4200"]')"
|
||||
assert_passkeys "$localhost_render" "$(printf '%s\n' \
|
||||
'hub-api PASSKEY_ORIGINS "http://localhost:4200"' \
|
||||
'hub-api PASSKEY_RP_ID "localhost"' \
|
||||
'hub-api PASSKEY_RP_NAME "Kerberos Hub"' | sort)"
|
||||
|
||||
legacy_render="$(helm template hub "$CHART_DIR" --set mode=ui \
|
||||
--set-json 'kerberoshub.extraEnv=[{"name":"PASSKEY_RP_ID","value":"example.com"}]')"
|
||||
printf '%s\n' "$legacy_render" | grep -q -- '- name: PASSKEY_RP_ID'
|
||||
|
||||
expect_invalid() {
|
||||
local output
|
||||
if output="$(helm template hub "$CHART_DIR" "${CONFIGURED_FLAGS[@]}" "$@" 2>&1)"; then
|
||||
echo "Invalid passkey settings unexpectedly rendered: $*" >&2
|
||||
return 1
|
||||
fi
|
||||
if [[ "$output" != *"passkeys"* ]]; then
|
||||
printf 'Rendering failed for an unexpected reason:\n%s\n' "$output" >&2
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
expect_invalid --set-string kerberoshub.api.passkeys.rpId=
|
||||
expect_invalid --set-json 'kerberoshub.api.passkeys.origins=[]'
|
||||
expect_invalid --set-json 'kerberoshub.api.passkeys.origins=["https://hub.example.com/"]'
|
||||
expect_invalid --set-json 'kerberoshub.api.passkeys.origins=["http://hub.example.com"]'
|
||||
expect_invalid --set-json 'kerberoshub.api.passkeys.origins=["https://hub.example.com","https://hub.example.com"]'
|
||||
expect_invalid --set-json 'kerberoshub.api.passkeys.origins="https://hub.example.com"'
|
||||
expect_invalid --set-json 'kerberoshub.api.passkeys.enabled="true"'
|
||||
expect_invalid --set-json 'kerberoshub.api.passkeys.rpId=123'
|
||||
expect_invalid --set-json 'kerberoshub.api.passkeys.rpName=123'
|
||||
expect_invalid --set-string kerberoshub.api.passkeys.origin=https://hub.example.com
|
||||
|
||||
echo "All Hub passkey configuration checks passed."
|
||||
Reference in New Issue
Block a user