In part one of this blog series, I covered Gloo Gateway and Confluent Cloud, Apache Kafka and external consumers, Event Gateway patterns, Gloo Gateway, and Using the Confluent Cloud REST API.
Here in the second and last part of the series, we will go over securing, controlling, and managing the Confluent Cloud REST API with Gloo Gateway. We will use Gloo Gateway’s advanced API Gateway functionalities to:
- Secure our Confluent Cloud REST API
- Apply access policies to secure the REST API, including access to Kafka topics.
- Apply rate limiting policies to control traffic from external consumers to our Kafka environment.
Installing Gloo Gateway
First we need to install Gloo Gateway in our Kubernetes cluster (detailed installation instructions can be found here). Follow the instructions to install Gloo Gateway version 2.3.2 onto your Kubernetes cluster. Make sure that you also install the extAuthService
and the rateLimiter
.
Exposing the Confluent Cloud REST API
With Gloo Gateway installed, we can now expose the Confluent Cloud REST API via the Gateway. To do that, we need to deploy an ExternalService
that creates an addressable destination in our Kubernetes cluster that points to the Confluent Cloud REST API. This will later allow us to create a route to this destination in our Gloo Gateway RouteTable.
Let’s first create a new confluent-cloud
namespace in which we can deploy our resources:
Most of the following commands require the cluster name of your Kubernetes cluster to be set. The easiest way to do this is to export the name of your Kubernetes cluster to an environment variable:
Apply the following ExternalService custom resource. This will create a destination inside your Kubernetes cluster that points to your Confluent Cloud REST API. Replace the {CONFLUENT_CLOUD_HOST} placeholder with the hostname of your Confluent Cloud environment (in my case this is pkc-z9doz.eu-west-1.aws.confluent.cloud):
Note that we use the property clientsideTls
to configure TLS Origination. This allows us in this example to use HTTP traffic (for sake of simplicity) on the Gateway, and use HTTPS in our communication with Confluent Cloud.
With our ExternalService
deployed, we can now deploy the VirtualGateway
and RouteTable
.
Apply the following VirtualGateway
custom resource. This will configure the Gloo Ingress Gateway to listen for HTTP traffic on port 80 for hostname kafka.example.com:
To be able to use the kafka.example.com hostname, add the kafka.example.com hostname to your /etc/hosts file, and point it to the IP Address of your Kubernetes cluster’s Ingress Gateway. When running this example on a local Kubernetes cluster, the address is simply 127.0.0.1:
We can now apply the RouteTable
, which configures the routing from our Ingress Gateway into our ExternalService
. Note that we apply the label route: confluent-cloud-rest
to our route. This label will later be used in the authentication and rate-limit policies to select our route. Make sure to replace the placeholders {CONFLUENT_CLOUD_HOST} and {KAFKA_CLUSTER_ID} with the values of your Confluent Cloud Kafka instance ID (in my case these values are pkc-z9doz.eu-west-1.aws.confluent.cloud and lkc-c834f3):
With the VirtualGateway
, RouteTable
and ExternalService
deployed, and the kafka.example.com hostname mapped to the right ip-address in our /etc/hosts file, the Confluent Cloud Kafka cluster can now be accessed over HTTP via Gloo Gateway.
We will again use the cURL command to retrieve the topic information from our Confluent Cloud Kafka cluster using the following command. Make sure to replace the {API-KEY} placeholders with the values of your Kafka cluster:
Confluent Cloud will send the same response we saw earlier, which contains information about the topics on your Kafka cluster. Note that we no longer have to specify the Confluent Cloud hostname and our Kafka instance ID, as the traffic routing is handled by our Gloo RouteTable
and ExternalService
.
Securing the Confluent Cloud RESTful API
With the base-configuration in place, and Gloo Gateway handling the HTTP traffic to Confluent Cloud REST API, we can enable more Gloo Gateway features. Let’s start by securing our Kafka endpoints with an additional Gloo Gateway API-Key.
You can use different mechanisms and protocols to secure your endpoints with Gloo Gateway, including OAuth2 and OpenID Connect. In this article we secure our APIs with API-Keys, as this architecture does not require any additional components, like an OAuth Provider, to be deployed on the Kubernetes cluster and be integrated with Gloo Gateway. (For more information about Gloo Gateway’s authentication and authorization capabilities, please consult the Gloo Gateway documentation.)
To secure the Kafka endpoints with an API-Key, we first need to create the API-Key Secret in Kubernetes. In this example, we simply will use a predefined API-Key. (In a production scenario you would use an API management tool such as Gloo Portal or Google Developer Portal, to generate an API key to use for your application’s domain.)
Apply the following Kubernetes secret which contains the api-key
, a user-id
and a user-email
entry. Note that all values have been encoded in Base64:
Next, create the external auth server that is responsible for verifying credentials and determine permissions:
Finally, create an ExtAuthPolicy that enforces authorization with an API-Key on applicable routes. In our case this is the route to ExternalService that routes the traffic to Confluent Cloud . Note that the route-policy gets applied to all routes that have the label confluent-cloud-rest, like the route we’ve created earlier. Also note that the API-Key is also selected by label (i.e. extauth: apikey):
When we now try to list our Kafka topics, Gloo Gateway returns a 401 – Unauthorized:
Adding the new Gloo API-Key in a request header gives us access to our topics again:
Note that we’re passing 2 API-Keys in our headers, 1 API-Key with header name api-key
for the Gloo Gateway authentication and one Confluent Cloud API-Key via the Authorization
header for the Confluent Cloud authentication. This is just an example of how to add another layer of security using Gloo Gateway. As mentioned earlier, you can add more sophisticated authentication, for example OAuth based authentication, or even multi-step authentication with OPA (Open Policy Agent) using similar Gloo ExtAuth constructs.
Rate Limiting the Confluent Cloud RESTful API
Another interesting feature that Gloo Gateway can add to our Kafka system is rate-limiting. Rate limiting allows us to limit the number of requests per time unit (seconds, minutes, hours, etc.) based on policies. It enables us to protect the service from mis-use by clients, enforce service and/or business limits based on service offering categories and business plans, etc.
As an example use case, let’s implement a rate limiting policy that only allows 3 requests per minute with the API-Key we defined earlier.
First we apply the RateLimitServerSettings
, which configures how clients connect to the rate-limiting server:
Now we need to configure the rate-limit server and client configurations using the RateLimitServerConfig and RateLimitClientConfig CRs. In this example, the rate-limiting descriptor applies the rate-limit for any unique userId. Remember that the userId field is a data field in our API-Key secret. Hence, this allows us to rate-limit per API-Key, as long as the userId field is unique per API-Key:
Finally, we can apply the RateLimitPolicy, which applies the rate-limit server config, client config and server settings to one or more routes. The routes are, as with the ExtAuthPolicy
, selected using labels:
Now when we execute our Kafka REST requests multiple times in a row(for example retrieving our Kafka topics information or sending records to the orders topic) we will see that after 3 requests per minute, we are rate limited and we get a 429 – Too Many Requests HTTP response. Execute the following request 4 times in a row, and observe how the last request will be rate-limited:
Now when we execute our Kafka REST requests multiple times in a row(for example retrieving our Kafka topics information or sending records to the orders topic) we will see that after 3 requests per minute, we are rate limited and we get a 429 – Too Many Requests HTTP response. Execute the following request 4 times in a row, and observe how the last request will be rate-limited:
Try to send a number of records to our orders topic. Observer how, after the 3rd request per minute, the requests are rate limited and a 429 – Too Many Requests HTTP response is returned:
Conclusion
Event-driven and event streaming architectures are popular architectural paradigms to implement real time data systems at scale. Often though, the benefits of event streaming platforms are only reaped internally in organizations, as exposing systems like Apache Kafka to external consumers can be difficult due to the use of non-standard protocols, security requirements, and network architectures. By using an API Gateway like Gloo Gateway, in combination with the Confluent Cloud REST API, we can create architectures in which the power of the event streaming platform can be safely and securely exposed to external consumers. Advanced functionalities like authentication and authorization based on API-Keys, OAuth and OPA, combined with features like rate-limiting, give us control over how the event streaming platform is exposed to consumers, provide fine-grained control over which consumers have access to which part of the system, and can protect the event streaming platform from external mis-use and potential abuse.
In this article we’ve shown a basic integration of Gloo Gateway with Confluent Cloud, laying the foundations of more advanced architectures powered by Gloo. Please consult the Gloo Gateway documentation to learn more about this powerful API Gateway and the features it provides.