From 3fb65e02852fb2b24872cc7a156e062e20835385 Mon Sep 17 00:00:00 2001 From: Hein Date: Fri, 20 Feb 2026 15:33:53 +0200 Subject: [PATCH] feat(hook): add AllowInsecure option for TLS verification * Introduced AllowInsecure field in Hook configuration to skip TLS certificate verification. * Updated database schema and models to support the new field. * Modified HTTP client behavior based on AllowInsecure setting. --- pkg/config/config.go | 17 +++++++++-------- pkg/hooks/manager.go | 15 ++++++++++++++- pkg/models/sql_public_hooks.go | 1 + pkg/storage/db.go | 4 +++- pkg/whatshooked/whatshooked.go | 13 +++++++------ sql/postgres/001_init_schema.up.sql | 1 + sql/schema.dbml | 1 + sql/sqlite/001_init_schema.sql | 1 + 8 files changed, 37 insertions(+), 16 deletions(-) diff --git a/pkg/config/config.go b/pkg/config/config.go index 7463089..3b6f48a 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -70,14 +70,15 @@ type BusinessAPIConfig struct { // Hook represents a registered webhook type Hook struct { - ID string `json:"id"` - Name string `json:"name"` - URL string `json:"url"` - Method string `json:"method"` - Headers map[string]string `json:"headers,omitempty"` - Active bool `json:"active"` - Events []string `json:"events,omitempty"` - Description string `json:"description,omitempty"` + ID string `json:"id"` + Name string `json:"name"` + URL string `json:"url"` + Method string `json:"method"` + Headers map[string]string `json:"headers,omitempty"` + Active bool `json:"active"` + Events []string `json:"events,omitempty"` + Description string `json:"description,omitempty"` + AllowInsecure bool `json:"allow_insecure,omitempty"` // Skip TLS certificate verification } // DatabaseConfig holds database connection information diff --git a/pkg/hooks/manager.go b/pkg/hooks/manager.go index a7f8b07..e7fd0d6 100644 --- a/pkg/hooks/manager.go +++ b/pkg/hooks/manager.go @@ -3,6 +3,7 @@ package hooks import ( "bytes" "context" + "crypto/tls" "encoding/json" "fmt" "io" @@ -335,6 +336,18 @@ func (m *Manager) sendToHook(ctx context.Context, hook config.Hook, payload inte eventCtx = context.Background() } + // Select the appropriate HTTP client. If the hook allows insecure TLS, use a + // dedicated client that skips certificate verification; otherwise use the shared client. + httpClient := m.client + if hook.AllowInsecure { + httpClient = &http.Client{ + Timeout: 30 * time.Second, + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, //nolint:gosec // intentional: user opted in via AllowInsecure + }, + } + } + // Publish hook triggered event m.eventBus.Publish(events.HookTriggeredEvent(eventCtx, hook.ID, hook.Name, hook.URL, payload)) @@ -391,7 +404,7 @@ func (m *Manager) sendToHook(ctx context.Context, hook config.Hook, payload inte logging.Debug("Sending to hook", "hook_id", hook.ID, "url", hook.URL) - resp, err := m.client.Do(req) + resp, err := httpClient.Do(req) if err != nil { logging.Error("Failed to send to hook", "hook_id", hook.ID, "error", err) m.eventBus.Publish(events.HookFailedEvent(eventCtx, hook.ID, hook.Name, err)) diff --git a/pkg/models/sql_public_hooks.go b/pkg/models/sql_public_hooks.go index 9486451..a468df3 100644 --- a/pkg/models/sql_public_hooks.go +++ b/pkg/models/sql_public_hooks.go @@ -11,6 +11,7 @@ type ModelPublicHook struct { bun.BaseModel `bun:"table:hooks,alias:hooks"` ID resolvespec_common.SqlString `bun:"id,type:varchar(36),pk," json:"id"` // UUID Active bool `bun:"active,type:boolean,default:true,notnull," json:"active"` + AllowInsecure bool `bun:"allow_insecure,type:boolean,default:false,notnull," json:"allow_insecure"` // Skip TLS certificate verification CreatedAt resolvespec_common.SqlTime `bun:"created_at,type:timestamp,default:now(),notnull," json:"created_at"` DeletedAt resolvespec_common.SqlTime `bun:"deleted_at,type:timestamp,nullzero," json:"deleted_at"` Description resolvespec_common.SqlString `bun:"description,type:text,nullzero," json:"description"` diff --git a/pkg/storage/db.go b/pkg/storage/db.go index 247fc5d..1507c0e 100644 --- a/pkg/storage/db.go +++ b/pkg/storage/db.go @@ -141,8 +141,10 @@ func createTablesSQLite(ctx context.Context) error { headers TEXT, events TEXT, active BOOLEAN NOT NULL DEFAULT 1, + allow_insecure BOOLEAN NOT NULL DEFAULT 0, retry_count INTEGER NOT NULL DEFAULT 3, - timeout_seconds INTEGER NOT NULL DEFAULT 30, + timeout INTEGER NOT NULL DEFAULT 30, + secret VARCHAR(255), description TEXT, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, diff --git a/pkg/whatshooked/whatshooked.go b/pkg/whatshooked/whatshooked.go index 9355f24..eba7ba7 100644 --- a/pkg/whatshooked/whatshooked.go +++ b/pkg/whatshooked/whatshooked.go @@ -226,12 +226,13 @@ func (wh *WhatsHooked) loadHooksFromDatabase(ctx context.Context) error { configHooks := make([]config.Hook, 0, len(dbHooks)) for _, dbHook := range dbHooks { hook := config.Hook{ - ID: dbHook.ID.String(), - Name: dbHook.Name.String(), - URL: dbHook.URL.String(), - Method: dbHook.Method.String(), - Description: dbHook.Description.String(), - Active: dbHook.Active, + ID: dbHook.ID.String(), + Name: dbHook.Name.String(), + URL: dbHook.URL.String(), + Method: dbHook.Method.String(), + Description: dbHook.Description.String(), + Active: dbHook.Active, + AllowInsecure: dbHook.AllowInsecure, } // Parse headers JSON if present diff --git a/sql/postgres/001_init_schema.up.sql b/sql/postgres/001_init_schema.up.sql index 58d066c..519f9dc 100644 --- a/sql/postgres/001_init_schema.up.sql +++ b/sql/postgres/001_init_schema.up.sql @@ -34,6 +34,7 @@ CREATE TABLE IF NOT EXISTS public.api_keys ( CREATE TABLE IF NOT EXISTS public.hooks ( active boolean NOT NULL DEFAULT true, + allow_insecure boolean NOT NULL DEFAULT false, created_at timestamp NOT NULL DEFAULT now(), deleted_at timestamp, description text, diff --git a/sql/schema.dbml b/sql/schema.dbml index 62ea228..ef1c233 100644 --- a/sql/schema.dbml +++ b/sql/schema.dbml @@ -47,6 +47,7 @@ Table hooks { headers text [note: 'JSON encoded headers'] events text [note: 'JSON array of event types'] active boolean [not null, default: true] + allow_insecure boolean [not null, default: false, note: 'Skip TLS certificate verification'] description text secret varchar(255) [note: 'HMAC signature secret'] retry_count int [not null, default: 3] diff --git a/sql/sqlite/001_init_schema.sql b/sql/sqlite/001_init_schema.sql index cd2a17d..3764971 100644 --- a/sql/sqlite/001_init_schema.sql +++ b/sql/sqlite/001_init_schema.sql @@ -51,6 +51,7 @@ CREATE TABLE IF NOT EXISTS hooks ( retry_count INTEGER NOT NULL DEFAULT 3, timeout INTEGER NOT NULL DEFAULT 30, active BOOLEAN NOT NULL DEFAULT 1, + allow_insecure BOOLEAN NOT NULL DEFAULT 0, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, deleted_at TIMESTAMP,