Skip to content

Commit

Permalink
Merge pull request #448 from rollbar/secure-headers-2.0
Browse files Browse the repository at this point in the history
Secure headers 2.0
  • Loading branch information
jondeandres committed Apr 27, 2016
2 parents 0ee400b + 3179c67 commit 054a032
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 36 deletions.
2 changes: 1 addition & 1 deletion lib/rollbar/middleware/js.rb
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def js_snippet
end

def script_tag(content, env)
if defined?(::SecureHeaders)
if defined?(::SecureHeaders) && ::SecureHeaders.respond_to?(:content_security_policy_script_nonce)
nonce = ::SecureHeaders.content_security_policy_script_nonce(::Rack::Request.new(env))
script_tag_content = "\n<script type=\"text/javascript\" nonce=\"#{nonce}\">#{content}</script>"
else
Expand Down
12 changes: 6 additions & 6 deletions lib/rollbar/plugin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,6 @@ def load!
end
end

private

def dependency(&block)
dependencies << block
end

def execute(&block)
callables << block
end
Expand All @@ -48,6 +42,12 @@ def execute!(&block)
block.call if load?
end

private

def dependency(&block)
dependencies << block
end

def load?
!loaded && dependencies.all?(&:call)
rescue => e
Expand Down
64 changes: 36 additions & 28 deletions lib/rollbar/plugins/rails.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,53 +17,61 @@
end

Rollbar.plugins.define('rails-rollbar.js') do
dependency { configuration.js_enabled }
dependency { defined?(Rails::VERSION) && Rails::VERSION::MAJOR >= 3 }

execute do
execute! do
module Rollbar
module Js
module Frameworks
# Adds Rollbar::Middleware::Js to the Rails middleware stack
# We need to delay the final insert to the last moment since
# this feature may be disable.
# But we need to prepare the middleware insert now because
# we need to use our Rails railtie initializer in case the
# customer is using SecureHeaders > 3.0
class Rails
def load
if secure_headers?
insert_middleware_after_secure_headers
else
insert_middleware
end
end
def load(plugin)
plugin_execute = plugin_execute_proc(plugin)

def insert_middleware_after_secure_headers
instance = self
return after_secure_headers(&plugin_execute) if secure_headers_middleware?

Rollbar::Railtie.initializer 'rollbar.js.frameworks.rails', :after => 'secure_headers.middleware' do |_app|
instance.insert_middleware
end
plugin_execute.call
end

def insert_middleware
require 'rollbar/middleware/js'

config = {
:options => Rollbar.configuration.js_options,
:enabled => Rollbar.configuration.js_enabled
}
rails_config.middleware.use(::Rollbar::Middleware::Js, config)
def after_secure_headers(&block)
Rollbar::Railtie.initializer('rollbar.js.frameworks.rails', :after => 'secure_headers.middleware', &block)
end

def secure_headers?
defined?(::SecureHeaders)
def plugin_execute_proc(plugin)
proc do
plugin.execute do
return unless Rollbar.configuration.js_enabled
require 'rollbar/middleware/js'

config = {
:options => Rollbar.configuration.js_options,
:enabled => Rollbar.configuration.js_enabled
}
::Rails.configuration.middleware.use(::Rollbar::Middleware::Js, config)
end
end
end

def rails_config
::Rails.configuration
def secure_headers_middleware?
begin
require 'secure_headers'
rescue LoadError
end

defined?(::SecureHeaders::Middleware)
end
end
end
end
end
end

execute do
Rollbar::Js::Frameworks::Rails.new.load
execute! do
Rollbar::Js::Frameworks::Rails.new.load(self)
end
end
31 changes: 30 additions & 1 deletion spec/rollbar/middleware/js_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@
end
end

context 'having a html 200 response and SecureHeaders defined' do
context 'having a html 200 response and SecureHeaders >= 3.0.0 defined' do
let(:body) { [html] }
let(:status) { 200 }
let(:headers) do
Expand All @@ -106,19 +106,48 @@

before do
Object.const_set('SecureHeaders', Module.new)
SecureHeaders.const_set('VERSION', '3.0.0')
allow(SecureHeaders).to receive(:content_security_policy_script_nonce) { 'lorem-ipsum-nonce' }
end

after do
Object.send(:remove_const, 'SecureHeaders')
end

it 'renders the snippet and config in the response with nonce in script tag when SecureHeaders installed' do
res_status, res_headers, response = subject.call(env)
new_body = response.body.join

expect(new_body).to include('<script type="text/javascript" nonce="lorem-ipsum-nonce">')
expect(new_body).to include("var _rollbarConfig = #{config[:options].to_json};")
expect(new_body).to include(snippet)
end
end

context 'having a html 200 response and SecureHeaders < 3.0.0 defined' do
let(:body) { [html] }
let(:status) { 200 }
let(:headers) do
{ 'Content-Type' => content_type }
end

before do
Object.const_set('SecureHeaders', Module.new)
SecureHeaders.const_set('VERSION', '2.4.0')
end

after do
Object.send(:remove_const, 'SecureHeaders')
end

it 'renders the snippet and config in the response without nonce in script tag when too old SecureHeaders installed' do
res_status, res_headers, response = subject.call(env)
new_body = response.body.join

expect(new_body).to include('<script type="text/javascript">')
expect(new_body).to include("var _rollbarConfig = #{config[:options].to_json};")
expect(new_body).to include(snippet)
end
end

context 'having a html 200 response without head', :add_js => false do
Expand Down

0 comments on commit 054a032

Please sign in to comment.