Aona API & Webhooks

Lesen Sie Ihre Sicherheitsereignisse über REST und empfangen Sie sie als signierte Webhooks. Beide Schnittstellen verwenden das OCSF-Format (Open Cybersecurity Schema Framework), sodass Sentinel, Splunk und Amazon Security Lake sie nativ aufnehmen können. Aona-spezifische Felder bleiben in enrichments[] erhalten.

Schnellstart

Erstellen Sie im Dashboard unter /api-keys einen Schlüssel mit dem Geltungsbereich events:read und dann:

curl -H "X-Api-Key: aona_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
     https://api.aona.ai/v1/events

Die Antwort ist keyset-paginiert: Übergeben Sie den zurückgegebenen next_cursor bei der nächsten Anfrage als ?cursor=. Cursor sind undurchsichtig und signiert, konstruieren Sie sie nicht von Hand.

Webhooks verifizieren, Node.js

Aona signiert jeden Webhook mit HMAC-SHA256. Verifizieren Sie vor dem Parsen des JSON-Bodys:

import { createHmac, timingSafeEqual } from "node:crypto";

/**
 * Verify an Aona webhook delivery.
 *
 *   const ok = verifyAonaWebhook({
 *     header: req.headers["x-aona-signature"],
 *     body: rawRequestBody,         // string, before JSON.parse
 *     secret: process.env.AONA_WEBHOOK_SECRET,
 *     previousSecret: process.env.AONA_WEBHOOK_SECRET_PREVIOUS, // optional during rotation
 *     toleranceSeconds: 300,
 *   });
 */
export function verifyAonaWebhook({
  header,
  body,
  secret,
  previousSecret,
  toleranceSeconds = 300,
}) {
  if (typeof header !== "string") return false;

  // Parse "t=<unix>,v1=<hex>"
  let t = null, v1 = null;
  for (const part of header.split(",")) {
    const [k, v] = part.split("=");
    if (k === "t") t = Number(v);
    else if (k === "v1") v1 = v;
  }
  if (!t || !v1 || !/^[0-9a-f]{64}$/i.test(v1)) return false;
  if (Math.abs(Math.floor(Date.now() / 1000) - t) > toleranceSeconds) return false;

  const payload = `${t}.${body}`;
  const tryVerify = (s) => {
    const expected = createHmac("sha256", s).update(payload).digest("hex");
    try {
      return timingSafeEqual(Buffer.from(v1, "hex"), Buffer.from(expected, "hex"));
    } catch {
      return false;
    }
  };

  if (tryVerify(secret)) return true;
  if (previousSecret && tryVerify(previousSecret)) return true;
  return false;
}

Webhooks verifizieren, Python

import hmac
import hashlib
import time


def verify_aona_webhook(header: str, body: str, secret: str,
                       previous_secret: str | None = None,
                       tolerance_seconds: int = 300) -> bool:
    """Verify an Aona webhook delivery.

    Pass the raw request body (bytes-or-string before JSON.parse) — the
    signature is computed over the wire payload, not the parsed dict.
    """
    if not isinstance(header, str):
        return False

    parsed = dict(part.split("=", 1) for part in header.split(",") if "=" in part)
    try:
        t = int(parsed["t"])
        v1 = parsed["v1"]
    except (KeyError, ValueError):
        return False
    if not (len(v1) == 64 and all(c in "0123456789abcdefABCDEF" for c in v1)):
        return False
    if abs(int(time.time()) - t) > tolerance_seconds:
        return False

    payload = f"{t}.{body}".encode("utf-8")
    def _try(s: str) -> bool:
        expected = hmac.new(s.encode("utf-8"), payload, hashlib.sha256).hexdigest()
        return hmac.compare_digest(v1.lower(), expected.lower())

    if _try(secret):
        return True
    if previous_secret and _try(previous_secret):
        return True
    return False

Secret-Rotation (ohne Ausfallzeit)

Wenn Sie das Signatur-Secret eines Webhooks im Dashboard rotieren, bleibt das vorherige Secret 24 Stunden lang gültig. Während dieses Zeitfensters werden beide Secrets erfolgreich verifiziert. Das empfohlene Muster ist im Verifizierungscode oben dargestellt: Versuchen Sie zuerst das aktuelle Secret und greifen Sie dann auf das vorherige zurück, falls Sie es haben. Aktualisieren Sie Ihre Umgebung auf das neue Secret und ziehen Sie das vorherige nach Belieben zurück.

Replay-Schutz

Die Komponente t= von X-Aona-Signature ist der Unix-Sekunden-Zeitstempel, zu dem wir die Nutzlast signiert haben. Der Verifizierer lehnt Zustellungen ab, bei denen |now - t| &gt; toleranceSeconds (Standard: 5 Minuten). Lockern Sie dies nicht ohne Grund, es ist das Einzige, was Sie davor schützt, dass jemand eine abgefangene Nutzlast erneut abspielt.

Idempotenz

Jede Zustellung enthält X-Aona-Delivery: &lt;uuid&gt;. Wenn eine Zustellung das Zeitlimit überschreitet und wir es erneut versuchen, senden wir dieselbe ID. Deduplizieren Sie darüber für „mindestens einmal“-Sicherheit, Empfänger, die sie in einem kleinen begrenzten Cache speichern, werden niemals zweimal auf dasselbe Ereignis reagieren.

OCSF-Ereignisreferenz

Aona-Ereignisse entsprechen OCSF class_uid 6005 (Application Activity / Web Resources Activity). Aona-eigene Felder erscheinen innerhalb von enrichments[] mit expliziten Typen.

{
  "id": "01J5e2-uuid-...",
  "version": "2026-05-23",
  "class_uid": 6005,
  "category_name": "Application Activity",
  "activity_name": "Access",
  "time": "2026-05-22T14:08:12.314Z",
  "actor": { "user": { "uid": "f6c1...-uuid" } },
  "app":   { "name": "Aona", "uid": "chat-gpt-platform-uuid" },
  "type_name":   "policy_violation",
  "disposition": "BLOCK",
  "metadata": {
    "product": { "name": "Aona Workforce AI Security" },
    "tenant_uid": "your-business-uuid"
  },
  "enrichments": [
    { "name": "data_security_risk", "value": 0.83, "type": "numeric" },
    { "name": "data_privacy_risk",  "value": 0.41, "type": "numeric" },
    { "name": "policy_id", "value": "policy-uuid", "type": "uid" },
    { "name": "action",    "value": "BLOCK",       "type": "string" },
    { "name": "chat_id",   "value": "abc-123",     "type": "string" }
  ]
}

Das vollständige Schema finden Sie in der OpenAPI-Spezifikation (maschinenlesbares JSON unter /v1/docs-json).

Statuscodes & Ratenbegrenzungen

Sicherheitshinweise