From 1d88033575504b2929fafaa4b57c5301f88cda53 Mon Sep 17 00:00:00 2001 From: pieced-ci Date: Sat, 16 May 2026 20:52:10 +0000 Subject: [PATCH] Sync chart from pieced-threema-gateway 0.1.1 --- deploy/helm/pieced-threema-gateway/Chart.yaml | 6 ++ .../templates/database.yaml | 20 +++++ .../templates/deployment.yaml | 80 +++++++++++++++++ .../templates/externalsecret.yaml | 45 ++++++++++ .../templates/ingress.yaml | 37 ++++++++ .../templates/networkpolicy.yaml | 87 +++++++++++++++++++ .../templates/service.yaml | 26 ++++++ .../helm/pieced-threema-gateway/values.yaml | 79 +++++++++++++++++ 8 files changed, 380 insertions(+) create mode 100644 deploy/helm/pieced-threema-gateway/Chart.yaml create mode 100644 deploy/helm/pieced-threema-gateway/templates/database.yaml create mode 100644 deploy/helm/pieced-threema-gateway/templates/deployment.yaml create mode 100644 deploy/helm/pieced-threema-gateway/templates/externalsecret.yaml create mode 100644 deploy/helm/pieced-threema-gateway/templates/ingress.yaml create mode 100644 deploy/helm/pieced-threema-gateway/templates/networkpolicy.yaml create mode 100644 deploy/helm/pieced-threema-gateway/templates/service.yaml create mode 100644 deploy/helm/pieced-threema-gateway/values.yaml diff --git a/deploy/helm/pieced-threema-gateway/Chart.yaml b/deploy/helm/pieced-threema-gateway/Chart.yaml new file mode 100644 index 0000000..28a65a8 --- /dev/null +++ b/deploy/helm/pieced-threema-gateway/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: pieced-threema-gateway +description: PieCed IT central Threema Gateway relay +type: application +version: 0.1.1 +appVersion: "0.1.1" diff --git a/deploy/helm/pieced-threema-gateway/templates/database.yaml b/deploy/helm/pieced-threema-gateway/templates/database.yaml new file mode 100644 index 0000000..8af766d --- /dev/null +++ b/deploy/helm/pieced-threema-gateway/templates/database.yaml @@ -0,0 +1,20 @@ +{{- if .Values.postgres.enabled }} +apiVersion: postgresql.cnpg.io/v1 +kind: Cluster +metadata: + name: pieced-threema-gateway-db + namespace: {{ .Values.namespace }} +spec: + instances: {{ .Values.postgres.instances }} + bootstrap: + initdb: + database: relay + owner: relay + storage: + size: {{ .Values.postgres.storage.size }} + storageClass: {{ .Values.postgres.storage.storageClass }} + resources: + {{- toYaml .Values.postgres.resources | nindent 4 }} + monitoring: + enablePodMonitor: true +{{- end }} diff --git a/deploy/helm/pieced-threema-gateway/templates/deployment.yaml b/deploy/helm/pieced-threema-gateway/templates/deployment.yaml new file mode 100644 index 0000000..bbf044c --- /dev/null +++ b/deploy/helm/pieced-threema-gateway/templates/deployment.yaml @@ -0,0 +1,80 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: pieced-threema-gateway + namespace: {{ .Values.namespace }} + labels: + app.kubernetes.io/name: pieced-threema-gateway + app.kubernetes.io/managed-by: helm +spec: + replicas: {{ .Values.replicas }} + selector: + matchLabels: + app.kubernetes.io/name: pieced-threema-gateway + template: + metadata: + labels: + app.kubernetes.io/name: pieced-threema-gateway + spec: + serviceAccountName: pieced-threema-gateway + containers: + - name: relay + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: 8080 + - name: metrics + containerPort: 9090 + env: + - name: LISTEN_HOST + value: "0.0.0.0" + - name: LISTEN_PORT + value: "8080" + - name: METRICS_PORT + value: "9090" + - name: LOG_LEVEL + value: {{ .Values.logLevel | quote }} + - name: OPENCLAW_URL_TEMPLATE + value: {{ .Values.openclawUrlTemplate | quote }} + - name: FORWARD_TIMEOUT_MS + value: {{ .Values.forwardTimeoutMs | quote }} + - name: DATABASE_URL + valueFrom: + secretKeyRef: + name: pieced-threema-gateway-db-app + key: uri + - name: THREEMA_API_IDENTITY + valueFrom: + secretKeyRef: + name: threema-credentials + key: api-identity + - name: THREEMA_API_SECRET + valueFrom: + secretKeyRef: + name: threema-credentials + key: api-secret + - name: THREEMA_PRIVATE_KEY + valueFrom: + secretKeyRef: + name: threema-credentials + key: private-key + - name: ADMIN_TOKEN + valueFrom: + secretKeyRef: + name: threema-admin-token + key: token + livenessProbe: + httpGet: + path: /healthz + port: http + initialDelaySeconds: 10 + periodSeconds: 30 + readinessProbe: + httpGet: + path: /readyz + port: http + initialDelaySeconds: 3 + periodSeconds: 10 + resources: + {{- toYaml .Values.resources | nindent 12 }} diff --git a/deploy/helm/pieced-threema-gateway/templates/externalsecret.yaml b/deploy/helm/pieced-threema-gateway/templates/externalsecret.yaml new file mode 100644 index 0000000..2aa8a38 --- /dev/null +++ b/deploy/helm/pieced-threema-gateway/templates/externalsecret.yaml @@ -0,0 +1,45 @@ +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: threema-credentials + namespace: {{ .Values.namespace }} +spec: + refreshInterval: 1h + secretStoreRef: + name: openbao-backend + kind: ClusterSecretStore + target: + name: threema-credentials + creationPolicy: Owner + data: + - secretKey: api-identity + remoteRef: + key: {{ .Values.secrets.threemaPath }} + property: api-identity + - secretKey: api-secret + remoteRef: + key: {{ .Values.secrets.threemaPath }} + property: api-secret + - secretKey: private-key + remoteRef: + key: {{ .Values.secrets.threemaPath }} + property: private-key +--- +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: threema-admin-token + namespace: {{ .Values.namespace }} +spec: + refreshInterval: 1h + secretStoreRef: + name: openbao-backend + kind: ClusterSecretStore + target: + name: threema-admin-token + creationPolicy: Owner + data: + - secretKey: token + remoteRef: + key: {{ .Values.secrets.adminTokenPath }} + property: token diff --git a/deploy/helm/pieced-threema-gateway/templates/ingress.yaml b/deploy/helm/pieced-threema-gateway/templates/ingress.yaml new file mode 100644 index 0000000..83ce31a --- /dev/null +++ b/deploy/helm/pieced-threema-gateway/templates/ingress.yaml @@ -0,0 +1,37 @@ +{{- if .Values.ingress.enabled }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: pieced-threema-gateway + namespace: {{ .Values.namespace }} + annotations: + {{- if .Values.ingress.tls.enabled }} + cert-manager.io/cluster-issuer: {{ .Values.ingress.tls.issuer | quote }} + {{- end }} + # Threema's outbound webhook IPs are publicly documented as the + # standard Threema infrastructure. Lock down if you want to be strict; + # otherwise leave open since the MAC check is the real security gate. + nginx.ingress.kubernetes.io/proxy-body-size: "128k" + nginx.ingress.kubernetes.io/proxy-read-timeout: "30" +spec: + ingressClassName: {{ .Values.ingress.className }} + {{- if .Values.ingress.tls.enabled }} + tls: + - hosts: + - {{ .Values.ingress.host }} + secretName: {{ .Values.ingress.tls.secretName }} + {{- end }} + rules: + - host: {{ .Values.ingress.host }} + http: + paths: + # Threema's CDN only ever hits /webhooks/threema. Don't expose + # /admin or /api from the internet — those go cluster-internal only. + - path: /webhooks/threema + pathType: Exact + backend: + service: + name: pieced-threema-gateway + port: + number: {{ .Values.service.port }} +{{- end }} diff --git a/deploy/helm/pieced-threema-gateway/templates/networkpolicy.yaml b/deploy/helm/pieced-threema-gateway/templates/networkpolicy.yaml new file mode 100644 index 0000000..8c2cc1c --- /dev/null +++ b/deploy/helm/pieced-threema-gateway/templates/networkpolicy.yaml @@ -0,0 +1,87 @@ +{{- if .Values.networkPolicy.enabled }} +# ============================================================================= +# Ingress: who can talk to the relay +# ============================================================================= +# Three sources: +# 1. The cluster Ingress controller (nginx-ingress) — for Threema webhooks +# hitting us through the LB. +# 2. The portal namespace — calls /admin and reads /metrics. +# 3. Tenant namespaces (managed by pieced-operator) — call /api/send. +# +# Egress: +# - DNS (kube-system) +# - Threema Gateway: msgapi.threema.ch:443 (FQDN-pinned) +# - Postgres in same namespace +# - HTTPS to tenant OpenClaw services in tenant namespaces (port 18789) +# ============================================================================= +apiVersion: cilium.io/v2 +kind: CiliumNetworkPolicy +metadata: + name: pieced-threema-gateway + namespace: {{ .Values.namespace }} +spec: + endpointSelector: + matchLabels: + app.kubernetes.io/name: pieced-threema-gateway + ingress: + # nginx-ingress + - fromEndpoints: + - matchLabels: + "k8s:io.cilium.k8s.namespace.labels.kubernetes.io/metadata.name": "ingress-nginx" + toPorts: + - ports: + - port: "8080" + protocol: TCP + # Portal + - fromEndpoints: + - matchLabels: + "k8s:io.cilium.k8s.namespace.labels.kubernetes.io/metadata.name": {{ .Values.networkPolicy.portalNamespace | quote }} + toPorts: + - ports: + - port: "8080" + protocol: TCP + - port: "9090" + protocol: TCP + # Tenant namespaces (pieced-operator-managed) + - fromEndpoints: + - matchLabels: + {{ .Values.networkPolicy.tenantNamespaceLabel | quote }}: {{ .Values.networkPolicy.tenantNamespaceLabelValue | quote }} + toPorts: + - ports: + - port: "8080" + protocol: TCP + egress: + # DNS + - toEndpoints: + - matchLabels: + "k8s:io.cilium.k8s.namespace.labels.kubernetes.io/metadata.name": "kube-system" + toPorts: + - ports: + - port: "53" + protocol: UDP + - port: "53" + protocol: TCP + # Threema Gateway public API + - toFQDNs: + - matchName: "msgapi.threema.ch" + toPorts: + - ports: + - port: "443" + protocol: TCP + # Postgres (same namespace) + - toEndpoints: + - matchLabels: + "cnpg.io/cluster": "pieced-threema-gateway-db" + toPorts: + - ports: + - port: "5432" + protocol: TCP + # Tenant OpenClaw services — port 18789, any tenant namespace + - toEndpoints: + - matchLabels: + {{ .Values.networkPolicy.tenantNamespaceLabel | quote }}: {{ .Values.networkPolicy.tenantNamespaceLabelValue | quote }} + toPorts: + - ports: + - port: "18789" + protocol: TCP +{{- end }} diff --git a/deploy/helm/pieced-threema-gateway/templates/service.yaml b/deploy/helm/pieced-threema-gateway/templates/service.yaml new file mode 100644 index 0000000..cff35ef --- /dev/null +++ b/deploy/helm/pieced-threema-gateway/templates/service.yaml @@ -0,0 +1,26 @@ +apiVersion: v1 +kind: Service +metadata: + name: pieced-threema-gateway + namespace: {{ .Values.namespace }} + labels: + app.kubernetes.io/name: pieced-threema-gateway +spec: + type: ClusterIP + selector: + app.kubernetes.io/name: pieced-threema-gateway + ports: + - name: http + port: {{ .Values.service.port }} + targetPort: 8080 + protocol: TCP + - name: metrics + port: {{ .Values.service.metricsPort }} + targetPort: 9090 + protocol: TCP +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: pieced-threema-gateway + namespace: {{ .Values.namespace }} diff --git a/deploy/helm/pieced-threema-gateway/values.yaml b/deploy/helm/pieced-threema-gateway/values.yaml new file mode 100644 index 0000000..b5bf7a7 --- /dev/null +++ b/deploy/helm/pieced-threema-gateway/values.yaml @@ -0,0 +1,79 @@ +# ============================================================================= +# pieced-threema-gateway Helm values +# ============================================================================= + +namespace: threema-gateway + +image: + repository: git.c5ai.ch/pieced/pieced-threema-gateway + tag: "0.1.1" + pullPolicy: IfNotPresent + +replicas: 1 + +service: + port: 8080 + metricsPort: 9090 + +# Internet-facing ingress so Threema's CDN can POST webhooks. +# DNS must resolve threemaGw.host to your cluster's LB IP. +ingress: + enabled: true + className: nginx + host: threema-gw.pieced.ch + tls: + enabled: true + # cert-manager ClusterIssuer name — matches the rest of pieced-gitops + issuer: letsencrypt-production + secretName: threema-gw-tls + +# CloudNativePG cluster created in-chart, mirrors portal-db pattern. +postgres: + enabled: true + instances: 1 + storage: + size: 5Gi + storageClass: longhorn-luks2 + resources: + requests: + cpu: 100m + memory: 256Mi + +# Secrets sourced from OpenBao via External Secrets Operator. +# Paths use the same convention as apps/portal/external-secrets.yaml: +# full key path starting with the KV v2 mount name (`secret/`), no +# `/data/` segment — ESO with the openbao-backend ClusterSecretStore +# rewrites that automatically for KV v2 paths. +secrets: + # Threema Gateway credentials — PieCed-wide, one identity for the platform. + threemaPath: secret/threema-gateway/credentials + # Admin token shared with pieced-portal. + adminTokenPath: secret/threema-gateway/admin + +# Template for inbound delivery to tenant OpenClaw instances. Verify your +# OpenClaw operator's Service naming before deploy. +openclawUrlTemplate: http://openclaw.tenant-{tenant}.svc.cluster.local:18789/webhooks/threema-relay + +forwardTimeoutMs: 8000 + +logLevel: info + +# Resources for the relay pod +resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 500m + memory: 512Mi + +# CiliumNetworkPolicy — restricts who can talk in and out. +networkPolicy: + enabled: true + # Tenant namespaces are matched by label set by the operator. + # Cedric's pieced-operator sets pieced.ch/managed-by=pieced-operator + # on every tenant namespace it provisions. + tenantNamespaceLabel: "k8s:io.cilium.k8s.namespace.labels.pieced.ch/managed-by" + tenantNamespaceLabelValue: "pieced-operator" + # The portal pod runs in this namespace (per apps/portal in pieced-gitops). + portalNamespace: pieced-system