---
title: "Kubernetes ingress controller for authenticating apps"
description: "Authenticate your application using kubernetes ingress"
canonical_url: "https://www.bigbinary.com/blog/using-kubernetes-ingress-authentication"
markdown_url: "https://www.bigbinary.com/blog/using-kubernetes-ingress-authentication.md"
---

# Kubernetes ingress controller for authenticating apps

Authenticate your application using kubernetes ingress

- Author: Rahul Mahale
- Published: August 14, 2018
- Categories: Kubernetes

[Kubernetes Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/)
has redefined the routing in this era of containerization and with all these
freehand routing techniques the thought of "My router my rules" seems real.

We use nginx-ingress as a routing service for our applications. There is a lot
more than routing we can do with ingress. One of the important features is
setting up authentication using ingress for our application. As all the traffic
goes from ingress to our service, it makes sense to setup authentication on
ingress.

As mentioned in
[ingress repository](https://github.com/kubernetes/ingress-nginx/tree/master/docs/examples/)
there are different types of techniques available for authentication including:

- Basic authentication
- Client-certs authentication
- External authentication
- Oauth external authentication

In this blog, we will set up authentication for the sample application using
basic ingress authentication technique.

#### Pre-requisites

- Access to working kubernetes cluster.

- Understanding of [Kubernetes](http://kubernetes.io/) terms like
  [pods](http://kubernetes.io/docs/user-guide/pods/),
  [deployments](http://kubernetes.io/docs/user-guide/deployments/),
  [services](https://kubernetes.io/docs/concepts/services-networking/service/),
  [configmap](https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/),
  [ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/)
  and
  [annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/)

First, let's create ingress resources from upstream example by running the
following command.

```bash

$ kubectl create -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/mandatory.yaml
namespace "ingress-nginx" created
deployment "default-http-backend" created
service "default-http-backend" created
configmap "nginx-configuration" created
configmap "tcp-services" created
configmap "udp-services" created
serviceaccount "nginx-ingress-serviceaccount" created
clusterrole "nginx-ingress-clusterrole" created
role "nginx-ingress-role" created
rolebinding "nginx-ingress-role-nisa-binding" created
clusterrolebinding "nginx-ingress-clusterrole-nisa-binding" created
deployment "nginx-ingress-controller" created

```

Now that ingress controller resources are created we need a service to access
the ingress.

Use following manifest to create service for ingress.

```yaml
apiVersion: v1
kind: Service
metadata:
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-backend-protocol: tcp
  labels:
    k8s-addon: ingress-nginx.addons.k8s.io
  name: ingress-nginx
  namespace: ingress-nginx
spec:
  externalTrafficPolicy: Cluster
  ports:
    - name: https
      port: 443
      protocol: TCP
      targetPort: http
    - name: http
      port: 80
      protocol: TCP
      targetPort: http
  selector:
    app: ingress-nginx
  type: LoadBalancer
```

Now, get the ELB endpoint and bind it with some domain name.

```bash

$kubectl create -f ingress-service.yml
service ingress-nginx created

$ kubectl -n ingress-nginx get svc  ingress-nginx -o wide
NAME            CLUSTER-IP      EXTERNAL-IP                                                               PORT(S)                      AGE       SELECTOR
ingress-nginx   100.71.250.56   abcghccf8540698e8bff782799ca8h04-1234567890.us-east-2.elb.amazonaws.com   80:30032/TCP,443:30108/TCP   10s       app=ingress-nginx

```

Let's create a deployment and service for our sample application kibana. We need
elasticsearch to run kibana.

Here is manifest for the sample application.

```yaml
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    app: kibana
  name: kibana
  namespace: ingress-nginx
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: kibana
    spec:
      containers:
        - image: kibana:latest
          name: kibana
          ports:
            - containerPort: 5601
---
apiVersion: v1
kind: Service
metadata:
  annotations:
  labels:
    app: kibana
  name: kibana
  namespace: ingress-nginx

spec:
  ports:
    - name: kibana
      port: 5601
      targetPort: 5601
  selector:
    app: kibana
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    app: elasticsearch
  name: elasticsearch
  namespace: ingress-nginx
spec:
  replicas: 1
  strategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: elasticsearch
    spec:
      containers:
        - image: elasticsearch:latest
          name: elasticsearch
          ports:
            - containerPort: 5601
---
apiVersion: v1
kind: Service
metadata:
  annotations:
  labels:
    app: elasticsearch
  name: elasticsearch
  namespace: ingress-nginx
spec:
  ports:
    - name: elasticsearch
      port: 9200
      targetPort: 9200
  selector:
    app: elasticsearch
```

Create the sample application.

```bash

kubectl apply -f kibana.yml
deployment "kibana" created
service "kibana" created
deployment "elasticsearch" created
service "elasticsearch" created

```

Now that we have created application and ingress resources, it's time to create
an ingress and access the application.

Use the following manifest to create ingress.

```yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
  name: kibana-ingress
  namespace: ingress-nginx
spec:
  rules:
    - host: logstest.myapp-staging.com
      http:
        paths:
          - path: /
            backend:
              serviceName: kibana
              servicePort: 5601
```

```bash

$kubectl -n ingress-nginx create -f ingress.yml
ingress "kibana-ingress" created.

```

Now that our application is up, when we access the kibana dashboard using URL
http://logstest.myapp-staging.com We directly have access to our Kibana
dashboard and anyone with this URL can access logs as shown in the following
image.

![Kibana dashboard without authentication](https://www.bigbinary.com/blog/images/images_used_in_blog/2018/using-kubernetes-ingress-authentication/kibana.png)

Now, let's set up a basic authentication using htpasswd.

Follow below commands to generate the secret for credentials.

Let's create an auth file with username and password.

```bash

$ htpasswd -c auth kibanaadmin
New password: <kibanaadmin>
New password:
Re-type new password:
Adding password for user kibanaadmin

```

Create k8s secret.

```bash

$ kubectl -n ingress-nginx create secret generic basic-auth --from-file=auth
secret "basic-auth" created

```

Verify the secret.

```yaml

kubectl get secret basic-auth -o yaml
apiVersion: v1
data:
  auth: Zm9vOiRhcHIxJE9GRzNYeWJwJGNrTDBGSERBa29YWUlsSDkuY3lzVDAK
kind: Secret
metadata:
  name: basic-auth
  namespace: ingress-nginx
type: Opaque

```

Use following annotations in our ingress manifest by updating the ingress
manifest.

```bash
kubectl -n ingress-nginx edit ingress kibana ingress
```

Paste the following annotations

```bash
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: basic-auth
nginx.ingress.kubernetes.io/auth-realm: "Kibana Authentication Required - kibanaadmin"

```

Now that ingress is updated, hit the URL again and as shown in the image below
we are asked for authentication.

![Kibana dashboard without authentication](https://www.bigbinary.com/blog/images/images_used_in_blog/2018/using-kubernetes-ingress-authentication/kibana_auth.png)

## Links

- [Human page](https://www.bigbinary.com/blog/using-kubernetes-ingress-authentication)
