Change kafka-oauth to use podman and simplify the quickstart procedures.
diff --git a/README.adoc b/README.adoc
index fecc37f..d42734a 100644
--- a/README.adoc
+++ b/README.adoc
@@ -98,7 +98,7 @@
| link:fhir/readme.adoc[Fhir] (fhir) | Health Care | An example showing how to work with Camel, FHIR and Spring Boot
| link:fhir-auth-tx/readme.adoc[Fhir Auth Tx] (fhir-auth-tx) | Health Care | An example showing how to work with Camel, FHIR Authorization, FHIR Transaction and Spring Boot
-
+
| link:validator/readme.adoc[Validator Spring Boot] (validator) | Input/Output Type Contract | An example showing how to work with declarative validation and Spring Boot
@@ -114,7 +114,7 @@
| link:metrics/README.adoc[Metrics] (metrics) | Management and Monitoring | An example showing how to work with Camel and Spring Boot and report metrics to Graphite
| link:observation/README.adoc[Micrometer Observation] (observation) | Management and Monitoring | An example showing how to trace incoming and outgoing messages from Camel with Micrometer Observation
-
+
| link:opentelemetry/README.adoc[OpenTelemetry] (opentelemetry) | Management and Monitoring | An example showing how to use Camel with OpenTelemetry
@@ -128,6 +128,8 @@
| link:kafka-avro/README.adoc[Kafka Avro] (kafka-avro) | Messaging | An example for Kafka avro
+| link:kafka-oauth/README.adoc[Kafka OAuth] (kafka-oauth) | Messaging | An example for Kafka authentication using OAuth
+
| link:kafka-offsetrepository/README.adoc[Kafka Offsetrepository] (kafka-offsetrepository) | Messaging | An example for Kafka offsetrepository
| link:paho-mqtt5-shared-subscriptions/README.adoc[Paho Mqtt5 Shared Subscriptions] (paho-mqtt5-shared-subscriptions) | Messaging | An example showing how to set up multiple mqtt5 consumers that use shared subscription feature of MQTT5
@@ -139,7 +141,7 @@
| link:widget-gadget/README.adoc[Widget Gadget] (widget-gadget) | Messaging | The widget and gadget example from EIP book, running on Spring Boot
| link:reactive-streams/readme.adoc[Reactive Streams] (reactive-streams) | Reactive | An example that shows how Camel can exchange data using reactive streams with Spring Boot reactor
-
+
| link:http-ssl/README.adoc[Http Ssl] (http-ssl) | Rest | An example showing the Camel HTTP component with Spring Boot and SSL
diff --git a/kafka-oauth/README.adoc b/kafka-oauth/README.adoc
index f76aacf..d975a7b 100644
--- a/kafka-oauth/README.adoc
+++ b/kafka-oauth/README.adoc
@@ -2,9 +2,9 @@
=== Introduction
-An example which shows how to integrate https://camel.apache.org/components/next/kafka-component.html[Camel with Kafka] with OAuth authentication using a client secret. The authentication is handled by Keycloak.
+An example that shows how to integrate https://camel.apache.org/components/next/kafka-component.html[Camel with Kafka] with OAuth authentication using a client secret. The authentication is handled by Keycloak.
-This example requires docker-compose as it will build and run a keycloak and kafka broker (setup with kraft mode).
+This example requires podman.
On the Kafka side it uses https://github.com/strimzi/strimzi-kafka-oauth[Strimzi Oauth for Apache Kafka], this library must also be set on the client side.
@@ -20,7 +20,7 @@
oauth.client.id="kafka-producer-client" \
oauth.client.secret="kafka-producer-client-secret" \
oauth.username.claim="preferred_username" \
- oauth.ssl.truststore.location="docker/certificates/ca-truststore.p12" \
+ oauth.ssl.truststore.location="containers/certificates/ca-truststore.p12" \
oauth.ssl.truststore.type="pkcs12" \
oauth.ssl.truststore.password="changeit" \
oauth.token.endpoint.uri="https://keycloak:8443/realms/demo/protocol/openid-connect/token" ;
@@ -31,24 +31,16 @@
* Set the hosts in /etc/hosts
-We have to set the IP addresses in /etc/hosts (check your OS how to do it), verify the current IP address and correctly set it as the example shows.
+We have to set the IP addresses in /etc/hosts (check your OS how to do it), verify the current IP address and correctly set it as the example shows. This is essential for the client application to reach keycloak and kafka hosts. In a production scenario those hosts names is going to be resolved by DNS.
----
192.168.0.104 keycloak
192.168.0.104 kafka
----
-* Build the project
-
-This command will download the required Strimzi OAuth libraries for Kafka and add it to the Kafka Broker directory, it will also build the camel spring boot example.
-----
-mvn package
-----
-
-* Launch the Keycloak server
+* Launch the Keycloak server. Note that the scripts runs a podman container with `host` network, so the keycloak and kafka server shares the same network as the client, this is for demo purposes only.
----
-cd docker
-docker-compose -f keycloak/compose.yml up
+./start_keycloak.sh
----
It must show the `demo` realm was imported successfully.
@@ -61,19 +53,18 @@
It also shows the server started.
----
[io.quarkus] (main) Keycloak 26.0.8 on JVM (powered by Quarkus 3.15.1) started in 9.169s. Listening on: http://0.0.0.0:8080 and https://0.0.0.0:8443
-[io.quarkus] (main) Profile prod activated.
+[io.quarkus] (main) Profile prod activated.
[io.quarkus] (main) Installed features: [agroal, cdi, hibernate-orm, jdbc-h2, keycloak, narayana-jta, opentelemetry, reactive-routes, rest, rest-jackson, smallrye-context-propagation, vertx]
----
* Launch the Kafka broker
-Open another terminal console and go to the docker directory:
+Open another terminal console and launch kafka broker:
----
-cd docker
-docker-compose -f kafka-oauth-strimzi/compose.yml up --build
+./start_kafka.sh
----
-It should show the kafka broker authenticated to the keycloak server using the kafka-broker client id.
+It should show the kafka broker authenticates to the keycloak server using the `kafka-broker` client id.
----
loginWithClientSecret() - tokenEndpointUrl: http://keycloak:8080/realms/demo/protocol/openid-connect/token, clientId: kafka-broker, clientSecret: k*********, scope: null, audience: null, connectTimeout: 20, readTimeout
: 60, retries: 0, retryPauseMillis: 0 (io.strimzi.kafka.oauth.common.OAuthAuthenticator)
@@ -82,16 +73,15 @@
It should show the kafka broker started
----
Kafka version: 3.9.0 (org.apache.kafka.common.utils.AppInfoParser)
-
[KafkaRaftServer nodeId=1] Kafka Server started (kafka.server.KafkaRaftServer)
----
=== Run the camel example
-As the project was already built, it's ready to run:
+Build and run the quickstart.
----
-mvn spring-boot:run
+mvn compile spring-boot:run
----
It should display the kafka OAuth settings, example:
@@ -116,10 +106,10 @@
=== Help and contributions
-If you hit any problem using Camel or have some feedback,
+If you hit any problem using Camel or have some feedback,
then please https://camel.apache.org/community/support/[let us know].
-We also love contributors,
+We also love contributors,
so https://camel.apache.org/community/contributing/[get involved] :-)
The Camel riders!
diff --git a/kafka-oauth/docker/certificates/ca-truststore.p12 b/kafka-oauth/containers/certificates/ca-truststore.p12
similarity index 100%
rename from kafka-oauth/docker/certificates/ca-truststore.p12
rename to kafka-oauth/containers/certificates/ca-truststore.p12
Binary files differ
diff --git a/kafka-oauth/docker/certificates/ca.crt b/kafka-oauth/containers/certificates/ca.crt
similarity index 100%
rename from kafka-oauth/docker/certificates/ca.crt
rename to kafka-oauth/containers/certificates/ca.crt
diff --git a/kafka-oauth/docker/certificates/ca.key b/kafka-oauth/containers/certificates/ca.key
similarity index 100%
rename from kafka-oauth/docker/certificates/ca.key
rename to kafka-oauth/containers/certificates/ca.key
diff --git a/kafka-oauth/docker/certificates/gen-ca.sh b/kafka-oauth/containers/certificates/gen-ca.sh
similarity index 100%
rename from kafka-oauth/docker/certificates/gen-ca.sh
rename to kafka-oauth/containers/certificates/gen-ca.sh
diff --git a/kafka-oauth/docker/kafka-oauth-strimzi/kafka/certificates/cluster.keystore.p12 b/kafka-oauth/containers/kafka/certificates/cluster.keystore.p12
similarity index 100%
rename from kafka-oauth/docker/kafka-oauth-strimzi/kafka/certificates/cluster.keystore.p12
rename to kafka-oauth/containers/kafka/certificates/cluster.keystore.p12
Binary files differ
diff --git a/kafka-oauth/docker/kafka-oauth-strimzi/kafka/certificates/cluster.truststore.p12 b/kafka-oauth/containers/kafka/certificates/cluster.truststore.p12
similarity index 100%
rename from kafka-oauth/docker/kafka-oauth-strimzi/kafka/certificates/cluster.truststore.p12
rename to kafka-oauth/containers/kafka/certificates/cluster.truststore.p12
Binary files differ
diff --git a/kafka-oauth/docker/kafka-oauth-strimzi/kafka/certificates/gen-kafka-certs.sh b/kafka-oauth/containers/kafka/certificates/gen-kafka-certs.sh
similarity index 100%
rename from kafka-oauth/docker/kafka-oauth-strimzi/kafka/certificates/gen-kafka-certs.sh
rename to kafka-oauth/containers/kafka/certificates/gen-kafka-certs.sh
diff --git a/kafka-oauth/docker/kafka-oauth-strimzi/kafka/config/ca-truststore.p12 b/kafka-oauth/containers/kafka/config/ca-truststore.p12
similarity index 100%
rename from kafka-oauth/docker/kafka-oauth-strimzi/kafka/config/ca-truststore.p12
rename to kafka-oauth/containers/kafka/config/ca-truststore.p12
Binary files differ
diff --git a/kafka-oauth/docker/kafka-oauth-strimzi/kafka/config/log4j.properties b/kafka-oauth/containers/kafka/config/log4j.properties
similarity index 100%
rename from kafka-oauth/docker/kafka-oauth-strimzi/kafka/config/log4j.properties
rename to kafka-oauth/containers/kafka/config/log4j.properties
diff --git a/kafka-oauth/docker/kafka-oauth-strimzi/kafka/functions.sh b/kafka-oauth/containers/kafka/scripts/functions.sh
similarity index 100%
rename from kafka-oauth/docker/kafka-oauth-strimzi/kafka/functions.sh
rename to kafka-oauth/containers/kafka/scripts/functions.sh
diff --git a/kafka-oauth/docker/kafka-oauth-strimzi/kafka/simple_kafka_config.sh b/kafka-oauth/containers/kafka/scripts/simple_kafka_config.sh
similarity index 100%
rename from kafka-oauth/docker/kafka-oauth-strimzi/kafka/simple_kafka_config.sh
rename to kafka-oauth/containers/kafka/scripts/simple_kafka_config.sh
diff --git a/kafka-oauth/docker/kafka-oauth-strimzi/kafka/start.sh b/kafka-oauth/containers/kafka/scripts/start.sh
similarity index 100%
rename from kafka-oauth/docker/kafka-oauth-strimzi/kafka/start.sh
rename to kafka-oauth/containers/kafka/scripts/start.sh
diff --git a/kafka-oauth/docker/keycloak/certificates/ca-truststore.p12 b/kafka-oauth/containers/keycloak/certificates/ca-truststore.p12
similarity index 100%
rename from kafka-oauth/docker/keycloak/certificates/ca-truststore.p12
rename to kafka-oauth/containers/keycloak/certificates/ca-truststore.p12
Binary files differ
diff --git a/kafka-oauth/docker/keycloak/certificates/gen-keycloak-certs.sh b/kafka-oauth/containers/keycloak/certificates/gen-keycloak-certs.sh
similarity index 100%
rename from kafka-oauth/docker/keycloak/certificates/gen-keycloak-certs.sh
rename to kafka-oauth/containers/keycloak/certificates/gen-keycloak-certs.sh
diff --git a/kafka-oauth/docker/keycloak/certificates/keycloak.server.keystore.p12 b/kafka-oauth/containers/keycloak/certificates/keycloak.server.keystore.p12
similarity index 100%
rename from kafka-oauth/docker/keycloak/certificates/keycloak.server.keystore.p12
rename to kafka-oauth/containers/keycloak/certificates/keycloak.server.keystore.p12
Binary files differ
diff --git a/kafka-oauth/docker/keycloak/compose.yml b/kafka-oauth/containers/keycloak/compose.yml
similarity index 100%
rename from kafka-oauth/docker/keycloak/compose.yml
rename to kafka-oauth/containers/keycloak/compose.yml
diff --git a/kafka-oauth/docker/keycloak/realms/demo-realm.json b/kafka-oauth/containers/keycloak/realms/demo-realm.json
similarity index 100%
rename from kafka-oauth/docker/keycloak/realms/demo-realm.json
rename to kafka-oauth/containers/keycloak/realms/demo-realm.json
diff --git a/kafka-oauth/docker/kafka-oauth-strimzi/compose.yml b/kafka-oauth/docker/kafka-oauth-strimzi/compose.yml
deleted file mode 100644
index 46831ca..0000000
--- a/kafka-oauth/docker/kafka-oauth-strimzi/compose.yml
+++ /dev/null
@@ -1,79 +0,0 @@
-services:
-
- #################################### KAFKA BROKER ####################################
- kafka:
- image: strimzi/example-kafka
- build: kafka/target
- container_name: kafka
- ports:
- - 9091:9091
- - 9092:9092
-
- # javaagent debug port
- #- 5005:5005
- command:
- - /bin/bash
- - -c
- - cd /opt/kafka && ./start.sh --kraft
-
- environment:
-
- # Java Debug
- #KAFKA_DEBUG: y
- #DEBUG_SUSPEND_FLAG: y
- #JAVA_DEBUG_PORT: 5005
-
- #
- # KAFKA Configuration
- #
- LOG_DIR: /home/kafka/logs
- KAFKA_PROCESS_ROLES: "broker,controller"
- KAFKA_NODE_ID: "1"
- KAFKA_CONTROLLER_QUORUM_VOTERS: "1@kafka:9091"
- KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER
- KAFKA_SASL_MECHANISM_CONTROLLER_PROTOCOL: PLAIN
-
- KAFKA_LISTENERS: "CONTROLLER://kafka:9091,CLIENT://kafka:9092"
- KAFKA_ADVERTISED_LISTENERS: "CLIENT://kafka:9092"
- KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: "CONTROLLER:SASL_PLAINTEXT,CLIENT:SASL_PLAINTEXT"
-
- KAFKA_INTER_BROKER_LISTENER_NAME: CLIENT
- KAFKA_SASL_MECHANISM_INTER_BROKER_PROTOCOL: OAUTHBEARER
-
- KAFKA_PRINCIPAL_BUILDER_CLASS: "io.strimzi.kafka.oauth.server.OAuthKafkaPrincipalBuilder"
-
- KAFKA_LISTENER_NAME_CONTROLLER_SASL_ENABLED_MECHANISMS: PLAIN
- KAFKA_LISTENER_NAME_CONTROLLER_PLAIN_SASL_JAAS_CONFIG: "org.apache.kafka.common.security.plain.PlainLoginModule required username=\"admin\" password=\"admin-password\" user_admin=\"admin-password\" user_bobby=\"bobby-secret\" ;"
-
- KAFKA_LISTENER_NAME_CLIENT_SASL_ENABLED_MECHANISMS: OAUTHBEARER
- KAFKA_LISTENER_NAME_CLIENT_OAUTHBEARER_SASL_JAAS_CONFIG: "org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required;"
- KAFKA_LISTENER_NAME_CLIENT_OAUTHBEARER_SASL_LOGIN_CALLBACK_HANDLER_CLASS: io.strimzi.kafka.oauth.client.JaasClientOauthLoginCallbackHandler
- KAFKA_LISTENER_NAME_CLIENT_OAUTHBEARER_SASL_SERVER_CALLBACK_HANDLER_CLASS: io.strimzi.kafka.oauth.server.JaasServerOauthValidatorCallbackHandler
-
- KAFKA_SUPER_USERS: "User:admin,User:service-account-kafka-broker"
-
- KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
-
-
- #
- # Strimzi OAuth Configuration
- #
-
- # Authentication config
- OAUTH_CLIENT_ID: "kafka-broker"
- OAUTH_CLIENT_SECRET: "kafka-broker-secret"
- OAUTH_TOKEN_ENDPOINT_URI: "http://${KEYCLOAK_HOST:-keycloak}:8080/realms/${REALM:-demo}/protocol/openid-connect/token"
-
- # Validation config
- OAUTH_VALID_ISSUER_URI: "https://${KEYCLOAK_HOST:-keycloak}:8443/realms/${REALM:-demo}"
- OAUTH_JWKS_ENDPOINT_URI: "http://${KEYCLOAK_HOST:-keycloak}:8080/realms/${REALM:-demo}/protocol/openid-connect/certs"
- #OAUTH_INTROSPECTION_ENDPOINT_URI: "http://${KEYCLOAK_HOST:-keycloak}:8080/realms/${REALM:-demo}/protocol/openid-connect/token/introspect"
-
-
- # username extraction from JWT token claim
- OAUTH_USERNAME_CLAIM: preferred_username
- OAUTH_CONNECT_TIMEOUT_SECONDS: "20"
-
- # For start.sh script to know where the keycloak is listening
- KEYCLOAK_HOST: ${KEYCLOAK_HOST:-keycloak}
- KEYCLOAK_URI: https://keycloak:8443
diff --git a/kafka-oauth/docker/kafka-oauth-strimzi/kafka/Dockerfile b/kafka-oauth/docker/kafka-oauth-strimzi/kafka/Dockerfile
deleted file mode 100644
index c5f1b84..0000000
--- a/kafka-oauth/docker/kafka-oauth-strimzi/kafka/Dockerfile
+++ /dev/null
@@ -1,12 +0,0 @@
-FROM quay.io/strimzi/kafka:0.45.0-kafka-3.9.0
-
-COPY libs/* /opt/kafka/libs/strimzi/
-COPY config/* /opt/kafka/config/
-COPY *.sh /opt/kafka/
-COPY certificates/*.p12 /tmp/kafka/
-
-USER root
-RUN chmod +x /opt/kafka/*.sh
-USER kafka
-
-CMD ["/bin/bash", "/opt/kafka/start.sh"]
\ No newline at end of file
diff --git a/kafka-oauth/pom.xml b/kafka-oauth/pom.xml
index 8857084..3cf63e2 100644
--- a/kafka-oauth/pom.xml
+++ b/kafka-oauth/pom.xml
@@ -35,7 +35,6 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<strimzi.version>0.15.0</strimzi.version>
- <nimbus.jose.version>9.37.2</nimbus.jose.version>
</properties>
<dependencyManagement>
@@ -101,16 +100,6 @@
<build>
<plugins>
<plugin>
- <artifactId>maven-clean-plugin</artifactId>
- <configuration>
- <filesets>
- <fileset>
- <directory>${basedir}/docker/kafka-oauth-strimzi/kafka/target</directory>
- </fileset>
- </filesets>
- </configuration>
- </plugin>
- <plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot-version}</version>
@@ -122,107 +111,6 @@
</execution>
</executions>
</plugin>
- <plugin>
- <artifactId>maven-resources-plugin</artifactId>
- <executions>
- <execution>
- <!-- copy the truststore CA to the camel-spring-boot, so the strimzi-oauth jaas login module
- connects to the keycloak https and trust the CA
- -->
- <id>copy-resources</id>
- <phase>compile</phase>
- <goals>
- <goal>copy-resources</goal>
- </goals>
- <configuration>
- <outputDirectory>target/classes</outputDirectory>
- <resources>
- <resource>
- <directory>${basedir}/docker/certificates/</directory>
- <includes>
- <include>ca-truststore.p12</include>
- </includes>
- </resource>
- </resources>
- </configuration>
- </execution>
- <execution>
- <!-- copy the required files to build the strimzi-oauth-kafka image -->
- <id>copy-resources-strimzi</id>
- <phase>package</phase>
- <goals>
- <goal>copy-resources</goal>
- </goals>
- <configuration>
- <outputDirectory>${basedir}/docker/kafka-oauth-strimzi/kafka/target</outputDirectory>
- <resources>
- <resource>
- <directory>${basedir}/docker/kafka-oauth-strimzi/kafka</directory>
- <includes>
- <include>functions.sh</include>
- <include>start.sh</include>
- <include>simple_kafka_config.sh</include>
- <include>Dockerfile</include>
- <include>config/</include>
- <include>certificates/</include>
- </includes>
- <filtering>false</filtering>
- </resource>
- </resources>
- </configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-dependency-plugin</artifactId>
- <executions>
- <execution>
- <id>copy</id>
- <phase>package</phase>
- <goals>
- <goal>copy</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- <artifactItems>
- <artifactItem>
- <groupId>io.strimzi</groupId>
- <artifactId>kafka-oauth-client</artifactId>
- <version>${strimzi.version}</version>
- </artifactItem>
- <artifactItem>
- <groupId>io.strimzi</groupId>
- <artifactId>kafka-oauth-server</artifactId>
- <version>${strimzi.version}</version>
- </artifactItem>
- <artifactItem>
- <groupId>io.strimzi</groupId>
- <artifactId>kafka-oauth-server-plain</artifactId>
- <version>${strimzi.version}</version>
- </artifactItem>
- <artifactItem>
- <groupId>io.strimzi</groupId>
- <artifactId>kafka-oauth-common</artifactId>
- <version>${strimzi.version}</version>
- </artifactItem>
- <artifactItem>
- <groupId>io.strimzi</groupId>
- <artifactId>kafka-oauth-keycloak-authorizer</artifactId>
- <version>${strimzi.version}</version>
- </artifactItem>
- <artifactItem>
- <groupId>com.nimbusds</groupId>
- <artifactId>nimbus-jose-jwt</artifactId>
- <version>${nimbus.jose.version}</version>
- </artifactItem>
- </artifactItems>
- <outputDirectory>${basedir}/docker/kafka-oauth-strimzi/kafka/target/libs</outputDirectory>
- <overWriteReleases>false</overWriteReleases>
- <overWriteSnapshots>true</overWriteSnapshots>
- </configuration>
- </plugin>
</plugins>
</build>
</project>
diff --git a/kafka-oauth/src/main/resources/application.properties b/kafka-oauth/src/main/resources/application.properties
index aabb7b1..db26cb2 100644
--- a/kafka-oauth/src/main/resources/application.properties
+++ b/kafka-oauth/src/main/resources/application.properties
@@ -26,7 +26,7 @@
oauth.client.id="kafka-producer-client" \
oauth.client.secret="kafka-producer-client-secret" \
oauth.username.claim="preferred_username" \
- oauth.ssl.truststore.location="docker/certificates/ca-truststore.p12" \
+ oauth.ssl.truststore.location="containers/certificates/ca-truststore.p12" \
oauth.ssl.truststore.type="pkcs12" \
oauth.ssl.truststore.password="changeit" \
oauth.token.endpoint.uri="https://keycloak:8443/realms/demo/protocol/openid-connect/token" ;
diff --git a/kafka-oauth/start_kafka.sh b/kafka-oauth/start_kafka.sh
new file mode 100755
index 0000000..984e490
--- /dev/null
+++ b/kafka-oauth/start_kafka.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+cd containers/kafka
+podman run -it --rm \
+ -p 9091:9091 \
+ -p 9092:9092 \
+ -e LOG_DIR=/home/kafka/logs \
+ -e KAFKA_PROCESS_ROLES="broker,controller" \
+ -e KAFKA_NODE_ID="1" \
+ -e KAFKA_CONTROLLER_QUORUM_VOTERS="1@kafka:9091" \
+ -e KAFKA_CONTROLLER_LISTENER_NAMES=CONTROLLER \
+ -e KAFKA_SASL_MECHANISM_CONTROLLER_PROTOCOL=PLAIN \
+ -e KAFKA_LISTENERS="CONTROLLER://kafka:9091,CLIENT://kafka:9092" \
+ -e KAFKA_ADVERTISED_LISTENERS="CLIENT://kafka:9092" \
+ -e KAFKA_LISTENER_SECURITY_PROTOCOL_MAP="CONTROLLER:SASL_PLAINTEXT,CLIENT:SASL_PLAINTEXT" \
+ -e KAFKA_INTER_BROKER_LISTENER_NAME=CLIENT \
+ -e KAFKA_SASL_MECHANISM_INTER_BROKER_PROTOCOL=OAUTHBEARER \
+ -e KAFKA_PRINCIPAL_BUILDER_CLASS="io.strimzi.kafka.oauth.server.OAuthKafkaPrincipalBuilder" \
+ -e KAFKA_LISTENER_NAME_CONTROLLER_SASL_ENABLED_MECHANISMS=PLAIN \
+ -e KAFKA_LISTENER_NAME_CONTROLLER_PLAIN_SASL_JAAS_CONFIG="org.apache.kafka.common.security.plain.PlainLoginModule required username=\"admin\" password=\"admin-password\" user_admin=\"admin-password\" user_bobby=\"bobby-secret\" ;" \
+ -e KAFKA_LISTENER_NAME_CLIENT_SASL_ENABLED_MECHANISMS=OAUTHBEARER \
+ -e KAFKA_LISTENER_NAME_CLIENT_OAUTHBEARER_SASL_JAAS_CONFIG="org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required;" \
+ -e KAFKA_LISTENER_NAME_CLIENT_OAUTHBEARER_SASL_LOGIN_CALLBACK_HANDLER_CLASS=io.strimzi.kafka.oauth.client.JaasClientOauthLoginCallbackHandler \
+ -e KAFKA_LISTENER_NAME_CLIENT_OAUTHBEARER_SASL_SERVER_CALLBACK_HANDLER_CLASS=io.strimzi.kafka.oauth.server.JaasServerOauthValidatorCallbackHandler \
+ -e KAFKA_SUPER_USERS="User:admin,User:service-account-kafka-broker" \
+ -e KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR=1 \
+ -e OAUTH_CLIENT_ID="kafka-broker" \
+ -e OAUTH_CLIENT_SECRET="kafka-broker-secret" \
+ -e OAUTH_TOKEN_ENDPOINT_URI="http://keycloak:8080/realms/demo/protocol/openid-connect/token" \
+ -e OAUTH_VALID_ISSUER_URI="https://keycloak:8443/realms/demo" \
+ -e OAUTH_JWKS_ENDPOINT_URI="http://keycloak:8080/realms/demo/protocol/openid-connect/certs" \
+ -e OAUTH_USERNAME_CLAIM=preferred_username \
+ -e OAUTH_CONNECT_TIMEOUT_SECONDS="20" \
+ -e KEYCLOAK_HOST=keycloak \
+ -e KEYCLOAK_URI=https://keycloak:8443 \
+ -u kafka \
+ --name kafka \
+ --network host \
+ -v ./scripts:/opt/kafka/scripts:Z \
+ -w /opt/kafka/scripts \
+ --entrypoint "./start.sh" \
+ quay.io/strimzi/kafka:0.45.0-kafka-3.9.0 \
+ --kraft
diff --git a/kafka-oauth/start_keycloak.sh b/kafka-oauth/start_keycloak.sh
new file mode 100755
index 0000000..ac63852
--- /dev/null
+++ b/kafka-oauth/start_keycloak.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+cd containers/keycloak
+podman run -it --rm \
+ -v ./realms:/opt/keycloak/data/import:Z \
+ -v ./certificates/keycloak.server.keystore.p12:/opt/keycloak/data/certs/keycloak.server.keystore.p12:Z \
+ -p 8080:8080 -p 8443:8443 \
+ -e KC_BOOTSTRAP_ADMIN_USERNAME=admin \
+ -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \
+ -e KC_HOSTNAME=keycloak \
+ -e KC_HOSTNAME_ADMIN_URL=https://keycloak:8443 \
+ -e KC_HTTP_ENABLED=true \
+ --name keycloak \
+ --network host \
+ quay.io/keycloak/keycloak:26.0 \
+ -v start --import-realm --features=token-exchange,authorization,scripts --https-key-store-file=/opt/keycloak/data/certs/keycloak.server.keystore.p12 --https-key-store-password=changeit
+cd -