Skip to content

Authentifizierung

Die Aster Policy Engine erzwingt ein dreischichtiges Sicherheitsmodell bei jeder Anfrage. Jede Schicht ist unabhängig; alle drei müssen erfüllt sein, damit eine Anfrage erfolgreich ist.

Schicht 1 — Mandantenisolierung (X-Tenant-Id)

Jede Anfrage muss einen X-Tenant-Id-Header enthalten. Dieser Header legt den Mandantenkontext der Anfrage fest: Richtlinien, Audit-Datensätze und alle Daten sind auf den angegebenen Mandanten beschränkt und für andere Mandanten nicht sichtbar.

Format: ^[a-zA-Z0-9_-]{1,64}$

Ein fehlender oder fehlerhafter X-Tenant-Id gibt sofort 400 Bad Request zurück, bevor eine andere Validierung durchgeführt wird.

bash
curl https://policy.aster-lang.dev/api/v1/policies \
  -H "X-Tenant-Id: acme-corp"

Mandanten-ID-Konventionen

Verwenden Sie einen stabilen, menschenlesbaren Bezeichner wie Ihren Organisationsslug oder Umgebungsnamen (z.B. acme-corp, acme-corp-staging). Mandanten-IDs sind groß-/kleinschreibungsempfindlich.

Schicht 2 — HMAC-Anfragensignierung

Jede Anfrage muss HMAC-Signatur-Header enthalten. Der Server validiert die Signatur, bevor die Anfrage verarbeitet wird, um Manipulation während der Übertragung und Replay-Angriffe zu verhindern.

Erforderliche Header

HeaderBeschreibung
X-Aster-SignatureHexadezimal kodierter HMAC-SHA256 der kanonischen Nachricht (siehe unten)
X-Aster-NonceZufällig generierter String (empfohlen 16+ Bytes, Hex oder UUID)
X-Aster-TimestampUnix-Zeitstempel in Millisekunden zum Zeitpunkt der Signierung

Eine Anfrage, bei der einer dieser drei Header fehlt, gibt 401 Unauthorized zurück.

Kanonisches Nachrichtenformat

Der HMAC wird über den folgenden pipe-getrennten String berechnet:

{HTTP-method}|{path}|{query}|{X-Aster-Timestamp}|{X-Aster-Nonce}|{body-sha256}
KomponenteBeschreibungBeispiel
HTTP-methodHTTP-Methode in GroßbuchstabenPOST
pathAnfrage-URI-Pfad/api/v1/policies/evaluate-source
queryRoher Abfragestring (leerer String wenn keiner)trace=true
X-Aster-TimestampZeitstempelwert aus Header1708776000000
X-Aster-NonceNonce-Wert aus Headerc3ab8ff13720e8ad9047dd39466b3c89
body-sha256Hexadezimaler SHA-256-Hash des rohen Anfragekörpers in Kleinbuchstabena1b2c3d4...

Der HMAC-Schlüssel ist das API-Geheimnis, das Ihrem Mandanten ausgestellt wurde. Das Geheimnis wird in dieser Prioritätsreihenfolge aufgelöst:

  1. Umgebungsvariable ASTER_HMAC_SECRET_{TENANT_ID} (Mandanten-ID in Großbuchstaben, Bindestriche durch Unterstriche ersetzt)
  2. Konfigurationseigenschaft aster.security.hmac.secret-key

Beispiel: Signaturberechnung (Bash)

bash
TENANT_ID="acme-corp"
TIMESTAMP=$(($(date +%s) * 1000))
NONCE=$(openssl rand -hex 16)
BODY='{"source":"Module demo.\n\nRule ping produce Text:\n  Return \"pong\".","functionName":"ping","context":{},"locale":"en-US"}'
API_SECRET="your-api-secret-here"
METHOD="POST"
PATH_URI="/api/v1/policies/evaluate-source"
QUERY=""

BODY_HASH=$(printf '%s' "${BODY}" | openssl dgst -sha256 | awk '{print $2}')
CANONICAL="${METHOD}|${PATH_URI}|${QUERY}|${TIMESTAMP}|${NONCE}|${BODY_HASH}"
SIGNATURE=$(printf '%s' "${CANONICAL}" | openssl dgst -sha256 -hmac "${API_SECRET}" | awk '{print $2}')

curl -X POST "https://policy.aster-lang.dev${PATH_URI}" \
  -H "Content-Type: application/json" \
  -H "X-Tenant-Id: ${TENANT_ID}" \
  -H "X-User-Role: MEMBER" \
  -H "X-Aster-Signature: ${SIGNATURE}" \
  -H "X-Aster-Nonce: ${NONCE}" \
  -H "X-Aster-Timestamp: ${TIMESTAMP}" \
  -d "${BODY}"

Replay-Schutz

Der Server lehnt Anfragen ab, bei denen X-Aster-Timestamp mehr als 5 Minuten (300.000 Millisekunden) in der Vergangenheit oder Zukunft liegt, und gibt 401 Unauthorized zurück. Außerdem wird jeder Nonce für die Dauer des Replay-Fensters gespeichert; eine zweite Anfrage mit demselben Nonce innerhalb des Fensters wird mit 409 Conflict abgelehnt.

Schicht 3 — Rollenbasierte Zugriffskontrolle (X-User-Role)

Der X-User-Role-Header enthält den Rollenanspruch des Aufrufers. Der Server erzwingt eine strenge Rollenhierarchie:

OWNER > ADMIN > MEMBER > VIEWER

Jede Rolle ist additiv: eine höhere Rolle erbt alle Berechtigungen der darunter liegenden Rollen.

Rollenberechtigungen

RolleErlaubte Aktionen
VIEWERGespeicherte Richtlinien lesen (GET)
MEMBERAlle VIEWER-Berechtigungen + Richtlinien evaluieren (POST an Evaluierungsendpunkte)
ADMINAlle MEMBER-Berechtigungen + Audit-Protokolle lesen und verifizieren
OWNERAlle ADMIN-Berechtigungen + Mandanteneinstellungen und RBAC-Zuweisungen verwalten

Endpunktanforderungen

EndpunktkategorieMindestrolle
Richtlinien-EvaluierungMEMBER
Richtlinienverwaltung (CRUD)MEMBER
Audit-Protokoll lesenADMIN
Audit-Protokoll-VerifizierungADMIN
MandantenverwaltungOWNER

Eine Anfrage mit unzureichender Rolle gibt 403 Forbidden zurück.

Optionale Header

HeaderBeschreibungStandard
X-User-IdIdentifiziert den Aufrufer in Audit-Protokollenanonymous

Beispiel: Vollständige Anfrage mit allen Schichten

bash
TENANT_ID="acme-corp"
TIMESTAMP=$(($(date +%s) * 1000))
NONCE=$(openssl rand -hex 16)
BODY='{"source":"Module demo.\n\nRule ping produce Text:\n  Return \"pong\".","functionName":"ping","context":{},"locale":"en-US"}'
API_SECRET="your-api-secret-here"
METHOD="POST"
PATH_URI="/api/v1/policies/evaluate-source"

BODY_HASH=$(printf '%s' "${BODY}" | openssl dgst -sha256 | awk '{print $2}')
SIGNATURE=$(printf '%s' "${METHOD}|${PATH_URI}||${TIMESTAMP}|${NONCE}|${BODY_HASH}" | openssl dgst -sha256 -hmac "${API_SECRET}" | awk '{print $2}')

curl -X POST "https://policy.aster-lang.dev${PATH_URI}" \
  -H "Content-Type: application/json" \
  -H "X-Tenant-Id: ${TENANT_ID}" \
  -H "X-User-Id: user@acme.com" \
  -H "X-User-Role: MEMBER" \
  -H "X-Aster-Signature: ${SIGNATURE}" \
  -H "X-Aster-Nonce: ${NONCE}" \
  -H "X-Aster-Timestamp: ${TIMESTAMP}" \
  -d "${BODY}"

Zusammenfassung

SchichtHeaderErforderlichFehlerantwort
1X-Tenant-IdImmer400 Bad Request
2X-Aster-Signature, X-Aster-Nonce, X-Aster-TimestampImmer401 Unauthorized
3X-User-RoleImmer403 Forbidden
X-User-IdOptionalStandard: anonymous

Veröffentlicht unter der MIT-Lizenz.