You are browsing documentation for an outdated version. See the latest documentation here.
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 Kong 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:
echo "
apiVersion: v1
kind: Service
metadata:
labels:
app: echo
name: echo
spec:
ports:
- port: 1025
name: tcp
protocol: TCP
targetPort: 1025
- port: 1026
name: udp
protocol: TCP
targetPort: 1026
- port: 1027
name: http
protocol: TCP
targetPort: 1027
selector:
app: echo
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: echo
name: echo
spec:
replicas: 1
selector:
matchLabels:
app: echo
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: echo
spec:
containers:
- image: kong/go-echo:latest
name: echo
ports:
- containerPort: 1027
env:
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
resources: {}
" | kubectl apply -f -
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:
Kong 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:
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
Content-Length: 140
Connection: keep-alive
Date: Fri, 21 Apr 2023 12:24:55 GMT
X-Kong-Upstream-Latency: 0
X-Kong-Proxy-Latency: 1
Via: kong/3.2.2
Welcome, you are connected to node docker-desktop.
Running on Pod echo-7f87468b8c-tzzv6.
In namespace default.
With IP address 10.1.0.237.
...
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:
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:
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