Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
87585e5
Replace SecureHeaders CSP tooling with built in Rails tooling
jmhooper Dec 27, 2021
46f02d8
add another TODO
jmhooper Dec 27, 2021
b5c72df
Merge branch 'main' into jmhooper-integrate-secure-headers
jmhooper Jan 7, 2022
bf7415b
move everything into 1 before action
jmhooper Jan 7, 2022
7265ad9
use rails CSP tooling on document capture step
jmhooper Jan 7, 2022
9002dd5
more like "TO DONE" amirite?
jmhooper Jan 7, 2022
78b6b8e
fix secure header invocation in template
jmhooper Jan 7, 2022
be7dfee
TODO note
jmhooper Jan 7, 2022
832c217
use opt out config
jmhooper Jan 7, 2022
8ddd50c
Merge branch 'main' into jmhooper-integrate-secure-headers
jmhooper Jan 14, 2022
29fdd54
add webpacker rules
jmhooper Jan 14, 2022
ad88fce
Been doing this over a decade and I swear to god how do I keep making…
jmhooper Jan 14, 2022
b6c2bb6
cleanup connect source
jmhooper Jan 14, 2022
18e88a2
re-add unsafe-eval in development
jmhooper Jan 14, 2022
d868776
comment out unsafe-inline / unsafe-eval and see what CI does
jmhooper Jan 14, 2022
5557487
clean up lint issue
jmhooper Jan 14, 2022
a688dba
put unsafe-eval back
jmhooper Jan 14, 2022
884b92d
slim up delta between test/production CSP
jmhooper Jan 14, 2022
0234e07
delint
jmhooper Jan 14, 2022
db74cdf
Merge branch 'main' into jmhooper-integrate-secure-headers
jmhooper Jan 21, 2022
31915da
try using dev tools in test
jmhooper Jan 21, 2022
10d9ee4
whooops
jmhooper Jan 21, 2022
b178ca4
delint
jmhooper Jan 21, 2022
76ba500
test cleanup and re-add the remove CSP middleware
jmhooper Jan 21, 2022
33d3831
fix last of the tests
jmhooper Jan 21, 2022
2cafd98
Merge branch 'main' into jmhooper-integrate-secure-headers
jmhooper Jan 21, 2022
6a923e8
cleanup from merge
jmhooper Jan 21, 2022
0c96530
reducing diff noise
jmhooper Jan 21, 2022
9fbe192
PULL THE LEVER, KRONK
jmhooper Jan 21, 2022
89540b2
a little re-organizing
jmhooper Jan 21, 2022
3ef6e29
whoops
jmhooper Jan 21, 2022
786509e
Add the default nonce generator
jmhooper Jan 22, 2022
2ae9357
some cleanup to break into a separate PR
jmhooper Jan 22, 2022
98772e2
Merge branch 'main' into jmhooper-integrate-secure-headers
jmhooper Jan 24, 2022
84f59ff
use the current_content_security_policy method
jmhooper Jan 24, 2022
3ccad15
fix document capature template test
jmhooper Jan 24, 2022
36d99d2
fix document capture concern issue
jmhooper Jan 24, 2022
c85e462
fix saml idp controller
jmhooper Jan 24, 2022
2fe8529
delint
jmhooper Jan 24, 2022
2332f79
mailer preview and unsafe inline
jmhooper Jan 24, 2022
c35cf30
Merge branch 'main' into jmhooper-integrate-secure-headers
jmhooper Jan 24, 2022
fb45906
i know how conditionals work
jmhooper Jan 25, 2022
c2ccd20
Merge branch 'main' into jmhooper-integrate-secure-headers
jmhooper Jan 25, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions app/controllers/concerns/idv/document_capture_concern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ module DocumentCaptureConcern
def override_document_capture_step_csp
return if params[:step] != 'document_capture'

if FeatureManagement.rails_csp_tooling_enabled?
override_document_capture_step_csp_with_rails_csp_tooling
else
override_document_capture_step_csp_with_secure_headers
end
end

def override_document_capture_step_csp_with_secure_headers
SecureHeaders.append_content_security_policy_directives(
request,
# required to run wasm until wasm-eval is available
Expand All @@ -13,5 +21,13 @@ def override_document_capture_step_csp
img_src: ['blob:'],
)
end

def override_document_capture_step_csp_with_rails_csp_tooling
policy = current_content_security_policy
policy.script_src(*policy.script_src, :unsafe_eval)
policy.style_src(*policy.style_src, :unsafe_inline)
policy.img_src(*policy.img_src, 'blob:')
request.content_security_policy = policy
end
end
end
5 changes: 1 addition & 4 deletions app/controllers/concerns/piv_cac_concern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,7 @@ def piv_session
end

def set_piv_cac_setup_csp_form_action_uris
override_content_security_policy_directives(
form_action: piv_cac_setup_csp_form_action_uris,
preserve_schemes: true,
)
override_form_action_csp(piv_cac_setup_csp_form_action_uris)
end

def piv_cac_setup_csp_form_action_uris
Expand Down
22 changes: 17 additions & 5 deletions app/controllers/concerns/secure_headers_concern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,31 @@ def apply_secure_headers_override
return if stored_url_for_user.blank?

authorize_form = OpenidConnectAuthorizeForm.new(authorize_params)

return unless authorize_form.valid?

override_csp_with_uris
override_form_action_csp(csp_uris)
end

def override_form_action_csp(uris)
if FeatureManagement.rails_csp_tooling_enabled?
apply_secure_headers_override_with_rails_csp_tooling(uris)
else
apply_secure_headers_override_with_secure_headers(uris)
end
end

def override_csp_with_uris
def apply_secure_headers_override_with_secure_headers(uris)
override_content_security_policy_directives(
form_action: csp_uris,
preserve_schemes: true,
form_action: uris,
)
end

def apply_secure_headers_override_with_rails_csp_tooling(uris)
policy = current_content_security_policy
policy.form_action(*uris)
request.content_security_policy = policy
end

def csp_uris
return ["'self'"] if stored_url_for_user.blank?
# Returns fully formed CSP array w/"'self'" and redirect_uris
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/openid_connect/authorization_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class AuthorizationController < ApplicationController
before_action :sign_out_if_prompt_param_is_login_and_user_is_signed_in, only: [:index]
before_action :store_request, only: [:index]
before_action :check_sp_active, only: [:index]
before_action :override_csp_with_uris, only: [:index]
before_action :apply_secure_headers_override, only: [:index]
before_action :confirm_user_is_authenticated_with_fresh_mfa, only: :index
before_action :prompt_for_password_if_ial2_request_and_pii_locked, only: [:index]
before_action :bump_auth_count, only: [:index]
Expand Down
3 changes: 2 additions & 1 deletion app/controllers/saml_idp_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class SamlIdpController < ApplicationController
include VerifyProfileConcern
include AuthorizationCountConcern
include BillableEventTrackable
include SecureHeadersConcern

prepend_before_action :skip_session_load, only: :metadata
prepend_before_action :skip_session_expiration, only: :metadata
Expand Down Expand Up @@ -118,7 +119,7 @@ def render_template_for(message, action_url, type)
csp_uris = SecureHeadersAllowList.csp_with_sp_redirect_uris(
action_url, decorated_session.sp_redirect_uris
)
override_content_security_policy_directives(form_action: csp_uris)
override_form_action_csp(csp_uris)

render(
template: 'saml_idp/shared/saml_post_binding',
Expand Down
34 changes: 34 additions & 0 deletions app/helpers/secure_headers_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
module SecureHeadersHelper
def backwards_compatible_javascript_tag(*args, **opts, &block)
if FeatureManagement.rails_csp_tooling_enabled?
javascript_tag(*args, opts.merge(nonce: true), &block)
else
nonced_javascript_tag(*args, **opts, &block)
end
end

def add_document_capture_image_urls_to_csp(request, urls)
cleaned_urls = urls.compact.map do |url|
URI(url).tap { |uri| uri.query = nil }.to_s
end

if FeatureManagement.rails_csp_tooling_enabled?
add_document_capture_image_urls_to_csp_with_rails_csp_tooling(request, cleaned_urls)
else
add_document_capture_image_urls_to_csp_with_secure_headers(request, cleaned_urls)
end
end

def add_document_capture_image_urls_to_csp_with_secure_headers(request, urls)
SecureHeaders.append_content_security_policy_directives(
request,
connect_src: urls,
)
end

def add_document_capture_image_urls_to_csp_with_rails_csp_tooling(request, urls)
policy = request.content_security_policy.clone
policy.connect_src(*policy.connect_src, *urls)
request.content_security_policy = policy
end
end
13 changes: 3 additions & 10 deletions app/views/idv/shared/_document_capture.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,10 @@
<%= tag.meta name: 'acuant-sdk-initialization-creds', content: IdentityConfig.store.acuant_sdk_initialization_creds %>
<%= stylesheet_link_tag 'document-capture' %>
<% end %>
<% SecureHeaders.append_content_security_policy_directives(
<% add_document_capture_image_urls_to_csp(
request,
connect_src: [
front_image_upload_url,
back_image_upload_url,
selfie_image_upload_url,
].
compact.
map { |url| URI(url).tap { |uri| uri.query = nil }.to_s },
[front_image_upload_url, back_image_upload_url, selfie_image_upload_url],
)

session_id = flow_session[:document_capture_session_uuid]
%>
<%= tag.div id: 'document-capture-form', data: {
Expand Down Expand Up @@ -147,7 +140,7 @@
) %>
</div>

<%= nonced_javascript_tag do %>
<%= backwards_compatible_javascript_tag do %>
<% asset_keys = [
'close-white-alt.svg',
'id-card.svg',
Expand Down
2 changes: 1 addition & 1 deletion app/views/layouts/base.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
) %>


<%= nonced_javascript_tag do %>
<%= backwards_compatible_javascript_tag do %>
document.documentElement.className = document.documentElement.className.replace(/\bno-js\b/, 'js');
<% end %>
<%= preload_link_tag font_url('identity-style-guide/dist/assets/fonts/source-sans-pro/sourcesanspro-regular-webfont.woff2') %>
Expand Down
2 changes: 1 addition & 1 deletion app/views/shared/_banner.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
</div>
</div>
<div class="usa-banner__content usa-accordion__content" id="gov-banner">
<%= nonced_javascript_tag do %>
<%= backwards_compatible_javascript_tag do %>
document.getElementById('gov-banner').setAttribute('hidden', '');
<% end %>
<div class="grid-row grid-gap-lg">
Expand Down
2 changes: 1 addition & 1 deletion app/views/shared/_dap_analytics.html.erb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!-- <%= t('notices.dap_participation') %> -->
<% dap_source = 'https://dap.digitalgov.gov/Universal-Federated-Analytics-Min.js?agency=GSA&subagency=TTS' %>
<%= nonced_javascript_tag({ src: dap_source, async: true, id: '_fed_an_ua_tag' }) do %>
<%= backwards_compatible_javascript_tag({ src: dap_source, async: true, id: '_fed_an_ua_tag' }) do %>
<% end %>
2 changes: 1 addition & 1 deletion app/views/shared/_failure.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,5 @@
<% presenter.next_steps.each do |step| %>
<p><%== step %></p>
<% end; if presenter.js %>
<%= nonced_javascript_tag presenter.js %>
<%= backwards_compatible_javascript_tag presenter.js %>
<% end %>
Loading