mirror of
https://github.com/kerberos-io/helm-charts.git
synced 2026-11-05 20:20:24 +00:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
56ea65c6e7 | ||
|
|
af4e1c36a9 |
@@ -21,6 +21,7 @@ jobs:
|
||||
bash scripts/check-admin-runtime.sh
|
||||
bash scripts/check-hardened-workers.sh
|
||||
bash scripts/check-frontend-runtime.sh
|
||||
bash scripts/check-hub-api-runtime.sh
|
||||
- name: Smoke test hardened frontend images and Service routing
|
||||
env:
|
||||
CLUSTER_SMOKE: "true"
|
||||
|
||||
@@ -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.170.0
|
||||
version: 0.170.1
|
||||
|
||||
# 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,30 @@ Uninstall the Kerberos Hub chart
|
||||
|
||||
helm uninstall hub -n kerberos-hub
|
||||
|
||||
### Hardened Hub API
|
||||
|
||||
Starting with chart **`0.170.1`**, `kerberoshub.api.securityContext` is rendered
|
||||
on the Hub API container and `kerberoshub.api.podSecurityContext` on its pod.
|
||||
The current image runs as `65532:65532` with a read-only root filesystem,
|
||||
privilege escalation disabled, all capabilities dropped and `RuntimeDefault`
|
||||
seccomp. A disk-backed `hub-api-tmp` emptyDir mounted at `/tmp`, with pod
|
||||
`fsGroup: 65532`, keeps attachment uploads and multipart parsing writable.
|
||||
API Service, ingress and port settings are unchanged.
|
||||
|
||||
Append custom mounts and volumes to the default lists rather than replacing
|
||||
`hub-api-tmp`. Helm replaces lists in overrides. Existing MongoDB TLS, API TLS,
|
||||
catalog and workflow-configuration mounts remain supported.
|
||||
|
||||
For a legacy image that requires its original identity or writable root
|
||||
filesystem, explicitly set both `kerberoshub.api.securityContext: null` and
|
||||
`kerberoshub.api.podSecurityContext: null`. Custom security settings are
|
||||
per-API; other workloads do not inherit them. When upgrading, check retained
|
||||
values (`--reuse-values` or GitOps overrides) so the security context and
|
||||
writable scratch mount stay aligned.
|
||||
|
||||
Run `bash scripts/check-hub-api-runtime.sh` to validate defaults, overrides,
|
||||
legacy opt-out, TLS/configuration mounts and deployment modes.
|
||||
|
||||
### Hardened frontend images
|
||||
|
||||
Starting with chart **`0.170.0`**, both frontends default to shell-free
|
||||
|
||||
@@ -140,6 +140,10 @@ spec:
|
||||
labels:
|
||||
app: hub-api
|
||||
spec:
|
||||
{{- with .Values.kerberoshub.api.podSecurityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.kerberoshub.serviceAccount.create }}
|
||||
serviceAccountName: {{ default (printf "%s-%s-sa" .Release.Name .Chart.Name | trunc 63 | trimSuffix "-") .Values.kerberoshub.serviceAccount.name }}
|
||||
{{- end }}
|
||||
@@ -229,6 +233,10 @@ spec:
|
||||
- name: hub-api
|
||||
image: "{{ .Values.global.imageRegistry }}{{ .Values.kerberoshub.api.repository }}:{{ .Values.kerberoshub.api.tag }}"
|
||||
imagePullPolicy: {{ .Values.kerberoshub.api.pullPolicy }}
|
||||
{{- with .Values.kerberoshub.api.securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.kerberoshub.api.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
|
||||
+38
-21
@@ -50,7 +50,6 @@ mongodb:
|
||||
# hub-pipeline-monitor, ...) instead of the one in uri, so the Atlas query
|
||||
# profiler and currentOp show which service issued an operation.
|
||||
appNamePerService: true
|
||||
|
||||
# Self-hosted mongodb, you could also use the uri property above.
|
||||
host: mongodb.mongodb
|
||||
adminDatabase: admin
|
||||
@@ -73,7 +72,6 @@ mongodb:
|
||||
caFileName: ""
|
||||
mountPath: "/etc/mongodb/tls"
|
||||
insecureSkipVerify: false
|
||||
|
||||
# Classifications supported by Hub filters, alerts, markers, and other
|
||||
# downstream processing. Classifier output keys must match these values.
|
||||
# Disable this to use the legacy classification catalog stored in MongoDB.
|
||||
@@ -115,7 +113,6 @@ deviceTags:
|
||||
# - key: anpr-pilot
|
||||
# label: ANPR pilot
|
||||
# description: Runs licence plate recognition on this camera
|
||||
|
||||
# Configuration packaging only: consuming contracts requires a compatible
|
||||
# API/frontend. Enabling this mounts files but does not register stage workers.
|
||||
workflowConfiguration:
|
||||
@@ -339,8 +336,27 @@ kerberoshub:
|
||||
api:
|
||||
repository: ghcr.io/uug-ai/hub-api
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.9.51"
|
||||
tag: "v1.11.31"
|
||||
replicas: 2
|
||||
podSecurityContext:
|
||||
fsGroup: 65532
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 65532
|
||||
runAsGroup: 65532
|
||||
readOnlyRootFilesystem: true
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop: ["ALL"]
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
# Keep writable scratch space for attachment uploads and multipart parsing.
|
||||
volumes:
|
||||
- name: hub-api-tmp
|
||||
emptyDir: {}
|
||||
volumeMounts:
|
||||
- name: hub-api-tmp
|
||||
mountPath: /tmp
|
||||
audit:
|
||||
enabled: true
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
@@ -375,6 +391,7 @@ kerberoshub:
|
||||
memory: 100Mi
|
||||
cpu: 250m
|
||||
# E-mail templates
|
||||
# Append custom mounts/volumes to the lists above; retain hub-api-tmp.
|
||||
#volumeMounts:
|
||||
# - name: custom-email-templates
|
||||
# mountPath: /mail
|
||||
@@ -793,7 +810,7 @@ kerberoshub:
|
||||
podSecurityContext: {}
|
||||
repository: ghcr.io/uug-ai/hub-cleanup
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.4.19"
|
||||
tag: "v1.4.26"
|
||||
replicas: 1 # Number of pods for the service.
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
# Optional extra volumes / volumeMounts for this deployment (empty = none).
|
||||
@@ -1158,7 +1175,7 @@ kerberoshub:
|
||||
podSecurityContext: {}
|
||||
repository: ghcr.io/uug-ai/hub-monitor-device
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.4.2"
|
||||
tag: "v1.4.10"
|
||||
replicas: 1 # Number of pods for the service.
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
logLevel: "info" # possible values: trace, debug, info, warn, error
|
||||
@@ -1246,7 +1263,7 @@ kerberospipeline:
|
||||
# argocd.argoproj.io/sync-wave: "10"
|
||||
repository: ghcr.io/uug-ai/hub-pipeline-event
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.3.1"
|
||||
tag: "v1.3.9"
|
||||
replicas: 1 # Number of pods for the service.
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
# Optional extra volumes / volumeMounts for this deployment (empty = none).
|
||||
@@ -1267,7 +1284,7 @@ kerberospipeline:
|
||||
# deploymentAnnotations:
|
||||
# argocd.argoproj.io/sync-wave: "70"
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.3.13"
|
||||
tag: "v1.3.29"
|
||||
replicas: 1 # Number of pods for the service.
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
# Optional extra volumes / volumeMounts for this deployment (empty = none).
|
||||
@@ -1288,7 +1305,7 @@ kerberospipeline:
|
||||
# deploymentAnnotations:
|
||||
# argocd.argoproj.io/sync-wave: "60"
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.6.26"
|
||||
tag: "v1.7.14"
|
||||
replicas: 1 # Number of pods for the service.
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
# Optional extra volumes / volumeMounts for this deployment (empty = none).
|
||||
@@ -1306,12 +1323,12 @@ kerberospipeline:
|
||||
throttler:
|
||||
securityContext: {}
|
||||
podSecurityContext: {}
|
||||
repository: uugai/hub-pipeline-throttler
|
||||
repository: ghcr.io/uug-ai/hub-pipeline-throttler
|
||||
deploymentAnnotations: {}
|
||||
# deploymentAnnotations:
|
||||
# argocd.argoproj.io/sync-wave: "30"
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.2.1"
|
||||
tag: "v1.2.10"
|
||||
replicas: 1 # Number of pods for the service.
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
# Optional extra volumes / volumeMounts for this deployment (empty = none).
|
||||
@@ -1334,7 +1351,7 @@ kerberospipeline:
|
||||
# deploymentAnnotations:
|
||||
# argocd.argoproj.io/sync-wave: "20"
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.3.18"
|
||||
tag: "v1.3.46"
|
||||
replicas: 1 # Number of pods for the service.
|
||||
audit:
|
||||
enabled: true
|
||||
@@ -1354,9 +1371,9 @@ kerberospipeline:
|
||||
# persistentVolumeClaim:
|
||||
# claimName: custom-layout-claim
|
||||
notifyTest:
|
||||
repository: uugai/hub-pipeline-notification-test
|
||||
repository: ghcr.io/uug-ai/hub-pipeline-notification-test
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.2.2"
|
||||
tag: "v1.2.6"
|
||||
replicas: 1 # Number of pods for the service.
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
resources:
|
||||
@@ -1377,7 +1394,7 @@ kerberospipeline:
|
||||
# deploymentAnnotations:
|
||||
# argocd.argoproj.io/sync-wave: "40"
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.8.22"
|
||||
tag: "v1.8.29"
|
||||
replicas: 1 # Number of pods for the service.
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
# Optional extra volumes / volumeMounts for this deployment (empty = none).
|
||||
@@ -1415,7 +1432,7 @@ kerberospipeline:
|
||||
# deploymentAnnotations:
|
||||
# argocd.argoproj.io/sync-wave: "50"
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v2.0.3"
|
||||
tag: "v2.0.9"
|
||||
replicas: 3 # Number of pods for the service.
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
# Optional extra volumes / volumeMounts for this deployment (empty = none).
|
||||
@@ -1441,7 +1458,7 @@ kerberospipeline:
|
||||
# deploymentAnnotations:
|
||||
# argocd.argoproj.io/sync-wave: "50"
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.3.15"
|
||||
tag: "v1.3.22"
|
||||
replicas: 2 # Number of pods for the service.
|
||||
prefetchCount: 0 # Max unacknowledged RabbitMQ messages per pod; 0 = service default (5).
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
@@ -1469,12 +1486,12 @@ kerberospipeline:
|
||||
counting:
|
||||
securityContext: {}
|
||||
podSecurityContext: {}
|
||||
repository: uugai/hub-pipeline-counting
|
||||
repository: ghcr.io/uug-ai/hub-pipeline-counting
|
||||
deploymentAnnotations: {}
|
||||
# deploymentAnnotations:
|
||||
# argocd.argoproj.io/sync-wave: "50"
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v2.0.0"
|
||||
tag: "v2.0.6"
|
||||
replicas: 1 # Number of pods for the service.
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
# Optional extra volumes / volumeMounts for this deployment (empty = none).
|
||||
@@ -1496,7 +1513,7 @@ kerberospipeline:
|
||||
# argocd.argoproj.io/sync-wave: "50"
|
||||
repository: ghcr.io/uug-ai/hub-pipeline-sprite
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.1.21"
|
||||
tag: "v1.1.27"
|
||||
replicas: 5 # Number of pods for the service.
|
||||
prefetchCount: 0 # Max unacknowledged RabbitMQ messages per pod; 0 = service default (5).
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
@@ -1523,7 +1540,7 @@ kerberospipeline:
|
||||
export:
|
||||
repository: ghcr.io/uug-ai/hub-pipeline-export
|
||||
pullPolicy: IfNotPresent
|
||||
tag: "v1.2.10"
|
||||
tag: "v1.2.20"
|
||||
replicas: 2 # Number of pods for the service.
|
||||
topologySpreadConstraints: [] # Optional pod topology spread constraints (empty = none).
|
||||
logLevel: "info" # possible values: trace, debug, info, warn, error
|
||||
|
||||
@@ -63,7 +63,7 @@ assert_line() {
|
||||
without_frontends() {
|
||||
awk '
|
||||
/^---$/ { skip=0 }
|
||||
/^# Source: hub\/templates\/kerberos-hub\/hub-frontend(-demo)?\.yaml$/ { skip=1 }
|
||||
/^# Source: hub\/templates\/kerberos-hub\/(hub-frontend(-demo)?|hub-api)\.yaml$/ { skip=1 }
|
||||
!skip { print }
|
||||
'
|
||||
}
|
||||
@@ -121,7 +121,7 @@ for mode in all pipeline ui; do
|
||||
done
|
||||
expected="${#names[@]}"
|
||||
[[ "$(without_frontends <<< "$hardened" | grep -c 'runAsUser: 65532')" == "$expected" ]]
|
||||
[[ "$(grep -c 'fsGroup: 65532' <<< "$hardened")" == "$expected" ]]
|
||||
[[ "$(without_frontends <<< "$hardened" | grep -c 'fsGroup: 65532')" == "$expected" ]]
|
||||
|
||||
# Image selection, Services, env and TLS mounts must not change.
|
||||
for pattern in '^[ ]+image:' '^[ ]+(port|targetPort|containerPort):' 'mongodb-tls'; do
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
CHART_DIR="${1:-charts/hub}"
|
||||
|
||||
resource() {
|
||||
local kind="$1" name="$2"
|
||||
awk -v kind="$kind" -v name="$name" '
|
||||
function emit() { if (matchedKind && matchedName) printf "%s", block }
|
||||
/^---$/ { emit(); block=""; matchedKind=0; matchedName=0 }
|
||||
{ block=block $0 "\n" }
|
||||
$0 == "kind: " kind { matchedKind=1 }
|
||||
$0 == " name: " name { matchedName=1 }
|
||||
END { emit() }
|
||||
'
|
||||
}
|
||||
|
||||
assert_line() {
|
||||
if ! grep -Eq -- "$2" <<< "$1"; then
|
||||
printf 'Missing expected Hub API setting: %s\n' "$2" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
fixtures=(
|
||||
--set workflowConfiguration.enabled=true
|
||||
--set mongodb.tls.enabled=true
|
||||
--set mongodb.tls.existingSecret=mongodb-ca
|
||||
--set kerberoshub.api.serverTLS.enabled=true
|
||||
--set kerberoshub.api.serverTLS.secretName=api-tls
|
||||
)
|
||||
|
||||
for mode in all ui pipeline; do
|
||||
defaults="$(helm template hub "$CHART_DIR" --set "mode=$mode" "${fixtures[@]}")"
|
||||
legacy="$(helm template hub "$CHART_DIR" --set "mode=$mode" "${fixtures[@]}" \
|
||||
--set kerberoshub.api.securityContext=null \
|
||||
--set kerberoshub.api.podSecurityContext=null)"
|
||||
configured="$(helm template hub "$CHART_DIR" --set "mode=$mode" "${fixtures[@]}" \
|
||||
--set kerberoshub.api.securityContext.runAsUser=1000 \
|
||||
--set kerberoshub.api.securityContext.runAsGroup=1000 \
|
||||
--set kerberoshub.api.podSecurityContext.fsGroup=1000)"
|
||||
helm lint "$CHART_DIR" --quiet --set "mode=$mode" "${fixtures[@]}"
|
||||
|
||||
if [[ "$mode" == pipeline ]]; then
|
||||
[[ -z "$(resource Deployment hub-api <<< "$defaults")" ]]
|
||||
[[ "$defaults" == "$legacy" && "$defaults" == "$configured" ]]
|
||||
echo "OK (pipeline): no Hub API resources or unrelated changes"
|
||||
continue
|
||||
fi
|
||||
|
||||
api="$(resource Deployment hub-api <<< "$defaults")"
|
||||
for pattern in \
|
||||
'^[ ]{6}securityContext:$' '^[ ]{8}fsGroup: 65532$' \
|
||||
'^[ ]{10}securityContext:$' '^[ ]{12}runAsUser: 65532$' \
|
||||
'^[ ]{12}runAsGroup: 65532$' '^[ ]{12}runAsNonRoot: true$' \
|
||||
'^[ ]{12}readOnlyRootFilesystem: true$' \
|
||||
'^[ ]{12}allowPrivilegeEscalation: false$' '^[ ]{12}capabilities:$' \
|
||||
'^[ ]{14}drop:$' '^[ ]{14}- ALL$' \
|
||||
'^[ ]{12}seccompProfile:$' '^[ ]{14}type: RuntimeDefault$' \
|
||||
'^[ ]+(- )?name: hub-api-tmp$' '^[ ]+(- )?emptyDir: \{\}$' \
|
||||
'^[ ]+(- )?mountPath: /tmp$' '^[ ]+secretName: mongodb-ca$' \
|
||||
'^[ ]+secretName: api-tls$' '^[ ]+mountPath: /etc/mongodb/tls$' \
|
||||
'^[ ]+mountPath: /etc/hub-api/tls$' \
|
||||
'^[ ]+mountPath: /etc/kerberos/configuration$' \
|
||||
'^[ ]+mountPath: /etc/kerberos/classifications$'; do
|
||||
assert_line "$api" "$pattern"
|
||||
done
|
||||
[[ "$(grep -c 'securityContext:' <<< "$api")" == 2 ]]
|
||||
old_api="$(resource Deployment hub-api <<< "$legacy")"
|
||||
if grep -q 'securityContext:' <<< "$old_api"; then
|
||||
echo "Legacy Hub API opt-out still renders a security context" >&2
|
||||
exit 1
|
||||
fi
|
||||
custom_api="$(resource Deployment hub-api <<< "$configured")"
|
||||
for field in runAsUser runAsGroup fsGroup; do
|
||||
assert_line "$custom_api" "^[ ]+$field: 1000$"
|
||||
done
|
||||
|
||||
# Only security settings change; preserve env, mounts, images and routing.
|
||||
for pattern in '^[ ]+image:' '^[ ]+(port|targetPort|containerPort):' \
|
||||
'^[ ]+(- )?(name|mountPath|secretName|value):'; do
|
||||
[[ "$(grep -E "$pattern" <<< "$defaults")" == "$(grep -E "$pattern" <<< "$legacy")" ]]
|
||||
[[ "$(grep -E "$pattern" <<< "$defaults")" == "$(grep -E "$pattern" <<< "$configured")" ]]
|
||||
done
|
||||
echo "OK ($mode): API security defaults, overrides, opt-out, scratch and TLS/config mounts"
|
||||
done
|
||||
Reference in New Issue
Block a user