From b26d0968e1afa453eaa672f86467f00bf1d1e721 Mon Sep 17 00:00:00 2001 From: Vitaliy Snurnitsin Date: Sat, 29 Jan 2022 15:47:26 +0300 Subject: [PATCH] add helm chart example --- helm/Chart.yaml | 2 + helm/README.md | 1 + helm/templates/configmap.yaml | 88 +++++++++++++++++++++++++ helm/templates/deployment.yaml | 117 +++++++++++++++++++++++++++++++++ helm/templates/ingress.yaml | 39 +++++++++++ helm/templates/rbac.yaml | 36 ++++++++++ helm/templates/secret.yaml | 8 +++ helm/templates/service.yaml | 57 ++++++++++++++++ helm/values.yaml | 26 ++++++++ 9 files changed, 374 insertions(+) create mode 100644 helm/Chart.yaml create mode 100644 helm/README.md create mode 100644 helm/templates/configmap.yaml create mode 100644 helm/templates/deployment.yaml create mode 100644 helm/templates/ingress.yaml create mode 100644 helm/templates/rbac.yaml create mode 100644 helm/templates/secret.yaml create mode 100644 helm/templates/service.yaml create mode 100644 helm/values.yaml diff --git a/helm/Chart.yaml b/helm/Chart.yaml new file mode 100644 index 0000000..71838aa --- /dev/null +++ b/helm/Chart.yaml @@ -0,0 +1,2 @@ +name: ovpn-admin +version: 1.0.0 diff --git a/helm/README.md b/helm/README.md new file mode 100644 index 0000000..eabf182 --- /dev/null +++ b/helm/README.md @@ -0,0 +1 @@ +helm chart example diff --git a/helm/templates/configmap.yaml b/helm/templates/configmap.yaml new file mode 100644 index 0000000..076e72d --- /dev/null +++ b/helm/templates/configmap.yaml @@ -0,0 +1,88 @@ +{{ $openvpnNetwork := required "A valid .Values.openvpn.subnet entry required!" .Values.openvpn.subnet }} +{{ $openvpnNetworkAddress := index (splitList "/" $openvpnNetwork) 0 }} +{{ $openvpnNetworkNetmask := index (splitList "/" $openvpnNetwork) 1 }} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: openvpn +data: + openvpn.conf: |- + user nobody + group nogroup + + mode server + tls-server + # dev-type tun + dev tun + proto tcp-server + port 1194 + # local 127.0.0.1 + management 127.0.0.1 8989 + + tun-mtu 1500 + mssfix + # only udp + #fragment 1300 + + keepalive 10 60 + client-to-client + persist-key + persist-tun + + cipher AES-128-CBC + duplicate-cn + + server {{ $openvpnNetworkAddress }} {{ $openvpnNetworkNetmask }} + + topology subnet + push "topology subnet" + push "route-metric 9999" + + verb 4 + + ifconfig-pool-persist /tmp/openvpn.ipp + status /tmp/openvpn.status + + key-direction 0 + + ca /etc/openvpn/certs/pki/ca.crt + key /etc/openvpn/certs/pki/private/server.key + cert /etc/openvpn/certs/pki/issued/server.crt + dh /etc/openvpn/certs/pki/dh.pem + crl-verify /etc/openvpn/certs/pki/crl.pem + tls-auth /etc/openvpn/certs/pki/ta.key + client-config-dir /etc/openvpn/ccd + + entrypoint.sh: |- + #!/bin/sh + set -x + + iptables -t nat -A POSTROUTING -s {{ $openvpnNetworkAddress }}/{{ $openvpnNetworkNetmask }} ! -d {{ $openvpnNetworkAddress }}/{{ $openvpnNetworkNetmask }} -j MASQUERADE + + mkdir -p /dev/net + if [ ! -c /dev/net/tun ]; then + mknod /dev/net/tun c 10 200 + fi + + wait_file() { + file_path="$1" + while true; do + if [ -f $file_path ]; then + break + fi + echo "wait $file_path" + sleep 2 + done + } + + easyrsa_path="/etc/openvpn/certs" + + wait_file "$easyrsa_path/pki/ca.crt" + wait_file "$easyrsa_path/pki/private/server.key" + wait_file "$easyrsa_path/pki/issued/server.crt" + wait_file "$easyrsa_path/pki/ta.key" + wait_file "$easyrsa_path/pki/dh.pem" + wait_file "$easyrsa_path/pki/crl.pem" + + openvpn --config /etc/openvpn/openvpn.conf diff --git a/helm/templates/deployment.yaml b/helm/templates/deployment.yaml new file mode 100644 index 0000000..1cc0538 --- /dev/null +++ b/helm/templates/deployment.yaml @@ -0,0 +1,117 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: openvpn +spec: + selector: + matchLabels: + app: openvpn + template: + metadata: + labels: + app: openvpn + spec: + {{- if .Values.openvpn.nodeSelector }} + nodeSelector: + {{- .Values.openvpn.nodeSelector | toYaml | indent 8 | printf "\n%s" }} + {{- end }} + {{- if .Values.openvpn.tolerations }} + tolerations: + {{- .Values.openvpn.tolerations | toYaml | indent 8 | printf "\n%s" }} + {{- end }} + terminationGracePeriodSeconds: 0 + serviceAccountName: openvpn + containers: + - name: ovpn-admin + image: {{ .Values.ovpnAdmin.image }} + command: + - /bin/sh + - -c + - /app/ovpn-admin + --storage.backend="kubernetes.secrets" + --listen.host="0.0.0.0" + --listen.port="8000" + --role="master" + {{- if hasKey .Values.openvpn "inlet" }} + {{- if eq .Values.openvpn.inlet "LoadBalancer" }} + --ovpn.server.behindLB + --ovpn.service="openvpn-external" + {{- end }} + {{- end }} + --mgmt=main="127.0.0.1:8989" + --ccd --ccd.path="/mnt/ccd" + --easyrsa.path="/mnt/certs" + {{- $externalHost := "" }} + {{- if hasKey .Values.openvpn "inlet" }} + {{- if eq .Values.openvpn.inlet "ExternalIP" }}{{ $externalHost = .Values.openvpn.externalIP }}{{- end }} + {{- end }} + {{- if hasKey .Values.openvpn "externalHost" }}{{ $externalHost = .Values.openvpn.externalHost }}{{- end }} + {{- if ne $externalHost "" }} + --ovpn.server="{{ $externalHost }}:{{ .Values.openvpn.externalPort | default 5416 | quote }}:tcp" + {{- end }} + ports: + - name: ovpn-admin + protocol: TCP + containerPort: 8000 + volumeMounts: + - name: certs + mountPath: /mnt/certs + - name: ccd + mountPath: /mnt/ccd + - name: openvpn + image: {{ .Values.openvpn.image }} + command: [ '/entrypoint.sh' ] + # imagePullPolicy: Always + securityContext: + allowPrivilegeEscalation: false + capabilities: + add: + - NET_ADMIN + - NET_RAW + - MKNOD + - SETGID + - SETUID + drop: + - ALL + ports: + - name: openvpn-tcp + protocol: TCP + containerPort: 1194 + {{- if eq .Values.openvpn.inlet "HostPort" }} + hostPort: {{ .Values.openvpn.hostPort }} + {{- end }} + volumeMounts: + - name: tmp + mountPath: /tmp + - name: dev-net + mountPath: /dev/net + - name: certs + mountPath: /etc/openvpn/certs + - name: ccd + mountPath: /etc/openvpn/ccd + - name: config + mountPath: /etc/openvpn/openvpn.conf + subPath: openvpn.conf + readOnly: true + - name: entrypoint + mountPath: /entrypoint.sh + subPath: entrypoint.sh + readOnly: true + volumes: + - name: tmp + emptyDir: {} + - name: dev-net + emptyDir: {} + - name: certs + emptyDir: {} + - name: ccd + emptyDir: {} + - name: config + configMap: + name: openvpn + defaultMode: 0644 + - name: entrypoint + configMap: + name: openvpn + defaultMode: 0755 diff --git a/helm/templates/ingress.yaml b/helm/templates/ingress.yaml new file mode 100644 index 0000000..8f227ef --- /dev/null +++ b/helm/templates/ingress.yaml @@ -0,0 +1,39 @@ +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ovpn-admin + annotations: + kubernetes.io/ingress.class: nginx + nginx.ingress.kubernetes.io/backend-protocol: HTTP + nginx.ingress.kubernetes.io/auth-type: basic + nginx.ingress.kubernetes.io/auth-realm: "Authentication Required" + nginx.ingress.kubernetes.io/auth-secret: basic-auth +spec: + tls: + - hosts: + - {{ .Values.domain }} + secretName: ingress-tls + rules: + - host: {{ .Values.domain }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: ovpn-admin + port: + name: http +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: ovpn-admin +spec: + secretName: ingress-tls + dnsNames: + - {{ .Values.domain }} + issuerRef: + name: letsencrypt + kind: ClusterIssuer diff --git a/helm/templates/rbac.yaml b/helm/templates/rbac.yaml new file mode 100644 index 0000000..4693d83 --- /dev/null +++ b/helm/templates/rbac.yaml @@ -0,0 +1,36 @@ +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: openvpn +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: openvpn +rules: +- apiGroups: + - "" + resources: + - services + verbs: + - get + - list +- apiGroups: + - "" + resources: + - secrets + verbs: + - "*" +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: openvpn +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: openvpn +subjects: +- kind: ServiceAccount + name: openvpn diff --git a/helm/templates/secret.yaml b/helm/templates/secret.yaml new file mode 100644 index 0000000..b2dd27d --- /dev/null +++ b/helm/templates/secret.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: basic-auth +type: Opaque +data: + auth: {{ print .Values.ovpnAdmin.basicAuth.user ":{PLAIN}" .Values.ovpnAdmin.basicAuth.password | b64enc | quote }} diff --git a/helm/templates/service.yaml b/helm/templates/service.yaml new file mode 100644 index 0000000..e04e626 --- /dev/null +++ b/helm/templates/service.yaml @@ -0,0 +1,57 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: ovpn-admin +spec: + clusterIP: None + ports: + - name: http + port: 8000 + protocol: TCP + targetPort: 8000 + selector: + app: openvpn +--- +{{- if hasKey .Values.openvpn "inlet" }} + + {{- if eq .Values.openvpn.inlet "LoadBalancer" }} +--- +apiVersion: v1 +kind: Service +metadata: + name: openvpn-external +spec: + externalTrafficPolicy: Local + type: LoadBalancer + ports: + - name: openvpn-tcp + protocol: TCP + port: {{ .Values.openvpn.externalPort | default 1194 }} + targetPort: openvpn-tcp + selector: + app: openvpn + {{- else if eq .Values.openvpn.inlet "ExternalIP" }} +--- +apiVersion: v1 +kind: Service +metadata: + name: openvpn-external +spec: + type: ClusterIP + externalIPs: + - {{ .Values.openvpn.externalIP }} + ports: + - name: openvpn-tcp + port: {{ .Values.openvpn.externalPort | default 1194 }} + protocol: TCP + targetPort: openvpn-tcp + selector: + app: openvpn + {{- else if eq .Values.openvpn.inlet "HostPort" }} +--- + {{- else }} + {{- cat "Unsupported inlet type" .inlet | fail }} + {{- end }} + +{{- end }} diff --git a/helm/values.yaml b/helm/values.yaml new file mode 100644 index 0000000..544e3dd --- /dev/null +++ b/helm/values.yaml @@ -0,0 +1,26 @@ +domain: changeme +ovpnAdmin: + image: changeme + basicAuth: + user: admin + password: changeme +openvpn: + image: changeme + subnet: 172.16.200.0/255.255.255.0 + # nodeSelector: + # node-role.kubernetes.io/master: "" + # tolerations: + # - effect: NoSchedule + # key: node-role.kubernetes.io/master + # + # // LoadBalancer or ExternalIP or HostPort + inlet: HostPort + # + # If inlet: ExternalIP + # externalIP: 1.2.3.4 + # externalPort: 1194 + # + # If inlet: HostPort + hostPort: 1194 + # Domain or ip for connect to OpenVPN server + # externalHost: 1.2.3.4