feat: TLS support for web (#301)

* Added TLS support for web

- Added optional configurations `cert_file` and `key_file` to run web server with https

Signed-off-by: Dmytro Bondar <git@bonddim.com>

* Helm chart update

- Refactored Ingress to use one host only (`config.web.external_url` is required)
- Added Certificate resource template (secret is mounted to container into `/app/certs/`)
- Added support for service with mixed protocols (exposes UI and Wireguard ports on same IP)
- Added helm-docs target to makefile
- Changed pod labels to use selectorLabels
- Removed default probes (app runs without healthy web)
- Removed sections from README

Signed-off-by: Dmytro Bondar <git@bonddim.com>

* Fix chart workflow path filter

* Fix chart lint issue

* Skip clean-up tested chart

* Try k3d cluster

---------

Signed-off-by: Dmytro Bondar <git@bonddim.com>
This commit is contained in:
Dmytro Bondar
2024-09-22 13:25:08 +02:00
committed by GitHub
parent e3d05a4678
commit 6ffe1a90ae
17 changed files with 289 additions and 274 deletions

View File

@@ -98,3 +98,12 @@ resources:
requests:
storage: {{ .Values.persistence.size | quote }}
{{- end -}}
{{/*
Define hostname
*/}}
{{- define "wg-portal.hostname" -}}
{{- if .Values.config.web.external_url -}}
{{- (urlParse (tpl .Values.config.web.external_url .)).hostname -}}
{{- end -}}
{{- end -}}

View File

@@ -7,7 +7,7 @@ metadata:
{{- tpl (toYaml .) $ | nindent 4 }}
{{- end }}
labels:
{{- include "wg-portal.labels" . | nindent 4 }}
{{- include "wg-portal.selectorLabels" . | nindent 4 }}
{{- with .Values.podLabels }}
{{- toYaml . | nindent 4 }}
{{- end }}
@@ -36,7 +36,7 @@ spec:
envFrom: {{- tpl (toYaml .) $ | nindent 8 }}
{{- end }}
ports:
- name: http
- name: web
containerPort: {{ .Values.service.web.port }}
protocol: TCP
{{- range $index, $port := .Values.service.wireguard.ports }}
@@ -65,6 +65,10 @@ spec:
readOnly: true
- name: data
mountPath: /app/data
{{- if and .Values.certificate.enabled (include "wg-portal.hostname" .) }}
- name: certs
mountPath: /app/certs
{{- end }}
{{- with .Values.volumeMounts }}
{{- tpl (toYaml .) $ | nindent 8 }}
{{- end }}
@@ -97,6 +101,11 @@ spec:
- name: config
secret:
secretName: {{ include "wg-portal.fullname" . }}
{{- if and .Values.certificate.enabled (include "wg-portal.hostname" .) }}
- name: certs
secret:
secretName: {{ include "wg-portal.fullname" . }}-tls
{{- end }}
{{- if not .Values.persistence.enabled }}
- name: data
emptyDir: {}

View File

@@ -0,0 +1,53 @@
{{/*
Define the service template
{{- include "wg-portal.service" (dict "context" $ "scope" .Values.service.<name> "ports" list "name" "<name>") -}}
*/}}
{{- define "wg-portal.service.tpl" -}}
apiVersion: v1
kind: Service
metadata:
{{- with .scope.annotations }}
annotations: {{- toYaml . | nindent 4 }}
{{- end }}
labels: {{- include "wg-portal.labels" .context | nindent 4 }}
name: {{ include "wg-portal.fullname" .context }}{{ ternary "" (printf "-%s" .name) (empty .name) }}
spec:
{{- with .scope.clusterIP }}
clusterIP: {{ . }}
{{- end }}
{{- with .scope.externalIPs }}
externalIPs: {{ toYaml . | nindent 4 }}
{{- end }}
{{- with .scope.externalName }}
externalName: {{ . }}
{{- end }}
{{- with .scope.externalTrafficPolicy }}
externalTrafficPolicy: {{ . }}
{{- end }}
{{- with .scope.healthCheckNodePort }}
healthCheckNodePort: {{ . }}
{{- end }}
{{- with .scope.loadBalancerIP }}
loadBalancerIP: {{ . }}
{{- end }}
{{- with .scope.loadBalancerSourceRanges }}
loadBalancerSourceRanges: {{ toYaml . | nindent 4 }}
{{- end }}
ports: {{- toYaml .ports | nindent 4 }}
{{- with .scope.publishNotReadyAddresses }}
publishNotReadyAddresses: {{ . }}
{{- end }}
{{- with .scope.sessionAffinity }}
sessionAffinity: {{ . }}
{{- end }}
{{- with .scope.sessionAffinityConfig }}
sessionAffinityConfig: {{ toYaml . | nindent 4 }}
{{- end }}
{{- with .scope.topologyKeys }}
topologyKeys: {{ toYaml . | nindent 4 }}
{{- end }}
{{- with .scope.type }}
type: {{ . }}
{{- end }}
selector: {{- include "wg-portal.selectorLabels" .context | nindent 4 }}
{{- end -}}

View File

@@ -0,0 +1,54 @@
{{/* https://cert-manager.io/docs/usage/certificate/#creating-certificate-resources */}}
{{- if and .Values.certificate.enabled (include "wg-portal.hostname" .) -}}
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: {{ include "wg-portal.fullname" . }}
labels: {{- include "wg-portal.labels" . | nindent 4 }}
spec:
secretName: {{ include "wg-portal.fullname" . }}-tls
{{- with .Values.certificate.secretTemplate }}
secretTemplate: {{ toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.certificate.privateKey }}
privateKey: {{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.certificate.keystores }}
keystores: {{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.certificate.duration }}
duration: {{ . }}
{{- end }}
{{- with .Values.certificate.renewBefore }}
renewBefore: {{ . }}
{{- end }}
{{- with .Values.certificate.usages }}
usages: {{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.certificate.subject }}
subject: {{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.certificate.commonName }}
commonName: {{ . }}
{{- end }}
dnsNames:
- {{ include "wg-portal.hostname" . }}
{{- with .Values.certificate.uris }}
uris: {{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.certificate.emailAddresses }}
emailAddresses: {{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.certificate.ipAddresses }}
ipAddresses: {{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.certificate.otherNames }}
otherNames: {{- toYaml . | nindent 4 }}
{{- end }}
issuerRef:
{{- with .Values.certificate.issuer.group }}
group: {{ . }}
{{- end }}
kind: {{ .Values.certificate.issuer.kind }}
name: {{ .Values.certificate.issuer.name }}
{{- end -}}

View File

@@ -1,4 +1,5 @@
{{- if .Values.ingress.enabled -}}
{{- $hostname := include "wg-portal.hostname" . -}}
{{- if and .Values.ingress.enabled $hostname -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
@@ -10,38 +11,20 @@ metadata:
spec:
ingressClassName: {{ .Values.ingress.className }}
rules:
- host: {{ .Values.ingress.host }}
- host: {{ $hostname }}
http:
paths:
- path: /
- path: {{ default "/" (urlParse (tpl .Values.config.web.external_url .)).path }}
pathType: {{ default "ImplementationSpecific" .pathType }}
backend:
service:
name: {{ include "wg-portal.fullname" . }}-web
name: {{ include "wg-portal.fullname" . }}
port:
name: http
{{- range .Values.ingress.extraHosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
pathType: {{ default "ImplementationSpecific" .pathType }}
backend:
service:
name: {{ include "wg-portal.fullname" . }}-web
port:
name: http
{{- end }}
{{- end }}
name: web
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
- {{ $hostname | quote }}
secretName: {{ include "wg-portal.fullname" . }}-tls
{{- end }}
{{- end }}

View File

@@ -32,10 +32,6 @@ stringData:
{{- end }}
web:
listening_address: :{{ .Values.service.web.port }}
{{- if and .Values.ingress.enabled (not (hasKey .Values.config.web "external_url")) }}
{{- $proto := ternary "http" "https" (empty .Values.ingress.tls) }}
external_url: {{ trimSuffix "/" (printf "%s://%s%s" $proto .Values.ingress.host .Values.ingress.path) }}
{{- end }}
{{- with .Values.config.web }}
{{- tpl (toYaml (omit . "listening_address")) $ | nindent 6 }}
{{- end }}

View File

@@ -1,16 +0,0 @@
apiVersion: v1
kind: Service
metadata:
{{- with .Values.service.web.annotations }}
annotations: {{- toYaml . | nindent 4 }}
{{- end }}
name: {{ include "wg-portal.fullname" . }}-web
labels: {{- include "wg-portal.labels" . | nindent 4 }}
spec:
ports:
- port: {{ .Values.service.web.port }}
targetPort: http
protocol: TCP
name: http
selector: {{- include "wg-portal.selectorLabels" . | nindent 4 }}
type: {{ .Values.service.web.type }}

View File

@@ -1,27 +0,0 @@
apiVersion: v1
kind: Service
metadata:
{{- with .Values.service.wireguard.annotations }}
annotations: {{- toYaml . | nindent 4 }}
{{- end }}
name: {{ include "wg-portal.fullname" . }}-wireguard
labels: {{- include "wg-portal.labels" . | nindent 4 }}
spec:
{{- with .Values.service.wireguard.externalTrafficPolicy }}
externalTrafficPolicy: {{ . }}
{{- end }}
{{- with .Values.service.wireguard.loadBalancerSourceRanges }}
loadBalancerSourceRanges: {{- toYaml . | nindent 4 }}
{{- end }}
ports:
{{- range $index, $port := .Values.service.wireguard.ports }}
- port: {{ $port }}
targetPort: wg{{ $index }}
protocol: UDP
name: wg{{ $index }}
{{- end }}
selector: {{- include "wg-portal.selectorLabels" . | nindent 4 }}
{{- with .Values.service.wireguard.sessionAffinity }}
sessionAffinity: {{ . }}
{{- end }}
type: {{ .Values.service.wireguard.type }}

View File

@@ -0,0 +1,14 @@
{{- $portsWeb := list (dict "name" "web" "port" .Values.service.web.port "protocol" "TCP" "targetPort" "web") -}}
{{- $ports := list -}}
{{- range $idx, $port := .Values.service.wireguard.ports -}}
{{- $name := printf "wg%d" $idx -}}
{{- $ports = append $ports (dict "name" $name "port" $port "protocol" "UDP" "targetPort" $name) -}}
{{- end -}}
{{- if .Values.service.mixed.enabled -}}
{{ include "wg-portal.service.tpl" (dict "context" . "scope" .Values.service.mixed "ports" (concat $portsWeb $ports)) }}
{{- else }}
{{ include "wg-portal.service.tpl" (dict "context" . "scope" .Values.service.web "ports" $portsWeb) }}
---
{{ include "wg-portal.service.tpl" (dict "context" . "scope" .Values.service.wireguard "ports" $ports "name" "wireguard") }}
{{- end -}}