Claude Desktop ile XSOAR
Entegrasyonu: CortexSynapse MCP Sunucusunun Sıfırdan Devreye Alınması
Bir Vaka
Çalışması – Kâmil AKDAĞ, MSc
Bu makale, Cortex XSOAR 6.13'ün, CortexSynapse
açık kaynak MCP sunucusu üzerinden Claude Desktop'a bağlanması; süreç boyunca
karşılaşılan üç ardışık entegrasyon hatasının teşhisi ve kalıcı çözümünü
içerir.
TL;DR (Çok Uzun; Okumadım)
Cortex XSOAR'ı Claude Desktop'a MCP üzerinden bağlamak
için CortexSynapse Docker imajını kullanırken üç farklı sorunla karşılaşıldı:
- SSL
sertifika doğrulama hatası: Yanlış env değişkeni ismi (XSOAR_VERIFY_SSL yerine kodda VERIFY_SSL bekleniyor).
- HTML
303 redirect cevapları: XSOAR_API_URL
değerinin sonundaki / çift slash'a yol açıp XSOAR'ı
API yerine UI'ya yönlendiriyor.
- HTTP
400 "string into Go value" hatası: MCP sunucusunun istek
body'sini double-encode etmesi; codegen tarafından üretilen üç dosyada json=body yerine json=(json.loads(body) if
isinstance(body, str) else body) patch'i gerekiyor; bu patch Dockerfile'a codegen
adımının ardından yerleştirilmeli.
Üçü çözüldükten sonra get_incidents, xsiam_get_alerts, update_incident, xsoar_indicators_search gibi tüm MCP araçları çalışır hale geldi.
1. Mimari
Bir SOC için Cortex XSOAR, incident orkestrasyonunun
merkezidir. Buna Claude Desktop'un
doğal dil ara yüzünü bir LLM destekli SOC katmanı olarak eklediğinizde şu
use-case'ler açılır:
- "Son
24 saatte severity ≥ High açılan kapanmamış incident'ları getir, owner
dağılımına göre özetle" gibi serbest sorgular.
- Triage
sırasında ilgili alert'lerin XQL tarafında karşılıklarını çekme.
- İndikatör
taraması, playbook tetikleme, endpoint isolate/unisolate gibi response
aksiyonları.
Bunu sağlamak için MCP (Model Context Protocol)
kullanılır. MCP, LLM client'ı (Claude Desktop/CoWork) ile harici sistemler
(XSOAR, XSIAM, Splunk vb.) arasında standart bir köprü sunar. CortexSynapse,
XSOAR/XSIAM API'sini MCP araçlarına dönüştüren açık kaynak bir Python
sunucusudur ve Docker imajı olarak çalıştırılır.
Akış:
Kullanıcı (Claude Desktop UI)
│
▼
Claude (LLM)
│ MCP tool call (JSON-RPC)
▼
Docker container: cortexsynapse ──HTTPS──►
Cortex XSOAR API
│
▼
JSON response (incident, alert, indicator vb.)
Claude
Desktop her oturumda container'ı claude_desktop_config.json'daki tanıma göre docker run ile başlatır; oturum kapandığında --rm flag'i sayesinde container otomatik silinir.
2. Önkoşullar
Bu
kurulumdan önce sahip olmanız gerekenler:
|
Bileşen |
Sürüm |
Amaç |
|
Claude
Desktop (desktop
app) |
Güncel |
LLM client
+ MCP host |
|
Docker
Desktop for Windows |
4.71.0 |
MCP
sunucusunu container olarak çalıştırma |
|
PowerShell |
Komutları
çalıştırma |
|
|
Python |
3.10 ve
üzeri (Windows tarafında) |
Patch
script'lerini çalıştırmak ve direct API testleri için |
|
Cortex
XSOAR |
6.x veya
8.x (XSIAM dahil) |
API
erişilebilir olmalı |
|
XSOAR API
Key |
Web
tipinde |
Settings →
Integrations → API Keys → "Get Your Key" |
|
CortexSynapse
kaynak kodu |
https://github.com/amshamah419/CortexSynapse |
İmajı
build etmek için |
Not: API key oluştururken minimum
gerekli yetkilerle başlayın. Read-only test için "Read Only" rolü,
response aksiyonları için ek izinler ekleyin. Key'i hiçbir transcript,
screenshot veya log içinde paylaşmayın; sızdığını fark ederseniz revoke ve rotate edin.
3. Sıfırdan Kurulum
Bu makaledeki hata-ayıklama sürecinden öğrendiklerimle
düzenlenmiş, sorunlara denk gelmemeniz
için iyileştirilmiş sıralama.
3.1. CortexSynapse kaynağını indir
GitHub'dan klonla veya ZIP indir, Desktop'a aç
cd C:\Users\<kullanıcı>\Desktop
Sonuç: C:\Users\<kullanıcı>\Desktop\CortexSynapse-main\
(Dockerfile, server/, codegen/, specs/ içerir)
3.2. Body double-encoding patch'ini Dockerfile'a ekle
CortexSynapse'in 1.27.0 sürümünde, MCP'nin body
parametresi httpx istemcisine olduğu gibi iletildiğinde XSOAR çift kodlanmış
JSON string olarak görüyor. Üretilmiş üç dosyaya (generated_xsoar_tools.py, generated_xsiam_tools.py, generated_unified_tools.py) tek satırlık bir patch yeterli ama
bu dosyalar build sırasında python -m codegen.generator ile yeniden üretildiği için patch'i
Dockerfile'a, codegen adımının hemen ardına eklemek gerekiyor.
PowerShell'de
(kaynak klasörünün içindeyken):
cd
C:\Users\<kullanıcı>\Desktop\CortexSynapse-main
@'
import pathlib
p = pathlib.Path("Dockerfile")
text = p.read_text(encoding="utf-8")
needle = "RUN python -m codegen.generator"
patch_line = "\nRUN sed -i
\"s|json=body|json=(json.loads(body) if isinstance(body, str) else
body)|g\" /app/server/generated_xsoar_tools.py
/app/server/generated_xsiam_tools.py /app/server/generated_unified_tools.py"
if "json.loads(body)" in text:
print("Dockerfile zaten patched")
else:
p.write_text(text.replace(needle, needle + patch_line),
encoding="utf-8")
print("Dockerfile patched")
'@ | python
Bu blok Python'u çağırarak Dockerfile'ı güvenli
şekilde değiştirir.
3.3. İmajı build et
docker build --no-cache -t cortexsynapse-patched .
--no-cache, eski
layer'ların yanlışlıkla yeniden kullanılmasını engeller. Build sonunda Successfully tagged cortexsynapse-patched:latest görmelisiniz.
3.4. Patch'in imaja yansıdığını doğrula
docker run --rm cortexsynapse-patched grep -c
"json.loads(body)" `
/app/server/generated_xsoar_tools.py `
/app/server/generated_xsiam_tools.py `
/app/server/generated_unified_tools.py
Beklenen
çıktı:
/app/server/generated_xsoar_tools.py:1
/app/server/generated_xsiam_tools.py:1
/app/server/generated_unified_tools.py:8
0
görüyorsanız Dockerfile patch satırı işlememiş demektir; 3.2'deki Python
bloğunu yeniden çalıştırın.
3.5. Claude Desktop MCP konfigürasyonunu yaz
Dosya yolu: %APPDATA%\Local\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Roaming\Claude\claude_desktop_config.json
{
"mcpServers": {
"cortex-xsoar": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"--read-only",
"--security-opt=no-new-privileges",
"-e", "XSOAR_API_URL",
"-e", "XSOAR_API_KEY",
"-e", "VERIFY_SSL=false",
"cortexsynapse-patched"
],
"env": {
"XSOAR_API_URL": "https://xsoar.ornek.com",
"XSOAR_API_KEY": "<API_KEY_BURAYA>"
}
}
}
}
Üç kritik
nokta:
- XSOAR_API_URL değeri trailing slash içermemeli (https://xsoar.example.com/ -- hatalı kullanım). Sondaki / çift slash'a yol açıp 303 redirect üretiyor.
- Env
değişkeni VERIFY_SSL (kod bu ismi okuyor); XSOAR_VERIFY_SSL ya da INSECURE çalışmıyor.
- İmaj
adı cortexsynapse-patched olmalı (orijinal cortexsynapse patch içermiyor).
3.6. Claude Desktop'u tamamen yeniden başlat
- Claude
Desktop penceresini kapatmak yetmez. Görev yöneticisinden ya da sistem
tray ikon üzerinden kapatın.
- Görev
Yöneticisi'nde Claude.exe veya benzeri kalan süreçleri
"End task" ile sonlandırın.
- Claude
Desktop'u tekrar açın.
İlk soruda Claude cortexsynapse-patched imajıyla
yeni bir container başlatır ve XSOAR araçları kullanılabilir hale gelir.
3.7. Doğrulama sorgusu
Claude
Desktop'ta yazın:
"XSOAR'daki
son 5 incident'ı listele"
Beklenen
sonuç: id, name, severity, status, owner, created kolonlarıyla bir tablo. Hata
gelirse sonraki bölümde yer alan analizlere odaklanın.
4. Vaka Analizi: Karşılaşılan 3 Sorun ve Tespit
Yöntemleri
Bu bölüm, sorunlar ortaya çıkarsa nasıl
tanılayacağınızı gösterir. Sıralama, gerçek hata-ayıklama sürecindeki sırayla
aynıdır, biri çözülmeden bir sonrakine geçilemiyor.
Sorun 1 — [SSL: CERTIFICATE_VERIFY_FAILED] self-signed
certificate
Tanılama: İlk MCP çağrısında SSL doğrulama hatası.
İlk çözüm: Container XSOAR_VERIFY_SSL=false yok diye doğrulamaya kalkıyor. Claude Desktop config'ine XSOAR_VERIFY_SSL=false eklendi, ama hata aynı kaldı.
Kritik tanılama: Container'ın gerçekten hangi env değişkenini
okuduğunu bulmak için kaynak kodda arandı:
docker exec <container_adı> sh -c "grep
-rniE 'verify_ssl|verify=' /app/server 2>/dev/null"
Çıktı:
/app/server/security.py:132: "verify_ssl":
os.getenv("VERIFY_SSL", "true").lower() == "true"
/app/server/generated_xsoar_tools.py:27: verify =
os.getenv("VERIFY_SSL", "true").lower() == "true"
Öğrenilen: Kod VERIFY_SSL okuyor, prefix'siz. Yanlış env adı set edildiği görüldü.
Çözüm: Claude Desktop config'inde VERIFY_SSL=false (3.5'teki nihai konfigürasyondaki gibi).
Çıkarılan ders: "Env değişkeni set ettim ama kod onu
görmüyor" şüphesinde, container'ın
kaynak kodunda env okuma satırını grep'leyin. Başka bir tartışmaya yer
kalmaz.
Sorun 2 — Boş cevap veya <a href="/#/404">See Other</a>
Tanılama: SSL düzeldikten sonra MCP çağrıları boş string ya da
303 redirect ile UI'ya yönlendirme dönüyor.
Kritik tanılama: Direkt API çağrısı ile MCP'yi devreden çıkarıp ham
HTTP cevabı incelendi:
Powershell
üzerinde
@'
import os, httpx
key = os.getenv("XSOAR_API_KEY")
for u in ["https://10.10.20.20//incidents/search",
"https://10.10.20.20/incidents/search"]:
r = httpx.post(u,
headers={"Authorization": key,
"Content-Type":"application/json",
"Accept":"application/json"},
json={"filter":{"size":1}}, verify=False,
follow_redirects=False, timeout=10)
print(u,
"->", r.status_code, "LEN", len(r.text),
"LOC:", r.headers.get("location",""))
'@ | docker exec -i <container_adı> python
Sonuç:
https://10.10.20.20//incidents/search -> 307 LEN 0
LOC: /incidents/search ← çift slash,
redirect
https://10.10.20.20/incidents/search -> 200 LEN 5865 LOC: ← tek slash, başarılı
Öğrenilen: XSOAR_API_URL=https://10.10.20.20/ değerinde sondaki / ile
birleştirilen /incidents/search route'u https://10.10.20.20//incidents/search üretiyor. XSOAR çift slash'ı 307
redirect ile temiz path'e yönlendiriyor; CortexSynapse'in httpx istemcisi
default follow_redirects=False çalıştığı için cevabı boş alıyor.
Çözüm: Claude Desktop config'indeki XSOAR_API_URL değerinden sondaki / silindi.
Çıkarılan
ders: API
URL'lerinde trailing slash yorucu olabilir.
Sorun #3 — 400 Bad Request: json: cannot unmarshal string into Go value
Tanılama: SSL ve URL düzeldi, MCP artık XSOAR'a başarıyla
bağlanıyor ama her body alan endpoint'te şu hata:
{"id": "bad_request",
"status": 400, "title": "Bad request",
"detail": "Request body is not
well-formed. It must be JSON.",
"error": "json: cannot
unmarshal string into Go value of type entities.SearchIncidentsData"}
XSOAR
gönderilen body'yi JSON-encoded string
olarak görüyor, beklediği object
değil.
Kritik
tanılama: İstek
dispatch kodu okundu:
# /app/server/generated_xsoar_tools.py
async def handler(arguments: Dict[str, Any]) ->
List[types.TextContent]:
body =
arguments.get("body")
...
resp = await
client.request(
method=method, url=url,
params=_sanitize_query(query),
headers=_sanitize_headers(headers),
json=body,
)
Body normalde JSON nesnesi olarak gitmeli. Ama bizim
tarafta önce yazıya çevriliyor. Sonra httpx bunu tekrar JSON’a çevirince
XSOAR’a beklenen JSON değil, JSON gibi görünen bir yazı gidiyor. Bu yüzden
XSOAR body’yi okuyamıyor.
Çözüm: Sunucu tarafında body string ise
parse et.
json=(json.loads(body) if isinstance(body, str) else
body)
Önemli Nokta: İnce ama önemli bir detay var: Bu düzeltmeyi sadece
host üzerindeki .py dosyalarına yapmak yeterli değil. Çünkü CortexSynapse
Docker imajı build edilirken RUN python -m codegen.generator komutu çalışıyor ve bu üç dosyayı container içinde
yeniden oluşturuyor. Yani host tarafında patch’lediğimiz dosyaların üzerine
build sırasında tekrar yazılıyor.
Doğru çözüm: Patch'i Dockerfile'a, codegen
adımının hemen ardına ek bir RUN sed -i ... satırı
olarak yerleştirmek. Bölüm 3.2'deki Python script'i tam olarak bunu yapıyor.
5. Nihai Patched Dockerfile (İlgili Kısım)
Patch
uygulandıktan sonra builder stage şöyle görünür:
# ... (önceki adımlar)
COPY server/
server/
COPY codegen/
codegen/
COPY specs/
specs/
RUN python -m codegen.generator
# ↓↓↓ EKLENEN SATIR ↓↓↓
RUN sed -i "s|json=body|json=(json.loads(body) if
isinstance(body, str) else body)|g" \
/app/server/generated_xsoar_tools.py \
/app/server/generated_xsiam_tools.py \
/app/server/generated_unified_tools.py
# ↑↑↑ EKLENEN SATIR ↑↑↑
RUN python -m build
# ... (stage-1 ile devam)
Bu satır, üretim adımı bittikten sonra üç jeneratör
çıktısındaki json=body ifadesini koşullu parse edici hale
dönüştürür. Build cache'leniyorsa --no-cache ile tekrar
build alın.
6. Uçtan Uca Doğrulama
Patch
uygulanmış imaj çalıştığında MCP üzerinden bu örnek dönecektir:
Claude
Desktop sorgusu:
XSOAR'daki
son 5 incident'ı listele
Beklenen MCP
çağrısı (özet):
tool: get_incidents
platform: xsoar
body: {"filter": {"page": 0,
"size": 5, "sort": [{"field":
"created", "asc": false}]}}
Beklenen
sonuç (örnek tablo):
|
ID |
Name |
Severity |
Status |
Owner |
Created (UTC) |
|
34763 |
Test |
3 (High) |
1 (Active) |
L1-L1 |
2026-04-16
12:06 |
|
34748 |
test3 |
0
(Unknown) |
0
(Pending) |
L1-L1 |
2026-03-19
08:27 |
|
34747 |
test2 |
0
(Unknown) |
0
(Pending) |
L1-L1 |
2026-03-19
08:26 |
|
34746 |
test1 |
0
(Unknown) |
0 (Pending) |
L1-L1 |
2026-03-19
08:26 |
|
34740 |
test cti 2 |
1 (Low) |
1 (Active) |
L1-L1 |
2026-03-13
15:48 |
Severity
referansı (Cortex XSOAR): 0=Unknown, 0.5=Informational, 1=Low, 2=Medium, 3=High, 4=Critical Status
referansı: 0=Pending, 1=Active, 2=Closed, 3=Archived
7. Tanılama Araç Kutusu
Aşağıdaki
komutlar bu projede defalarca işe yaradı. Bir SOC engineer'ın MCP entegrasyon
problemlerinde başvurabileceği "first responder" set'i:
# Çalışan container'ları gör
docker ps --format "{{.Names}} {{.Image}}"
# Container'ın aktif env değişkenleri
docker exec <NAME> env | findstr /I "XSOAR
VERIFY API"
# MCP server log'u (initialize, tool list, hata
mesajları)
docker logs --tail 100 <NAME>
# Container'ın kaynak kodunda bir terimi grep'le
docker exec <NAME> sh -c "grep -rniE 'pattern'
/app/server"
# Direct API testi (MCP'yi devreden çıkar)
@'
import os, httpx
url =
os.getenv("XSOAR_API_URL").rstrip("/") +
"/incidents/search"
r = httpx.post(url,
headers={"Authorization":
os.getenv("XSOAR_API_KEY"),
"Content-Type":"application/json",
"Accept":"application/json"},
json={"filter":{"size":1}}, verify=False,
timeout=10)
print(r.status_code, r.text[:300])
'@ | docker exec -i <NAME> python
# Imaj içinde patch var mı?
docker run --rm <IMAGE> grep -c "json.loads(body)"
/app/server/generated_xsoar_tools.py
8. Güvenlik Tedbirleri
- API key
yönetimi: claude_desktop_config.json plaintext key barındırır.
Endpoint protection (Cortex, CrowdStrike, Defender) bu dosyayı taramalı,
MFA-protected disk encryption (BitLocker) zorunlu olmalı.
- Container
hardening:
Config'deki --read-only, --rm, --security-opt=no-new-privileges flag'leri olduğu gibi
korunmalı. Read-only filesystem, --rm ile birlikte container'da yapılan herhangi bir
değişikliğin kalıcı olmasını engeller.
- Network
segmentation: XSOAR
API'si genelde yönetim VLAN'inde. Claude Desktop'un çalıştığı endpoint'in
oraya direkt erişimi varsa lateral movement riski artar. Mümkünse jump
host veya bastion üzerinden tünellenmeli.
- Audit
log:
XSOAR'da MCP entegrasyonu için ayrı bir API key oluşturup audit log'unu (Settings → Audit Trail) bu key'in aktivitesi
açısından izlemek, anomali tespitini kolaylaştırır.
- API key
minimum yetki:
Read-only test için "Read Only" rolü, response aksiyonları
(isolate, quarantine vb.) için ek izinleri kademeli ekleyin.
"Admin" rolü ile MCP key oluşturmaktan kaçının.
9. SOC Use-Case Çıkarımı
CortexSynapse-patched
çalışır hale geldikten sonra MCP üzerinden kullanılabilen tool'ların bir kısmı:
|
Tool |
Senaryo |
|
get_incidents |
"Son
24 saatte yüksek severity'li, owner'ı atanmamış incident'ları listele" |
|
update_incident |
"ID
34763'ü 'In Progress' yap ve owner'ı bana ata" |
|
xsoar_indicators_search |
"Son
7 gün içinde feed'lerden gelen IP indicator'larını getir, reputation'a göre
filtrele" |
|
xsiam_get_alerts |
"Endpoint
X üzerinde son 1 saatte tetiklenen alert'leri çek" |
|
xsiam_start_xql_query |
Doğal
dilden XQL sorgusu kurma (LLM-assisted hunt) |
|
xsiam_isolate / xsiam_unisolate |
Endpoint
izolasyonu / geri alma |
|
xsiam_run_script |
Belirli
endpoint'lerde script çalıştırma (DFIR triage) |
LLM-assisted
SOC operasyonlarına ilgi duyan ekipler için doğal başlangıç noktaları:
- Triage
kısaltma: Yeni
gelen incident'ı (get_incident_extra_data) çekip alert pattern'ini
önceki kapatılmış incident'larla karşılaştırma; benzer geçmiş kararları
öneri olarak sunma.
- Detection
coverage map:
XSOAR'daki incident type dağılımını MITRE ATT&CK technique mapping'i
ile çapraz kontrol, kapsam boşluklarını çıkarma.
- Threat
hunt explainer:
Verilen bir XQL hunt sorgusunu (saia_explain_spl benzeri) doğal dile çevirme, çıktıyı geçen ay
ile karşılaştırma.
10. Sonuç
Bu vaka, açık kaynak bir MCP sunucusunun gerçek bir
kurumsal XSOAR ortamına entegrasyonunda karşılaşılan üç farklı katmandaki
sorunun (env adı uyuşmazlığı, URL trailing slash, body double-encoding,
multi-stage build patch konumu) sırasıyla nasıl tanımlanıp çözüldüğünü gösterdi.
Bu hatalardan hiçbiri kaynaklarda yazmıyordu; her biri kaynak kodu okuyarak,
direct API testleriyle ve Docker build davranışını tersine çevirerek ortaya
çıktı.
SOC otomasyonunda LLM katmanını orkestrasyona bağlamak
herkesin söylediği kadar tak-çalıştır bir iş değil ama hangi katmanda neyin
nasıl çalıştığını bir kez kavradığınızda, tekrar kuruluşu oldukça kısalıyor.
Yorumlar
Yorum Gönder