
# keenauth_webhook_endpoint

La ressource `keenauth_webhook_endpoint` gère un point de terminaison de webhook : une adresse HTTPS qui reçoit les événements de l'environnement, signés selon Standard Webhooks. Le fournisseur ne conserve le secret de signature dans l'état que chiffré avec une clé publique RSA que vous lui fournissez.

```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
}
```

## Arguments

- `url` est obligatoire : `https` uniquement, sans port ou avec le port 443, sans informations utilisateur, sans fragment, et un nom d'hôte plutôt qu'une adresse IP (2048 caractères au maximum).
- `key` est unique dans l'environnement (`^[a-z0-9][a-z0-9_-]{0,63}$`). Si vous l'omettez, l'API le génère sous la forme `endpoint-<8 derniers caractères de l'ID>`.
- `event_types` liste les types d'événements du catalogue (100 au maximum). Un ensemble vide, valeur par défaut, désigne tous les types sauf les types `authentication.*` à fort volume, que vous devez nommer explicitement.
- `event_schema_versions` associe un type d'événement à une version de schéma de charge utile. Chaque type doit faire partie de ceux que le point de terminaison reçoit.
- `payload_mode` vaut `thin` (valeur par défaut : identifiants, noms des champs modifiés et champs d'état, sans données personnelles) ou `full`.
- `rate_limit_per_second` va de 1 à 1000 ; la valeur par défaut est 50.
- `status` vaut `enabled` (valeur par défaut) ou `disabled_by_user`.

Chaque argument peut être modifié sur place. Les mises à jour n'envoient que les champs modifiés sous forme de JSON Merge Patch, avec l'ETag de la dernière lecture dans `If-Match`. Si le point de terminaison a été modifié ailleurs depuis la dernière lecture, l'application échoue avec `412` et rien n'est modifié ; exécutez à nouveau plan pour examiner la dérive.

## Le secret de signature n'est jamais stocké en clair

L'API ne renvoie le secret de signature (`idp_whsec_…`) qu'à la création du point de terminaison et lors de sa rotation. Avec `public_key`, le fournisseur chiffre le secret avec RSA-OAEP (SHA-256, MGF1 SHA-256, étiquette vide) et n'écrit dans `encrypted_signing_secret` que le texte chiffré encodé en base64. Sans `public_key`, le secret est écarté ; faites-le tourner ultérieurement avec `keenauth webhook-endpoints rotate-secret` ou définissez `public_key`. Le secret en clair n'atteint jamais l'état, le fichier de plan, une sortie ou un journal.

Créez la paire de clés une seule fois, en dehors d'OpenTofu, et gardez la clé privée hors de votre configuration :

```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
```

Après `tofu apply`, déchiffrez le secret et transmettez-le au destinataire :

```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` doit être une clé publique RSA encodée en PEM (`PUBLIC KEY` ou `RSA PUBLIC KEY`) d'au moins 2048 bits. Une clé privée ou une clé plus petite est rejetée au moment de plan.

## Rotation

Le secret est renouvelé lorsque vous définissez ou modifiez `public_key`, et lorsque `rotation_trigger` prend une nouvelle valeur, par exemple l'ID d'une ressource `time_rotating`. Après une rotation, l'ancien secret continue de signer en parallèle du nouveau pendant `previous_secret_ttl_hours` (de 0 à 168 ; la valeur par défaut de l'API est 24 ; 0 le supprime immédiatement), afin que le destinataire puisse basculer sans manquer d'événements. `previous_secret_expires_at` indique quand l'ancien secret cesse d'être valide. Supprimer `public_key` retire seulement `encrypted_signing_secret` ; cela ne déclenche pas de rotation du secret.

## Limites et statut

Un point de terminaison activé compte dans la limite du forfait par environnement : Free 3, Startup 20, Business 20, Enterprise 50. La création ou l'activation d'un point de terminaison supplémentaire échoue avec `403 quota_exceeded` ; désactivez ou supprimez un autre point de terminaison, ou passez à un forfait supérieur.

KeenAuth désactive un point de terminaison qui continue d'échouer (`disabled_by_failure`) ou dont le destinataire répond `410 Gone` (`disabled_by_receiver`). Le plan suivant affiche le retour à la valeur `status` configurée, et son application réactive le point de terminaison.

## Import

Importez avec l'ID du point de terminaison ou avec sa clé :

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

Le secret de signature ne peut pas être relu, donc `encrypted_signing_secret` est vide après l'import. Si votre configuration définit `public_key`, la prochaine application fait tourner le secret et livre le nouveau secret chiffré.

Les envois de test, les rejeux et les nouvelles tentatives de livraison sont des actions ponctuelles, et non de la configuration. Utilisez `keenauth webhook-endpoints test`, `replay` et `deliveries` pour les réaliser.
