From 6a3b129a4bf164b0bc8c93beb672cd1c101e7186 Mon Sep 17 00:00:00 2001 From: Arno DUBOIS Date: Fri, 6 Mar 2020 22:35:35 +0100 Subject: [PATCH] [stable/unifi] Adding captive portal service (#21241) * [stable/unifi] Adding captive portal service Signed-off-by: Arno Dubois Signed-off-by: Arno DUBOIS * [stable/unifi] Annnd bumping version Signed-off-by: Arno Dubois Signed-off-by: Arno DUBOIS * Added an enabled switch Signed-off-by: Arno DUBOIS * [stable/unifi] Fixing feedbacks Signed-off-by: Arno DUBOIS * [stable/unifi] Adding captive portal ingress Signed-off-by: Arno DUBOIS * [stable/unifi] Better table formatting Signed-off-by: Arno DUBOIS * [stable/unifi] Fixed ingress Signed-off-by: Arno DUBOIS Co-authored-by: Arno DUBOIS --- charts/unifi/Chart.yaml | 2 +- charts/unifi/README.md | 156 +++++++++++--------- charts/unifi/templates/captive-ingress.yaml | 39 +++++ charts/unifi/templates/captive-svc.yaml | 61 ++++++++ charts/unifi/templates/deployment.yaml | 8 + charts/unifi/templates/unified-svc.yaml | 17 +++ charts/unifi/values.yaml | 41 +++++ 7 files changed, 255 insertions(+), 69 deletions(-) create mode 100644 charts/unifi/templates/captive-ingress.yaml create mode 100644 charts/unifi/templates/captive-svc.yaml diff --git a/charts/unifi/Chart.yaml b/charts/unifi/Chart.yaml index 03418128..abd0a472 100644 --- a/charts/unifi/Chart.yaml +++ b/charts/unifi/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v1 appVersion: 5.11.50 description: Ubiquiti Network's Unifi Controller name: unifi -version: 0.6.1 +version: 0.6.2 keywords: - ubiquiti - unifi diff --git a/charts/unifi/README.md b/charts/unifi/README.md index 87fdecb8..e8ac1e82 100644 --- a/charts/unifi/README.md +++ b/charts/unifi/README.md @@ -34,74 +34,89 @@ The command removes all the Kubernetes components associated with the chart and The following tables lists the configurable parameters of the Unifi chart and their default values. -| Parameter | Description | Default | -| -------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ---------------------------- | -| `image.repository` | Image repository | `jacobalberty/unifi` | -| `image.tag` | Image tag. Possible values listed [here][docker]. | `5.11.50` | -| `image.pullPolicy` | Image pull policy | `IfNotPresent` | -| `strategyType` | Specifies the strategy used to replace old Pods by new ones | `Recreate` | -| `guiService.type` | Kubernetes service type for the Unifi GUI | `ClusterIP` | -| `guiService.port` | Kubernetes port where the Unifi GUI is exposed | `8443` | -| `guiService.annotations` | Service annotations for the Unifi GUI | `{}` | -| `guiService.labels` | Custom labels | `{}` | -| `guiService.loadBalancerIP` | Loadbalance IP for the Unifi GUI | `{}` | -| `guiService.loadBalancerSourceRanges` | List of IP CIDRs allowed access to load balancer (if supported) | None | -| `guiService.externalTrafficPolicy` | Set the externalTrafficPolicy in the Service to either Cluster or Local | `Cluster` | -| `controllerService.type` | Kubernetes service type for the Unifi Controller communication | `NodePort` | -| `controllerService.port` | Kubernetes port where the Unifi Controller is exposed - this needs to be reachable by the unifi devices on the network | `8080` | -| `controllerService.annotations` | Service annotations for the Unifi Controller | `{}` | -| `controllerService.labels` | Custom labels | `{}` | -| `controllerService.loadBalancerIP` | Loadbalance IP for the Unifi Controller | `{}` | -| `controllerService.loadBalancerSourceRanges` | List of IP CIDRs allowed access to load balancer (if supported) | None | -| `controllerService.externalTrafficPolicy` | Set the externalTrafficPolicy in the Service to either Cluster or Local | `Cluster` | -| `stunService.type` | Kubernetes service type for the Unifi STUN | `NodePort` | -| `stunService.port` | Kubernetes UDP port where the Unifi STUN is exposed | `3478` | -| `stunService.annotations` | Service annotations for the Unifi STUN | `{}` | -| `stunService.labels` | Custom labels | `{}` | -| `stunService.loadBalancerIP` | Loadbalance IP for the Unifi STUN | `{}` | -| `stunService.loadBalancerSourceRanges` | List of IP CIDRs allowed access to load balancer (if supported) | None | -| `stunService.externalTrafficPolicy` | Set the externalTrafficPolicy in the Service to either Cluster or Local | `Cluster` | -| `discoveryService.type` | Kubernetes service type for AP discovery | `NodePort` | -| `discoveryService.port` | Kubernetes UDP port for AP discovery | `10001` | -| `discoveryService.annotations` | Service annotations for AP discovery | `{}` | -| `discoveryService.labels` | Custom labels | `{}` | -| `discoveryService.loadBalancerIP` | Loadbalance IP for AP discovery | `{}` | -| `discoveryService.loadBalancerSourceRanges` | List of IP CIDRs allowed access to load balancer (if supported) | None | -| `discoveryService.externalTrafficPolicy` | Set the externalTrafficPolicy in the Service to either Cluster or Local | `Cluster` | -| `unifiedService.enabled` | Use a single service for GUI, controller, STUN, and discovery | `false` | -| `unifiedService.type` | Kubernetes service type for the unified service | `ClusterIP` | -| `unifiedService.annotations` | Annotations for the unified service | `{}` | -| `unifiedService.labels` | Custom labels for the unified service | `{}` | -| `unifiedService.loadBalancerIP` | Load balancer IP for the unified service | None | -| `unifiedService.loadBalancerSourceRanges` | List of IP CIDRs allowed access to the load balancer (if supported) | None | -| `unifiedService.externalTrafficPolicy` | Set the externalTrafficPolicy in the service to either Cluster or Local | `Cluster` | -| `ingress.enabled` | Enables Ingress | `false` | -| `ingress.annotations` | Ingress annotations | `{}` | -| `ingress.labels` | Custom labels | `{}` | -| `ingress.path` | Ingress path | `/` | -| `ingress.hosts` | Ingress accepted hostnames | `chart-example.local` | -| `ingress.tls` | Ingress TLS configuration | `[]` | -| `timezone` | Timezone the Unifi controller should run as, e.g. 'America/New York' | `UTC` | -| `runAsRoot` | Run the controller as UID0 (root user); if set to false, will give container SETFCAP instead | `false` | -| `UID` | Run the controller as user UID | `999` | -| `GID` | Run the controller as group GID | `999` | -| `mongodb.enabled` | Use external MongoDB for data storage | `false` | -| `mongodb.dbUri` | external MongoDB URI | `mongodb://mongo/unifi` | -| `mongodb.statDbUri` | external MongoDB statdb URI | `mongodb://mongo/unifi_stat` | -| `mongodb.databaseName` | external MongoDB database name | `unifi` | -| `persistence.enabled` | Use persistent volume to store data | `true` | -| `persistence.size` | Size of persistent volume claim | `5Gi` | -| `persistence.existingClaim` | Use an existing PVC to persist data | `nil` | -| `persistence.storageClass` | Type of persistent volume claim | `-` | -| `persistence.accessModes` | Persistence access modes | `[]` | -| `extraConfigFiles` | Dictionary containing files mounted to `/configmap` inside the pod (See [values.yaml](values.yaml) for examples) | `{}` | -| `extraJvmOpts` | List of additional JVM options, e.g. `["-Dlog4j.configurationFile=file:/configmap/log4j2.xml"]` | `[]` | -| `resources` | CPU/Memory resource requests/limits | `{}` | -| `nodeSelector` | Node labels for pod assignment | `{}` | -| `tolerations` | Toleration labels for pod assignment | `[]` | -| `affinity` | Affinity settings for pod assignment | `{}` | -| `podAnnotations` | Key-value pairs to add as pod annotations | `{}` | -| `deploymentAnnotations` | Key-value pairs to add as deployment annotations | `{}` | +| Parameter | Default | Description | +|-------------------------------------------------|------------------------------|------------------------------------------------------------------------------------------------------------------------| +| `image.repository` | `jacobalberty/unifi` | Image repository | +| `image.tag` | `5.11.50` | Image tag. Possible values listed [here][docker]. | +| `image.pullPolicy` | `IfNotPresent` | Image pull policy | +| `strategyType` | `Recreate` | Specifies the strategy used to replace old Pods by new ones | +| `guiService.type` | `ClusterIP` | Kubernetes service type for the Unifi GUI | +| `guiService.port` | `8443` | Kubernetes port where the Unifi GUI is exposed | +| `guiService.annotations` | `{}` | Service annotations for the Unifi GUI | +| `guiService.labels` | `{}` | Custom labels | +| `guiService.loadBalancerIP` | `{}` | Loadbalance IP for the Unifi GUI | +| `guiService.loadBalancerSourceRanges` | None | List of IP CIDRs allowed access to load balancer (if supported) | +| `guiService.externalTrafficPolicy` | `Cluster` | Set the externalTrafficPolicy in the Service to either Cluster or Local | +| `captivePortalService.enabled` | `false` | Install the captive portal service (needed if you want guest captive portal) | +| `captivePortalService.type` | `ClusterIP` | Kubernetes service type for the captive portal | +| `captivePortalService.http` | `8880` | Kubernetes port where the captive portal is exposed | +| `captivePortalService.https` | `8843` | Kubernetes port where the captive portal is exposed (with SSL) | +| `captivePortalService.annotations` | `{}` | Service annotations for the captive portal | +| `captivePortalService.labels` | `{}` | Custom labels | +| `captivePortalService.loadBalancerIP` | `{}` | Loadbalance IP for the Unifi GUI | +| `captivePortalService.loadBalancerSourceRanges` | None | List of IP CIDRs allowed access to load balancer (if supported) | +| `captivePortalService.externalTrafficPolicy` | `Cluster` | Set the externalTrafficPolicy in the Service to either Cluster or Local | +| `captivePortalService.ingress.enabled` | `false` | Enables Ingress (for the captive portal, the main ingress needs to be enabled for the controller to be accessible) | +| `captivePortalService.ingress.annotations` | `{}` | Ingress annotations for the captive portal | +| `captivePortalService.ingress.labels` | `{}` | Custom labels for the captive portal | +| `captivePortalService.ingress.path` | `/` | Ingress path for the captive portal | +| `captivePortalService.ingress.hosts` | `chart-example.local` | Ingress accepted hostnames for the captive portal | +| `captivePortalService.ingress.tls` | `[]` | Ingress TLS configuration for the captive portal | +| `controllerService.type` | `NodePort` | Kubernetes service type for the Unifi Controller communication | +| `controllerService.port` | `8080` | Kubernetes port where the Unifi Controller is exposed - this needs to be reachable by the unifi devices on the network | +| `controllerService.annotations` | `{}` | Service annotations for the Unifi Controller | +| `controllerService.labels` | `{}` | Custom labels | +| `controllerService.loadBalancerIP` | `{}` | Loadbalance IP for the Unifi Controller | +| `controllerService.loadBalancerSourceRanges` | None | List of IP CIDRs allowed access to load balancer (if supported) | +| `controllerService.externalTrafficPolicy` | `Cluster` | Set the externalTrafficPolicy in the Service to either Cluster or Local | +| `stunService.type` | `NodePort` | Kubernetes service type for the Unifi STUN | +| `stunService.port` | `3478` | Kubernetes UDP port where the Unifi STUN is exposed | +| `stunService.annotations` | `{}` | Service annotations for the Unifi STUN | +| `stunService.labels` | `{}` | Custom labels | +| `stunService.loadBalancerIP` | `{}` | Loadbalance IP for the Unifi STUN | +| `stunService.loadBalancerSourceRanges` | None | List of IP CIDRs allowed access to load balancer (if supported) | +| `stunService.externalTrafficPolicy` | `Cluster` | Set the externalTrafficPolicy in the Service to either Cluster or Local | +| `discoveryService.type` | `NodePort` | Kubernetes service type for AP discovery | +| `discoveryService.port` | `10001` | Kubernetes UDP port for AP discovery | +| `discoveryService.annotations` | `{}` | Service annotations for AP discovery | +| `discoveryService.labels` | `{}` | Custom labels | +| `discoveryService.loadBalancerIP` | `{}` | Loadbalance IP for AP discovery | +| `discoveryService.loadBalancerSourceRanges` | None | List of IP CIDRs allowed access to load balancer (if supported) | +| `discoveryService.externalTrafficPolicy` | `Cluster` | Set the externalTrafficPolicy in the Service to either Cluster or Local | +| `unifiedService.enabled` | `false` | Use a single service for GUI, controller, STUN, and discovery | +| `unifiedService.type` | `ClusterIP` | Kubernetes service type for the unified service | +| `unifiedService.annotations` | `{}` | Annotations for the unified service | +| `unifiedService.labels` | `{}` | Custom labels for the unified service | +| `unifiedService.loadBalancerIP` | None | Load balancer IP for the unified service | +| `unifiedService.loadBalancerSourceRanges` | None | List of IP CIDRs allowed access to the load balancer (if supported) | +| `unifiedService.externalTrafficPolicy` | `Cluster` | Set the externalTrafficPolicy in the service to either Cluster or Local | +| `ingress.enabled` | `false` | Enables Ingress | +| `ingress.annotations` | `{}` | Ingress annotations | +| `ingress.labels` | `{}` | Custom labels | +| `ingress.path` | `/` | Ingress path | +| `ingress.hosts` | `chart-example.local` | Ingress accepted hostnames | +| `ingress.tls` | `[]` | Ingress TLS configuration | +| `timezone` | `UTC` | Timezone the Unifi controller should run as, e.g. 'America/New York' | +| `runAsRoot` | `false` | Run the controller as UID0 (root user); if set to false, will give container SETFCAP instead | +| `UID` | `999` | Run the controller as user UID | +| `GID` | `999` | Run the controller as group GID | +| `mongodb.enabled` | `false` | Use external MongoDB for data storage | +| `mongodb.dbUri` | `mongodb://mongo/unifi` | external MongoDB URI | +| `mongodb.statDbUri` | `mongodb://mongo/unifi_stat` | external MongoDB statdb URI | +| `mongodb.databaseName` | `unifi` | external MongoDB database name | +| `persistence.enabled` | `true` | Use persistent volume to store data | +| `persistence.size` | `5Gi` | Size of persistent volume claim | +| `persistence.existingClaim` | `nil` | Use an existing PVC to persist data | +| `persistence.storageClass` | `-` | Type of persistent volume claim | +| `persistence.accessModes` | `[]` | Persistence access modes | +| `extraConfigFiles` | `{}` | Dictionary containing files mounted to `/configmap` inside the pod (See [values.yaml](values.yaml) for examples) | +| `extraJvmOpts` | `[]` | List of additional JVM options, e.g. `["-Dlog4j.configurationFile=file:/configmap/log4j2.xml"]` | +| `resources` | `{}` | CPU/Memory resource requests/limits | +| `nodeSelector` | `{}` | Node labels for pod assignment | +| `tolerations` | `[]` | Toleration labels for pod assignment | +| `affinity` | `{}` | Affinity settings for pod assignment | +| `podAnnotations` | `{}` | Key-value pairs to add as pod annotations | +| `deploymentAnnotations` | `{}` | Key-value pairs to add as deployment annotations | Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, @@ -123,6 +138,9 @@ Read through the [values.yaml](values.yaml) file. It has several commented out s - `guiService`: Represents the main web UI and is what one would normally point the ingress to. +- `captivePortalService`: This service is used to allow the captive portal webpage + to be accessible. It needs to be reachable by the clients connecting to your guest + network. - `controllerService`: This is needed in order for the unifi devices to talk to the controller and must be otherwise exposed to the network where the unifi devices run. If you run this as a `NodePort` (the default setting), make sure @@ -136,10 +154,12 @@ Read through the [values.yaml](values.yaml) file. It has several commented out s article][ubnt 4] for more information. ## Ingress and HTTPS + Unifi does [not support HTTP][unifi] so if you wish to use the guiService, you need to ensure that you use a backend transport of HTTPS. An example entry in `values.yaml` to achieve this is as follows: + ``` ingress: enabled: true diff --git a/charts/unifi/templates/captive-ingress.yaml b/charts/unifi/templates/captive-ingress.yaml new file mode 100644 index 00000000..0ae9dbbb --- /dev/null +++ b/charts/unifi/templates/captive-ingress.yaml @@ -0,0 +1,39 @@ +{{- if (and .Values.captivePortalService.ingress.enabled (not .Values.unifiedService.enabled)) }} +{{- $fullName := include "unifi.fullname" . -}} +{{- $ingressPath := .Values.captivePortalService.ingress.path -}} +{{- $unifiedServiceEnabled := .Values.unifiedService.enabled -}} +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: {{ $fullName }}-captive + labels: + app.kubernetes.io/name: {{ include "unifi.name" . }} + helm.sh/chart: {{ include "unifi.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- with .Values.captivePortalService.ingress.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: +{{- if .Values.captivePortalService.ingress.tls }} + tls: + {{- range .Values.captivePortalService.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} +{{- end }} + rules: + {{- range .Values.captivePortalService.ingress.hosts }} + - host: {{ . }} + http: + paths: + - path: {{ $ingressPath }} + backend: + serviceName: {{ $fullName }}-captivePortalService + servicePort: captive-http + {{- end }} +{{- end }} diff --git a/charts/unifi/templates/captive-svc.yaml b/charts/unifi/templates/captive-svc.yaml new file mode 100644 index 00000000..43853cf8 --- /dev/null +++ b/charts/unifi/templates/captive-svc.yaml @@ -0,0 +1,61 @@ +{{ if (and .Values.captivePortalService.enabled (not .Values.unifiedService.enabled)) }} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "unifi.fullname" . }}-captivePortalService + labels: + app.kubernetes.io/name: {{ include "unifi.name" . }} + helm.sh/chart: {{ include "unifi.chart" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- if .Values.captivePortalService.labels }} +{{ toYaml .Values.captivePortalService.labels | indent 4 }} +{{- end }} +{{- with .Values.captivePortalService.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: +{{- if (or (eq .Values.captivePortalService.type "ClusterIP") (empty .Values.captivePortalService.type)) }} + type: ClusterIP + {{- if .Values.captivePortalService.clusterIP }} + clusterIP: {{ .Values.captivePortalService.clusterIP }} + {{end}} +{{- else if eq .Values.captivePortalService.type "LoadBalancer" }} + type: {{ .Values.captivePortalService.type }} + {{- if .Values.captivePortalService.loadBalancerIP }} + loadBalancerIP: {{ .Values.captivePortalService.loadBalancerIP }} + {{- end }} + {{- if .Values.captivePortalService.loadBalancerSourceRanges }} + loadBalancerSourceRanges: +{{ toYaml .Values.captivePortalService.loadBalancerSourceRanges | indent 4 }} + {{- end -}} +{{- else }} + type: {{ .Values.captivePortalService.type }} +{{- end }} +{{- if .Values.captivePortalService.externalIPs }} + externalIPs: +{{ toYaml .Values.captivePortalService.externalIPs | indent 4 }} +{{- end }} + {{- if .Values.captivePortalService.externalTrafficPolicy }} + externalTrafficPolicy: {{ .Values.captivePortalService.externalTrafficPolicy }} + {{- end }} + ports: + - port: {{ .Values.captivePortalService.http }} + targetPort: captive-http + protocol: TCP + name: captive-http +{{ if (and (eq .Values.captivePortalService.type "NodePort") (not (empty .Values.captivePortalService.nodePorts.http))) }} + nodePort: {{.Values.captivePortalService.nodePorts.http}} +{{ end }} + - port: {{ .Values.captivePortalService.https }} + targetPort: captive-https + protocol: TCP + name: captive-https +{{ if (and (eq .Values.captivePortalService.type "NodePort") (not (empty .Values.captivePortalService.nodePorts.https))) }} + nodePort: {{.Values.captivePortalService.nodePorts.https}} +{{ end }} + selector: + app.kubernetes.io/name: {{ include "unifi.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} +{{ end }} diff --git a/charts/unifi/templates/deployment.yaml b/charts/unifi/templates/deployment.yaml index fa66e72b..c93d4448 100644 --- a/charts/unifi/templates/deployment.yaml +++ b/charts/unifi/templates/deployment.yaml @@ -50,6 +50,14 @@ spec: - name: stun containerPort: 3478 protocol: UDP + {{ if .Values.captivePortalService.enabled }} + - name: captive-http + containerPort: 8880 + protocol: TCP + - name: captive-https + containerPort: 8843 + protocol: TCP + {{ end }} {{- if not .Values.runAsRoot }} securityContext: capabilities: diff --git a/charts/unifi/templates/unified-svc.yaml b/charts/unifi/templates/unified-svc.yaml index 125c3580..05ba0f39 100644 --- a/charts/unifi/templates/unified-svc.yaml +++ b/charts/unifi/templates/unified-svc.yaml @@ -69,6 +69,23 @@ spec: {{ if (and (eq .Values.unifiedService.type "NodePort") (not (empty .Values.guiService.nodePort))) }} nodePort: {{.Values.guiService.nodePort}} {{ end }} +{{ if .Values.captivePortalService.enabled }} + - name: captive-http + port: {{ .Values.captivePortalService.http }} + protocol: TCP + targetPort: captive-http +{{ if (and (eq .Values.unifiedService.type "NodePort") (not (empty .Values.captivePortalService.http))) }} + nodePort: {{.Values.captivePortalService.nodePorts.http}} +{{ end }} + - name: captive-https + port: {{ .Values.captivePortalService.https }} + protocol: TCP + targetPort: captive-https +{{ if (and (eq .Values.unifiedService.type "NodePort") (not (empty .Values.captivePortalService.https))) }} + nodePort: {{.Values.captivePortalService.nodePorts.https}} +{{ end }} +{{ end }} + selector: app.kubernetes.io/name: {{ include "unifi.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} diff --git a/charts/unifi/values.yaml b/charts/unifi/values.yaml index 910b28df..4609dbda 100644 --- a/charts/unifi/values.yaml +++ b/charts/unifi/values.yaml @@ -59,6 +59,47 @@ guiService: ## Set the externalTrafficPolicy in the Service to either Cluster or Local # externalTrafficPolicy: Cluster +captivePortalService: + enabled: false + type: ClusterIP + http: 8880 + https: 8843 + ## Specify the nodePort value for the LoadBalancer and NodePort service types. + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## + # nodePort: + # http: 8880 + # https: 8843 + ## Provide any additional annotations which may be required. This can be used to + ## set the LoadBalancer service type to internal only. + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer + ## + annotations: {} + labels: {} + ## Use loadBalancerIP to request a specific static IP, + ## otherwise leave blank + ## + loadBalancerIP: + # loadBalancerSourceRanges: [] + ## Set the externalTrafficPolicy in the Service to either Cluster or Local + # externalTrafficPolicy: Cluster + + + # Ingress settings only for the captive portal + ingress: + enabled: false + annotations: {} + # nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + path: / + hosts: + - chart-example.local + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + controllerService: type: NodePort port: 8080