Indonesian CGIProxy:   [ UP ]   [Manage cookies]

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:

  1. The public IP address for your NGINX Ingress Controller instance.
IC_IP=<ip-address>
  1. The HTTP port of the same instance.
IC_HTTP_PORT=<port number>
  1. 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:

yaml
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.yaml

Create 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.

yaml
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.yaml

Create a file named virtual-server.yaml for the VirtualServer resource. The policies field references the access control Policy created in the previous section.

yaml
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.yaml

Use curl to attempt to access the application:

curl --resolve webapp.example.com:$IC_HTTP_PORT:$IC_IP http://webapp.example.com:$IC_HTTP_PORT
text
<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.

yaml
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.yaml

Attempt to access the application again:

curl --resolve webapp.example.com:$IC_HTTP_PORT:$IC_IP http://webapp.example.com:$IC_HTTP_PORT
text
Server address: 10.64.0.13:8080
Server name: webapp-5cbbc7bd78-wf85w

The 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:

yaml
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.yaml

Create 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.

yaml
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.yaml

Create 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.

yaml
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.yaml

Create 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.

yaml
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

  1. Send a request with an IP in the allowed 10.0.0.0/8 range using the X-Real-IP header:

    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.1 is in the allowed range.

  2. 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.

yaml
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.yaml

The Ingress resource picks up the change automatically because the policy name (webapp-policy) stays the same.

  1. Send a request with an IP in the now-denied 10.0.0.0/8 range:

    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.

  2. 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.