Skip to content

Commit 619c7e9

Browse files
committed
feat: redact potentially sensitive headers in the webhook resource
1 parent abccf7a commit 619c7e9

File tree

4 files changed

+56
-6
lines changed

4 files changed

+56
-6
lines changed

lib/pact_broker/api/decorators/webhook_request_decorator.rb

+5-1
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,15 @@ class WebhookRequestDecorator < BaseDecorator
77

88
property :method
99
property :url
10-
property :headers, getter: lambda { | _ | headers.empty? ? nil : headers }
10+
property :headers, getter: lambda { | _ | headers.empty? ? nil : self.redacted_headers }
1111
property :body
1212
property :username
1313
property :password, getter: lambda { | _ | display_password }
1414

15+
16+
def redacted_headers
17+
represented.headers
18+
end
1519
end
1620
end
1721
end

lib/pact_broker/domain/webhook_request.rb

+11-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
require 'pact_broker/logging'
55
require 'pact_broker/messages'
66
require 'net/http'
7-
require 'pact_broker/webhooks/redact_logs'
87
require 'pact_broker/webhooks/render'
98
require 'pact_broker/api/pact_broker_urls'
109
require 'pact_broker/build_http_options'
@@ -27,6 +26,7 @@ class WebhookRequest
2726

2827
include PactBroker::Logging
2928
include PactBroker::Messages
29+
HEADERS_TO_REDACT = [/authorization/i, /token/i]
3030

3131
attr_accessor :method, :url, :headers, :body, :username, :password, :uuid
3232

@@ -52,6 +52,13 @@ def display_password
5252
password.nil? ? nil : "**********"
5353
end
5454

55+
def redacted_headers
56+
headers.each_with_object({}) do | (name, value), new_headers |
57+
redact = HEADERS_TO_REDACT.any?{ | pattern | name =~ pattern }
58+
new_headers[name] = redact ? "**********" : value
59+
end
60+
end
61+
5562
def execute pact, verification, options = {}
5663
logs = StringIO.new
5764
execution_logger = Logger.new(logs)
@@ -84,8 +91,9 @@ def build_request uri, pact, verification, execution_logger
8491
req = http_request(uri)
8592
execution_logger.info "HTTP/1.1 #{method.upcase} #{url_with_credentials(pact, verification)}"
8693

94+
headers_to_log = redacted_headers
8795
headers.each_pair do | name, value |
88-
execution_logger.info Webhooks::RedactLogs.call("#{name}: #{value}")
96+
execution_logger.info "#{name}: #{headers_to_log[name]}"
8997
req[name] = value
9098
end
9199

@@ -166,7 +174,7 @@ def log_error e, execution_logger, options
166174
end
167175

168176
def to_s
169-
"#{method.upcase} #{url}, username=#{username}, password=#{display_password}, headers=#{headers}, body=#{body}"
177+
"#{method.upcase} #{url}, username=#{username}, password=#{display_password}, headers=#{redacted_headers}, body=#{body}"
170178
end
171179

172180
def http_request(uri)

spec/lib/pact_broker/api/decorators/webhook_decorator_spec.rb

+7
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ module Decorators
8888
expect(parsed_json[:request]).to_not have_key :headers
8989
end
9090
end
91+
92+
context 'when the headers contain sensitve information' do
93+
let(:headers) { { 'Authorization' => 'foo' } }
94+
it 'redacts them' do
95+
expect(parsed_json[:request][:headers][:'Authorization']).to eq "**********"
96+
end
97+
end
9198
end
9299

93100
describe 'from_json' do

spec/lib/pact_broker/domain/webhook_request_spec.rb

+33-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ module Domain
1616
let(:username) { nil }
1717
let(:password) { nil }
1818
let(:url) { 'http://example.org/hook' }
19+
let(:headers) { {'Content-Type' => 'text/plain', 'Authorization' => 'foo'} }
1920
let(:body) { 'body' }
2021
let(:logs) { StringIO.new }
2122
let(:execution_logger) { Logger.new(logs) }
@@ -29,7 +30,7 @@ module Domain
2930
WebhookRequest.new(
3031
method: 'post',
3132
url: url,
32-
headers: {'Content-Type' => 'text/plain', 'Authorization' => 'foo'},
33+
headers: headers,
3334
username: username,
3435
password: password,
3536
body: body)
@@ -58,6 +59,36 @@ module Domain
5859
end
5960
end
6061

62+
describe "redacted_headers" do
63+
let(:headers) do
64+
{
65+
'Authorization' => 'foo',
66+
'X-authorization' => 'bar',
67+
'token' => 'bar',
68+
'Token' => 'bar',
69+
'X-Auth-Token' => 'bar',
70+
'X-Authorization-Token' => 'bar',
71+
'OK' => 'ok'
72+
}
73+
end
74+
75+
let(:expected_headers) do
76+
{
77+
'Authorization' => '**********',
78+
'X-authorization' => '**********',
79+
'token' => '**********',
80+
'Token' => '**********',
81+
'X-Auth-Token' => '**********',
82+
'X-Authorization-Token' => '**********',
83+
'OK' => 'ok'
84+
}
85+
end
86+
87+
it "redacts sensitive headers" do
88+
expect(subject.redacted_headers).to eq expected_headers
89+
end
90+
end
91+
6192
describe "execute" do
6293
let!(:http_request) do
6394
stub_request(:post, "http://example.org/hook").
@@ -126,7 +157,7 @@ module Domain
126157
end
127158

128159
it "redacts potentially sensitive headers" do
129-
expect(logs).to include "Authorization: [REDACTED]"
160+
expect(logs).to include "Authorization: **********"
130161
end
131162

132163
it "logs the request body" do

0 commit comments

Comments
 (0)