Commit e44c0183 authored by Douglas Barbosa Alexandre's avatar Douglas Barbosa Alexandre

Merge branch 'csp-websocket-support' into 'master'

Adding websocket origins to connect-src to support Safari

See merge request gitlab-org/gitlab!70932
parents e026940c 383e747d
...@@ -35,6 +35,10 @@ module Gitlab ...@@ -35,6 +35,10 @@ module Gitlab
# However Safari seems to read child-src first so we'll just keep both equal # However Safari seems to read child-src first so we'll just keep both equal
directives['child_src'] = directives['frame_src'] directives['child_src'] = directives['frame_src']
# connect_src with 'self' includes https/wss variations of the origin,
# however, safari hasn't covered this yet and we need to explicitly add
# support for websocket origins until Safari catches up with the specs
allow_websocket_connections(directives)
allow_webpack_dev_server(directives) if Rails.env.development? allow_webpack_dev_server(directives) if Rails.env.development?
allow_cdn(directives, Settings.gitlab.cdn_host) if Settings.gitlab.cdn_host.present? allow_cdn(directives, Settings.gitlab.cdn_host) if Settings.gitlab.cdn_host.present?
allow_customersdot(directives) if Rails.env.development? && ENV['CUSTOMER_PORTAL_URL'].present? allow_customersdot(directives) if Rails.env.development? && ENV['CUSTOMER_PORTAL_URL'].present?
...@@ -67,6 +71,22 @@ module Gitlab ...@@ -67,6 +71,22 @@ module Gitlab
arguments.strip.split(' ').map(&:strip) arguments.strip.split(' ').map(&:strip)
end end
def self.allow_websocket_connections(directives)
http_ports = [80, 443]
host = Gitlab.config.gitlab.host
port = Gitlab.config.gitlab.port
secure = Gitlab.config.gitlab.https
protocol = secure ? 'wss' : 'ws'
ws_url = "#{protocol}://#{host}"
unless http_ports.include?(port)
ws_url = "#{ws_url}:#{port}"
end
append_to_directive(directives, 'connect_src', ws_url)
end
def self.allow_webpack_dev_server(directives) def self.allow_webpack_dev_server(directives)
secure = Settings.webpack.dev_server['https'] secure = Settings.webpack.dev_server['https']
host_and_port = "#{Settings.webpack.dev_server['host']}:#{Settings.webpack.dev_server['port']}" host_and_port = "#{Settings.webpack.dev_server['host']}:#{Settings.webpack.dev_server['port']}"
......
...@@ -11,6 +11,7 @@ RSpec.describe Gitlab::ContentSecurityPolicy::ConfigLoader do ...@@ -11,6 +11,7 @@ RSpec.describe Gitlab::ContentSecurityPolicy::ConfigLoader do
directives: { directives: {
base_uri: 'http://example.com', base_uri: 'http://example.com',
child_src: "'self' https://child.example.com", child_src: "'self' https://child.example.com",
connect_src: "'self' ws://example.com",
default_src: "'self' https://other.example.com", default_src: "'self' https://other.example.com",
script_src: "'self' https://script.exammple.com ", script_src: "'self' https://script.exammple.com ",
worker_src: "data: https://worker.example.com", worker_src: "data: https://worker.example.com",
...@@ -52,6 +53,28 @@ RSpec.describe Gitlab::ContentSecurityPolicy::ConfigLoader do ...@@ -52,6 +53,28 @@ RSpec.describe Gitlab::ContentSecurityPolicy::ConfigLoader do
expect(directives['child_src']).to eq(directives['frame_src']) expect(directives['child_src']).to eq(directives['frame_src'])
end end
context 'adds all websocket origins to support Safari' do
it 'with insecure domain' do
stub_config_setting(host: 'example.com', https: false)
expect(directives['connect_src']).to eq("'self' ws://example.com")
end
it 'with secure domain' do
stub_config_setting(host: 'example.com', https: true)
expect(directives['connect_src']).to eq("'self' wss://example.com")
end
it 'with custom port' do
stub_config_setting(host: 'example.com', port: '1234')
expect(directives['connect_src']).to eq("'self' ws://example.com:1234")
end
it 'with custom port and secure domain' do
stub_config_setting(host: 'example.com', https: true, port: '1234')
expect(directives['connect_src']).to eq("'self' wss://example.com:1234")
end
end
context 'when CDN host is defined' do context 'when CDN host is defined' do
before do before do
stub_config_setting(cdn_host: 'https://example.com') stub_config_setting(cdn_host: 'https://example.com')
...@@ -67,10 +90,11 @@ RSpec.describe Gitlab::ContentSecurityPolicy::ConfigLoader do ...@@ -67,10 +90,11 @@ RSpec.describe Gitlab::ContentSecurityPolicy::ConfigLoader do
context 'when sentry is configured' do context 'when sentry is configured' do
before do before do
stub_sentry_settings stub_sentry_settings
stub_config_setting(host: 'example.com')
end end
it 'adds sentry path to CSP without user' do it 'adds sentry path to CSP without user' do
expect(directives['connect_src']).to eq("'self' dummy://example.com/43") expect(directives['connect_src']).to eq("'self' ws://example.com dummy://example.com/43")
end end
end end
...@@ -113,6 +137,7 @@ RSpec.describe Gitlab::ContentSecurityPolicy::ConfigLoader do ...@@ -113,6 +137,7 @@ RSpec.describe Gitlab::ContentSecurityPolicy::ConfigLoader do
expect(policy.directives['base-uri']).to eq([csp_config[:directives][:base_uri]]) expect(policy.directives['base-uri']).to eq([csp_config[:directives][:base_uri]])
expect(policy.directives['default-src']).to eq(expected_config(:default_src)) expect(policy.directives['default-src']).to eq(expected_config(:default_src))
expect(policy.directives['connect-src']).to eq(expected_config(:connect_src))
expect(policy.directives['child-src']).to eq(expected_config(:child_src)) expect(policy.directives['child-src']).to eq(expected_config(:child_src))
expect(policy.directives['worker-src']).to eq(expected_config(:worker_src)) expect(policy.directives['worker-src']).to eq(expected_config(:worker_src))
expect(policy.directives['report-uri']).to eq(expected_config(:report_uri)) expect(policy.directives['report-uri']).to eq(expected_config(:report_uri))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment