Defense-Plugin-Architektur: CrowdStrike, Jamf und Baramundi in unter 30 Minuten integrieren
Jede SOC-Plattform behauptet einen "umfangreichen Integrations-Katalog". Die meisten meinen damit eine fixe Liste Partner-Connectoren, gepflegt vom Engineering-Team des Anbieters. Echte Erweiterbarkeit heißt: Ihre Engineers können in einem Nachmittag eine neue Integration schreiben. Hier das Plugin-Interface, das das möglich macht, sowie die drei illustrativen Integrationen (CrowdStrike, Jamf, Baramundi), an denen wir es beweisen.

TL;DR. Messen Sie eine Security-Plattform nicht an der Größe ihres Integrations-Katalogs. Entscheidend ist, wie lange Ihr Team, nicht das des Anbieters, braucht, um eine Integration zu ergänzen, die der Katalog nicht enthält. Lautet die Antwort "ein Nachmittag", halten Sie mit neuen Angriffen Schritt; lautet sie "Partner-Ticket aufmachen und zwei Quartale warten", fallen Sie zurück. Die Form des Plugin-Interfaces entscheidet, welche der beiden Sie bekommen.
Die Integrations-Katalog-Seite auf jeder SOC-Anbieter-Website hat dieselbe Länge und denselben Inhalt. EDR-Anbieter, MDM, Vuln-Scanner, Ticketing, Chat, Cloud-Plattformen, die Marquee-Logos rotieren, der zugrundeliegende Claim ist identisch: "wir unterstützen alles, was Sie schon nutzen."
Zwei Fragen zeigen, ob der Claim real ist.
Erstens: Können Ihre Engineers eine neue Integration schreiben, ohne ein Ticket beim Anbieter zu eröffnen? Zweitens: Falls ja, wie lange dauert es? "Ein Nachmittag" ist eine andere Plattform als "zwei Wochen Reverse-Engineering an einem undokumentierten Interface". Beide können technisch erweiterbar genannt werden.
Dieser Beitrag geht durch die Plugin-Architektur im Defense-Modul von Krasper Suite, die Schicht, die mit Endpoint-, Identity- und Device-Management-Systemen spricht. Die drei illustrativen Integrationen sind CrowdStrike (EDR), Jamf (Apple MDM) und Baramundi (UEM). Konkret genug, um zu beweisen, dass das Muster gegen echte Anbieter-APIs mit sehr unterschiedlichen Shapes funktioniert; gleichzeitig Stellvertreter für die längere Antwort: jede davon könnte von einer:einem Kunden-Engineer in deutlich unter einer Stunde gegen das unten beschriebene Interface ersetzt oder erweitert werden.
Inhalt
- Die Integrations-Steuer: wofür Plugin-Architektur eigentlich da ist
- Das Defense-Plugin-Interface
- Metadata-Discovery und Registrierung
- Ein Custom-Plugin in etwa 50 Zeilen
- Das Health-Check-Muster, das die meisten Plugins überspringen
- Plugin-Lifecycle: Install, Enable, Version, Retire
- Warum drei verschiedene Anbieter das Muster beweisen
1. Die Integrations-Steuer: wofür Plugin-Architektur eigentlich da ist
Jede SOC-Plattform zahlt eine Integrations-Steuer. Die Form hängt davon ab, wie die Plattform gebaut ist.
Sind Integrationen nur First-Party, also geschrieben, gepflegt und ausgeliefert vom Anbieter, taucht die Steuer als Latenz auf. Ein neues Release des EDR, auf den Sie sich verlassen, ändert ein Feld in seiner API; der SOC-Anbieter bemerkt es drei Wochen später; die gepatchte Integration shippt im nächsten Quartals-Release; Ihre Detection-Coverage hat in der Zwischenzeit eine stille Lücke.
Sind Integrationen First-Party plus Partner-Programm, verschiebt sich die Steuer auf Koordination. Neue Anbieter müssen über ein Partner-Agreement onboarded werden, bevor sie integriert werden können. Die existierenden Integrationen sind gut supported; die, die nicht existieren, brauchen sechs bis zwölf Monate, egal wie trivial die API ist.
Plugin-Architektur ist, was die Integrations-Steuer bei den Engineers belässt, die dem Problem am nächsten sind: Ihren. Ein gut designtes Plugin-Interface heißt: ein neuer EDR, ein neues MDM, eine neue Asset-Quelle kann von Ihrem Team, nach Ihrem Zeitplan, gegen Ihre Security-Requirements integriert werden. Der Plattform-Anbieter pflegt das Interface; die Integrationen dagegen sind Arbeit, die jede:r Kompetente machen kann.
2. Das Defense-Plugin-Interface
Ein Defense-Plugin in Suite ist alles, was vier Verträge implementiert:
- Asset-Discovery: gegeben einen Tenant-Kontext, gib die Assets zurück, die dieses System kennt, im kanonischen Asset-Modell.
- Telemetry-Ingest: subscribe oder polle Security-Events vom System, normalisiere sie ins Event-Schema der Plattform und publishe sie auf den gemeinsamen Bus.
- Action-Execution: akzeptiere Action-Requests (Endpoint isolieren, Policy durchsetzen, Datei abrufen, Script ausführen) und führe sie gegen die Upstream-API aus, mit expliziter Failure-Semantik.
- Health: beantworte autoritativ, ob das Plugin aktuell funktionsfähig ist, mit genug Detail, dass ein:e Operator:in es fixen kann.
Drei davon sind offensichtlich; das vierte (Health) ist das, was die meisten selbstgebauten Integrationen überspringen, und zugleich das, was entscheidet, ob das Plugin um 3 Uhr morgens von jemand anderem als der:dem Autor:in bedient werden kann.
┌──────────────────────────────────────────────┐ │ DefensePlugin (interface) │ │ │ │ + describe() → PluginMetadata │ │ + discover_assets() → AssetRecord[] │ │ + ingest() → AsyncIterator[Event] │ │ + execute(action) → ActionResult │ │ + health() → HealthReport │ └──────────────────────────────────────────────┘
Jede Methode hat einen typisierten Return; jeder externe Call hat begrenzte Timeouts; jeder Seiteneffekt läuft durch dieselbe Idempotenz-Schicht, die der Rest der Plattform nutzt. Plugin-Autor:innen implementieren diese Garantien nicht; sie erben sie von der Basisklasse.
3. Metadata-Discovery und Registrierung
Ein neues Plugin braucht keinen Plattform-Redeploy. Die Discovery-Loop holt es aus der Plugin-Registry, liest seine Metadata und macht es für Tenant-Konfiguration verfügbar. Die Metadata beschreibt, was das Plugin behauptet zu tun, welche Credentials es braucht, welche Actions es unterstützt und welchen Version-Vertrag es garantiert.
┌──────────────────────────────────────────────┐
│ PluginMetadata │
│ │
│ name: "acme-edr-plugin" │
│ version: "1.2.0" │
│ vendor: "acme" │
│ capabilities: │
│ - asset_discovery │
│ - telemetry_ingest │
│ - action.isolate_endpoint │
│ - action.run_remediation_script │
│ credentials_schema: { ... JSON Schema ... } │
│ api_contract_version: "1" │
└──────────────────────────────────────────────┘
api_contract_version ist das tragende Feld. Es ist die Version des Plugin-Interfaces der Plattform, gegen die das Plugin gebaut wurde, nicht die Version der Anbieter-API. Die Plattform weigert sich, Plugins zu laden, deren Vertragsversion sie nicht erfüllen kann; das verhindert den Failure-Mode, in dem ein altes Plugin still gegen ein neueres Interface fehlläuft.
Capabilities sind explizit und granular. Ein Plugin, das nur Asset-Discovery macht, wird nicht gebeten, Actions auszuführen. Das Operator-UI zeigt basierend auf deklarierten Capabilities, was das Plugin kann, und beugt so den "wir haben versucht, diese Integration zu nutzen, aber sie unterstützt nicht, was wir brauchen"-Überraschungen drei Wochen nach Produktiv-Start.
4. Ein Custom-Plugin in etwa 50 Zeilen
Der schnellste Weg, das Interface zu demonstrieren, ist durchzugehen, wie ein minimales Plugin tatsächlich aussieht. Das Beispiel unten ist eine Skizze, illustrativ und nicht produktionsreif, der Integration eines fiktiven EDR-Produkts namens Acme in Suite.
from suite_plugins import (
DefensePlugin, PluginMetadata, AssetRecord,
Event, ActionResult, HealthReport,
)
from suite_plugins.errors import UpstreamError
class AcmeEdrPlugin(DefensePlugin):
def describe(self) -> PluginMetadata:
return PluginMetadata(
name="acme-edr-plugin",
version="1.0.0",
vendor="acme",
capabilities=[
"asset_discovery",
"telemetry_ingest",
"action.isolate_endpoint",
],
credentials_schema={
"type": "object",
"required": ["api_token", "base_url"],
"properties": {
"api_token": {"type": "string"},
"base_url": {"type": "string", "format": "uri"},
},
},
api_contract_version="1",
)
async def discover_assets(self):
async for raw in self.client.list_endpoints():
yield AssetRecord(
native_id=raw["device_id"],
resolution_hints={
"serial": raw.get("serial_number"),
"mac": raw.get("primary_mac"),
"hostname": raw.get("hostname"),
},
os=raw.get("os_platform"),
last_seen=raw.get("last_checkin_at"),
)
async def ingest(self):
async for raw in self.client.stream_alerts():
yield Event(
event_type="edr.alert.created",
native_id=raw["alert_id"],
native_asset_id=raw["device_id"],
severity=raw["severity"],
payload=raw,
)
async def execute(self, action):
if action.type == "isolate_endpoint":
try:
await self.client.isolate(action.target.native_id)
return ActionResult.success()
except UpstreamError as e:
return ActionResult.failure(reason=str(e))
return ActionResult.unsupported()
async def health(self) -> HealthReport:
try:
await self.client.ping()
return HealthReport.ok()
except UpstreamError as e:
return HealthReport.degraded(reason=str(e))
Fünf Methoden, kein Infrastruktur-Code. Das Plugin managet keine eigene Datenbank, implementiert keine eigene Auth-Schicht, rollt keine eigene Retry-Logik. Die Basisklasse und die Runtime handlen das. Die:der Plugin-Autor:in schreibt den anbieter-spezifischen Code und sonst nichts.
Das Muster, das zählt: Jede Methode mappt sauber auf einen Vertrag, den die Plattform schon versteht. AssetRecord ist die kanonische Asset-Form, die der Resolver der Plattform erwartet. Event ist die Form, die der Event-Bus abonniert. ActionResult ist die Form, die jede Playbook-Node versteht. Das Plugin erfindet kein Vokabular; es mappt das Anbieter-Vokabular ins der Plattform.
5. Das Health-Check-Muster, das die meisten Plugins überspringen
health() sieht trivial aus: Upstream rufen, ok oder degraded zurückgeben. Was einen echten Health-Check von einem Häkchen-Check unterscheidet, ist Spezifität.
Ein Health-Check, der "ok" oder "fail" zurückgibt, ist kaum nützlich. Die:der Operator:in erfährt, dass die Integration kaputt ist; sie:er erfährt nicht, warum. Die:der Plugin-Autor:in wird sowieso gepaged.
Ein nützlicher Health-Check gibt genug Struktur zur Triage zurück:
┌────────────────────────────────────────────┐ │ HealthReport │ │ │ │ status: ok | degraded | down │ │ upstream_reachable: bool │ │ auth_valid: bool │ │ rate_limit_remaining: int | null │ │ last_successful_call: timestamp │ │ message: human-readable detail │ └────────────────────────────────────────────┘
Jetzt sieht die:der Operator:in auf einen Blick, dass die Integration down ist, weil Authentication vor drei Stunden gescheitert ist, nicht weil das Netz kaputt ist, nicht weil der Upstream rate-limited. Sie:er kann die Credentials in der Tenant-Konfiguration rotieren, und das Plugin erholt sich, ohne dass jemand Code anfasst.
Die Plattform ruft health() auf jedem Plugin in regelmäßiger Kadenz und exponiert das Ergebnis im Operations-Dashboard. Derselbe Call läuft auch als Readiness-Check, bevor irgendein Playbook, das vom Plugin abhängt, ausführt. Ein Playbook läuft nie still gegen eine bekannt-kaputte Integration.
6. Plugin-Lifecycle: Install, Enable, Version, Retire
Ein Plugin-Leben hat vier Phasen, jede mit expliziter Semantik.
Beim Install wird ein neues Plugin hochgeladen oder aus der Plugin-Registry geholt. Die Plattform validiert die Metadata, prüft die Vertragsversion und registriert es als verfügbar für die Tenant-Konfiguration, aktiv ist es damit für niemanden.
Ein Tenant aktiviert es anschließend, indem er Credentials konfiguriert. Die Plattform schickt diese durch die Schema-Validierung, ruft einmal health(), um zu bestätigen, dass die Konfiguration funktioniert, und markiert das Plugin erst dann als aktiv für diesen Tenant. Ein gescheiterter Health-Check hält es hier davon ab, überhaupt im kaputten Zustand live zu gehen.
Neue Versionen installieren neben der alten. Tenants migrieren einzeln statt alle zugleich, nichts erzwingt ein flottenweites Upgrade; eine Version mit Breaking-Change bumpt api_contract_version, und die vorige bleibt installierbar für Tenants, die noch nicht gewechselt sind.
Zuletzt lässt sich ein Plugin stilllegen. Es wird als deprecated markiert, Tenants werden benachrichtigt, neue können es nicht mehr aktivieren, bestehende bekommen eine Migrations-Deadline. Danach geht es in Read-Only: bereits ingestete Events bleiben abfragbar, aber keine neue Discovery, kein Ingest und keine Action laufen mehr.
Dieser Lifecycle ist unglamourös, aber tragend. Ohne ihn akkumulieren Integrationen für immer, niemand weiß sicher, welche noch gepflegt werden, und die operative Oberfläche wächst still, bis der nächste Incident enthüllt, welche Integrationen monatelang still kaputt waren. Der Lifecycle macht Integrations-Health zu einer sichtbaren, auditierbaren Eigenschaft der Plattform.
7. Warum drei verschiedene Anbieter das Muster beweisen
Die drei Integrationen, die wir im Defense-Modul von Suite ausliefern (CrowdStrike, Jamf und Baramundi), existieren als empirischer Beweis, dass das obige Plugin-Interface über sehr unterschiedliche Upstream-Shapes generalisiert.
CrowdStrike exponiert einen Streaming-Alert-Feed mit hohem Durchsatz und eine REST-API für Actions; das ingest() des Plugins subscribiert den Stream, execute() ruft die REST-Endpoints. Jamf ist Apple-zentrisch, MDM-shaped, mit einem anderen Vokabular um Devices und Configuration-Profiles; das Plugin mappt dieses Vokabular in die kanonischen Asset- und Action-Shapes, die der Rest der Plattform spricht. Baramundi deckt Windows-zentrisches UEM mit Patching und Software-Inventory; das Plugin handlet Bulk-Asset-Enumeration und Software-Installed-Events.
Diese drei Anbieter exponieren völlig unterschiedliche API-Stile und Domänen-Modelle, und dennoch erreichen sie die Plattform alle über dasselbe Plugin-Interface, jeweils in deutlich unter einem Tag von einer:einem einzigen Engineer umsetzbar. Genau dafür ist die Architektur da. Die Integrationen selbst sind fast nebensächlich; worauf es ankommt, ist, dass das Interface sie austauschbar macht.
Wenn Sie aktuell einen vierten EDR, ein anderes MDM, ein UEM nutzen, gegen das wir nicht gebaut haben: gegen dasselbe Interface implementieren Sie. Die Plattform muss den Anbieter vorab nicht kennen.
Abschluss
Ein Integrations-Katalog ist ein schlechtes Maß für eine Security-Plattform. Es zählt, wie günstig Ihr eigenes Team sie erweitern kann, wenn der Katalog nicht reicht, und ein gut geformtes Plugin-Interface, mit typisierten Verträgen, metadata-getriebener Discovery, echten Health-Checks und explizitem Lifecycle, hält diese Kosten vorhersehbar und niedrig.
Der nächste Beitrag dieser Serie schaut auf eine spezifische Konsequenz dieser Architektur: wie die Plattform Partial-Failure-Szenarien handhabt, in denen ein Plugin in einem Multi-Step-Playbook nicht verfügbar ist. Magie steckt darin nicht, nur viel explizites Error-Routing, das, wie die vorherigen Beiträge argumentiert haben, die tatsächliche Form reifer Automatisierung ist.
Weiterlesen
- Plugin Architectures in Production Systems, Design-Patterns für erweiterbare Plattformen
- NIST SP 800-128: Guide for Security-Focused Configuration Management
- MITRE D3FEND: Hardening and Isolation-Techniken, referenziert von EDR-Integrationen
Unternehmensinfrastruktur abzusichern?
Vereinbaren Sie ein technisches Briefing. Kein Sales-Pitch, nur Architekten und Ihr Team.