Deploy a Policy for access control
This topic describes how to use F5 NGINX Ingress Controller to apply and update a Policy for access control. You can use access control policies with VirtualServer custom resources or with Ingress resources using the nginx.org/policies annotation.
You should have a working NGINX Ingress Controller instance.
For ease of use in shell commands, set the following shell variables:
- The public IP address for your NGINX Ingress Controller instance.
IC_IP=<ip-address>- The HTTP port of the same instance.
IC_HTTP_PORT=<port number>- The HTTPS port of the same instance (used for the Ingress resource example).
IC_HTTPS_PORT=<port number>Create the file webapp.yaml with the following contents:
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
spec:
replicas: 1
selector:
matchLabels:
app: webapp
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: webapp
image: nginxdemos/nginx-hello:plain-text
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: webapp-svc
spec:
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: http
selector:
app: webapp
Apply it using kubectl:
kubectl apply -f webapp.yamlCreate a file named access-control-policy-deny.yaml. The highlighted deny field will be used by the example application, and should be changed to the subnet of your machine.
apiVersion: k8s.nginx.org/v1
kind: Policy
metadata:
name: webapp-policy
spec:
accessControl:
deny:
- 10.0.0.0/8
Apply the policy:
kubectl apply -f access-control-policy-deny.yamlCreate a file named virtual-server.yaml for the VirtualServer resource. The policies field references the access control Policy created in the previous section.
apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
name: webapp
spec:
host: webapp.example.com
policies:
- name: webapp-policy
upstreams:
- name: webapp
service: webapp-svc
port: 80
routes:
- path: /
action:
pass: webapp
Apply the policy:
kubectl apply -f virtual-server.yamlUse curl to attempt to access the application:
curl --resolve webapp.example.com:$IC_HTTP_PORT:$IC_IP http://webapp.example.com:$IC_HTTP_PORT<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
</body>
</html>The 403 response is expected, successfully blocking your machine.
Update the Policy with the file access-control-policy-allow.yaml, setting the allow field to the subnet of your machine.
apiVersion: k8s.nginx.org/v1
kind: Policy
metadata:
name: webapp-policy
spec:
accessControl:
allow:
- 10.0.0.0/8
Apply the Policy:
kubectl apply -f access-control-policy-allow.yamlAttempt to access the application again:
curl --resolve webapp.example.com:$IC_HTTP_PORT:$IC_IP http://webapp.example.com:$IC_HTTP_PORTServer address: 10.64.0.13:8080
Server name: webapp-5cbbc7bd78-wf85wThe successful response demonstrates that the policy has been updated.
You can also apply access control policies to standard Kubernetes Ingress resources using the nginx.org/policies annotation. This section walks through a complete example.
Create the file cafe.yaml with the following contents:
apiVersion: apps/v1
kind: Deployment
metadata:
name: coffee
spec:
replicas: 2
selector:
matchLabels:
app: coffee
template:
metadata:
labels:
app: coffee
spec:
containers:
- name: coffee
image: nginxdemos/nginx-hello:plain-text
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: coffee-svc
spec:
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: http
selector:
app: coffee
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: tea
spec:
replicas: 3
selector:
matchLabels:
app: tea
template:
metadata:
labels:
app: tea
spec:
containers:
- name: tea
image: nginxdemos/nginx-hello:plain-text
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: tea-svc
labels:
spec:
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: http
selector:
app: tea
Apply it using kubectl:
kubectl apply -f cafe.yamlCreate the file nginx-config.yaml to configure NGINX to trust the X-Real-IP header. This ensures the access control policy uses the client IP provided in that header.
kind: ConfigMap
apiVersion: v1
metadata:
name: nginx-config
data:
set-real-ip-from: "0.0.0.0/0,::/0"
real-ip-header: "X-Real-IP"
Apply the ConfigMap:
kubectl apply -f nginx-config.yamlCreate a file named access-control-policy-allow.yaml. The highlighted allow field permits traffic from the 10.0.0.0/8 CIDR range and blocks all other addresses.
apiVersion: k8s.nginx.org/v1
kind: Policy
metadata:
name: webapp-policy
spec:
accessControl:
allow:
- 10.0.0.0/8
Apply the policy:
kubectl apply -f access-control-policy-allow.yamlCreate a file named cafe-ingress.yaml for the Ingress resource. The highlighted nginx.org/policies annotation references the access control Policy created in the previous step.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: cafe-ingress
annotations:
nginx.org/policies: "webapp-policy"
spec:
ingressClassName: nginx
tls:
- hosts:
- cafe.example.com
secretName: tls-secret
rules:
- host: cafe.example.com
http:
paths:
- path: /tea
pathType: Prefix
backend:
service:
name: tea-svc
port:
number: 80
- path: /coffee
pathType: Prefix
backend:
service:
name: coffee-svc
port:
number: 80
Apply the Ingress:
kubectl apply -f cafe-ingress.yaml-
Send a request with an IP in the allowed
10.0.0.0/8range using theX-Real-IPheader:curl --resolve cafe.example.com:$IC_HTTPS_PORT:$IC_IP https://cafe.example.com:$IC_HTTPS_PORT/coffee --insecure -H "X-Real-IP: 10.0.0.1"text Server address: 10.244.0.6:8080 Server name: coffee-7586895968-r26zn ...The request succeeds because
10.0.0.1is in the allowed range. -
Send a request with an IP outside the allowed range:
curl --resolve cafe.example.com:$IC_HTTPS_PORT:$IC_IP https://cafe.example.com:$IC_HTTPS_PORT/coffee --insecure -H "X-Real-IP: 192.168.1.1"text <html> <head><title>403 Forbidden</title></head> <body> <center><h1>403 Forbidden</h1></center> </body> </html>The 403 response confirms that NGINX blocks clients outside the allowed range.
Update the Policy with the file access-control-policy-deny.yaml, which denies traffic from the 10.0.0.0/8 CIDR range and allows all other addresses.
apiVersion: k8s.nginx.org/v1
kind: Policy
metadata:
name: webapp-policy
spec:
accessControl:
deny:
- 10.0.0.0/8
Apply the updated Policy:
kubectl apply -f access-control-policy-deny.yamlThe Ingress resource picks up the change automatically because the policy name (webapp-policy) stays the same.
-
Send a request with an IP in the now-denied
10.0.0.0/8range:curl --resolve cafe.example.com:$IC_HTTPS_PORT:$IC_IP https://cafe.example.com:$IC_HTTPS_PORT/coffee --insecure -H "X-Real-IP: 10.0.0.1"text <html> <head><title>403 Forbidden</title></head> <body> <center><h1>403 Forbidden</h1></center> </body> </html>The same IP that was previously allowed is now rejected.
-
Send a request with an IP outside the denied range:
curl --resolve cafe.example.com:$IC_HTTPS_PORT:$IC_IP https://cafe.example.com:$IC_HTTPS_PORT/coffee --insecure -H "X-Real-IP: 192.168.1.1"text Server address: 10.244.0.6:8080 Server name: coffee-7586895968-r26zn ...Clients outside the denied range are now allowed through.