diff --git a/deployments/helm-charts/wso2-ae-platform/templates/asdlc-api/deployment.yaml b/deployments/helm-charts/wso2-ae-platform/templates/asdlc-api/deployment.yaml index 3eeefba1..83b8b898 100644 --- a/deployments/helm-charts/wso2-ae-platform/templates/asdlc-api/deployment.yaml +++ b/deployments/helm-charts/wso2-ae-platform/templates/asdlc-api/deployment.yaml @@ -208,8 +208,10 @@ spec: {{- end }} - name: repos emptyDir: {} +{{- if .Values.taskSigning.privateKeyPem }} --- -# ConfigMap holding the task-signing RSA private key +# ConfigMap holding the task-signing RSA private key (only if custom key provided). +# If not provided, the auto-generation hook job creates this ConfigMap instead. apiVersion: v1 kind: ConfigMap metadata: @@ -220,6 +222,7 @@ metadata: app.kubernetes.io/part-of: wso2-agentic-engineer data: task-signing.pem: {{ .Values.taskSigning.privateKeyPem | quote }} +{{- end }} {{- if .Values.github.appPrivateKeyPem }} --- # ConfigMap holding the GitHub App private key diff --git a/deployments/helm-charts/wso2-ae-platform/values.yaml b/deployments/helm-charts/wso2-ae-platform/values.yaml index 5a9dc63c..9ec49b44 100644 --- a/deployments/helm-charts/wso2-ae-platform/values.yaml +++ b/deployments/helm-charts/wso2-ae-platform/values.yaml @@ -62,38 +62,15 @@ postgres: taskSigning: issuer: "asdlc-bff" audience: "git-service" - # RSA-2048 private key (PKCS#8 PEM). Replace with a real key for production. - # To generate: openssl genrsa -out key.pem 2048 - # Then pass: --set-file taskSigning.privateKeyPem=key.pem - privateKeyPem: | - -----BEGIN PRIVATE KEY----- - MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDhmTw2cgBL8NKT - 7QPvS868J4tO1koe6zyw8LtHAyWQvsLT5FTdX+ziHV0AWq/AN6iOS9WbPum8IvLb - 3nX8p8IihAV4Esur+CaTsujtIMuMQXrD5/qzQ+VC0BpdVIF85M46EGL8rQb8qqwr - myxS8jFfx/oYVZAXz8ifTT12rrSKoUbvhQJL78xKstK5VEWPPnfnqEfft1R6NvBp - kjsUjSEm8hFOwpyajG3Z+gAQYztvNNvSA7w+CQp+qUyElpfH23fW5Xy8zKlhD/2L - wNazbw/kGpv6jSAxXngNDdiXHals8OYcsN1fkVlFl+Ey2KvdIsJuAg49x2GDvExb - 1B0w07cpAgMBAAECggEAI+Xq120PkAX7tC9Ac4kYFgei2sItnDrpduxvmI6vIRfB - z87jFDDp9Fcgz+geVFNm/nGhxWje76GODJ+bHb+iHDTu29r9ztkXZmRPPUB9M03O - F7NnyLPSnO2ZbGWAj1unV0T5Q2TTGkycRfoUtQQ2CBw9tzaSTb+yGGtFjweg0fgo - YUu+Cvkc8kbMRuAd2xQhSGda1DDmFy9piGWA2C5YMtqg1UQLfbSgIqilG14pzE+p - MewJUjEV+cmcCM5LHq9gfdHWwCLby79uD4a9JOyo2pu0yQKj2Qfx0ba1IPwB3lCo - BjY/IRtcSFSU2rRGoA4L9k5iMs43FPNstEa1pmpbWwKBgQDzE2qT8N/ZPeK/74FG - x1gE6sHKIPImHUeOpismlHOqgm+FXjVxRBMfkLF/UIqb7DtrR0NffUhE5rPoDnti - 6Bh/INuNw9m3Reb8Fz2V9WQtNluK1emN36B1Dt/8hjp9SpKdCPlrQXvUMLzQmTtQ - Pf6OMtdP8CO/1lJRCfBXru36NwKBgQDtl+4dCOiAqJbQSIUGVj4mlMBpTsnWnR22 - Cqo5vD/+omDmG4N9s+z32GqX/wOdc0CXmJQe4tchjc5KqdIzyD6dtNcRbSUTG8GN - Z63QrRvwh49vGIByWnyIhLoIgW/pDHI8GCQQE3FVHz4vguqwStB+mm4BTX537eOz - IZfrbmGpnwKBgC2aG+mLTAOOh6aogSFNLqclf5uzGJqr7YvGgtvnB9gaRl/H79DD - C69lTtdqvcZIyFD0+p/EejVq7p9/cAh7MHVRLb9n2cV3WME8fvJOKjANPZlLTliu - doTfeIgAiqKMxfqt/1Tu4RNK3XFo/eas6r+0rA40KBDKXYEUk0Fv8Pd7AoGAVgAK - doQE9J0Rie7WB8cr0/c/9l5IfOB+IqiVmTRkzZylCmWnINcBzWyOmNn7ywAuvzDB - XLSrPkAADdKOfaPb1mXg+zPQmawQUUjYB5LBbD0FVCdARyQts5SnafDAO1EAAHSU - iSUgfrlCXxw6KvnJoinv65TLVEnNg8eDH/riau0CgYAi9dr6XJZHiUVaOZdtwx4p - 3w72TQL88U/Oo+eHnRLhOjnmmJqRLgyRGHrCGDlfD1SiZB+mAJ0k45IGiZhY7EiR - oN+c4BLjYh/EGoex7E3Nsw8euG7XGsmN3/F6FSp70NRxyqv2uhUROOO+bgm2AlUd - V6O9MjpVr7CIwk8nzchWpg== - -----END PRIVATE KEY----- + # Auto-generated by Helm hook Job (wso2-agentic-engineer-bundle/task-signing-key-job.yaml) + # on first install. Subsequent helm upgrades preserve the existing key, ensuring that + # task JWTs remain valid across pod restarts and cluster upgrades. + # + # To override with a custom key (for production): + # helm install ... --set-file taskSigning.privateKeyPem=my-key.pem + # + # If provided, this value is used; otherwise the hook Job auto-generates it. + privateKeyPem: "" # ── Smee webhook relay (optional) ──────────────────────────────────────────── # For local k3d clusters where GitHub cannot deliver webhooks directly. diff --git a/deployments/helm-charts/wso2-agentic-engineer-bundle/templates/task-signing-key-job.yaml b/deployments/helm-charts/wso2-agentic-engineer-bundle/templates/task-signing-key-job.yaml new file mode 100644 index 00000000..fbf89212 --- /dev/null +++ b/deployments/helm-charts/wso2-agentic-engineer-bundle/templates/task-signing-key-job.yaml @@ -0,0 +1,125 @@ +--- +# ServiceAccount for the task signing key generator Job +apiVersion: v1 +kind: ServiceAccount +metadata: + name: wso2-ae-key-generator + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/part-of: wso2-agentic-engineer + annotations: + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-weight": "-10" + "helm.sh/hook-delete-policy": before-hook-creation +--- +# ClusterRole for the key generator — minimal permissions +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: wso2-ae-key-generator + labels: + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/part-of: wso2-agentic-engineer + annotations: + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-weight": "-10" + "helm.sh/hook-delete-policy": before-hook-creation +rules: + - apiGroups: [""] + resources: ["configmaps"] + verbs: ["get", "create", "patch"] +--- +# ClusterRoleBinding for the key generator +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: wso2-ae-key-generator + labels: + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/part-of: wso2-agentic-engineer + annotations: + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-weight": "-10" + "helm.sh/hook-delete-policy": before-hook-creation +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: wso2-ae-key-generator +subjects: + - kind: ServiceAccount + name: wso2-ae-key-generator + namespace: {{ .Release.Namespace }} +--- +# Post-install/upgrade Job: generate BFF task signing key if it doesn't exist +# Runs before main Deployments so ConfigMap is ready for them to mount. +# Idempotent — subsequent runs reuse the existing ConfigMap, avoiding JWT invalidation. +apiVersion: batch/v1 +kind: Job +metadata: + name: wso2-ae-generate-task-signing-key + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/part-of: wso2-agentic-engineer + app.kubernetes.io/component: key-generator + annotations: + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-weight": "-9" + "helm.sh/hook-delete-policy": before-hook-creation +spec: + backoffLimit: 3 + ttlSecondsAfterFinished: 300 + template: + metadata: + labels: + app.kubernetes.io/part-of: wso2-agentic-engineer + app.kubernetes.io/component: key-generator + spec: + restartPolicy: Never + serviceAccountName: wso2-ae-key-generator + containers: + - name: keygen + image: alpine:latest + imagePullPolicy: IfNotPresent + command: + - sh + - -c + - | + set -e + + # Install kubectl if not available (alpine doesn't include it) + if ! command -v kubectl &>/dev/null; then + echo "Installing kubectl..." + apk add --no-cache kubectl + fi + + CONFIGMAP_NAME="asdlc-api-task-signing-key" + KEY_FILE="/tmp/task-signing.pem" + + echo "Checking if task signing key ConfigMap already exists..." + if kubectl get configmap "$CONFIGMAP_NAME" -n {{ .Release.Namespace }} >/dev/null 2>&1; then + echo "✅ Task signing key ConfigMap already exists (reusing existing key)" + echo " This preserves JWT verification across helm upgrades and pod restarts" + exit 0 + fi + + echo "🔐 Generating new RSA 2048 task signing key..." + if ! command -v openssl &>/dev/null; then + apk add --no-cache openssl + fi + openssl genpkey -algorithm RSA -out "$KEY_FILE" -pkeyopt rsa_keygen_bits:2048 + + if [ ! -f "$KEY_FILE" ]; then + echo "❌ Failed to generate signing key" + exit 1 + fi + + echo "📦 Storing in ConfigMap..." + kubectl create configmap "$CONFIGMAP_NAME" \ + --from-file=task-signing.pem="$KEY_FILE" \ + -n {{ .Release.Namespace }} \ + --dry-run=client -o yaml | kubectl apply -f - + + echo "✅ Task signing key generated and stored in ConfigMap" + echo " Key will be reused on future helm upgrades (idempotent)"