Compare commits

..
Author SHA1 Message Date
KilianandClaude Opus 5.5 b186ce94ba hub: pass allowUnlockedBucket through to hub-audit s3 destinations (#213)
The audit ConfigMap copies an allowlist of s3 fields, so the new
hub-audit allowUnlockedBucket option (uug-ai/hub-audit#16) was dropped.
Chart 0.168.2.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 15:32:29 +01:00
Cédric Verstraeten 584ea33ce6 Merge pull request #212 from kerberos-io/fix/hub-publish-0.168.1-20261030
Publish hub chart 0.168.1 (passkey flag, S3 Object Lock audit)
2026-10-30 13:55:18 +01:00
Cedric VerstraetenandClaude Opus 5.5 4442c9c201 fix(hub): publish 0.168.1 with passkey flag and S3 Object Lock audit
#211, #210 and #209 all bumped the chart to 0.168.0. The release was
cut from #211, so chart-releaser skipped the later merges and the
passkey feature flag (#210) and S3 Object Lock audit destinations (#209)
were never published. Bump to 0.168.1 to release them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 12:40:12 +00:00
KilianandClaude Opus 5.5 c1e15368c7 feat(hub): S3 Object Lock audit destinations (0.168.0) (#209)
Render kerberoshub.audit.destinations per type: webhook as before, or s3
with bucket, region, prefix, endpoint and forcePathStyle. An optional
credentialsSecret mounts the access key files hub-audit reads; without it
the pod's AWS identity is used. kerberoshub.audit.serviceAccount adds an
optional ServiceAccount for hub-audit alone, so IRSA access to the audit
bucket isn't granted to every Hub workload. Invalid combinations fail at
render time. Webhook-only output is unchanged.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 13:23:28 +01:00
Cédric Verstraeten 8d86eefba5 Merge pull request #210 from kerberos-io/feat/hub-passkeys-feature-flag-20261030
Set FEATURE_PASSKEYS_ENABLED from passkeys.enabled (0.168.0)
2026-10-30 13:22:48 +01:00
KilianandClaude Opus 5.5 78d83e368f feat(hub): frontend flag for the media detail Analysis block (0.168.0) (#211)
kerberoshub.frontend.features.media.detail.analysis.enabled sets
FEATURE_MEDIA_DETAIL_ANALYSIS_ENABLED on hub-frontend and
hub-frontend-demo. Defaults to "true", matching the frontend default.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 13:21:02 +01:00
Cedric VerstraetenandClaude Opus 5.5 e899f070f8 feat(hub): set FEATURE_PASSKEYS_ENABLED from passkeys.enabled (0.168.0)
Hub API and frontend now gate passkeys behind FEATURE_PASSKEYS_ENABLED.
kerberoshub.api.passkeys.enabled sets it to "true" on Hub API alongside
the passkey configuration, and passes the same value to the frontend and
demo frontend, so one switch turns passkeys on or off everywhere.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 11:01:05 +00:00
Cédric Verstraeten 4a643aa5c2 Merge pull request #203 from kerberos-io/feat/media-forward-flag
feat(hub): frontend flag for the Forward media action (0.167.0)
2026-10-28 19:36:04 +01:00
Cédric Verstraeten fdca7b1196 Merge branch 'main' into feat/media-forward-flag 2026-10-28 19:35:47 +01:00
Cédric VerstraetenandCopilot 5a130b7301 Merge pull request #208 from kerberos-io/fix/admin-runtime-release
Publish Hub chart 0.167.3 for the hardened Admin deployment rollout.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-10-28 19:30:32 +01:00
Kilian BouteandClaude Opus 5.5 e228fd36fb feat(hub): frontend flag for the Forward media action (0.167.0)
Add kerberoshub.frontend.features.media.forward.enabled (default "true"),
rendered as FEATURE_MEDIA_FORWARD_ENABLED on hub-frontend and the demo
frontend. Setting it to "false" hides the bulk Forward media action in
the Recordings Actions menu.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 12:52:02 +00:00
10 changed files with 190 additions and 27 deletions
+1 -1
View File
@@ -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.167.3
version: 0.168.2
# 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
+16 -3
View File
@@ -260,7 +260,7 @@ kerberoshub:
| Value | Default | Purpose |
| --- | --- | --- |
| `kerberoshub.api.passkeys.enabled` | `false` | Inject passkey configuration into Hub API pods only |
| `kerberoshub.api.passkeys.enabled` | `false` | Turns passkeys on: sets `FEATURE_PASSKEYS_ENABLED` on Hub API and the frontend, and injects the passkey configuration into Hub API pods |
| `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` |
@@ -278,7 +278,14 @@ HTTPS and a compatible browser are required. Local development may use
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.
Since chart `0.168.1`, Hub API and frontend images that include the passkey
feature flag also require `FEATURE_PASSKEYS_ENABLED=true`. `enabled` sets it on
both, so the API answers `501 FEATURE_NOT_SUPPORTED` and the frontend hides
passkeys when it is `false`. If you configure passkeys through
`kerberoshub.extraEnv` instead, add `FEATURE_PASSKEYS_ENABLED=true` there and in
the frontend environment too.
Apply values with a Helm upgrade or GitOps sync; changes trigger an API and frontend 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
@@ -716,6 +723,8 @@ kerberospipeline:
| `kerberoshub.frontend.features.devices.analyticsEnabled` | Enable or disable the Analytics tab on device detail pages. | `"true"` |
| `kerberoshub.frontend.features.devices.developerToolsEnabled` | Enable or disable owner-only live Agent logs and terminal access on device detail pages. | `"true"` |
| `kerberoshub.frontend.features.dashboard.sitesFullscreenEnabled` | Enable or disable the fullscreen Sites map on the Dashboard. | `"true"` |
| `kerberoshub.frontend.features.media.forward.enabled` | Enable or disable the bulk Forward media action in the Recordings Actions menu. | `"true"` |
| `kerberoshub.frontend.features.media.detail.analysis.enabled` | Enable or disable the Analysis block (dominant colors, thumbnail, sprite, motion) on the media detail page. | `"true"` |
| `kerberoshub.frontend.features.media.filter.date.enabled` | Enable or disable `kerberoshub.frontend.features.media.filter.date`. | `"true"` |
| `kerberoshub.frontend.features.media.filter.sites.enabled` | Enable or disable `kerberoshub.frontend.features.media.filter.sites`. | `"true"` |
| `kerberoshub.frontend.features.media.filter.groups.enabled` | Enable or disable `kerberoshub.frontend.features.media.filter.groups`. | `"true"` |
@@ -791,7 +800,11 @@ kerberospipeline:
| `kerberoshub.audit.dispatchInterval` | How often the mounted destination configuration is reloaded and eligible destinations are polled. | `"5s"` |
| `kerberoshub.audit.leaseDuration` | Per-destination lease duration. It must exceed every destination timeout by at least 30 seconds. | `"2m"` |
| `kerberoshub.audit.terminationGracePeriodSeconds` | Pod termination grace period. Keep this longer than `leaseDuration` so an in-flight cycle can finish. | `150` |
| `kerberoshub.audit.destinations` | Webhook destinations. Each entry supports `id`, `enabled`, `url`, delivery limits, filters, public `headers`, `bearerTokenSecret`, and arbitrary `secretHeaders`. Destination IDs retain independent checkpoints. | `[]` |
| `kerberoshub.audit.destinations` | Audit destinations. Every entry supports `id`, `type` (`webhook` by default, or `s3`), `enabled`, delivery limits and filters. Webhooks add `url`, public `headers`, `bearerTokenSecret` and arbitrary `secretHeaders`. S3 destinations add `s3.bucket`, `s3.region`, optional `s3.prefix`, `s3.endpoint` and `s3.forcePathStyle` for S3-compatible stores, and an optional `credentialsSecret` (`name`, `accessKeyIdKey`, `secretAccessKeyKey`); without it the pod's AWS identity is used. The bucket must have Object Lock with a `COMPLIANCE` default retention unless `s3.allowUnlockedBucket` is `true` (stores without Object Lock such as Garage; the archive is then deletable). Destination IDs retain independent checkpoints. | `[]` |
| `kerberoshub.audit.serviceAccount.create` | Create a ServiceAccount used only by hub-audit, for example for S3 access through IRSA. | `false` |
| `kerberoshub.audit.serviceAccount.name` | Name of the hub-audit ServiceAccount; with `create: false`, an existing ServiceAccount to use. Defaults to `hub-audit` when created; when empty and not created, `kerberoshub.serviceAccount` applies. | `""` |
| `kerberoshub.audit.serviceAccount.annotations` | Annotations for the hub-audit ServiceAccount, such as `eks.amazonaws.com/role-arn`. | `{}` |
| `kerberoshub.audit.serviceAccount.labels` | Labels for the hub-audit ServiceAccount. | `{}` |
| `kerberoshub.audit.serviceMonitor.enabled` | Create a Prometheus `ServiceMonitor` for audit service metrics. | `true` |
| `kerberoshub.audit.serviceMonitor.interval` | Audit service metrics scrape interval. | `"15s"` |
| `kerberoshub.audit.volumes` | Additional pod volumes, for example a private webhook CA bundle. | `[]` |
@@ -10,33 +10,60 @@
{{- fail (printf "duplicate audit destination id %q" $id) -}}
{{- end -}}
{{- $_ := set $destinationIDs $id true -}}
{{- $url := required (printf "url is required for audit destination %s" $id) $destination.url -}}
{{- $type := default "webhook" $destination.type -}}
{{- $entry := dict
"id" $id
"type" (default "webhook" $destination.type)
"type" $type
"enabled" $destination.enabled
"url" $url
"timeoutSeconds" (default 10 $destination.timeoutSeconds)
"batchSize" (default 100 $destination.batchSize)
"maxAttempts" (default 10 $destination.maxAttempts)
"startAt" (default "latest" $destination.startAt)
"headers" (default dict $destination.headers)
"filters" (default dict $destination.filters) -}}
{{- $secretRoot := printf "/var/run/secrets/audit-destinations/%s" $id -}}
{{- $bearer := default dict $destination.bearerTokenSecret -}}
{{- if gt (len $bearer) 0 -}}
{{- $secretName := required (printf "bearerTokenSecret.name is required for destination %s" $id) $bearer.name -}}
{{- $secretKey := default "token" $bearer.key -}}
{{- $_ := set $entry "bearerTokenFile" (printf "%s/bearer-%s" $secretRoot (sha256sum (printf "%s:%s" $secretName $secretKey) | trunc 12)) -}}
{{- end -}}
{{- $headerFiles := dict -}}
{{- range $headerName, $secret := (default dict $destination.secretHeaders) -}}
{{- $secretName := required (printf "secretName is required for destination %s header %s" $id $headerName) $secret.secretName -}}
{{- $secretKey := required (printf "secretKey is required for destination %s header %s" $id $headerName) $secret.secretKey -}}
{{- $_ := set $headerFiles $headerName (printf "%s/header-%s" $secretRoot (sha256sum (printf "%s:%s:%s" $headerName $secretName $secretKey) | trunc 12)) -}}
{{- end -}}
{{- if gt (len $headerFiles) 0 -}}
{{- $_ := set $entry "headerFiles" $headerFiles -}}
{{- if eq $type "webhook" -}}
{{- if or $destination.s3 $destination.credentialsSecret -}}
{{- fail (printf "audit destination %s is a webhook and cannot set s3 or credentialsSecret" $id) -}}
{{- end -}}
{{- $_ := set $entry "url" (required (printf "url is required for audit destination %s" $id) $destination.url) -}}
{{- $_ := set $entry "headers" (default dict $destination.headers) -}}
{{- $bearer := default dict $destination.bearerTokenSecret -}}
{{- if gt (len $bearer) 0 -}}
{{- $secretName := required (printf "bearerTokenSecret.name is required for destination %s" $id) $bearer.name -}}
{{- $secretKey := default "token" $bearer.key -}}
{{- $_ := set $entry "bearerTokenFile" (printf "%s/bearer-%s" $secretRoot (sha256sum (printf "%s:%s" $secretName $secretKey) | trunc 12)) -}}
{{- end -}}
{{- $headerFiles := dict -}}
{{- range $headerName, $secret := (default dict $destination.secretHeaders) -}}
{{- $secretName := required (printf "secretName is required for destination %s header %s" $id $headerName) $secret.secretName -}}
{{- $secretKey := required (printf "secretKey is required for destination %s header %s" $id $headerName) $secret.secretKey -}}
{{- $_ := set $headerFiles $headerName (printf "%s/header-%s" $secretRoot (sha256sum (printf "%s:%s:%s" $headerName $secretName $secretKey) | trunc 12)) -}}
{{- end -}}
{{- if gt (len $headerFiles) 0 -}}
{{- $_ := set $entry "headerFiles" $headerFiles -}}
{{- end -}}
{{- else if eq $type "s3" -}}
{{- if or $destination.url $destination.headers $destination.bearerTokenSecret $destination.secretHeaders -}}
{{- fail (printf "audit destination %s is s3 and cannot set url, headers, bearerTokenSecret or secretHeaders" $id) -}}
{{- end -}}
{{- $s3 := required (printf "s3 is required for audit destination %s" $id) $destination.s3 -}}
{{- $settings := dict
"bucket" (required (printf "s3.bucket is required for audit destination %s" $id) $s3.bucket)
"region" (required (printf "s3.region is required for audit destination %s" $id) $s3.region) -}}
{{- range $key := list "prefix" "endpoint" "forcePathStyle" "allowUnlockedBucket" -}}
{{- if hasKey $s3 $key -}}
{{- $_ := set $settings $key (get $s3 $key) -}}
{{- end -}}
{{- end -}}
{{- $credentials := default dict $destination.credentialsSecret -}}
{{- if gt (len $credentials) 0 -}}
{{- $secretName := required (printf "credentialsSecret.name is required for destination %s" $id) $credentials.name -}}
{{- $_ := set $settings "accessKeyIdFile" (printf "%s/access-key-id-%s" $secretRoot (sha256sum (printf "%s:%s" $secretName (default "access-key-id" $credentials.accessKeyIdKey)) | trunc 12)) -}}
{{- $_ := set $settings "secretAccessKeyFile" (printf "%s/secret-access-key-%s" $secretRoot (sha256sum (printf "%s:%s" $secretName (default "secret-access-key" $credentials.secretAccessKeyKey)) | trunc 12)) -}}
{{- end -}}
{{- $_ := set $entry "s3" $settings -}}
{{- else -}}
{{- fail (printf "audit destination %s has unsupported type %q (webhook or s3)" $id $type) -}}
{{- end -}}
{{- $destinations = append $destinations $entry -}}
{{- end -}}
@@ -437,6 +437,8 @@ spec:
value: "{{ .Values.kerberoshub.api.mfaIssuer }}"
{{- if .Values.kerberoshub.api.passkeys.enabled }}
- name: FEATURE_PASSKEYS_ENABLED
value: "true"
- 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
@@ -0,0 +1,16 @@
{{- if and .Values.audit.enabled (default dict .Values.kerberoshub.audit.serviceAccount).create }}
{{- $serviceAccount := .Values.kerberoshub.audit.serviceAccount }}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ default "hub-audit" $serviceAccount.name }}
namespace: {{ .Release.Namespace }}
{{- with $serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with $serviceAccount.labels }}
labels:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
@@ -26,7 +26,12 @@ spec:
app: hub-audit
spec:
terminationGracePeriodSeconds: {{ .Values.kerberoshub.audit.terminationGracePeriodSeconds }}
{{- if .Values.kerberoshub.serviceAccount.create }}
{{- $auditServiceAccount := default dict .Values.kerberoshub.audit.serviceAccount }}
{{- if $auditServiceAccount.create }}
serviceAccountName: {{ default "hub-audit" $auditServiceAccount.name }}
{{- else if $auditServiceAccount.name }}
serviceAccountName: {{ $auditServiceAccount.name }}
{{- else if .Values.kerberoshub.serviceAccount.create }}
serviceAccountName: {{ default (printf "%s-%s-sa" .Release.Name .Chart.Name | trunc 63 | trimSuffix "-") .Values.kerberoshub.serviceAccount.name }}
{{- end }}
{{- with .Values.imagePullSecrets }}
@@ -41,10 +46,22 @@ spec:
{{- range $index, $destination := .Values.kerberoshub.audit.destinations }}
{{- $bearer := default dict $destination.bearerTokenSecret }}
{{- $secretHeaders := default dict $destination.secretHeaders }}
{{- if or (gt (len $bearer) 0) (gt (len $secretHeaders) 0) }}
{{- $credentials := default dict $destination.credentialsSecret }}
{{- if or (gt (len $bearer) 0) (gt (len $secretHeaders) 0) (gt (len $credentials) 0) }}
- name: audit-dest-{{ sha256sum $destination.id | trunc 12 }}
projected:
sources:
{{- if gt (len $credentials) 0 }}
{{- $accessKeyIdKey := default "access-key-id" $credentials.accessKeyIdKey }}
{{- $secretAccessKeyKey := default "secret-access-key" $credentials.secretAccessKeyKey }}
- secret:
name: {{ required (printf "credentialsSecret.name is required for destination %s" $destination.id) $credentials.name | quote }}
items:
- key: {{ $accessKeyIdKey | quote }}
path: access-key-id-{{ sha256sum (printf "%s:%s" $credentials.name $accessKeyIdKey) | trunc 12 }}
- key: {{ $secretAccessKeyKey | quote }}
path: secret-access-key-{{ sha256sum (printf "%s:%s" $credentials.name $secretAccessKeyKey) | trunc 12 }}
{{- end }}
{{- if gt (len $bearer) 0 }}
- secret:
name: {{ required (printf "bearerTokenSecret.name is required for destination %s" $destination.id) $bearer.name | quote }}
@@ -98,7 +115,8 @@ spec:
{{- range $index, $destination := .Values.kerberoshub.audit.destinations }}
{{- $bearer := default dict $destination.bearerTokenSecret }}
{{- $secretHeaders := default dict $destination.secretHeaders }}
{{- if or (gt (len $bearer) 0) (gt (len $secretHeaders) 0) }}
{{- $credentials := default dict $destination.credentialsSecret }}
{{- if or (gt (len $bearer) 0) (gt (len $secretHeaders) 0) (gt (len $credentials) 0) }}
- name: audit-dest-{{ sha256sum $destination.id | trunc 12 }}
mountPath: /var/run/secrets/audit-destinations/{{ $destination.id }}
readOnly: true
@@ -241,6 +241,8 @@ spec:
value: "{{ .Values.kerberoshub.frontend.features.workflows.enabled }}"
- name: FEATURE_AUDIT_ENABLED
value: "{{ .Values.kerberoshub.frontend.features.audit.enabled }}"
- name: FEATURE_PASSKEYS_ENABLED
value: "{{ .Values.kerberoshub.api.passkeys.enabled }}"
- name: FEATURE_DAY_OVERVIEW_ENABLED
value: "{{ .Values.kerberoshub.frontend.features.dayOverview.enabled }}"
- name: FEATURE_DEVICE_ANALYTICS_ENABLED
@@ -365,6 +367,10 @@ spec:
value: "{{ .Values.kerberoshub.frontend.features.faceRedaction.classifierTracksEnabled }}"
# features > media
- name: FEATURE_MEDIA_FORWARD_ENABLED
value: "{{ .Values.kerberoshub.frontend.features.media.forward.enabled }}"
- name: FEATURE_MEDIA_DETAIL_ANALYSIS_ENABLED
value: "{{ .Values.kerberoshub.frontend.features.media.detail.analysis.enabled }}"
- name: FEATURE_MEDIA_FILTER_DATE_ENABLED
value: "{{ .Values.kerberoshub.frontend.features.media.filter.date.enabled }}"
- name: FEATURE_MEDIA_FILTER_SITES_ENABLED
@@ -320,6 +320,8 @@ spec:
value: "{{ .Values.kerberoshub.frontend.features.workflows.enabled }}"
- name: FEATURE_AUDIT_ENABLED
value: "{{ .Values.kerberoshub.frontend.features.audit.enabled }}"
- name: FEATURE_PASSKEYS_ENABLED
value: "{{ .Values.kerberoshub.api.passkeys.enabled }}"
- name: FEATURE_DAY_OVERVIEW_ENABLED
value: "{{ .Values.kerberoshub.frontend.features.dayOverview.enabled }}"
- name: FEATURE_DEVICE_ANALYTICS_ENABLED
@@ -457,6 +459,10 @@ spec:
value: "{{ .Values.kerberoshub.frontend.features.faceRedaction.classifierTracksEnabled }}"
# features > media
- name: FEATURE_MEDIA_FORWARD_ENABLED
value: "{{ .Values.kerberoshub.frontend.features.media.forward.enabled }}"
- name: FEATURE_MEDIA_DETAIL_ANALYSIS_ENABLED
value: "{{ .Values.kerberoshub.frontend.features.media.detail.analysis.enabled }}"
- name: FEATURE_MEDIA_FILTER_DATE_ENABLED
value: "{{ .Values.kerberoshub.frontend.features.media.filter.date.enabled }}"
- name: FEATURE_MEDIA_FILTER_SITES_ENABLED
+44 -1
View File
@@ -655,6 +655,13 @@ kerberoshub:
sitesFullscreenEnabled: "true" # Enable or disable the fullscreen Sites map 'true' or 'false'
# Media page
media:
# Bulk "Forward media" action in the Recordings Actions menu (on-demand forwarding of metadata-only recordings).
forward:
enabled: "true" # Enable or disable the Forward media action in media 'true' or 'false'
# Analysis block (dominant colors, thumbnail, sprite, motion) on the media detail page.
detail:
analysis:
enabled: "true" # Enable or disable the Analysis block on the media detail page 'true' or 'false'
filter:
date:
enabled: "true" # Enable or disable date filter in media 'true' or 'false'
@@ -812,7 +819,8 @@ kerberoshub:
requests:
memory: 10Mi
cpu: 10m
# Dispatches canonical audit_events to one or more external webhook sinks.
# Dispatches canonical audit_events to one or more destinations: webhook
# sinks, or S3 Object Lock buckets for immutable storage.
# Credentials are always read from existing Secrets and never stored here.
audit:
repository: ghcr.io/uug-ai/hub-audit
@@ -826,6 +834,16 @@ kerberoshub:
volumes: []
volumeMounts: []
extraEnv: []
# Optional ServiceAccount for hub-audit alone, for example to grant S3 access
# through IRSA without giving it to every Hub workload. When create is false
# and name is set, that existing ServiceAccount is used; otherwise the pod
# falls back to kerberoshub.serviceAccount.
serviceAccount:
create: false
name: ""
annotations: {}
# eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/hub-audit-archive
labels: {}
serviceMonitor:
enabled: true
interval: 15s
@@ -853,6 +871,31 @@ kerberoshub:
# actions: []
# categories: []
# outcomes: [] # success | failure
# S3 Object Lock destination (requires a hub-audit release with S3 support).
# The bucket needs versioning, Object Lock and a COMPLIANCE default
# retention; hub-audit refuses to deliver otherwise. Each batch is written
# as <prefix>/<id>/yyyy/mm/dd/<firstId>-<lastId>.ndjson.gz.
# - id: immutable-archive
# type: s3
# enabled: true
# timeoutSeconds: 30
# batchSize: 500
# startAt: beginning
# s3:
# bucket: hub-audit-archive
# region: eu-west-1
# prefix: hub
# endpoint: https://minio.example.com # S3-compatible stores only
# forcePathStyle: true # usually needed for MinIO
# # Only for stores without Object Lock (e.g. Garage): skips the lock
# # check, so archived batches are deletable. Needs hub-audit with #16.
# allowUnlockedBucket: false
# # Omit credentialsSecret to use the pod's AWS identity (IRSA via
# # kerberoshub.audit.serviceAccount, or an instance profile).
# credentialsSecret:
# name: audit-immutable-archive
# accessKeyIdKey: access-key-id
# secretAccessKeyKey: secret-access-key
# resources:
# requests:
# memory: 32Mi
+33 -1
View File
@@ -33,6 +33,30 @@ assert_passkeys() {
fi
}
extract_feature() {
awk '
/^---/ { deployment=0; name=""; flag=0 }
/^kind: Deployment$/ { deployment=1 }
deployment && /^ name:/ { name=$2 }
deployment && /- name: FEATURE_PASSKEYS_ENABLED$/ { flag=1; next }
flag && /value:/ {
value=$0
sub(/^[[:space:]]*value: /, "", value)
print name, value
flag=0
}
' | sort
}
assert_feature() {
local rendered="$1" expected="$2" actual
actual="$(printf '%s\n' "$rendered" | extract_feature)"
if [[ "$actual" != "$expected" ]]; then
printf 'Unexpected FEATURE_PASSKEYS_ENABLED:\n%s\nExpected:\n%s\n' "$actual" "$expected" >&2
return 1
fi
}
CONFIGURED_FLAGS=(
--set-json kerberoshub.api.passkeys.enabled=true
--set-json 'kerberoshub.api.passkeys.rpId="example.com"'
@@ -50,14 +74,22 @@ for mode in all ui pipeline; do
configured_render="$(helm template hub "$CHART_DIR" --set "mode=$mode" "${CONFIGURED_FLAGS[@]}")"
if [[ "$mode" == pipeline ]]; then
assert_passkeys "$configured_render" ""
assert_feature "$default_render" ""
assert_feature "$configured_render" ""
else
assert_passkeys "$configured_render" "$expected"
assert_feature "$default_render" 'hub-frontend "false"'
assert_feature "$configured_render" "$(printf '%s\n' 'hub-api "true"' 'hub-frontend "true"')"
fi
echo "OK ($mode): defaults opt out; enabled settings affect Hub API only"
echo "OK ($mode): defaults opt out; enabled settings configure Hub API and flag the frontend"
done
disabled_render="$(helm template hub "$CHART_DIR" "${CONFIGURED_FLAGS[@]}" --set kerberoshub.api.passkeys.enabled=false)"
assert_passkeys "$disabled_render" ""
assert_feature "$disabled_render" 'hub-frontend "false"'
demo_render="$(helm template hub "$CHART_DIR" "${CONFIGURED_FLAGS[@]}" --set kerberoshub.frontend.demoEnabled=true)"
assert_feature "$demo_render" "$(printf '%s\n' 'hub-api "true"' 'hub-frontend "true"' 'hub-frontend-demo "true"')"
localhost_render="$(helm template hub "$CHART_DIR" --set mode=ui \
--set kerberoshub.api.passkeys.enabled=true \