This is a proof of concept on securing Kafka resources – most notably Kafka topics – with Authorino.
The implementation should work with Authorino v0.6.0 and relies on Strimzi v0.23.0. It is quite limited regarding the types of permission that can be modeled. It is NOT meant for production.
Characteristics of the implementation:
- Relies on Strimzi support for Kafka broker OAuth authentication
- Relies on Strimzi support for Kafka broker authorization with Keycloak
- Does NOT use Keycloak
- Uses Authorino to issue OAuth access tokens and to provide the user permissions, the latter "pretending to be" Keycloak Authorization Service API
- Clients authentication is based on API keys, handled by Authorino, and exchanged for short-lived access tokens (Authorino Wristband tokens)
- Connection with the Kafka brokers is established bearing the Authorino Wristband token, which are verified and validated by the broker after fetching the JWKS from an Auhtorino endpoint
- Client permissions are stored in the annotations of Kubernetes
Secret
s that represent the API keys - Kafka authorization request (based on Strimzi's
keycloak
authorization type) just bounces back permission claims already present in the Authorino Wristband token obtained and used in the authentication phase
Limitations of the implementation:
- Not very different from Kafka's standard ACL-based authorization, with the extra limitation that the API keys can only store permission info about one Kafka resource at a time.
- Authorino wristbands are only supplied on client startup, and neither the clients, nor the Kafka brokers refresh the token afterwards. Consequently, permissions last until the token expires or the restarts and obtains a new one again by exchanging with the API key.
- Cannot leverage authorization based on OPA policies, Authorino JSON pattern-matching authz or Kubernetes RBAC, that evaluate in request-time based upon combination of principal information (present in the access token) and resource/operation information, due to constraints of Strimzi's
keycloak
authorizer, which does not supply information about resources nor operations on the request for permission; rather, the authorizer can only provide a static list of permissions in the response.
Steps 1-5 below are for installing and deploying Authorino on a Kubernetes cluster started locally with Kind, using some Authorino trial tooling from the Authorino repo. If you prefer handling Authorino installation and deployment by yourself, perhaps on another Kubernetes server of preference where you want to try this PoC, you can skip directly to step 6. In this case, make sure to create on your Kubernetes server a Namespace
named kafka
, where Authorino and all the other resources involved in the PoC must be created.
- Start a local Kubernetes cluster with Kind
kind create cluster --name strimzi-authorino-demo
- Install the Authorino Operator
TMP_DIR=$(mktemp -d) && cd $TMP_DIR
git clone --depth 1 --branch main https://github.com/Kuadrant/authorino-operator.git .
kubectl create namespace authorino-operator && make install deploy
rm -rf $TMP_DIR
- Create the namespace for the project
kubectl create namespace kafka
- Install cert-manager and Authorino CRD
TMP_DIR=$(mktemp -d) && cd $TMP_DIR
git clone --depth 1 --branch main https://github.com/kuadrant/authorino.git .
make cert-manager # installs https://github.com/jetstack/cert-manager - skip it if already installed
make certs NAMESPACE=kafka
rm -rf $TMP_DIR
- Deploy Authorino
kubectl -n kafka apply -f -<<EOF
apiVersion: operator.authorino.kuadrant.io/v1beta1
kind: Authorino
metadata:
name: authorino
spec:
image: quay.io/3scale/authorino:latest
clusterWide: false
listener:
tls:
enabled: true
certSecretRef:
name: authorino-server-cert
oidcServer:
tls:
enabled: true
certSecretRef:
name: authorino-oidc-server-cert
EOF
- Clone this repo
git clone [email protected]:guicassolato/strimzi-authorino.git && cd strimzi-authorino
- Setup the Envoy proxy
kubectl -n kafka apply -f envoy-proxy.yaml
- Install the Strimzi operator
kubectl -n kafka apply -f strimzi-install.yaml
- Create the Authorino
AuthConfig
s and KubernetesService
s for authentication and authorization
kubectl -n kafka apply -f authentication-service.yaml
kubectl -n kafka apply -f authentication.yaml
kubectl -n kafka apply -f authorization-service.yaml
kubectl -n kafka apply -f authorization.yaml
- Create the Kafka cluster
kubectl -n kafka apply -f kafka-cluster.yaml
- Share access with the Kafka client applications (producer and consumer) by creating API keys for them (as Kubernetes
Secret
resources)
kubectl -n kafka apply -f kafka-producer-api-key.yaml
kubectl -n kafka apply -f kafka-consumer-api-key.yaml
- Start the producer and attach to the interactive shell of the container
kubectl -n kafka apply -f kafka-producer.yaml
kubectl -n kafka attach -it pod/kafka-producer # <========= holds the shell
Note: You may need to press Enter once, to see the prompt.
- Produce a first "Hello" message
> Hello # [Enter]
- Start the consumer and watch the logs
kubectl -n kafka apply -f kafka-consumer.yaml
kubectl -n kafka logs -f pod/kafka-consumer # <========= holds the shell
Here are some enhancements/next steps to improve this PoC towards having a proper Authorino authorizer for the Kafka brokers.
- Implement (in Java) an Authorino Kafka Authorizer, to replace the current pretend-to-be Keycloak workaround, and integrate it through Strimzi Custom Authorization.
- Support for token refresh.