feat: use keying for webhook secrets (#10059)

- Follow up of forgejo/forgejo!5041, forgejo/forgejo!6074, forgejo/forgejo!8692, forgejo/forgejo!9923
- The `webhook` table contains a encrypted header authorization.
- Use `keying` to safely store this secret and bound them to the table, column and row id
- The migration isn't spectacular but does closely follow what we learned in the previous three migrations: use a transaction and delete records when you can't decrypt them.

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/10059
Reviewed-by: Mathieu Fenniak <mfenniak@noreply.codeberg.org>
Reviewed-by: oliverpool <oliverpool@noreply.codeberg.org>
Co-authored-by: Gusted <postmaster@gusted.xyz>
Co-committed-by: Gusted <postmaster@gusted.xyz>
This commit is contained in:
Gusted 2025-12-22 15:51:37 +01:00 committed by Gusted
parent aa4a597b21
commit 4e83f85b75
11 changed files with 258 additions and 57 deletions

View file

@ -102,9 +102,7 @@ func TestWebhookDeliverAuthorizationHeader(t *testing.T) {
IsActive: true,
Type: webhook_module.GITEA,
}
err := hook.SetHeaderAuthorization("Bearer s3cr3t-t0ken")
require.NoError(t, err)
require.NoError(t, webhook_model.CreateWebhook(db.DefaultContext, hook))
require.NoError(t, webhook_model.CreateWebhook(t.Context(), hook, "Bearer s3cr3t-t0ken"))
hookTask := &webhook_model.HookTask{
HookID: hook.ID,
@ -112,7 +110,7 @@ func TestWebhookDeliverAuthorizationHeader(t *testing.T) {
PayloadVersion: 2,
}
hookTask, err = webhook_model.CreateHookTask(db.DefaultContext, hookTask)
hookTask, err := webhook_model.CreateHookTask(db.DefaultContext, hookTask)
require.NoError(t, err)
assert.NotNil(t, hookTask)
@ -168,7 +166,7 @@ func TestWebhookDeliverHookTask(t *testing.T) {
ContentType: webhook_model.ContentTypeJSON,
Meta: `{"message_type":0}`, // text
}
require.NoError(t, webhook_model.CreateWebhook(db.DefaultContext, hook))
require.NoError(t, webhook_model.CreateWebhook(db.DefaultContext, hook, ""))
t.Run("Version 1", func(t *testing.T) {
hookTask := &webhook_model.HookTask{
@ -296,7 +294,7 @@ func TestWebhookDeliverSpecificTypes(t *testing.T) {
ContentType: 0, // set to 0 so that falling back to default request fails with "invalid content type"
Meta: "{}",
}
require.NoError(t, webhook_model.CreateWebhook(db.DefaultContext, hook))
require.NoError(t, webhook_model.CreateWebhook(db.DefaultContext, hook, ""))
hookTask := &webhook_model.HookTask{
HookID: hook.ID,