Skip to content
KitploitKITPLOIT
أدواتالمدونة
إرسال
أدواتالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

··الخلاصات·اتصال·الخصوصية·© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
kafka-keycloak-oauth — Apache Kafka 4.1.0 (KRaft) مع مصادقة Keycloak OAuth2 باستخدام Strimzi - يتجاوز قيد قائمة العناوين المسموح بها في CVE-2025-27817 | Kitploit
أدوات/GitHubGitHub/oriolrius/kafka-keycloak-oauth
أمن البنية التحتية السحابيةتحليل الثغرات الأمنيةتدقيق التكوينDevSecOpsالمصادقةالتعلم والتعليم
GitHuboriolrius/kafka-keycloak-oauth

kafka-keycloak-oauth

Apache Kafka 4.1.0 (KRaft) مع مصادقة Keycloak OAuth2 باستخدام Strimzi - يتجاوز قيد قائمة العناوين المسموح بها في CVE-2025-27817

عرض المستودع
53منذ 10 أشهرلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة

Apache Kafka 4.1.0 مع مصادقة Keycloak OAuth2

Apache Kafka 4.1.0 جاهز للإنتاج (وضع KRaft) مع مصادقة Keycloak 26.1.1 OAuth2/OIDC باستخدام صورة Strimzi Kafka.

لماذا هذا المشروع مقارنة بـ kafka-oauth-keycloak-tls-demo

هذا تطوير للإثبات السابق للمفهوم مع تحسينات كبيرة:

  • Strimzi OAuth 0.17.0 (مقابل 1.0.0) - إصدار إنتاج مستقر مدمج في صورة Strimzi Kafka 0.48.0
  • لا حاجة لبناء Docker مخصص - يستخدم صورة Strimzi الرسمية مع OAuth مثبت مسبقًا، مما يلغي تعقيد Dockerfile
  • الوعي بـ CVE-2025-27817 - يوثق قيود قائمة عناوين URL ولماذا يتجاوزها Strimzi OAuth
  • بنية مبسطة - وضع KRaft المدمج الفردي (broker+controller)، وليس بنية مقسمة
  • التركيز على عميل librdkafka - تم اختباره مع confluent-kafka-python (يعمل بدون مشاكل قائمة عناوين URL)، وليس عملاء Java الأصليين
  • توثيق تقني شامل - قائمة فحص الإنتاج، استكشاف الأخطاء وإصلاحها، ضبط الأداء، تفاصيل تعيين principal
  • إدارة شهادات أنظف - شهادات أمثلة مرفقة للاختبار الفوري
  • إعداد Keycloak آلي - إنشاء realm/client/mapper بنصوص برمجية مع تكوين الجمهور
  • مجموعة اختبار Python عاملة - تتحقق من تسليم الرسائل الشامل عبر OAuth
  • معالجة صريحة لعنوان URL للمُصدر - يوثق ازدواجية العنوان الداخلي مقابل الخارجي لنقطة نهاية الرمز مقابل التحقق من المُصدر

البنية

  • توزيع Kafka: صورة Strimzi Kafka 0.48.0 (تتضمن Apache Kafka 4.1.0 + Strimzi OAuth 0.17.0 مثبتة مسبقًا)
  • إصدار Kafka: Apache Kafka 4.1.0 (KRaft مدمج broker+controller)
  • مكتبة OAuth: Strimzi Kafka OAuth 0.17.0 (مدمجة في الصورة، تتجاوز قيد قائمة عناوين URL الخاص بـ CVE-2025-27817)
  • مزود OAuth: Keycloak 26.1.1
  • الأمان: SASL_SSL (OAuth) للعملاء الخارجيين، PLAINTEXT للاتصال بين الوسطاء، SSL مع CA ذاتي التوقيع

سياق CVE-2025-27817

قدم Apache Kafka 4.0.0+ قائمة عناوين URL (org.apache.kafka.sasl.oauthbearer.allowed.urls) كخاصية نظام JVM لإصلاح ثغرة SSRF/قراءة الملفات التعسفية. هذا يكسر استخدام OAuth القياسي في عملاء Apache Kafka الأصليين.

الحل: مكتبة Strimzi Kafka OAuth لا تنفذ هذا القيد، مما يتيح وظيفة OAuth مع Kafka 4.1.0.

المتطلبات الأساسية

  • Docker Compose
  • Python 3.x مع uv (للاختبار)
  • OpenSSL (لتوليد الشهادات)

بدء سريع

root@kitploit:~
# توليد شهادات SSL
cd kafka-security
./generate-certs.sh
cd ..

# بدء الخدمات
docker compose up -d

# التحقق من Keycloak
curl http://localhost:8080/health/ready

# إعداد realm وعملاء Keycloak
./scripts/setup-keycloak.sh

# اختبار منتج OAuth
source ~/.venv/bin/activate
uv pip install confluent-kafka
python tests/quick_test.py

طوبولوجيا الشبكة

root@kitploit:~
keycloak:8080 (HTTP) ←→ kafka-broker:9093 (SASL_SSL/OAuth)
                      ↔ kafka-broker:19092 (PLAINTEXT/inter-broker)
                      ↔ kafka-broker:29093 (PLAINTEXT/KRaft controller)

تكوين SSL

هيكل CA

  • CA الجذرية: kafka-security/ca-cert + ca-key
  • مخزن مفاتيح الوسطاء: kafka-security/broker/kafka.server.keystore.jks (يحتوي على شهادة الخادم + المفتاح الخاص)
  • مخزن الثقة للوسطاء: kafka-security/broker/kafka.server.truststore.jks (يحتوي على شهادة CA)
  • كلمة المرور: changeit (جميع مخازن المفاتيح/الثقة)

تفاصيل الشهادة

root@kitploit:~
# شهادة الوسطاء
CN=kafka-broker
SAN=DNS:kafka-broker,DNS:localhost,IP:127.0.0.1

# الصلاحية: 3650 يومًا
# خوارزمية المفتاح: RSA 2048-bit
# خوارزمية التوقيع: SHA256withRSA

تكوين Keycloak OAuth

Realm: kafka-realm

العملاء

kafka-broker (سري)

  • معرف العميل: kafka-broker
  • سر العميل: يتم توليده تلقائيًا بواسطة setup-keycloak.sh
  • الغرض: مصادقة OAuth بين الوسطاء
  • أدوات التعيين:
    • أداة تعيين الجمهور: تضيف kafka-broker إلى مطالبة aud في JWT
    • أداة تعيين اسم المستخدم: تتضمن preferred_username في الرمز

kafka-producer (سري)

  • معرف العميل: kafka-producer
  • سر العميل: يتم توليده تلقائيًا
  • الغرض: عملاء المنتجين الخارجيين
  • المنح: client_credentials
  • أدوات التعيين: نفس kafka-broker

kafka-consumer (سري)

  • معرف العميل: kafka-consumer
  • سر العميل: يتم توليده تلقائيًا
  • الغرض: عملاء المستهلكين الخارجيين
  • المنح: client_credentials
  • أدوات التعيين: نفس kafka-broker

نقطة نهاية الرمز

root@kitploit:~
POST http://localhost:8080/realms/kafka-realm/protocol/openid-connect/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
&client_id=kafka-producer
&client_secret=<secret>
&scope=profile email

هيكل رمز JWT

root@kitploit:~
{
  "aud": ["kafka-broker", "account"],
  "iss": "http://localhost:8080/realms/kafka-realm",
  "azp": "kafka-producer",
  "preferred_username": "service-account-kafka-producer",
  "scope": "profile email"
}

تكوين Kafka

وضع KRaft (kraft-config.properties)

root@kitploit:~
# هوية العقدة
node.id=1
process.roles=broker,controller
controller.quorum.voters=1@kafka-broker:29093

# المستمعون
listeners=SASL_SSL://0.0.0.0:9093,PLAINTEXT://0.0.0.0:19092,CONTROLLER://0.0.0.0:29093
advertised.listeners=SASL_SSL://localhost:9093,PLAINTEXT://kafka-broker:19092
listener.security.protocol.map=SASL_SSL:SASL_SSL,PLAINTEXT:PLAINTEXT,CONTROLLER:PLAINTEXT
inter.broker.listener.name=PLAINTEXT
controller.listener.names=CONTROLLER

# آلية SASL
sasl.enabled.mechanisms=OAUTHBEARER

# معالجات Strimzi OAuth (لكل مستمع لـ SASL_SSL)
listener.name.sasl_ssl.oauthbearer.sasl.login.callback.handler.class=io.strimzi.kafka.oauth.client.JaasClientOauthLoginCallbackHandler
listener.name.sasl_ssl.oauthbearer.sasl.server.callback.handler.class=io.strimzi.kafka.oauth.server.JaasServerOauthValidatorCallbackHandler

# تكوين OAuth عبر JAAS
listener.name.sasl_ssl.oauthbearer.sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \
  oauth.client.id="kafka-broker" \
  oauth.client.secret="<secret>" \
  oauth.token.endpoint.uri="http://keycloak:8080/realms/kafka-realm/protocol/openid-connect/token" \
  oauth.valid.issuer.uri="http://localhost:8080/realms/kafka-realm" \
  oauth.jwks.endpoint.uri="http://keycloak:8080/realms/kafka-realm/protocol/openid-connect/certs" \
  oauth.username.claim="preferred_username";

معلمات Strimzi OAuth الرئيسية

  • oauth.client.id: معرف العميل للحصول على الرمز
  • oauth.client.secret: سر العميل للحصول على الرمز
  • oauth.token.endpoint.uri: نقطة نهاية رمز Keycloak (يستخدم الوسطاء اسم المضيف الداخلي keycloak:8080)
  • oauth.valid.issuer.uri: مُصدر JWT المتوقع (يجب أن يطابق مطالبة iss في الرمز، يستخدم localhost:8080 الخارجي)
  • oauth.jwks.endpoint.uri: نقطة نهاية JWKS للتحقق من توقيع JWT
  • oauth.username.claim: مطالبة JWT لاستخراج principal

التفويض

root@kitploit:~
authorizer.class.name=org.apache.kafka.metadata.authorizer.StandardAuthorizer
super.users=User:kafka-broker;User:ANONYMOUS
allow.everyone.if.no.acl.found=true

ملاحظة: حاليًا متساهل للاختبار. يجب استخدام ACLs في الإنتاج.

تكوين العميل

منتج Python (confluent-kafka)

root@kitploit:~
from confluent_kafka import Producer

conf = {
    'bootstrap.servers': 'localhost:9093',
    'security.protocol': 'SASL_SSL',
    'sasl.mechanisms': 'OAUTHBEARER',
    'sasl.oauthbearer.method': 'oidc',
    'sasl.oauthbearer.client.id': 'kafka-producer',
    'sasl.oauthbearer.client.secret': '<secret>',
    'sasl.oauthbearer.token.endpoint.url': 'http://localhost:8080/realms/kafka-realm/protocol/openid-connect/token',
    'ssl.ca.location': 'kafka-security/ca-cert',
    'ssl.endpoint.identification.algorithm': 'none',
}

producer = Producer(conf)
producer.produce('topic', b'message')
producer.flush()

مستهلك Python (confluent-kafka)

root@kitploit:~
from confluent_kafka import Consumer

conf = {
    'bootstrap.servers': 'localhost:9093',
    'group.id': 'test-group',
    'security.protocol': 'SASL_SSL',
    'sasl.mechanisms': 'OAUTHBEARER',
    'sasl.oauthbearer.method': 'oidc',
    'sasl.oauthbearer.client.id': 'kafka-consumer',
    'sasl.oauthbearer.client.secret': '<secret>',
    'sasl.oauthbearer.token.endpoint.url': 'http://localhost:8080/realms/kafka-realm/protocol/openid-connect/token',
    'ssl.ca.location': 'kafka-security/ca-cert',
    'ssl.endpoint.identification.algorithm': 'none',
    'auto.offset.reset': 'earliest',
}

consumer = Consumer(conf)
consumer.subscribe(['topic'])
while True:
    msg = consumer.poll(1.0)
    if msg: print(msg.value())

لماذا يعمل librdkafka

يستخدم confluent-kafka-python librdkafka (مكتبة C) التي تنفذ OAuth عبر sasl.oauthbearer.method=oidc. هذا التنفيذ لا يتحقق من خاصية النظام org.apache.kafka.sasl.oauthbearer.allowed.urls التي تحظر عملاء Apache Kafka Java الأصليين.

استكشاف الأخطاء وإصلاحها

التحقق من رمز OAuth

root@kitploit:~
TOKEN=$(curl -s -X POST http://localhost:8080/realms/kafka-realm/protocol/openid-connect/token \
  -d "grant_type=client_credentials" \
  -d "client_id=kafka-producer" \
  -d "client_secret=<secret>" | jq -r .access_token)

echo $TOKEN | cut -d. -f2 | base64 -d 2>/dev/null | jq .

المطالبات المتوقعة:

root@kitploit:~
{
  "aud": ["kafka-broker", "account"],
  "iss": "http://localhost:8080/realms/kafka-realm",
  "azp": "kafka-producer",
  "preferred_username": "service-account-kafka-producer"
}

فحص سجلات OAuth للوسطاء

root@kitploit:~
docker logs kafka-broker 2>&1 | grep -E "Strimzi|JWTSignatureValidator|OAUTHBEARER"

المتوقع:

root@kitploit:~
[io.strimzi.kafka.oauth.validator.JWTSignatureValidator] JWKS keys change detected

التحقق من مستمعي الوسطاء

root@kitploit:~
docker exec kafka-broker netstat -tlnp | grep java

المتوقع:

root@kitploit:~
tcp6  0.0.0.0:9093   LISTEN  (SASL_SSL)
tcp6  0.0.0.0:19092  LISTEN  (PLAINTEXT)
tcp6  0.0.0.0:29093  LISTEN  (CONTROLLER)

فحص بيانات KRaft الوصفية

root@kitploit:~
docker exec kafka-broker cat /var/lib/kafka/data/meta.properties

المتوقع:

root@kitploit:~
version=1
cluster.id=kafka-cluster-01
node.id=1

المشكلات الشائعة

المشكلة: {"status":"invalid_token"}

  • السبب: فشل التحقق من توقيع JWT
  • الحل: تحقق من أن oauth.jwks.endpoint.uri يمكن الوصول إليه من حاوية الوسطاء
  • الفحص: docker exec kafka-broker curl http://keycloak:8080/realms/kafka-realm/protocol/openid-connect/certs

المشكلة: Token audience mismatch

  • السبب: مطالبة aud في JWT لا تحتوي على kafka-broker
  • الحل: قم بتشغيل ./scripts/setup-keycloak.sh لإضافة أداة تعيين الجمهور
  • التحقق: فك تشفير الرمز وتحقق من أن مطالبة aud تتضمن kafka-broker

المشكلة: Token issuer mismatch

  • السبب: iss في JWT لا يطابق oauth.valid.issuer.uri
  • الحل: تأكد من أن oauth.valid.issuer.uri=http://localhost:8080/realms/kafka-realm (اسم المضيف الخارجي)
  • ملاحظة: يستخدم الوسطاء http://keycloak:8080 لنقطة نهاية الرمز لكنه يتحقق مقابل مُصدر http://localhost:8080

المشكلة: فشل عملاء Kafka Java الأصليين مع خطأ قائمة عناوين URL

  • السبب: إصلاح CVE-2025-27817 في Apache Kafka 4.1.0
  • الحل: استخدم عملاء يعتمدون على librdkafka (confluent-kafka-python) أو Strimzi OAuth على جانب الوسطاء (مُكوَّن بالفعل)

ضبط الأداء

تحديث الرمز

رموز JWT من Keycloak تنتهي صلاحيتها بعد 5 دقائق. يتعامل Strimzi OAuth تلقائيًا مع التحديث:

  • oauth.refresh.token: غير مستخدم (منح client_credentials)
  • يتم تخزين الرمز مؤقتًا وتحديثه قبل 30 ثانية من انتهاء الصلاحية

تخزين JWKS مؤقت

root@kitploit:~
sasl.oauthbearer.jwks.endpoint.refresh.ms=3600000  # ساعة واحدة
sasl.oauthbearer.jwks.endpoint.retry.backoff.ms=100
sasl.oauthbearer.jwks.endpoint.retry.backoff.max.ms=10000

إعدادات الاتصال

root@kitploit:~
connections.max.idle.ms=600000
connection.failed.authentication.delay.ms=1000

قائمة فحص الإنتاج

  • استبدال الشهادات ذاتية التوقيع بشهادات موقعة من CA
  • تحديث ssl.endpoint.identification.algorithm=https (إزالة none)
  • تكوين ACLs المناسبة (إزالة allow.everyone.if.no.acl.found=true)
  • إعداد ACLs:
    root@kitploit:~
    kafka-acls --bootstrap-server localhost:9093 \
      --command-config admin.properties \
      --add --allow-principal User:kafka-producer \
      --operation Write --topic '*'
    
  • تدوير أسرار عملاء Keycloak
  • تفعيل HTTPS في Keycloak
  • تحديث oauth.token.endpoint.uri و oauth.jwks.endpoint.uri إلى عناوين HTTPS
  • تكوين مراقبة Kafka (JMX, Prometheus)
  • إعداد تجميع السجلات لمسار تدقيق OAuth
  • اختبار سيناريوهات تجاوز الفشل
  • توثيق إجراءات تدوير الأسرار
  • تفعيل اتحاد المستخدمين في Keycloak (LDAP/AD) إذا لزم الأمر

هيكل الدليل

root@kitploit:~
.
├── docker-compose.yml              # التنسيق
├── .env                            # الأسرار (مستثنى من git)
├── kafka-config/
│   ├── kraft-config.properties     # تكوين وسيط Kafka
│   ├── producer.properties         # تكوين OAuth للمنتج (لأدوات CLI)
│   └── consumer.properties         # تكوين OAuth للمستهلك (لأدوات CLI)
├── kafka-security/
│   ├── generate-certs.sh           # مولّد شهادات SSL
│   ├── ca-cert                     # شهادة CA الجذرية
│   ├── ca-key                      # المفتاح الخاص لـ CA الجذرية
│   └── broker/
│       ├── kafka.server.keystore.jks
│       └── kafka.server.truststore.jks
├── scripts/
│   └── setup-keycloak.sh           # إعداد realm/عملاء Keycloak
└── tests/
    └── quick_test.py               # اختبار التحقق من OAuth

ملاحظات تقنية

لماذا صورة Strimzi Kafka بدلاً من صورة Apache Kafka الرسمية

تُستخدم صورة Strimzi Kafka (quay.io/strimzi/kafka:0.48.0-kafka-4.1.0) بدلاً من صورة Apache Kafka الرسمية للأسباب التالية:

  1. دعم OAuth مدمج: تتضمن مكتبة Strimzi OAuth 0.17.0 مثبتة مسبقًا (الفئات: io.strimzi.kafka.oauth.*)
  2. تجاوز CVE-2025-27817: لا تنفذ مكتبة Strimzi OAuth قيد قائمة عناوين URL الذي يكسر OAuth الأصلي في Kafka
  3. جاهز للإنتاج: مُختبَر في بيئات Kubernetes عبر مشغل Strimzi
  4. صورة واحدة: لا حاجة لتنزيل وتركيب ملفات JAR الخاصة بـ OAuth يدويًا

تفصيل الصورة:

  • Strimzi Kafka 0.48.0 = إصدار/إصدار صورة Docker
  • Apache Kafka 4.1.0 = إصدار وسيط Kafka المدمج بالداخل
  • Strimzi OAuth 0.17.0 = إصدار مكتبة OAuth المدمجة بالداخل

ازدواجية عنوان URL للمُصدر

يحتوي تكوين الوسطاء على عنوانين URL:

  • oauth.token.endpoint.uri=http://keycloak:8080/... (شبكة Docker الداخلية)
  • oauth.valid.issuer.uri=http://localhost:8080/... (خارجي، يطابق مطالبة iss في JWT)

هذا لأن:

  • يجلب الوسطاء الرموز باستخدام اسم DNS الداخلي
  • يصدر Keycloak الرموز بعنوان مُصدر خارجي (مُكوَّن في إعدادات realm)
  • يتطلب التحقق من JWT تطابقًا دقيقًا للمُصدر

تعيين Principal

يستخرج الوسطاء principal من مطالبة preferred_username في JWT:

root@kitploit:~
service-account-kafka-producer → User:service-account-kafka-producer

تشير ACLs إلى هذا principal للتفويض.

توافق الإصدارات

المكوّنالإصدارملاحظات
Apache Kafka4.1.0وضع KRaft (بدون ZooKeeper)
صورة Strimzi Kafka0.48.0صورة Docker: quay.io/strimzi/kafka:0.48.0-kafka-4.1.0
مكتبة Strimzi OAuth0.17.0مدمجة مسبقًا في صورة Strimzi Kafka 0.48.0
Keycloak26.1.1أحدث إصدار LTS
librdkafka2.12.0+دعم OAuth OIDC
confluent-kafka-python2.12.0+يطابق إصدار librdkafka

المراجع

  • Strimzi Kafka OAuth
  • أمان Apache Kafka
  • Keycloak OIDC
  • CVE-2025-27817
  • وضع KRaft
تنزيل الأداة