API security is a critical aspect of modern web and mobile application development, where APIs serve as the backbone for communication between different systems. In this context, securing these APIs is paramount. Two technologies that have emerged as leading tools for enhancing API security are Kong Gateway and Open Policy Agent (OPA). Kong Gateway provides a robust API management solution with flexible routing, load balancing, and security policies, while OPA enables fine-grained, customizable policy enforcement. Together, these tools form a comprehensive framework for securing APIs at scale.
In this article, we will explore how to enhance API security using Kong Gateway for securing APIs and OPA for handling policy decisions, complete with code examples and a thorough discussion of the concepts.
What is Kong Gateway?
Kong Gateway is an open-source, cloud-native API gateway built on NGINX that helps organizations manage, monitor, and secure their APIs. As an API gateway, it acts as a reverse proxy, intercepting incoming API requests and forwarding them to the appropriate backend services.
Key features of Kong Gateway include:
- Rate limiting: Control the number of requests an API can handle.
- Authentication and Authorization: Supports various forms of authentication (OAuth2, JWT, API keys, etc.).
- Traffic control: Manages load balancing, retries, circuit breakers, and more.
- Logging and Monitoring: Provides extensive metrics for monitoring traffic.
Basic Setup of Kong Gateway
First, let’s start by setting up Kong Gateway on a Docker environment. Here’s how you can configure a basic Kong Gateway:
docker network create kong-net
# Start a PostgreSQL instance for Kong
docker run -d –name kong-database \
–network=kong-net \
-p 5432:5432 \
-e “POSTGRES_USER=kong” \
-e “POSTGRES_DB=kong” \
postgres:9.6
# Run the Kong Gateway instance
docker run -d –name kong \
–network=kong-net \
-e “KONG_DATABASE=postgres” \
-e “KONG_PG_HOST=kong-database” \
-e “KONG_CASSANDRA_CONTACT_POINTS=kong-database” \
-e “KONG_ADMIN_LISTEN=0.0.0.0:8001” \
-p 8000:8000 \
-p 8001:8001 \
kong
Now that Kong is running, you can use its Admin API (available at port 8001
) to configure services and routes.
Securing APIs with Kong
Kong supports multiple security plugins, including OAuth2, JWT, and basic authentication. Here’s how to secure an API using the JWT Plugin.
Create a Service
A Service represents an upstream API that Kong manages.
curl -i -X POST http://localhost:8001/services/ \
--data name=my-service \
--data url='http://httpbin.org'
Create a Route
Routes define how incoming requests map to services.
curl -i -X POST http://localhost:8001/services/my-service/routes \
--data 'hosts[]=example.com'
Enable JWT Plugin
JWT authentication requires clients to send a JWT token with their requests.
curl -i -X POST http://localhost:8001/services/my-service/plugins \
--data name=jwt
Add a Consumer
A Consumer represents a client using the API. Each consumer is issued credentials.
curl -i -X POST http://localhost:8001/consumers/ \
--data username=example-user
Add JWT Credentials for the Consumer
curl -i -X POST http://localhost:8001/consumers/example-user/jwt
With these steps, we’ve enabled basic API security using JWT authentication on Kong Gateway. Now, any request made to the route requires a valid JWT token.
Introduction to Open Policy Agent (OPA)
Open Policy Agent (OPA) is a general-purpose policy engine that can be integrated into various systems to provide policy-based access control. OPA decouples policy decisions from application logic, making it easier to manage security rules across microservices and APIs.
OPA operates based on the Rego language, which allows you to write declarative policies. These policies can be used for fine-grained access control, filtering data, and enforcing various business rules.
How OPA Works
- Input: OPA receives an input, which is typically the request data (HTTP headers, method, path, etc.).
- Policy Evaluation: Based on the input, OPA evaluates the request against predefined policies written in Rego.
- Decision: OPA returns a decision that determines whether the request should be allowed or denied.
Example of OPA Policy
Let’s consider a basic example where OPA is used to authorize API requests based on user roles.
package example.authz
default allow = false
allow {
input.user == “admin”
}
allow {
input.method == “GET”
input.path == “/public”
}
This policy defines two rules:
- Allow access if the user is “admin.”
- Allow access to all GET requests on the
/public
endpoint.
Now, let’s integrate OPA with Kong Gateway to enforce these policies.
Integrating Kong Gateway with OPA
To enhance API security, you can integrate Kong Gateway with OPA, delegating authorization decisions to OPA while leveraging Kong’s features for authentication, rate limiting, and logging.
Step-by-Step Integration of Kong and OPA
Deploy OPA
You can run OPA as a standalone service or within a Docker container. For example:
docker run -d --name opa -p 8181:8181 openpolicyagent/opa:latest run --server
Create OPA Policies
You can write policies in Rego and store them within OPA. Save the following policy as authz.rego
and load it into OPA:
package kong.authz
default allow = false
allow {
input.method == “GET”
}
allow {
input.user == “admin”
}
Load this policy into OPA using the following command:
curl -X PUT --data-binary @authz.rego localhost:8181/v1/policies/authz
Configure Kong to Use OPA
You need to write a Kong plugin that queries OPA for authorization decisions. The plugin can make an HTTP call to the OPA server with the request details.
Here’s an example Kong plugin in Lua:
local http = require "resty.http"
local function authorize()
local httpc = http.new()
local res, err = httpc:request_uri(“http://localhost:8181/v1/data/kong/authz/allow”, {
method = “POST”,
body = ngx.req.get_body_data(),
headers = {
[“Content-Type”] = “application/json”,
}
})
if not res then
ngx.log(ngx.ERR, “Failed to query OPA: “, err)
return ngx.exit(500)
end
local body = cjson.decode(res.body)
if not body.result then
ngx.log(ngx.ERR, “OPA denied access”)
return ngx.exit(403)
end
end
return authorize
Deploy the Plugin on Kong
After writing the plugin, install it in your Kong instance and configure it for your API service.
curl -i -X POST http://localhost:8001/services/my-service/plugins \
--data name=opa-authz
This plugin will query OPA to decide whether or not to allow a request based on the predefined policies.
Testing the Integration
You can now test the integration by sending requests to the API via Kong. For example, sending a GET
request as an admin user should be allowed:
curl -H "Authorization: Bearer <admin_token>" http://localhost:8000/my-service
A POST
request from a non-admin user will be denied based on the OPA policy.
curl -X POST http://localhost:8000/my-service
Conclusion
In this article, we have explored how to enhance API security by combining Kong Gateway with Open Policy Agent (OPA). Kong Gateway provides robust features for managing API traffic, authentication, and rate limiting, while OPA offers a flexible and powerful way to implement fine-grained, dynamic access control policies.
By integrating these two tools, you can ensure that your APIs are protected not just at the network level, but also at the authorization level, providing more control over who can access your services. This approach allows you to adapt to evolving security requirements and ensure that policies are consistently enforced across all APIs.
The combination of Kong Gateway for API management and OPA for policy decisions enables organizations to build scalable, secure, and compliant API-driven architectures, addressing the complexities of modern distributed systems. This solution not only enhances security but also improves maintainability by decoupling policy logic from the application code.