Browse Source

Fixes: #4510 - HTTP BasicAuth for Webhooks.

Martin Gruner 1 year ago
parent
commit
16819411ec

+ 4 - 2
app/assets/javascripts/app/models/webhook.coffee

@@ -1,12 +1,14 @@
 class App.Webhook extends App.Model
-  @configure 'Webhook', 'name', 'endpoint', 'signature_token', 'ssl_verify', 'note', 'active'
+  @configure 'Webhook', 'name', 'endpoint', 'signature_token', 'ssl_verify', 'basic_auth_username', 'basic_auth_password', 'note', 'active'
   @extend Spine.Model.Ajax
   @url: @apiPath + '/webhooks'
   @configure_attributes = [
-    { name: 'name',             display: __('Name'),                      tag: 'input',     type: 'text', limit: 100, null: false },
+    { name: 'name',             display: __('Name'),                      tag: 'input',     type: 'text', limit: 250, null: false },
     { name: 'endpoint',         display: __('Endpoint'),                  tag: 'input',     type: 'text', limit: 300, null: false, placeholder: 'https://target.example.com/webhook' },
     { name: 'signature_token',  display: __('HMAC SHA1 Signature Token'), tag: 'input',     type: 'text', limit: 100, null: true },
     { name: 'ssl_verify',       display: __('SSL Verify'),                tag: 'boolean',   null: true, translate: true, options: { true: 'yes', false: 'no'  }, default: true },
+    { name: 'basic_auth_username', display: __('HTTP Basic Authentication Username'), tag: 'input', type: 'text', limit: 250, null: true, item_class: 'formGroup--halfSize' },
+    { name: 'basic_auth_password', display: __('HTTP Basic Authentication Password'), tag: 'input', type: 'text', limit: 250, null: true, item_class: 'formGroup--halfSize' },
     { name: 'note',             display: __('Note'),                      tag: 'textarea', note: '', limit: 250, null: true },
     { name: 'active',           display: __('Active'),                    tag: 'active',    default: true },
     { name: 'updated_at',       display: __('Updated'),                   tag: 'datetime',  readonly: 1 },

+ 2 - 0
app/jobs/trigger_webhook_job.rb

@@ -83,6 +83,8 @@ class TriggerWebhookJob < ApplicationJob
         headers:          headers,
         signature_token:  webhook.signature_token,
         verify_ssl:       webhook.ssl_verify,
+        user:             webhook.basic_auth_username,
+        password:         webhook.basic_auth_password,
         log:              {
           facility: 'webhook',
         },

+ 2 - 0
db/migrate/20120101000010_create_ticket.rb

@@ -542,6 +542,8 @@ class CreateTicket < ActiveRecord::Migration[4.2]
       t.column :endpoint,                   :string, limit: 300,  null: false
       t.column :signature_token,            :string, limit: 200,  null: true
       t.column :ssl_verify,                 :boolean,             null: false, default: true
+      t.column :basic_auth_username,        :string, limit: 250,  null: true
+      t.column :basic_auth_password,        :string, limit: 250,  null: true
       t.column :note,                       :string, limit: 500,  null: true
       t.column :active,                     :boolean,             null: false, default: true
       t.column :updated_by_id,              :integer,             null: false

+ 12 - 0
db/migrate/20230328093547_webhooks_basic_auth.rb

@@ -0,0 +1,12 @@
+# Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/
+
+class WebhooksBasicAuth < ActiveRecord::Migration[6.1]
+  def change
+    # return if it's a new setup
+    return if !Setting.exists?(name: 'system_init_done')
+
+    add_column :webhooks, :basic_auth_username, :string, limit: 250, null: true
+    add_column :webhooks, :basic_auth_password, :string, limit: 250, null: true
+    Webhook.reset_column_information
+  end
+end

+ 8 - 0
i18n/zammad.pot

@@ -5303,6 +5303,14 @@ msgstr ""
 msgid "HTML Sanitizer Processing Timeout"
 msgstr ""
 
+#: app/assets/javascripts/app/models/webhook.coffee
+msgid "HTTP Basic Authentication Password"
+msgstr ""
+
+#: app/assets/javascripts/app/models/webhook.coffee
+msgid "HTTP Basic Authentication Username"
+msgstr ""
+
 #: app/assets/javascripts/app/controllers/widget/http_log.coffee
 msgid "HTTP Log"
 msgstr ""

+ 20 - 0
spec/jobs/trigger_webhook_job_spec.rb

@@ -107,6 +107,26 @@ RSpec.describe TriggerWebhookJob, type: :job do
       end
     end
 
+    context 'with HTTP BasicAuth configured' do
+      let(:webhook) { create(:webhook, endpoint: endpoint, basic_auth_username: 'user', basic_auth_password: 'passw0rd') }
+
+      it 'generates a request with Authorization header' do
+        expect(WebMock).to have_requested(:post, endpoint)
+          .with(body: payload, headers: headers)
+          .with { |req| req.headers['Authorization'] == "Basic #{Base64.strict_encode64('user:passw0rd')}" }
+      end
+    end
+
+    context 'without HTTP BasicAuth configured' do
+      let(:webhook)  { create(:webhook, endpoint: endpoint) }
+
+      it 'generates a request without Authorization header' do
+        expect(WebMock).to have_requested(:post, endpoint)
+          .with(body: payload, headers: headers)
+          .with { |req| !req.headers.key?('Authorization') }
+      end
+    end
+
     context 'when response is not JSON' do
 
       let(:response_body) { 'Thanks!' }