Skip to main content

Authorize Kong Gateway requests with Permit

Authorize requests that pass through Kong Gateway with a Permit.io policy, without adding permission checks to your service code. This page is for developers who already route and authenticate traffic with Kong. You run the Permit policy decision point (PDP) next to Kong, put a reverse proxy in front of the PDP to add the PDP API key, then configure the Kong Open Policy Agent (OPA) plugin on a route to ask the PDP about each request.

The Kong OPA plugin cannot send the PDP its API key

The PDP answers any request to /kong that has no Authorization: Bearer <API key> header with HTTP 401. In the PDP repository, horizon/tests/test_enforcer_api.py lists /kong in PROTECTED_ENFORCER_ENDPOINTS and test_enforcer_endpoint_missing_token_returns_401 asserts the 401 for every endpoint in that list. The Kong OPA plugin has no configuration field for the headers it sends to OPA, so a plugin pointed straight at the PDP gets 401 on every request, and the plugin turns any non-200 answer into HTTP 500 for the client. Point the plugin at a reverse proxy that adds the header, as 2. Add the API key with a reverse proxy describes. Without that proxy, every request through the protected route fails.

How the Kong integration works

The Permit PDP is built on OPA, so Kong's standard OPA plugin can call it. When the PDP runs with the Kong integration enabled, it exposes a /kong endpoint that reads the input the OPA plugin sends and runs a permission check:

Check fieldValue the PDP uses
UserThe username of the Kong consumer that made the request
ActionThe HTTP method of the request, in lowercase (for example, get or post)
Resource typeDerived from the request path (see Map request paths to resources)
Tenantdefault

The PDP answers with the decision in a result field. When the PDP allows the request, Kong forwards it to your service. When the PDP denies it, Kong returns HTTP 403. You manage the policy in the Permit dashboard, and Permit keeps it as policy as code.

Prerequisites

  • Kong Gateway configured to route requests to your backend, with authentication handled by Kong so each request has a consumer
  • The Kong OPA plugin, which Kong provides on Kong Gateway Enterprise
  • Docker on a host that Kong can reach, for the PDP and the reverse proxy
  • A Permit.io policy with resources named after your route paths, and actions named after lowercase HTTP methods (Configure your first RBAC policy)
  • Your environment API key (Get your API key)

1. Run the PDP next to Kong

The PDP is a container that makes authorization decisions. Permit's cloud configures it, and the PDP evaluates checks locally with the policy it has received.

Run the PDP with the Kong integration enabled. Replace YOUR_PERMIT_API_KEY with your environment API key:

docker run \
-p 7766:7000 \
--env PDP_API_KEY=YOUR_PERMIT_API_KEY \
--env PDP_DEBUG=True \
--env PDP_KONG_INTEGRATION=true \
permitio/pdp-v2:latest

The command maps port 7766 on the host to the PDP's port 7000. PDP_KONG_INTEGRATION=true enables the /kong endpoint. Without it, the PDP answers /kong requests with HTTP 503.

2. Add the API key with a reverse proxy

Kong sends no Authorization header to the PDP, so put a proxy between Kong and the PDP that adds one. The following NGINX configuration listens on port 8080, adds the API key, and forwards to the PDP on 7766. Replace YOUR_PERMIT_API_KEY with your environment API key, and PDP_HOST with the host that runs the PDP:

events {}

http {
server {
listen 8080;

location /kong {
proxy_pass http://PDP_HOST:7766/kong;
proxy_set_header Authorization "Bearer YOUR_PERMIT_API_KEY";
}
}
}

Save the configuration as pdp-proxy.conf and run it as a container on a host Kong can reach:

docker run \
-p 8080:8080 \
-v "$PWD/pdp-proxy.conf:/etc/nginx/nginx.conf:ro" \
nginx:stable

Check that the proxy reaches the PDP and authenticates. The request body below is not a valid Kong query, so the PDP rejects the body rather than the caller:

curl -i -X POST http://localhost:8080/kong -H "Content-Type: application/json" -d '{}'

Read the status line: 401 means the API key in proxy_set_header is missing or wrong, and any other status means the proxy added a key that the PDP accepted. A connection error means the proxy can't reach the PDP at the proxy_pass address.

The proxy holds your environment API key

Anyone who can reach the proxy can send permission checks to your PDP, and anyone who can read pdp-proxy.conf can change that environment's policy through the Permit API. Run the proxy on a network that only Kong can reach, and keep the configuration file out of source control.

3. Add the OPA plugin to a Kong route

In Kong Manager, open the route you want to protect and add a plugin. The Add plugin link is in the Plugins section of the route page.

Kong Manager route page with the Plugins section and the Add plugin link

Choose the OPA plugin and set these fields to the address of the reverse proxy from step 2, not the address of the PDP:

Plugin fieldValueWhy
Config.include Consumer In Opa InputCheckedThe PDP uses the consumer's username as the user key. Without the consumer, the PDP denies every request.
Config.Opa HostThe IP address or host name of the reverse proxy, for example 192.168.60.231Where Kong sends the check
Config.Opa Port8080The port the reverse proxy listens on
Config.Opa Path/kongThe PDP endpoint for Kong
Config.Opa ProtocolhttpThe protocol between Kong and the reverse proxy

4. Verify the permission check

  1. Send a request through the Kong route as a consumer who has permission for the action on the resource. Kong forwards the request to your service.
  2. Send the same request as a consumer without that permission. Kong returns HTTP 403.
  3. Open Audit Log in the Permit dashboard. Each request appears as a decision with the consumer's username, the lowercase HTTP method, and the resource type. See View and filter audit logs.

Use this table when a request through the route fails:

SymptomCauseFix
Kong returns 500 for every requestThe plugin points at the PDP instead of the reverse proxy, so the PDP answers 401Set Config.Opa Host and Config.Opa Port to the reverse proxy from step 2
Kong returns 500 and the PDP logs nothingKong can't reach the reverse proxy, or the proxy can't reach the PDPRun the curl check in step 2 from the Kong host
The proxy container exits with host not found in upstreamNGINX resolves the proxy_pass host at startup, and the host in the configuration doesn't resolveReplace PDP_HOST with a host name or IP address the proxy container can resolve
The PDP logs Got request from Kong with no consumerThe plugin doesn't include the consumerCheck Config.include Consumer In Opa Input in the plugin configuration
The PDP logs no matching routeNo rule in kong_routes.json matches the request pathAdd a rule for the path to the route mapping file

Map request paths to resources

The PDP picks the resource type from the request path with the first matching rule:

Request pathResource type
/v<number>/<segment>..., for example /v1/repo/42<segment> (repo)
/<segment>..., for example /repo<segment> (repo)
/index

The rules come from the file /config/kong_routes.json in the PDP container, which holds a JSON array of [regular expression, resource] pairs. The resource element is either a resource type name or the index of a capture group whose value is the resource type. The default file is:

[
["/v\\d+/([^/]+).*", 0],
["/([^/]+).*", 0],
["/", "index"]
]

To use your own mapping, mount a replacement file over /config/kong_routes.json when you run the PDP container, for example -v "$PWD/kong_routes.json:/config/kong_routes.json:ro". The PDP reads the file at startup, so restart the container after you change it. If no rule matches a path, the PDP denies the request.

Next steps