charts: add wonderwall-forward-auth

Co-Authored-By: Thomas Siegfried Krampl <thomas.siegfried.krampl@nav.no>
This commit is contained in:
Trong Huu Nguyen
2025-05-21 10:37:49 +02:00
parent 3543fe08cd
commit 53dc9d9f40
15 changed files with 438 additions and 11 deletions

View File

@@ -33,7 +33,7 @@ jobs:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # ratchet:actions/checkout@v4
- name: Install cosign
uses: sigstore/cosign-installer@3454372f43399081ed03b604cb2d021dabca52bb # ratchet:sigstore/cosign-installer@main
uses: sigstore/cosign-installer@e9a05e6d32d7ed22b5656cd874ef31af58d05bfa # ratchet:sigstore/cosign-installer@main
with:
cosign-release: 'v2.2.3'
- name: Verify runner image
@@ -48,6 +48,36 @@ jobs:
push: true
push_ghcr: true
workload_identity_provider: ${{ secrets.NAIS_IO_WORKLOAD_IDENTITY_PROVIDER }}
outputs:
version: ${{ steps.build_push_sign.outputs.version }}
charts:
needs: build
name: Build and push chart
if: github.ref == 'refs/heads/master'
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
strategy:
fail-fast: false
matrix:
chart: ["wonderwall", "wonderwall-forward-auth"]
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # ratchet:actions/checkout@v4
- id: "auth"
name: "Authenticate to Google Cloud"
uses: "google-github-actions/auth@6fc4af4b145ae7821d527454aa9bd537d1f2dc5f" # ratchet:google-github-actions/auth@v2
with:
workload_identity_provider: ${{ secrets.NAIS_IO_WORKLOAD_IDENTITY_PROVIDER }}
service_account: "gh-wonderwall@nais-io.iam.gserviceaccount.com"
token_format: "access_token"
- name: "Login to registry"
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # ratchet:docker/login-action@v3
with:
registry: "${{ env.GOOGLE_REGISTRY }}/nais-io/nais/feature"
username: "oauth2accesstoken"
password: "${{ steps.auth.outputs.access_token }}"
- uses: azure/setup-helm@b9e51907a09c216f16ebe8536097933489208112 # ratchet:azure/setup-helm@v4
name: 'Setup Helm'
with:
@@ -55,16 +85,16 @@ jobs:
- name: Package chart
id: package_chart
env:
CHART_PATH: ./charts/wonderwall
CHART_PATH: ./charts/${{ matrix.chart }}
run: |
base_version="$(yq '.version' < "${{ env.CHART_PATH }}/Chart.yaml")"
chart_version="${base_version}-${{ steps.build_push_sign.outputs.version }}"
base_version="1.0.0"
chart_version="${base_version}-${{ needs.build.outputs.version }}"
yq eval \
'.version="'"$chart_version"'"' \
"${{ env.CHART_PATH }}/Chart.yaml" --inplace
yq eval \
'.image.tag="${{ steps.build_push_sign.outputs.version }}"' \
'.image.tag="${{ needs.build.outputs.version }}"' \
"${{ env.CHART_PATH }}/values.yaml" --inplace
# helm dependency update "${{ env.CHART_PATH }}"
@@ -79,10 +109,6 @@ jobs:
chart="${{ steps.package_chart.outputs.archive }}"
echo "Pushing: $chart"
helm push "$chart" oci://${{ env.GOOGLE_REGISTRY }}/nais-io/nais/feature
outputs:
chart_name: ${{ steps.package_chart.outputs.name }}
chart_version: ${{ steps.package_chart.outputs.version }}
chart_archive: ${{ steps.package_chart.outputs.archive }}
rollout:
name: Rollout
if: github.actor != 'dependabot[bot]' && github.ref == 'refs/heads/master'
@@ -90,8 +116,12 @@ jobs:
runs-on: fasit-deploy
permissions:
id-token: write
strategy:
fail-fast: false
matrix:
chart: ["wonderwall", "wonderwall-forward-auth"]
steps:
- uses: nais/fasit-deploy@v2 # ratchet:exclude
with:
chart: oci://${{ env.GOOGLE_REGISTRY }}/nais-io/nais/feature/${{ needs.build.outputs.chart_name }}
version: ${{ needs.build.outputs.chart_version }}
chart: oci://${{ env.GOOGLE_REGISTRY }}/nais-io/nais/feature/${{ matrix.chart }}
version: "1.0.0-${{ needs.build.outputs.chart_version }}"

1
.gitignore vendored
View File

@@ -5,6 +5,7 @@ run.sh
*.iml
.env*
*.out
*.tgz
# nix stuffs
/.direnv

View File

@@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/

View File

@@ -0,0 +1,6 @@
dependencies:
- name: valkey
repository: https://charts.bitnami.com/bitnami
version: 3.0.7
digest: sha256:d6621585cb66ddc9802c7a6303b20a33a5970aeaaaf57ee9b45d1cbd9f7a7b27
generated: "2025-05-20T14:28:10.651543+02:00"

View File

@@ -0,0 +1,9 @@
apiVersion: v2
name: wonderwall-forward-auth
description: Forward-auth service for loadbalancer-fa
type: application
version: 1.0.0
dependencies:
- name: valkey
version: 3.0.7
repository: https://charts.bitnami.com/bitnami

View File

@@ -0,0 +1,35 @@
environmentKinds:
- management
timeout: "1800s"
values:
openid.clientID:
required: true
computed:
template: |
{{ .Env.wonderwall_forward_auth_zitadel_client_id | quote }}
openid.clientSecret:
required: true
computed:
template: |
{{ .Env.wonderwall_forward_auth_zitadel_client_secret | quote }}
replicas.min:
config:
type: int
replicas.max:
config:
type: int
session.cookieEncryptionKey:
description: Cookie encryption key, 256 bits (e.g. 32 ASCII characters) encoded with standard base64.
computed:
template: |
{{ .Env.wonderwall_forward_auth_encryption_key | quote }}
sso.domain:
description: Domain for forward auth
computed:
template: |
{{ .Tenant.Name }}.cloud.nais.io
sso.defaultRedirectURL:
description: Default redirect URL for forward auth
computed:
template: |
{{ subdomain . "console" | quote }}

View File

@@ -0,0 +1,62 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "wonderwall-forward-auth.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "wonderwall-forward-auth.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "wonderwall-forward-auth.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "wonderwall-forward-auth.labels" -}}
helm.sh/chart: {{ include "wonderwall-forward-auth.chart" . }}
{{ include "wonderwall-forward-auth.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "wonderwall-forward-auth.selectorLabels" -}}
app.kubernetes.io/name: {{ include "wonderwall-forward-auth.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "wonderwall-forward-auth.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "wonderwall-forward-auth.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,89 @@
---
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
reloader.stakater.com/search: "true"
labels:
{{- include "wonderwall-forward-auth.labels" . | nindent 4 }}
name: {{ include "wonderwall-forward-auth.fullname" . }}
spec:
replicas: 2
selector:
matchLabels:
{{- include "wonderwall-forward-auth.selectorLabels" . | nindent 6 }}
template:
metadata:
annotations:
kubectl.kubernetes.io/default-container: {{ include "wonderwall-forward-auth.fullname" . }}
labels:
{{- include "wonderwall-forward-auth.labels" . | nindent 8 }}
{{ printf "%s-client" .Values.valkey.fullnameOverride }}: "true"
name: {{ include "wonderwall-forward-auth.fullname" . }}
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- podAffinityTerm:
labelSelector:
matchExpressions:
- key: "app.kubernetes.io/name"
operator: In
values:
- "{{ include "wonderwall-forward-auth.fullname" . }}"
topologyKey: kubernetes.io/hostname
weight: 10
containers:
- env:
- name: WONDERWALL_REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: {{ .Values.valkey.fullnameOverride }}
key: "valkey-password"
envFrom:
- secretRef:
name: {{ include "wonderwall-forward-auth.fullname" . }}
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
path: /oauth2/ping
port: http
name: {{ include "wonderwall-forward-auth.fullname" . }}
ports:
- containerPort: 8080
name: http
protocol: TCP
readinessProbe:
httpGet:
path: /oauth2/ping
port: http
resources:
{{- toYaml .Values.resources | nindent 12 }}
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
readOnlyRootFilesystem: true
runAsGroup: 1069
runAsNonRoot: true
runAsUser: 1069
seccompProfile:
type: RuntimeDefault
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /tmp
name: writable-tmp
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext:
seccompProfile:
type: RuntimeDefault
terminationGracePeriodSeconds: 30
volumes:
- emptyDir: {}
name: writable-tmp

View File

@@ -0,0 +1,21 @@
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
labels:
{{- include "wonderwall-forward-auth.labels" . | nindent 4 }}
name: {{ include "wonderwall-forward-auth.fullname" . }}
spec:
minReplicas: {{ .Values.replicas.min }}
maxReplicas: {{ .Values.replicas.max }}
metrics:
- resource:
name: cpu
target:
averageUtilization: 75
type: Utilization
type: Resource
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ include "wonderwall-forward-auth.fullname" . }}

View File

@@ -0,0 +1,23 @@
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/proxy-buffer-size: 16k
nginx.ingress.kubernetes.io/enable-global-auth: "false"
labels:
{{- include "wonderwall-forward-auth.labels" . | nindent 4 }}
name: {{ include "wonderwall-forward-auth.fullname" . }}
spec:
ingressClassName: {{ .Values.ingressClassName }}
rules:
- host: {{ .Values.sso.domain }}
http:
paths:
- backend:
service:
name: {{ include "wonderwall-forward-auth.fullname" . }}
port:
number: 80
path: /
pathType: ImplementationSpecific

View File

@@ -0,0 +1,21 @@
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
labels:
{{- include "wonderwall-forward-auth.labels" . | nindent 4 }}
name: {{ include "wonderwall-forward-auth.fullname" . }}
spec:
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: nais-system
podSelector:
matchLabels:
nais.io/ingressClass: {{ .Values.ingressClassName }}
podSelector:
matchLabels:
{{- include "wonderwall-forward-auth.selectorLabels" . | nindent 6 }}
policyTypes:
- Ingress

View File

@@ -0,0 +1,12 @@
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
labels:
{{- include "wonderwall-forward-auth.labels" . | nindent 4 }}
name: {{ include "wonderwall-forward-auth.fullname" . }}
spec:
{{- toYaml .Values.podDisruptionBudget | nindent 2 }}
selector:
matchLabels:
{{- include "wonderwall-forward-auth.selectorLabels" . | nindent 6 }}

View File

@@ -0,0 +1,32 @@
---
apiVersion: v1
kind: Secret
type: kubernetes.io/Opaque
metadata:
name: {{ include "wonderwall-forward-auth.fullname" . }}
annotations:
reloader.stakater.com/match: "true"
labels:
{{- include "wonderwall-forward-auth.labels" . | nindent 4 }}
stringData:
WONDERWALL_BIND_ADDRESS: "0.0.0.0:8080"
WONDERWALL_COOKIE_SAME_SITE: "None"
WONDERWALL_METRICS_BIND_ADDRESS: "0.0.0.0:8081"
WONDERWALL_INGRESS: "https://{{ .Values.sso.domain }}"
WONDERWALL_SHUTDOWN_WAIT_BEFORE_PERIOD: "5s"
WONDERWALL_OPENID_PROVIDER: "openid"
WONDERWALL_OPENID_CLIENT_ID: "{{ .Values.openid.clientID | required ".Values.openid.clientID is required." }}"
WONDERWALL_OPENID_CLIENT_SECRET: "{{ .Values.openid.clientSecret | required ".Values.openid.clientSecret is required." }}"
WONDERWALL_OPENID_WELL_KNOWN_URL: "{{ .Values.openid.wellKnownURL | required ".Values.openid.wellKnownURL is required." }}"
WONDERWALL_ENCRYPTION_KEY: "{{ .Values.session.cookieEncryptionKey | required ".Values.session.cookieEncryptionKey is required." }}"
WONDERWALL_REDIS_URI: "redis://{{ .Values.valkey.fullnameOverride }}-primary:6379"
WONDERWALL_REDIS_USERNAME: "default"
WONDERWALL_SESSION_MAX_LIFETIME: "{{ .Values.session.maxLifetime | required ".Values.session.maxLifetime is required." }}"
WONDERWALL_SESSION_FORWARD_AUTH: "true"
WONDERWALL_SESSION_INACTIVITY: "{{ .Values.session.inactivity | required ".Values.session.inactivity is required." }}"
WONDERWALL_SESSION_INACTIVITY_TIMEOUT: "{{ .Values.session.inactivityTimeout | required ".Values.session.inactivityTimeout is required." }}"
WONDERWALL_SSO_DOMAIN: "{{ .Values.sso.domain | required ".Values.sso.domain is required." }}"
WONDERWALL_SSO_ENABLED: "true"
WONDERWALL_SSO_MODE: "server"
WONDERWALL_SSO_SESSION_COOKIE_NAME: "{{ .Values.session.cookieName | required ".Values.session.cookieName is required." }}"
WONDERWALL_SSO_SERVER_DEFAULT_REDIRECT_URL: "{{ .Values.sso.defaultRedirectURL | required ".Values.sso.defaultRedirectURL is required." }}"

View File

@@ -0,0 +1,16 @@
---
apiVersion: v1
kind: Service
metadata:
labels:
{{- include "wonderwall-forward-auth.labels" . | nindent 4 }}
name: {{ include "wonderwall-forward-auth.fullname" . }}
spec:
type: ClusterIP
ports:
- name: http
port: 80
protocol: TCP
targetPort: http
selector:
{{- include "wonderwall-forward-auth.selectorLabels" . | nindent 4 }}

View File

@@ -0,0 +1,47 @@
nameOverride: ""
fullnameOverride: ""
image:
repository: europe-north1-docker.pkg.dev/nais-io/nais/images/wonderwall
tag: latest
resources:
limits:
cpu: "2"
memory: 512Mi
requests:
cpu: 100m
memory: 64Mi
replicas:
min: 2
max: 4
podDisruptionBudget:
maxUnavailable: 1
ingressClassName: nais-ingress-fa
openid:
clientID:
clientSecret:
wellKnownURL: https://auth.nais.io/.well-known/openid-configuration
session:
maxLifetime: 10h
# 256 bits key, in standard base64 encoding
cookieEncryptionKey:
cookieName: nais-io-forward-auth
inactivity: true
inactivityTimeout: 1h
sso:
defaultRedirectURL:
domain:
valkey:
fullnameOverride: "wonderwall-forward-auth-valkey"
architecture: "standalone"
primary:
resourcesPreset: "medium"
persistence:
enabled: false
networkPolicy:
enabled: true
allowExternal: false
allowExternalEgress: false