From 8513efef38525ac6125150a02e4e6a0af7abb1ac Mon Sep 17 00:00:00 2001 From: Johnny Horvi Date: Thu, 4 Apr 2024 10:10:32 +0200 Subject: [PATCH] Add config for forward auth server Co-authored-by: Frode Sundby Co-authored-by: Trong Huu Nguyen Co-authored-by: Thomas Siegfried Krampl --- charts/wonderwall/Feature.yaml | 11 ++ charts/wonderwall/templates/_helpers.tpl | 27 ++++ charts/wonderwall/templates/fa-azureapp.yaml | 16 +++ .../wonderwall/templates/fa-deployment.yaml | 115 ++++++++++++++++++ charts/wonderwall/templates/fa-ingress.yaml | 25 ++++ charts/wonderwall/templates/fa-secret.yaml | 28 +++++ charts/wonderwall/templates/fa-service.yaml | 17 +++ .../wonderwall/templates/networkpolicy.yaml | 13 +- charts/wonderwall/values.yaml | 9 +- 9 files changed, 256 insertions(+), 5 deletions(-) create mode 100644 charts/wonderwall/templates/fa-azureapp.yaml create mode 100644 charts/wonderwall/templates/fa-deployment.yaml create mode 100644 charts/wonderwall/templates/fa-ingress.yaml create mode 100644 charts/wonderwall/templates/fa-secret.yaml create mode 100644 charts/wonderwall/templates/fa-service.yaml diff --git a/charts/wonderwall/Feature.yaml b/charts/wonderwall/Feature.yaml index 8d4ab15..7c7843d 100644 --- a/charts/wonderwall/Feature.yaml +++ b/charts/wonderwall/Feature.yaml @@ -21,6 +21,17 @@ values: description: Aiven Prometheus integration endpoint ID. computed: template: '"{{ .Env.aiven_prometheus_endpoint_id }}"' + azure.forwardAuth: + description: Enables forward auth server + config: + type: boolean + azure.ssoDomain: + description: Cookie domain for forward auth + config: + type: string + azure.ssoDefaultRedirectURL: + config: + type: string idporten.openidResourceIndicator: description: Resource indicator for audience-restricted tokens. required: true diff --git a/charts/wonderwall/templates/_helpers.tpl b/charts/wonderwall/templates/_helpers.tpl index 88637e5..6f150a3 100644 --- a/charts/wonderwall/templates/_helpers.tpl +++ b/charts/wonderwall/templates/_helpers.tpl @@ -43,6 +43,14 @@ app.kubernetes.io/managed-by: {{ .Release.Service }} team: nais {{- end }} +{{/* +Common labels for forward auth +*/}} +{{- define "wonderwall.labelsForwardAuth" -}} +{{ include "wonderwall.labels" . }} +app: wonderwall-fa +{{- end }} + {{/* Common labels for ID-porten */}} @@ -59,6 +67,14 @@ app.kubernetes.io/name: {{ include "wonderwall.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end }} +{{/* +Selector labels for forward auth +*/}} +{{- define "wonderwall.selectorLabelsForwardAuth" -}} +{{ include "wonderwall.selectorLabels" . }} +app: wonderwall-fa +{{- end }} + {{/* Selector labels for ID-porten */}} @@ -78,6 +94,17 @@ Create the name of the service account to use {{- end }} {{- end }} +{{/* +Azure SSO server URL. +*/}} +{{- define "wonderwall.azure.ssoServerURL" -}} +{{- if not .Values.azure.ssoServerHost }} +{{- fail ".Values.azure.ssoServerHost is required." }} +{{ else }} +{{- printf "https://%s" .Values.azure.ssoServerHost }} +{{- end }} +{{- end }} + {{/* ID-porten SSO server URL. */}} diff --git a/charts/wonderwall/templates/fa-azureapp.yaml b/charts/wonderwall/templates/fa-azureapp.yaml new file mode 100644 index 0000000..1bbfc2d --- /dev/null +++ b/charts/wonderwall/templates/fa-azureapp.yaml @@ -0,0 +1,16 @@ +{{ if .Values.azure.forwardAuth }} +--- +apiVersion: nais.io/v1 +kind: AzureAdApplication +metadata: + name: {{ include "wonderwall.fullname" . }}-fa + labels: + {{- include "wonderwall.labelsForwardAuth" . | nindent 4 }} +spec: + secretName: {{ .Values.azure.clientSecretName }} + allowAllUsers: true + logoutUrl: "{{ include "wonderwall.azure.ssoServerURL" . }}/oauth2/logout/frontchannel" + replyUrls: + - url: "{{- include "wonderwall.azure.ssoServerURL" . }}/oauth2/callback" + tenant: nav.no +{{ end }} diff --git a/charts/wonderwall/templates/fa-deployment.yaml b/charts/wonderwall/templates/fa-deployment.yaml new file mode 100644 index 0000000..7492310 --- /dev/null +++ b/charts/wonderwall/templates/fa-deployment.yaml @@ -0,0 +1,115 @@ +{{- if .Values.azure.forwardAuth -}} +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + reloader.stakater.com/search: "true" + labels: + aiven: enabled + azure: enabled + name: {{ include "wonderwall.fullname" . }}-fa +spec: + replicas: 2 + selector: + matchLabels: + {{- include "wonderwall.selectorLabelsForwardAuth" . | nindent 6 }} + template: + metadata: + annotations: + kubectl.kubernetes.io/default-container: wonderwall-fa + prometheus.io/path: / + prometheus.io/port: "8081" + prometheus.io/scrape: "true" + labels: + aiven: enabled + azure: enabled + {{- include "wonderwall.labelsForwardAuth" . | nindent 8 }} + name: wonderwall-fa + spec: + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchExpressions: + - key: "app.kubernetes.io/name" + operator: In + values: + - "{{ include "wonderwall.name" . }}" + topologyKey: kubernetes.io/hostname + weight: 10 + containers: + - env: + - name: WONDERWALL_REDIS_URI + valueFrom: + secretKeyRef: + key: REDIS_URI_WONDERWALL_AZURE + name: {{ .Values.azure.redisSecretName }} + - name: OTEL_SERVICE_NAME + value: {{ .Values.otel.serviceName }} + - name: OTEL_EXPORTER_OTLP_ENDPOINT + value: {{ .Values.otel.endpoint }} + - name: OTEL_RESOURCE_ATTRIBUTES + value: {{ .Values.otel.resourceAttributes }} + - name: WONDERWALL_REDIS_USERNAME + valueFrom: + secretKeyRef: + key: REDIS_USERNAME_WONDERWALL_AZURE + name: {{ .Values.azure.redisSecretName }} + - name: WONDERWALL_REDIS_PASSWORD + valueFrom: + secretKeyRef: + key: REDIS_PASSWORD_WONDERWALL_AZURE + name: {{ .Values.azure.redisSecretName }} + envFrom: + - secretRef: + name: "{{ .Values.azure.clientSecretName }}" + - secretRef: + name: "{{ .Values.azure.ssoServerSecretName }}" + image: {{ .Values.image.repository }}:{{ .Values.image.tag }} + imagePullPolicy: IfNotPresent + livenessProbe: + httpGet: + path: /oauth2/ping + port: http + name: wonderwall-fa + 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 + imagePullSecrets: {{ toYaml .Values.imagePullSecrets }} + restartPolicy: Always + schedulerName: default-scheduler + securityContext: + seccompProfile: + type: RuntimeDefault + serviceAccountName: {{ include "wonderwall.fullname" . }} + terminationGracePeriodSeconds: 30 + volumes: + - emptyDir: {} + name: writable-tmp +{{- end }} diff --git a/charts/wonderwall/templates/fa-ingress.yaml b/charts/wonderwall/templates/fa-ingress.yaml new file mode 100644 index 0000000..71cae67 --- /dev/null +++ b/charts/wonderwall/templates/fa-ingress.yaml @@ -0,0 +1,25 @@ +{{ if .Values.azure.forwardAuth }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + nginx.ingress.kubernetes.io/proxy-buffer-size: 16k + prometheus.io/path: /oauth2/ping + prometheus.io/scrape: "true" + labels: + {{- include "wonderwall.labelsForwardAuth" . | nindent 4 }} + name: {{ include "wonderwall.fullname" . }}-fa +spec: + ingressClassName: {{ .Values.azure.ingressClassName }} + rules: + - host: {{ .Values.azure.ssoDomain }} + http: + paths: + - backend: + service: + name: {{ include "wonderwall.fullname" . }}-fa + port: + number: 80 + path: / + pathType: ImplementationSpecific +{{ end }} diff --git a/charts/wonderwall/templates/fa-secret.yaml b/charts/wonderwall/templates/fa-secret.yaml new file mode 100644 index 0000000..536e91f --- /dev/null +++ b/charts/wonderwall/templates/fa-secret.yaml @@ -0,0 +1,28 @@ +{{ if .Values.azure.forwardAuth }} +--- +apiVersion: v1 +kind: Secret +type: kubernetes.io/Opaque +metadata: + name: "{{ .Values.azure.ssoServerSecretName }}" + annotations: + reloader.stakater.com/match: "true" + labels: + {{- include "wonderwall.labels" . | nindent 4 }} +stringData: + WONDERWALL_BIND_ADDRESS: "0.0.0.0:8080" + WONDERWALL_METRICS_BIND_ADDRESS: "0.0.0.0:8081" + WONDERWALL_INGRESS: "{{- include "wonderwall.azure.ssoServerURL" . }}" + WONDERWALL_SHUTDOWN_WAIT_BEFORE_PERIOD: "5s" + WONDERWALL_OPENID_PROVIDER: "azure" + WONDERWALL_REDIS_CONNECTION_IDLE_TIMEOUT: "{{ .Values.redis.connectionIdleTimeout }}" + WONDERWALL_ENCRYPTION_KEY: "{{ .Values.azure.sessionCookieEncryptionKey | required ".Values.azure.sessionCookieEncryptionKey is required." }}" + WONDERWALL_SESSION_MAX_LIFETIME: "{{ .Values.azure.sessionMaxLifetime | required ".Values.azure.sessionMaxLifetime is required." }}" + WONDERWALL_SESSION_REFRESH: "false" + WONDERWALL_SESSION_REFRESH_AUTO: "false" + WONDERWALL_SSO_DOMAIN: "{{ .Values.azure.ssoDomain | required ".Values.azure.ssoDomain is required." }}" + WONDERWALL_SSO_ENABLED: "true" + WONDERWALL_SSO_MODE: "server" + WONDERWALL_SSO_SESSION_COOKIE_NAME: "{{ .Values.azure.sessionCookieName | required ".Values.azure.sessionCookieName is required." }}" + WONDERWALL_SSO_SERVER_DEFAULT_REDIRECT_URL: "{{ .Values.azure.ssoDefaultRedirectURL | required ".Values.azure.ssoDefaultRedirectURL is required." }}" +{{ end }} diff --git a/charts/wonderwall/templates/fa-service.yaml b/charts/wonderwall/templates/fa-service.yaml new file mode 100644 index 0000000..44d89e2 --- /dev/null +++ b/charts/wonderwall/templates/fa-service.yaml @@ -0,0 +1,17 @@ +{{ if .Values.azure.forwardAuth }} +apiVersion: v1 +kind: Service +metadata: + labels: + {{- include "wonderwall.labelsForwardAuth" . | nindent 4 }} + name: {{ include "wonderwall.fullname" . }}-fa +spec: + type: ClusterIP + ports: + - name: http + port: 80 + protocol: TCP + targetPort: http + selector: + {{- include "wonderwall.selectorLabelsForwardAuth" . | nindent 4 }} +{{ end }} diff --git a/charts/wonderwall/templates/networkpolicy.yaml b/charts/wonderwall/templates/networkpolicy.yaml index 873bef1..526e49a 100644 --- a/charts/wonderwall/templates/networkpolicy.yaml +++ b/charts/wonderwall/templates/networkpolicy.yaml @@ -1,9 +1,8 @@ -{{ if .Values.idporten.enabled }} apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: labels: - {{- include "wonderwall.labelsIdporten" . | nindent 4 }} + {{- include "wonderwall.labels" . | nindent 4 }} name: {{ include "wonderwall.fullname" . }}-idporten spec: egress: @@ -31,6 +30,13 @@ spec: podSelector: matchLabels: app.kubernetes.io/name: prometheus + - from: + - namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: nais-system + podSelector: + matchLabels: + nais.io/ingressClass: {{ .Values.azure.ingressClassName }} - from: - namespaceSelector: matchLabels: @@ -44,8 +50,7 @@ spec: linkerd.io/is-control-plane: "true" podSelector: matchLabels: - {{- include "wonderwall.selectorLabelsIdporten" . | nindent 6 }} + {{- include "wonderwall.selectorLabels" . | nindent 6 }} policyTypes: - Ingress - Egress -{{ end }} diff --git a/charts/wonderwall/values.yaml b/charts/wonderwall/values.yaml index f877a75..0103edf 100644 --- a/charts/wonderwall/values.yaml +++ b/charts/wonderwall/values.yaml @@ -12,9 +12,16 @@ aiven: redisPlan: azure: enabled: true + clientSecretName: azure-sso-secret + ingressClassName: nais-ingress-fa redisSecretName: wonderwall-azure-redis-rw - sessionRefresh: true + forwardAuth: false + sessionCookieName: forwardauth + ssoDomain: + ssoDefaultRedirectURL: sessionMaxLifetime: 10h + sessionRefresh: true + ssoServerSecretName: wonderwall-azure-sso-server idporten: enabled: true clientAccessTokenLifetime: 3600