Create an Ingress with Basic Authentication (nginx)

If you install Longhorn on a Kubernetes cluster with kubectl or Helm, you will need to create an Ingress to allow external traffic to reach the Longhorn UI.

Authentication is not enabled by default for kubectl and Helm installations. In these steps, you’ll learn how to create an Ingress with basic authentication using annotations for the nginx ingress controller.

  1. Create a basic auth file auth. It’s important the file generated is named auth (actually - that the secret has a key data.auth), otherwise the Ingress returns a 503.

     $ USER=<USERNAME_HERE>; PASSWORD=<PASSWORD_HERE>; echo "${USER}:$(openssl passwd -stdin -apr1 <<< ${PASSWORD})" >> auth
  2. Create a secret:

     $ kubectl -n longhorn-system create secret generic basic-auth --from-file=auth
  3. Create an Ingress manifest longhorn-ingress.yml :

    Since v1.2.0, Longhorn supports uploading backing image from the UI, so please specify nginx.ingress.kubernetes.io/proxy-body-size: 10000m as below to ensure uploading images work as expected.

     apiVersion: networking.k8s.io/v1
     kind: Ingress
     metadata:
       name: longhorn-ingress
       namespace: longhorn-system
       annotations:
         # type of authentication
         nginx.ingress.kubernetes.io/auth-type: basic
         # prevent the controller from redirecting (308) to HTTPS
         nginx.ingress.kubernetes.io/ssl-redirect: 'false'
         # name of the secret that contains the user/password definitions
         nginx.ingress.kubernetes.io/auth-secret: basic-auth
         # message to display with an appropriate context why the authentication is required
         nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required '
         # custom max body size for file uploading like backing image uploading
         nginx.ingress.kubernetes.io/proxy-body-size: 10000m
     spec:
       rules:
       - http:
           paths:
           - pathType: Prefix
             path: "/"
             backend:
               service:
                 name: longhorn-frontend
                 port:
                   number: 80
  4. Create the Ingress:

     $ kubectl -n longhorn-system apply -f longhorn-ingress.yml

e.g.:

$ USER=foo; PASSWORD=bar; echo "$\{USER}:$(openssl passwd -stdin -apr1 <<< $\{PASSWORD})" >> auth
$ cat auth
foo:$apr1$FnyKCYKb$6IP2C45fZxMcoLwkOwf7k0

$ kubectl -n longhorn-system create secret generic basic-auth --from-file=auth
secret/basic-auth created
$ kubectl -n longhorn-system get secret basic-auth -o yaml
apiVersion: v1
data:
  auth: Zm9vOiRhcHIxJEZueUtDWUtiJDZJUDJDNDVmWnhNY29Md2tPd2Y3azAK
kind: Secret
metadata:
  creationTimestamp: "2020-05-29T10:10:16Z"
  name: basic-auth
  namespace: longhorn-system
  resourceVersion: "2168509"
  selfLink: /api/v1/namespaces/longhorn-system/secrets/basic-auth
  uid: 9f66233f-b12f-4204-9c9d-5bcaca794bb7
type: Opaque

$ echo "
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: longhorn-ingress
  namespace: longhorn-system
  annotations:
    # type of authentication
    nginx.ingress.kubernetes.io/auth-type: basic
    # prevent the controller from redirecting (308) to HTTPS
    nginx.ingress.kubernetes.io/ssl-redirect: 'false'
    # name of the secret that contains the user/password definitions
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    # message to display with an appropriate context why the authentication is required
    nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required '
spec:
  rules:

* http:
  paths:
 ** pathType: Prefix
path: "/"
backend:
  service:
    name: longhorn-frontend
    port:
      number: 80
" | kubectl -n longhorn-system create -f -
ingress.networking.k8s.io/longhorn-ingress created

$ kubectl -n longhorn-system get ingress
NAME               HOSTS   ADDRESS                                     PORTS   AGE
longhorn-ingress   *       45.79.165.114,66.228.45.37,97.107.142.125   80      2m7s

$ curl -v http://97.107.142.125/

* Trying 97.107.142.125...
* TCP_NODELAY set
* Connected to 97.107.142.125 (97.107.142.125) port 80 (#0)
+
____
GET / HTTP/1.1
Host: 97.107.142.125
User-Agent: curl/7.64.1
Accept: _/_

< HTTP/1.1 401 Unauthorized
< Server: openresty/1.15.8.1
< Date: Fri, 29 May 2020 11:47:33 GMT
< Content-Type: text/html
< Content-Length: 185
< Connection: keep-alive
< WWW-Authenticate: Basic realm="Authentication Required"
<