
# keenauth_webhook_endpoint

Die Ressource `keenauth_webhook_endpoint` verwaltet einen Webhook-Endpunkt: eine HTTPS-Adresse, die die Ereignisse der Umgebung empfängt und mit Standard Webhooks signiert wird. Der Provider speichert das Signaturgeheimnis nur verschlüsselt mit einem RSA-Public-Key, den Sie ihm übergeben, im State.

```terraform
resource "keenauth_webhook_endpoint" "orders" {
  key         = "orders"
  url         = "https://hooks.example.com/keenauth"
  description = "Order service"
  event_types = ["user.created", "user.updated", "organization.created"]
  event_schema_versions = {
    "user.created" = 1
  }
  public_key = file("${path.module}/webhook-secret-key.pub.pem")

  rotation_trigger          = time_rotating.webhook_secret.id
  previous_secret_ttl_hours = 48
}

resource "time_rotating" "webhook_secret" {
  rotation_days = 90
}

output "orders_webhook_secret_encrypted" {
  value = keenauth_webhook_endpoint.orders.encrypted_signing_secret
}
```

## Argumente

- `url` ist erforderlich: nur `https`, kein Port oder Port 443, keine Benutzerinformationen, kein Fragment und ein Hostname statt einer IP-Adresse (höchstens 2048 Zeichen).
- `key` ist in der Umgebung eindeutig (`^[a-z0-9][a-z0-9_-]{0,63}$`). Wenn Sie ihn weglassen, leitet die API `endpoint-<letzte 8 Zeichen der ID>` ab.
- `event_types` listet Ereignistypen aus dem Katalog auf (höchstens 100). Eine leere Menge, der Standardwert, bedeutet alle Typen außer den umfangreichen `authentication.*`-Typen, die Sie ausdrücklich nennen müssen.
- `event_schema_versions` ordnet einem Ereignistyp eine Version des Payload-Schemas zu. Jeder Typ muss einer sein, den der Endpunkt empfängt.
- `payload_mode` ist `thin` (der Standardwert: IDs, geänderte Feldnamen und Statusfelder, keine personenbezogenen Daten) oder `full`.
- `rate_limit_per_second` liegt zwischen 1 und 1000; der Standardwert ist 50.
- `status` ist `enabled` (der Standardwert) oder `disabled_by_user`.

Jedes Argument wird direkt aktualisiert. Updates senden nur die geänderten Felder als JSON Merge Patch, mit dem ETag des letzten Lesevorgangs als `If-Match`. Wurde der Endpunkt seit dem letzten Lesen anderswo geändert, schlägt das Apply mit `412` fehl, und nichts wird geändert; führen Sie plan erneut aus, um die Abweichung zu prüfen.

## Das Signaturgeheimnis wird nie im Klartext gespeichert

Die API gibt das Signaturgeheimnis (`idp_whsec_…`) nur beim Erstellen des Endpunkts und bei einer Rotation des Geheimnisses zurück. Mit `public_key` verschlüsselt der Provider das Geheimnis mit RSA-OAEP (SHA-256, MGF1 SHA-256, leeres Label) und schreibt nur den Base64-Chiffretext nach `encrypted_signing_secret`. Ohne `public_key` wird das Geheimnis verworfen; rotieren Sie es später mit `keenauth webhook-endpoints rotate-secret` oder setzen Sie `public_key`. Das Klartext-Geheimnis gelangt weder in den State, eine Plan-Datei, eine Ausgabe noch in ein Log.

Erzeugen Sie das Schlüsselpaar einmalig außerhalb von OpenTofu und halten Sie den privaten Schlüssel aus Ihrer Konfiguration heraus:

```shell
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -out webhook-secret-key.pem
openssl pkey -in webhook-secret-key.pem -pubout -out webhook-secret-key.pub.pem
```

Nach `tofu apply` entschlüsseln Sie das Geheimnis und geben es an den Empfänger weiter:

```shell
tofu output -raw orders_webhook_secret_encrypted | base64 -d | \
  openssl pkeyutl -decrypt -inkey webhook-secret-key.pem \
    -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 -pkeyopt rsa_mgf1_md:sha256
```

`public_key` muss ein PEM-kodierter RSA-Public-Key (`PUBLIC KEY` oder `RSA PUBLIC KEY`) mit mindestens 2048 Bit sein. Ein privater Schlüssel oder ein kleinerer Schlüssel wird bereits bei plan abgelehnt.

## Rotation

Das Geheimnis wird rotiert, wenn Sie `public_key` setzen oder ändern und wenn sich `rotation_trigger` auf einen neuen Wert ändert, zum Beispiel auf die ID einer `time_rotating`-Ressource. Nach einer Rotation signiert das alte Geheimnis zusammen mit dem neuen weiter, und zwar für `previous_secret_ttl_hours` (0 bis 168; der API-Standardwert ist 24; 0 verwirft es sofort), damit der Empfänger ohne verpasste Ereignisse umstellen kann. `previous_secret_expires_at` zeigt, wann das alte Geheimnis endet. Das Entfernen von `public_key` entfernt nur `encrypted_signing_secret`; es rotiert das Geheimnis nicht.

## Limits und Status

Ein aktivierter Endpunkt zählt pro Umgebung auf das Limit des Plans: Free 3, Startup 20, Business 20, Enterprise 50. Das Erstellen oder Aktivieren eines weiteren schlägt mit `403 quota_exceeded` fehl; deaktivieren oder löschen Sie einen anderen Endpunkt oder wechseln Sie den Plan.

KeenAuth deaktiviert einen Endpunkt, der immer wieder fehlschlägt (`disabled_by_failure`), oder dessen Empfänger mit `410 Gone` antwortet (`disabled_by_receiver`). Der nächste plan zeigt die Änderung zurück auf den konfigurierten `status`, und das Anwenden aktiviert den Endpunkt wieder.

## Import

Importieren Sie mit der Endpunkt-ID oder seinem Schlüssel:

```shell
tofu import keenauth_webhook_endpoint.orders orders
```

Das Signaturgeheimnis kann nicht zurückgelesen werden, daher ist `encrypted_signing_secret` nach dem Import leer. Setzt Ihre Konfiguration `public_key`, rotiert das nächste Apply das Geheimnis und liefert das neue verschlüsselt aus.

Testsendungen, Wiederholungen und Zustellversuche sind einmalige Aktionen und keine Konfiguration. Verwenden Sie dafür `keenauth webhook-endpoints test`, `replay` und `deliveries`.
