Skip to content
Kong Logo | Kong Docs Logo
search
  • We're Hiring!
  • Docs
    • Kong Gateway
    • Kong Konnect
    • Kong Mesh
    • Plugin Hub
    • decK
    • Kubernetes Ingress Controller
    • Insomnia
    • Kuma

    • Docs contribution guidelines
  • Plugin Hub
  • Support
  • Community
  • Kong Academy
Get a Demo Start Free Trial
  • Kong Gateway
  • Kong Konnect
  • Kong Mesh
  • Plugin Hub
  • decK
  • Kubernetes Ingress Controller
  • Insomnia
  • Kuma

  • Docs contribution guidelines
  • 2.8.x (latest)
  • 2.7.x
  • 2.6.x
  • 2.5.x
  • 2.4.x
  • 2.3.x
  • 2.2.x
  • 2.1.x
  • 2.0.x
  • 1.3.x
  • 1.2.x
  • 1.1.x
  • 1.0.x
    • FAQ
    • Version Support Policy
    • Stages of Software Availability
    • Changelog
    • Architecture
    • Custom Resources
    • Deployment Methods
    • Kong for Kubernetes with Kong Enterprise
    • High-Availability and Scaling
    • Resource Classes
    • Security
    • Ingress Resource API Versions
    • Gateway API
    • Kong Ingress on Minikube
    • Kong for Kubernetes
    • Kong for Kubernetes Enterprise
    • Kong for Kubernetes with Kong Enterprise
    • Kong Ingress on AKS
    • Kong Ingress on EKS
    • Kong Ingress on GKE
    • Admission Webhook
    • Installing Gateway APIs
    • Getting Started with KIC
    • Upgrading from previous versions
    • Upgrading to Kong 3.x
    • Getting Started using Istio
      • Using the KongPlugin Resource
      • Using the KongIngress Resource
      • Using KongConsumer and KongCredential Resources
      • Using the TCPIngress Resource
      • Using the UDPIngress Resource
    • Using the ACL and JWT Plugins
    • Using cert-manager with Kong
    • Allowing Multiple Authentication Methods
    • Configuring a Fallback Service
    • Using an External Service
    • Configuring HTTPS Redirects for Services
    • Using Redis for Rate Limiting
    • Integrate KIC with Prometheus/Grafana
    • Configuring Circuit-Breaker and Health-Checking
    • Setting up a Custom Plugin
    • Using Ingress with gRPC
    • Setting up Upstream mTLS
    • Exposing a TCP Service
    • Exposing a UDP Service
    • Using the mTLS Auth Plugin
    • Configuring Custom Entities
    • Using the OpenID Connect Plugin
    • Rewriting Hosts and Paths
    • Preserving Client IP Address
    • Using Kong with Knative
    • Using Multiple Backend Services
    • KIC Annotations
    • CLI Arguments
    • Custom Resource Definitions
    • Plugin Compatibility
    • Version Compatibility
    • Supported Kong Router Flavors
    • Troubleshooting
    • Prometheus Metrics
    • Feature Gates
    • Supported Gateway API Features

github-edit-pageEdit this page

report-issueReport an issue

enterprise-switcher-iconSwitch to OSS

On this page
  • Installation
  • Installing the Gateway APIs
  • Testing connectivity to Kong Gateway
  • Deploy an upstream HTTP application
  • Create a configuration group
  • Add routing configuration
  • Add JWT authentication to the service
  • Provision consumers
  • Provision JWT credentials
    • Create Secrets
    • Assign the credentials
    • Send authenticated requests
  • Adding access control
    • Create ACL plugins
    • Configure plugins on routing configuration
    • Add consumers to groups
    • Send authorized requests
Kubernetes Ingress Controller
2.8.x (latest)
  • Home
  • Kubernetes Ingress Controller
  • Guides
  • Configuring ACL Plugin

Configuring ACL Plugin

This guide walks through configuring the Kong ACL Plugin. The ACL Plugin requires the use of at least one Authentication plugin. This example uses the JWT Auth Plugin.

Installation

Please follow the deployment documentation to install the Kubernetes Ingress Controller onto your Kubernetes cluster.

Installing the Gateway APIs

If you wish to use the Gateway APIs examples, follow the supplemental Gateway APIs installation instructions.

Testing connectivity to Kong Gateway

This guide assumes that PROXY_IP environment variable is set to contain the IP address or URL pointing to Kong Gateway. If you’ve not done so, follow one of the deployment guides to configure this environment variable.

If everything is setup correctly, making a request to Kong Gateway should return back a HTTP 404 Not Found status code:

curl -i $PROXY_IP

Response:

HTTP/1.1 404 Not Found
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Content-Length: 48
X-Kong-Response-Latency: 0
Server: kong/3.0.0

{"message":"no Route matched with those values"}

This is expected since Kong Gateway doesn’t know how to proxy the request yet.

Deploy an upstream HTTP application

To proxy requests, you need an upstream application to proxy to. Deploying this echo server provides a simple application that returns information about the Pod it’s running in:

kubectl apply -f https://bit.ly/echo-service

Response:

service/echo created
deployment.apps/echo created

Create a configuration group

Ingress and Gateway APIs controllers need a configuration that indicates which set of routing configuration they should recognize. This allows multiple controllers to coexist in the same cluster. Before creating individual routes, you need to create a class configuration to associate routes with:

Ingress
Gateway APIs

Official distributions of Kubernetes Ingress Controller come with a kong IngressClass by default. If kubectl get ingressclass kong does not return a not found error, you can skip this command.

echo "
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  name: kong
spec:
  controller: ingress-controllers.konghq.com/kong
" | kubectl apply -f -

Response:

ingressclass.networking.k8s.io/kong configured
echo "
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: GatewayClass
metadata:
  name: kong
  annotations:
    konghq.com/gatewayclass-unmanaged: 'true'

spec:
  controllerName: konghq.com/kic-gateway-controller
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
  name: kong
spec:
  gatewayClassName: kong
  listeners:
  - name: proxy
    port: 80
    protocol: HTTP
  - name: proxy-ssl
    port: 443
    protocol: HTTPS
" | kubectl apply -f -

Response:

gatewayclass.gateway.networking.k8s.io/kong created
gateway.gateway.networking.k8s.io/kong created

Once the controller has acknowledged the Gateway, it will show the proxy IP in its status:

kubectl get gateway kong

Response:

NAME   CLASS   ADDRESS        READY   AGE
kong   kong    203.0.113.42   True    4m46s

Kubernetes Ingress Controller recognizes the kong IngressClass and konghq.com/kic-gateway-controller GatewayClass by default. Setting the CONTROLLER_INGRESS_CLASS or CONTROLLER_GATEWAY_API_CONTROLLER_NAME environment variable to another value overrides these defaults.

Add routing configuration

Create routing configuration to proxy /lemon requests to the echo server:

Ingress
Gateway APIs
echo "
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: lemon
  annotations:
    konghq.com/strip-path: 'true'
spec:
  ingressClassName: kong
  rules:
  - host: kong.example
    http:
      paths:
      - path: /lemon
        pathType: ImplementationSpecific
        backend:
          service:
            name: echo
            port:
              number: 80
" | kubectl apply -f -

Response:

ingress.networking.k8s.io/lemon created
echo "
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: lemon
  annotations:
    konghq.com/strip-path: 'true'
spec:
  parentRefs:
  - name: kong
  hostnames:
  - 'kong.example'
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /lemon
    backendRefs:
    - name: echo
      kind: Service
      port: 80
" | kubectl apply -f -

Response:

httproute.gateway.networking.k8s.io/lemon created

Test the routing rule:

curl -i http://kong.example/lemon --resolve kong.example:80:$PROXY_IP

Response:

HTTP/1.1 200 OK
Content-Type: text/plain; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Date: Thu, 10 Nov 2022 22:10:40 GMT
Server: echoserver
X-Kong-Upstream-Latency: 0
X-Kong-Proxy-Latency: 0
Via: kong/3.0.0



Hostname: echo-fc6fd95b5-6lqnc

Pod Information:
	node name:	kind-control-plane
	pod name:	echo-fc6fd95b5-6lqnc
	pod namespace:	default
	pod IP:	10.244.0.9
...

If everything is deployed correctly, you should see the above response. This verifies that Kong Gateway can correctly route traffic to an application running inside Kubernetes.

Once the first route is working, create a second pointing to the same Service:

Ingress
Gateway APIs
echo "
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: lime
  annotations:
    konghq.com/strip-path: 'true'
spec:
  ingressClassName: kong
  rules:
  - host: kong.example
    http:
      paths:
      - path: /lime
        pathType: ImplementationSpecific
        backend:
          service:
            name: echo
            port:
              number: 80
" | kubectl apply -f -

Response:

ingress.networking.k8s.io/lime created
echo "
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: lime
  annotations:
    konghq.com/strip-path: 'true'
spec:
  parentRefs:
  - name: kong
  hostnames:
  - 'kong.example'
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /lime
    backendRefs:
    - name: echo
      kind: Service
      port: 80
" | kubectl apply -f -

Response:

httproute.gateway.networking.k8s.io/lime created

Add JWT authentication to the service

With Kong, adding authentication in front of an API is as simple as enabling a plugin. To start, create a KongPlugin resource:

echo "
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
  name: app-jwt
plugin: jwt
" | kubectl apply -f -

Response:

kongplugin.configuration.konghq.com/app-jwt

Then, associate the plugin to the Ingress rules we created earlier:

kubectl annotate service echo konghq.com/plugins=app-jwt

Response:

service.networking.k8s.io/echo annotated

Any requests matching the proxying rules for demo-get and demo post will now require a valid JWT and the consumer for the JWT to be associate with the right ACL.

Requests without credentials are now rejected:

curl -si http://kong.example/lemon --resolve kong.example:80:$PROXY_IP

Response:

HTTP/1.1 401 Unauthorized
Date: Fri, 09 Dec 2022 23:51:35 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Content-Length: 26
X-Kong-Response-Latency: 1
Server: kong/3.0.1

{"message":"Unauthorized"

Provision consumers

To access the protected endpoints, create two consumers:

echo "apiVersion: configuration.konghq.com/v1
kind: KongConsumer
metadata:
  name: admin
  annotations:
    kubernetes.io/ingress.class: kong
username: admin
" | kubectl apply -f -

Response:

kongconsumer.configuration.konghq.com/admin created
echo "apiVersion: configuration.konghq.com/v1
kind: KongConsumer
metadata:
  name: user
  annotations:
    kubernetes.io/ingress.class: kong
username: user
" | kubectl apply -f -

Response:

kongconsumer.configuration.konghq.com/user created

Provision JWT credentials

JWT is a standard for tokens stored in JSON. They include a metadata section about the algorithms used to construct the JWT, information (“claims”) about the token and its bearer, and a cryptographic signature that recipients can use to verify the validity of the token.

As valid JWTs are not easily constructed by hand, you can use the jwt.io tool to generate cryptographic keys and sign your JWTs. Select the RS256 option from the Algorithm dropdown for this guide.

Create Secrets

Credentials are stored in Secrets with a kongCredType key whose value indicates the type of credential:

kubectl create secret \
  generic admin-jwt  \
  --from-literal=kongCredType=jwt  \
  --from-literal=key="admin-issuer" \
  --from-literal=algorithm=RS256 \
  --from-literal=rsa_public_key="-----BEGIN PUBLIC KEY-----
  MIIBIjA....
  -----END PUBLIC KEY-----"

kubectl create secret \
  generic user-jwt  \
  --from-literal=kongCredType=jwt  \
  --from-literal=key="user-issuer" \
  --from-literal=algorithm=RS256 \
  --from-literal=rsa_public_key="-----BEGIN PUBLIC KEY-----
  MIIBIjA....
  -----END PUBLIC KEY-----"

Response:

secret/admin-jwt created
secret/user-jwt created

Replace the RSA key strings with your own from jwt.io.

Assign the credentials

To associate the JWT Secrets with your consumers, you must add their name to the credentials array in the KongConsumers:

kubectl patch --type json kongconsumer admin \
  -p='[{
    "op":"add",
    "path":"/credentials",
    "value":["admin-jwt"]
  }]'

Response:

kongconsumer.configuration.konghq.com/admin patched
kubectl patch --type json kongconsumer user \
  -p='[{
    "op":"add",
    "path":"/credentials",
    "value":["user-jwt"]
  }]'

Response:

kongconsumer.configuration.konghq.com/user patched

Send authenticated requests

To send an authenticated request, you must create signed JWTs for your users. On jwt.io, add an issuer matching the key field from your Secrets to the JWT payload (for example, "iss":"admin-isuer", for the admin-jwt Secret). The “Encoded” output will update automatically. Copy the “Encoded” value and store it in an environment variable:

export ADMIN_JWT=eyJhbG...

Do the same for USER_JWT for the user-jwt Secret.

Once you have the JWTs stored, you can send them in an Authorization header:

curl -I -H "Authorization: Bearer ${USER_JWT}" http://kong.example/lemon --resolve kong.example:80:$PROXY_IP

Response:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 947
Connection: keep-alive
Server: gunicorn/19.9.0
Date: Mon, 06 Apr 2020 06:45:45 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
X-Kong-Upstream-Latency: 7
X-Kong-Proxy-Latency: 2
Via: kong/3.1.1

Adding access control

The JWT plugin (and other Kong authentication plugins) only provide authentication, not authorization. They can identify a consumer, and will reject any unidentified requests, but will not restrict which consumers can access which protected URLs. Any consumer with a JWT credential can access any JWT-protected URL, even when the JWT plugins for those URLs are configured separately.

Create ACL plugins

To provide authorization, or restrictions on which consumers can access which URLs, you need to also add the ACL plugin, which can assign groups to consumers and restrict access to URLs by group. Create two plugins, one which allows only an admin group, and one which allows both admin and user:

echo "
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
  name: admin-acl
plugin: acl
config:
  allow: ['admin']
" | kubectl apply -f -

Response:

kongplugin.configuration.konghq.com/admin-acl created
echo "
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
  name: anyone-acl
plugin: acl
config:
  allow: ['admin','user']
" | kubectl apply -f -

Response:

kongplugin.configuration.konghq.com/anyone-acl created

Configure plugins on routing configuration

After creating plugins, add them to the routing configuration you created earlier:

Ingress
Gateway APIs
kubectl annotate ingress lemon konghq.com/plugins=admin-acl
kubectl annotate ingress lime konghq.com/plugins=anyone-acl

Response:

ingress.networking.k8s.io/lemon annotated
ingress.networking.k8s.io/lime annotated
kubectl annotate httproute lemon konghq.com/plugins=admin-acl
kubectl annotate httproute lime konghq.com/plugins=anyone-acl

Response:

httproute.gateway.networking.k8s.io/lemon annotated
httproute.gateway.networking.k8s.io/lime annotated

Add consumers to groups

Group assignments are handled via credentials:

kubectl create secret \
  generic admin-acl \
  --from-literal=kongCredType=acl  \
  --from-literal=group=admin

kubectl create secret \
  generic user-acl \
  --from-literal=kongCredType=acl  \
  --from-literal=group=user

Response:

secret/admin-acl created
secret/user-acl created

Like the authentication credentials, these need to be bound to their consumers via their credentials array:

kubectl patch --type json kongconsumer admin \
  -p='[{
    "op":"add",
    "path":"/credentials/-",
    "value":"admin-acl" 
  }]'
kubectl patch --type json kongconsumer user \
  -p='[{
    "op":"add",
    "path":"/credentials/-",
    "value":"user-acl" 
  }]'

Response:

kongconsumer.configuration.konghq.com/admin patched
kongconsumer.configuration.konghq.com/user patched

Send authorized requests

The admin consumer can now access either URL:

curl -sI http://kong.example/lemon -H "Authorization: Bearer ${ADMIN_JWT}" --resolve kong.example:80:$PROXY_IP | grep HTTP
curl -sI http://kong.example/lime -H "Authorization: Bearer ${ADMIN_JWT}" --resolve kong.example:80:$PROXY_IP | grep HTTP

Response:

HTTP/1.1 200 OK
HTTP/1.1 200 OK

user, however, can only access the URL that permits the user group:

curl -sI http://kong.example/lemon -H "Authorization: Bearer ${USER_JWT}" --resolve kong.example:80:$PROXY_IP | grep HTTP
curl -sI http://kong.example/lime -H "Authorization: Bearer ${USER_JWT}" --resolve kong.example:80:$PROXY_IP | grep HTTP

Response:

HTTP/1.1 403 Forbidden
HTTP/1.1 200 OK
Thank you for your feedback.
Was this page useful?
  • Kong
    THE CLOUD CONNECTIVITY COMPANY

    Kong powers reliable digital connections across APIs, hybrid and multi-cloud environments.

    • Company
    • Customers
    • Events
    • Investors
    • Careers Hiring!
    • Partners
    • Press
    • Contact
  • Products
    • Kong Konnect
    • Kong Gateway
    • Kong Mesh
    • Get Started
    • Pricing
  • Resources
    • eBooks
    • Webinars
    • Briefs
    • Blog
    • API Gateway
    • Microservices
  • Open Source
    • Install Kong Gateway
    • Kong Community
    • Kubernetes Ingress
    • Kuma
    • Insomnia
  • Solutions
    • Decentralize
    • Secure & Govern
    • Create a Dev Platform
    • API Gateway
    • Kubernetes
    • Service Mesh
Star
  • Terms•Privacy
© Kong Inc. 2023