keenauth_webhook_endpoint
La risorsa keenauth_webhook_endpoint gestisce un endpoint webhook: un indirizzo HTTPS che riceve gli eventi dell'ambiente, firmati con Standard Webhooks. Il provider conserva il segreto di firma nello stato solo cifrato con una chiave pubblica RSA che gli fornisci.
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
}
Argomenti
urlè obbligatorio: solohttps, nessuna porta o porta 443, nessuna informazione utente, nessun frammento, e un nome host invece di un indirizzo IP (al massimo 2048 caratteri).keyè univoca nell'ambiente (^[a-z0-9][a-z0-9_-]{0,63}$). Se la ometti, l'API la ricava comeendpoint-<ultimi 8 caratteri dell'ID>.event_typeselenca i tipi di evento del catalogo (al massimo 100). Un insieme vuoto, il default, significa tutti i tipi tranne i tipiauthentication.*, ad alto volume, che devi indicare esplicitamente.event_schema_versionsassocia un tipo di evento a una versione dello schema del payload. Ogni tipo deve essere uno di quelli che l'endpoint riceve.payload_modeèthin(il default: ID, nomi dei campi modificati e campi di stato, senza dati personali) oppurefull.rate_limit_per_secondva da 1 a 1000; il default è 50.statusèenabled(il default) oppuredisabled_by_user.
Ogni argomento cambia sul posto. Gli aggiornamenti inviano solo i campi modificati come JSON Merge Patch, con l'ETag dell'ultima lettura come If-Match. Se l'endpoint è stato modificato altrove dopo l'ultima lettura, l'apply fallisce con 412 e non cambia nulla; esegui di nuovo plan per rivedere la divergenza.
Il segreto di firma non viene mai memorizzato in chiaro
L'API restituisce il segreto di firma (idp_whsec_…) solo quando l'endpoint viene creato e quando il segreto viene ruotato. Con public_key, il provider cifra il segreto con RSA-OAEP (SHA-256, MGF1 SHA-256, etichetta vuota) e scrive in encrypted_signing_secret solo il testo cifrato in base64. Senza public_key il segreto viene scartato; ruotalo in seguito con keenauth webhook-endpoints rotate-secret oppure imposta public_key. Il segreto in chiaro non arriva mai allo stato, a un file di piano, a un output o a un log.
Crea la coppia di chiavi una sola volta, fuori da OpenTofu, e tieni la chiave privata fuori dalla configurazione:
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
Dopo tofu apply, decifra il segreto e consegnalo al ricevitore:
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 deve essere una chiave pubblica RSA codificata in PEM (PUBLIC KEY o RSA PUBLIC KEY) di almeno 2048 bit. Una chiave privata o una chiave più piccola viene rifiutata al momento del plan.
Rotazione
Il segreto viene ruotato quando imposti o modifichi public_key, e quando rotation_trigger cambia in un nuovo valore, per esempio l'ID di una risorsa time_rotating. Dopo una rotazione il vecchio segreto continua a firmare accanto al nuovo per previous_secret_ttl_hours (da 0 a 168; il default dell'API è 24; 0 lo elimina subito), così il ricevitore può passare al nuovo senza perdere eventi. previous_secret_expires_at mostra quando il vecchio segreto smette di valere. Rimuovere public_key elimina solo encrypted_signing_secret; non ruota il segreto.
Limiti e stato
Un endpoint abilitato conta nel limite del piano per ambiente: Free 3, Startup 20, Business 20, Enterprise 50. Creare o abilitare un endpoint in più fallisce con 403 quota_exceeded; disabilita o elimina un altro endpoint, oppure passa a un piano superiore.
KeenAuth disabilita un endpoint che continua a fallire (disabled_by_failure) oppure il cui ricevitore risponde 410 Gone (disabled_by_receiver). Il plan successivo mostra la modifica tornando allo status configurato, e applicandola l'endpoint viene di nuovo abilitato.
Import
Importa con l'ID dell'endpoint o con la sua key:
tofu import keenauth_webhook_endpoint.orders orders
Il segreto di firma non può essere riletto, quindi encrypted_signing_secret è vuoto dopo l'import. Se la tua configurazione imposta public_key, il prossimo apply ruota il segreto e consegna quello nuovo cifrato.
I test di invio, i replay e i nuovi tentativi di consegna sono azioni una tantum, non configurazione. Per questi usa keenauth webhook-endpoints test, replay e deliveries.