{{- if .Values.bootstrap.enabled }} --- apiVersion: batch/v1 kind: Job metadata: name: {{ include "terdut-server.fullname" . }}-bootstrap namespace: {{ .Release.Namespace }} labels: {{- include "terdut-server.labels" . | nindent 4 }} annotations: helm.sh/hook: post-install,post-upgrade helm.sh/hook-weight: "0" helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded spec: backoffLimit: 3 template: metadata: labels: {{- include "terdut-server.selectorLabels" . | nindent 8 }} app.kubernetes.io/component: bootstrap spec: restartPolicy: OnFailure serviceAccountName: {{ include "terdut-server.fullname" . }}-bootstrap containers: - name: bootstrap # alpine/curl, not alpine:3 + `apk add curl`. Installing the binary at run time # writes it into the container's writable upper layer, which is exactly the # signature Falco's `Drop and execute new binary in container` (MITRE TA0003) # exists to catch -- this hook emitted two Critical events on every single # upgrade. See Ryuvia/charts#100. It also made `helm upgrade` depend on the # Alpine CDN answering, since this runs as a post-upgrade hook and a failed # hook fails the release. # # Still a full Alpine underneath, so sh, cat, sleep, grep, cut, head and tail # are all present (verified in-cluster 2026-09-04). The image declares # ENTRYPOINT ["/entrypoint.sh"], which `command:` below overrides -- do not # change `command:` to `args:`. image: alpine/curl:8.21.0@sha256:a1c44bab54d88e18ea9a6a4ecefab7f2d230b968567b78960fcaff8d51b7f067 command: - /bin/sh - -c - | SERVICE_URL="http://{{ include "terdut-server.fullname" . }}:{{ .Values.service.port }}" SECRET_NAME="{{ include "terdut-server.bootstrapSecretName" . }}" K8S_API="https://kubernetes.default.svc" SA_TOKEN="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" CA_CERT="/var/run/secrets/kubernetes.io/serviceaccount/ca.crt" NAMESPACE="$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)" echo "Waiting for terdut-server to be ready..." RETRIES=60 while [ "$RETRIES" -gt 0 ]; do curl -sf "$SERVICE_URL/healthz" > /dev/null 2>&1 && break RETRIES=$((RETRIES - 1)) sleep 2 done if [ "$RETRIES" -eq 0 ]; then echo "Timed out waiting for server to be ready." exit 1 fi echo "Server is ready." RESPONSE=$(curl -s -w "\n%{http_code}" -X POST "$SERVICE_URL/api/bootstrap" \ -H "Content-Type: application/json" \ -d '{"username":"{{ .Values.bootstrap.username }}","email":"{{ .Values.bootstrap.email }}"}') HTTP_CODE=$(echo "$RESPONSE" | tail -1) BODY=$(echo "$RESPONSE" | head -1) if [ "$HTTP_CODE" = "403" ]; then echo "Server already bootstrapped, nothing to do." exit 0 fi if [ "$HTTP_CODE" != "201" ]; then echo "Bootstrap failed (HTTP $HTTP_CODE): $BODY" exit 1 fi API_KEY=$(echo "$BODY" | grep -o '"key":"[^"]*"' | cut -d'"' -f4) if [ -z "$API_KEY" ]; then echo "Failed to extract API key from response." exit 1 fi echo "Bootstrap succeeded. Storing API key in secret '$SECRET_NAME'." HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \ -X POST "$K8S_API/api/v1/namespaces/$NAMESPACE/secrets" \ --cacert "$CA_CERT" \ -H "Authorization: Bearer $SA_TOKEN" \ -H "Content-Type: application/json" \ -d "$(printf '{"apiVersion":"v1","kind":"Secret","metadata":{"name":"%s"},"stringData":{"api-key":"%s"}}' "$SECRET_NAME" "$API_KEY")") if [ "$HTTP_CODE" != "201" ]; then echo "Failed to create secret (HTTP $HTTP_CODE)." exit 1 fi echo "Secret '$SECRET_NAME' created successfully." {{- end }}