Use Nginx Ingress Smartly for authentication based on paths

Gaurav Wadghule
3 min readJan 4, 2023

Sometimes there is a need to block or restrict some paths in applications. If you are using Nginx ingress in Kubernetes then this will be very easy for you.

Let's deploy one sample application. this go-rest-api application is having 3 endpoints.

deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: go-rest-api-test
name: go-rest-api-test
namespace: demo
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app: go-rest-api-test
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: go-rest-api-test
spec:
containers:
- image: wadghulegaurav/go-rest-api
imagePullPolicy: Always
name: go-rest-api
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}

service.yaml

apiVersion: v1
kind: Service
metadata:
labels:
app: go-rest-api-test
name: go-rest-api-test
spec:
ports:
- port: 80
protocol: TCP
targetPort: 8080
selector:
app: go-rest-api-test
sessionAffinity: None
type: ClusterIP

I have listed down all the use cases where we can use authentication for service endpoints.

1, Block all endpoints except a few endpoints.

This Scenario comes into the picture when you are the service provider and you don't want to whole application to your clients or users then you can block all endpoints and keep open specific endpoints with basic authentication.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
external-dns.alpha.kubernetes.io/hostname: go-rest-api-test.your-app.com
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/affinity: cookie
nginx.ingress.kubernetes.io/affinity-mode: persistent
nginx.ingress.kubernetes.io/configuration-snippet: |-
location / {
deny all;
return 406;
}
nginx.ingress.kubernetes.io/proxy-body-size: 200m
nginx.ingress.kubernetes.io/proxy-buffering: "off"
nginx.ingress.kubernetes.io/proxy-connect-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
nginx.ingress.kubernetes.io/whitelist-source-range: 156.201.141.198/32
name: go-rest-api-test
spec:
rules:
- host: go-rest-api-test.your-app.com
http:
paths:
- backend:
serviceName: go-rest-api-test
servicePort: 80
path: /
pathType: ImplementationSpecific
tls:
- hosts:
- go-rest-api-test.your-app.com
secretName: your_tls_secret

If you look at the above ingress.yaml carefully you will see that we are using configuration-snippet to block all traffic and return 406 which means the endpoint is not accepted. along with that you can use whitelist-source-range to whitelist IPs.

Now with the below ingress, we are going to allow some specific endpoints.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
external-dns.alpha.kubernetes.io/hostname: go-rest-api-test.your-app.com
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/affinity: cookie
nginx.ingress.kubernetes.io/affinity-mode: persistent
nginx.ingress.kubernetes.io/auth-realm: Authentication Required - blah-blah service
nginx.ingress.kubernetes.io/auth-secret: basic-auth-go-rest
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/proxy-body-size: 200m
nginx.ingress.kubernetes.io/proxy-buffering: "off"
nginx.ingress.kubernetes.io/proxy-connect-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
name: go-rest-api-test-allow
spec:
rules:
- host: go-rest-api-test.your-app.com
http:
paths:
- backend:
serviceName: go-rest-api-test
servicePort: 80
path: /ping
pathType: ImplementationSpecific
tls:
- hosts:
- go-rest-api-test.your-app.com
secretName: your_tls_secret

here in this quick tutorial, I am going to deploy one service where all its endpoints will be blocked and only one endpoint is open for the outer world. But that one endpoint will have basic authentication on it.

Here in the above ingress we have used basic authentication which required auth credentials from Kubernetes secret. you can create this secret with the below commands.

htpasswd -c auth 
New password: <bar>
New password:
Re-type new password:
Adding password for user foo
$ kubectl create secret generic basic-auth-go-rest --from-file=auth

2. Allow traffic from a specific IP range.

This can be achieved with nginx.ingress.kubernetes.io/whitelist-source-range annotation.

3. Deny all traffic on specific endpoints.

For this, you can use the below annotation which blocks all requests which are coming on “ / ”

nginx.ingress.kubernetes.io/configuration-snippet: |-
location / {
deny all;
return 406;
}

--

--