Event Authorization in Kafka/Redpanda
- Description of the Feature
- The current architecture of the MSD is "unnatural" in several respects, i.e. different from that of productive microservice systems such as an eCommerce system. The players virtually live in a "demilitarized zone" with dedicated (Rabbit MQ) queues, instead of participating directly in the event stream in Kafka/Redpanda. The main reason for this is the "Fog of War" concept. The players should not see everything that happens between the services and between services and other players happens. This could be changed by authorizing access to events in Kafka/Redpanda. The players could then participate directly in the event stream, and the services would authorize the inter-service communication specially authorized. This is supposed to be prototyped in this feature.
- Author
- Samuel Miebach, Bernhard Sprenger
- Implemented During
- WASP II "Microservices und Event-getriebene Architektur (MEA), SS2024, as topic (A3)
- Status
- ongoing
- Repositories
-
- https://gitlab.com/the-microservice-dungeon/devops-team/deployments/kafka-rabbitmq-connector (Branch AuthKafka): Made the connector send the events like before but now to the topics in Kafka/Redpanda.
- https://gitlab.com/the-microservice-dungeon/core-services/game (Branch AuthKafka): Game now creates the player specific topic in Kafka/Redpanda and a topic named "player-public" where all public events go. Also gets authenticated and authorized.
- https://gitlab.com/the-microservice-dungeon/core-services/map (Branch AuthKafka): Map now has its own authentication and authorization done with Kafka.
- https://gitlab.com/the-microservice-dungeon/core-services/robot (Branch AuthKafka): Robot now has its own authentication and authorization done with Kafka.
- https://gitlab.com/the-microservice-dungeon/core-services/trading (Branch AuthKafka): Trading now has its own authentication and authorization done with Kafka.
- https://gitlab.com/the-microservice-dungeon/devops-team/development-envs/local-dev-environment (Branch AuthKafka): Removed RabbitMQ and added Redpanda-Connect as a possible solution to route the events to the player topics with the needed pipeline config to do it.
- https://gitlab.com/the-microservice-dungeon/player-teams/skeletons/player-java-springboot (Branch auth-kafka): Removed RabbitMQ and added a KafkaListener to recieve events send from the the MicroServiceDungeon game.
- https://gitlab.com/the-microservice-dungeon/core-services/game (Branch AuthKafka): Removed RabbitMQ and added a KafkaListener and SASL to recieve events send from the the MicroServiceDungeon game. Player Monte(Branch auth-kafka)
- Last Update
- 2025-02-04
Old Architecture
Services

Integration

New Architecture
Changes
Player(Java)
The PlayerExternalEventListener.java has been adapted to function as a @KafkaListener, enabling it to receive events sent via Kafka (Redpanda) that are intended for each player. The listener is configured to listen to two topics: one is a public topic where messages are broadcast to every player in the game, and the other is a private topic dedicated to each individual player, identified by their unique player ID. For player developers, nothing changes in terms of how events are produced. Events are generated and handled exactly as before.
Game
The PlayerExchangeManager.kt has been replaced by the PlayerTopicManager.kt to ease the transition from RabbitMQ queues to Kafka event streams. This shift involved some minor adjustments to ensure seamless integration. The PlayerTopicManager.kt is now responsible for creating and managing all necessary topics, enabling event delivery to every player. In addition, we added an AdminClient that is used to empty the Topics of the player and the public Topic before each game. It also used to create a User and the read Permission of the User when a new Player is registered or joins a Game.
local-dev-environment
Some .yaml files got adjusted to now define Redpanda-Connect instead of RabbitMQ in our Docker cluster. Redpanda Console was modified to be usable when Auth is required. Also the for the ACL needed setup commands for the Core Services were added to redpanda’s start script.
kafka-rabbitmq-connector
The KafkaRabbitMQConnectorApplication.java is now a KafkaKafkaConnectorApplication.java which means some minor adjustments were made to use Kafka instead of RabbitMQ.
redpanda-connect
Redpanda-Connect is the Connector solution of redpanda and uses a simple config style setup to process Events from all possible sources and send these to all possible sources. In our case we use the kafka part of the connector and listen and send to kafka which is redpanda. The connector take the events like the old KafkaRabbitMQCOnnector and then sends these to the player specific Topics or the public Topic. A big problem with the redpanda-connector is that it can only send the events to one Topic and not to multiple Topics like events that can occur in multiplayer that are send to two player like a Fight that is send to the two players involed.
Fog of War
The Fog of War is maintained using Kafka’s authentication and authorization features. Players authenticate/log in with a username and password. Kafka’s Access Control Lists (ACLs) authorize each player and ensure that players only have READ access to their private topic and the public topic. So each player now has to add a password in their application.properties like this dungeon.playerPassword=${PLAYER_PASSOWRD:password}.
What Topics do the Services need?
As we want to have dedicated User-Permission even for our internal services we need to know what topics they read, write or create. The services always create the topic they write to and no other service is ever going to write to a topic they never created. A notable exception is the topic “command” as it seems to be only published by the GameService and no service listen to it as they all get the Commands via a Rest call from Game. In addition this topic is auto created by Kafka/Redpanda and not by Game.
Here is a table of needed permission of the Services for each Topic:
Service | Create / Write | Read |
---|---|---|
Game | status, playerStatus, roundStatus, command, error | robot |
Map | gameworld, planet, error | robot |
Robot | robot, error | status, roundStatus, gameworld, trade-sell, trade-buy |
Trading | bank, trade-sell, trade-buy, prices, error | status, roundStatus, playerStatus, robot, bank, trade-sell, trade-buy, prices |
Redpanda Connect | status, roundStatus, planet, robot, bank, prices, trade-sell, trade-buy, error |
Cli Commands needed for ACL
Based on the now known Topic we can create the ACL (Access Control List) that gets bound to the Users we create. Each Service is now going to get its own User on which is need Permission is going to be bound too. The write/create and read Permission is to ensure seperation its own binding. The binding are also having the consumer group the Services consume from included insuring they only use their correct one. For Game we give it an extra binding which allows it to create Topics that a prefixed with “player-”, this allows it to make the public Topic and all invidual Topic of the Players.
rpk acl user create game -p game --user admin --password admin --sasl-mechanism SCRAM-SHA-256
rpk acl user create map -p map --user admin --password admin --sasl-mechanism SCRAM-SHA-256
rpk acl user create robot -p robot --user admin --password admin --sasl-mechanism SCRAM-SHA-256
rpk acl user create trading -p trading --user admin --password admin --sasl-mechanism SCRAM-SHA-256
rpk acl user create redpanda-connect -p redpanda-connect --user admin --password admin --sasl-mechanism SCRAM-SHA-256
rpk acl create --allow-principal User:game --group game --operation read --topic robot --user admin --password admin --sasl-mechanism SCRAM-SHA-256
rpk acl create --allow-principal User:game --group game --operation create --operation write --topic status --topic playerStatus --topic roundStatus --topic command --topic error --user admin --password admin --sasl-mechanism SCRAM-SHA-256
rpk acl create --allow-principal User:game --group game --operation all --resource-pattern-type prefixed --topic player- --user admin --password admin --sasl-mechanism SCRAM-SHA-256
rpk acl create --allow-principal User:map --group map --operation read --topic robot --user admin --password admin --sasl-mechanism SCRAM-SHA-256
rpk acl create --allow-principal User:map --group map --operation create --operation write --topic gameworld --topic planet --topic error --user admin --password admin --sasl-mechanism SCRAM-SHA-256
rpk acl create --allow-principal User:robot --group robot --operation read --topic status --topic roundStatus --topic gameworld --topic trade-sell --topic trade-buy --user admin --password admin --sasl-mechanism SCRAM-SHA-256
rpk acl create --allow-principal User:robot --group robot --operation create --operation write --topic robot --topic error --user admin --password admin --sasl-mechanism SCRAM-SHA-256
rpk acl create --allow-principal User:trading --group trading --operation read --topic status --topic roundStatus --topic playerStatus --topic robot --topic bank --topic trade-sell --topic trade-buy --topic prices --user admin --password admin --sasl-mechanism SCRAM-SHA-256
rpk acl create --allow-principal User:trading --group trading --operation create --operation write --topic bank --topic trade-sell --topic trade-buy --topic prices --topic error --user admin --password admin --sasl-mechanism SCRAM-SHA-256
rpk acl create --allow-principal User:redpanda-connect --group redpanda-connect --operation all --topic status --topic roundStatus --topic planet --topic robot --topic bank --topic prices --topic trade-sell --topic trade-buy --topic error --user admin --password admin --sasl-mechanism SCRAM-SHA-256
rpk acl create --allow-principal User:redpanda-connect --group redpanda-connect --operation all --resource-pattern-type prefixed --topic player- --user admin --password admin --sasl-mechanism SCRAM-SHA-256
For Players we create their User using their Name as this is set by themselves and known before joining a game. The topics themselves are deleted and created each game to remove their contents by the GameService as otherwise new Players would consume the Old Events in the Public Topic. The User is created for each new Player that is registerd by the GameService
This is an example rpk cli for User creation on which we based then the needed info for the Kafka API
rpk acl user create player-monte -p password
rpk acl create --allow-principal User:player-monte --group PLAYERID --operation read --topic player-PLAYERID --topic player-public
The PLAYERID needs to be substituted by the player UUID that is given to each player with their registration with the Game Service.
If a possible Fog of War viaolation can be allowed the use of the resource pattern type prefixed with player as prefix can be used as the the player only has access to events in all Player Topics.
rpk acl create --allow-principal User:player-monte --operation read --resource-pattern-type prefixed --topic player-
Issue with Kafka SASL Authentication
When Kafka’s SASL authentication is enabled, the player no longer receives the critical GAME STARTED event needed to kick off further processing. Notably, other services integrated with Kafka, using the same SASL authentication setup, continue to function without issues. Despite confirming that permissions and configurations are correct, the player fails to receive the first event when SASL authentication is enabled.