Skip to content

Commit

Permalink
allow only to configure response temaplet via configuration or ENV va…
Browse files Browse the repository at this point in the history
…riables
  • Loading branch information
GustavoCaso committed Aug 25, 2023
1 parent 5bac2ba commit 848c156
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 57 deletions.
40 changes: 17 additions & 23 deletions lib/datadog/appsec/configuration/settings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def self.extended(base)
add_settings!(base)
end

# rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/BlockLength
# rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/BlockLength,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
def self.add_settings!(base)
base.class_eval do
settings :appsec do
Expand Down Expand Up @@ -96,47 +96,41 @@ def self.add_settings!(base)
end

settings :block do
# HTTP status code to block with
option :status do |o|
o.type :int
o.default 403
end

# only applies to redirect status codes
option :location do |o|
o.type :string
o.setter { |v| URI(v) unless v.nil? }
end

# only applies to non-redirect status codes with bodies
settings :templates do
option :html do |o|
o.env 'DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML'
o.type :string
o.type :string, nilable: true
o.setter do |value|
raise(ArgumentError, "appsec.templates.html: file not found: #{value}") unless File.exist?(value)
if value
raise(ArgumentError, "appsec.templates.html: file not found: #{value}") unless File.exist?(value)

File.open(value, 'rb', &:read) || ''
File.open(value, 'rb', &:read) || ''
end
end
end

option :json do |o|
o.env 'DD_APPSEC_HTTP_BLOCKED_TEMPLATE_JSON'
o.type :string
o.type :string, nilable: true
o.setter do |value|
raise(ArgumentError, "appsec.templates.json: file not found: #{value}") unless File.exist?(value)
if value
raise(ArgumentError, "appsec.templates.json: file not found: #{value}") unless File.exist?(value)

File.open(value, 'rb', &:read) || ''
File.open(value, 'rb', &:read) || ''
end
end
end

option :text do |o|
o.env 'DD_APPSEC_HTTP_BLOCKED_TEMPLATE_TEXT'
o.type :string
o.type :string, nilable: true
o.setter do |value|
raise(ArgumentError, "appsec.templates.text: file not found: #{value}") unless File.exist?(value)
if value
raise(ArgumentError, "appsec.templates.text: file not found: #{value}") unless File.exist?(value)

File.open(value, 'rb', &:read) || ''
File.open(value, 'rb', &:read) || ''
end
end
end
end
Expand Down Expand Up @@ -179,7 +173,7 @@ def self.add_settings!(base)
end
end
end
# rubocop:enable Metrics/AbcSize,Metrics/MethodLength,Metrics/BlockLength
# rubocop:enable Metrics/AbcSize,Metrics/MethodLength,Metrics/BlockLength,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
end
end
end
Expand Down
30 changes: 3 additions & 27 deletions lib/datadog/appsec/response.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,12 @@ def negotiate(env)

Datadog.logger.debug { "negotiated response content type: #{content_type}" }

headers = { 'Content-Type' => content_type }
headers['Location'] = location.to_s if redirect?

body = []
body << content(content_type) unless redirect?
body << content(content_type)

Response.new(
status: status,
headers: headers,
status: 403,
headers: { 'Content-Type' => content_type },
body: body,
)
end
Expand All @@ -55,7 +52,6 @@ def negotiate(env)
}.freeze

DEFAULT_CONTENT_TYPE = 'application/json'
REDIRECT_STATUS = [301, 302, 303, 307, 308].freeze

def content_type(env)
return DEFAULT_CONTENT_TYPE unless env.key?('HTTP_ACCEPT')
Expand All @@ -75,29 +71,9 @@ def content_type(env)
DEFAULT_CONTENT_TYPE
end

def status
Datadog.configuration.appsec.block.status
end

def redirect?
REDIRECT_STATUS.include?(status)
end

def location
Datadog.configuration.appsec.block.location
end

def content(content_type)
content_format = CONTENT_TYPE_TO_FORMAT[content_type]

unless content_format
Datadog.logger.debug do
"Unsupported Content Type for blocking response. `#{content_type}` defaulting to text/html"
end

return Datadog::AppSec::Assets.blocked(format: :html)
end

using_default = Datadog.configuration.appsec.block.templates.using_default?(content_format)

if using_default
Expand Down
6 changes: 0 additions & 6 deletions spec/datadog/appsec/configuration/settings_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -632,12 +632,6 @@ def patcher
end
end
end

describe 'location' do
end

describe 'status' do
end
end
end
end
28 changes: 27 additions & 1 deletion spec/datadog/appsec/response_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
end

describe '.status' do
subject(:content_type) { described_class.negotiate(env).status }
subject(:status) { described_class.negotiate(env).status }

it { is_expected.to eq 403 }
end
Expand All @@ -23,22 +23,48 @@
expect(env).to receive(:[]).with('HTTP_ACCEPT').and_return(accept)
end

shared_examples_for 'with custom response body' do |type|
before do
File.write("test.#{type}", 'testing')
Datadog.configuration.appsec.block.templates.send("#{type}=", "test.#{type}")
end

after do
File.delete("test.#{type}")
Datadog.configuration.appsec.reset!
end

it { is_expected.to eq ['testing'] }
end

context 'with unsupported Accept headers' do
let(:accept) { 'application/xml' }

it { is_expected.to eq [Datadog::AppSec::Assets.blocked(format: :json)] }
end

context('with Accept: text/html') do
let(:accept) { 'text/html' }

it { is_expected.to eq [Datadog::AppSec::Assets.blocked(format: :html)] }

it_behaves_like 'with custom response body', :html
end

context('with Accept: application/json') do
let(:accept) { 'application/json' }

it { is_expected.to eq [Datadog::AppSec::Assets.blocked(format: :json)] }

it_behaves_like 'with custom response body', :json
end

context('with Accept: text/plain') do
let(:accept) { 'text/plain' }

it { is_expected.to eq [Datadog::AppSec::Assets.blocked(format: :text)] }

it_behaves_like 'with custom response body', :text
end
end

Expand Down

0 comments on commit 848c156

Please sign in to comment.