diff --git a/settings.py b/settings.py index bfbb766bea..27efbe0e9b 100644 --- a/settings.py +++ b/settings.py @@ -78,6 +78,8 @@ DOMAIN = SERVICES_DOMAIN = urlparse(SITE_URL).netloc SERVICES_URL = SITE_URL INTERNAL_SITE_URL = 'http://nginx' EXTERNAL_SITE_URL = SITE_URL +STATIC_URL = '%s/static/' % EXTERNAL_SITE_URL +MEDIA_URL = '%s/user-media/' % EXTERNAL_SITE_URL CODE_MANAGER_URL = ( os.environ.get('CODE_MANAGER_URL') or 'http://olympia.test:5000') @@ -136,10 +138,15 @@ USE_FAKE_FXA_AUTH = True CSP_REPORT_URI = '/csp-report' RESTRICTED_DOWNLOAD_CSP['REPORT_URI'] = CSP_REPORT_URI -# Allow GA over http + www subdomain in local development. +# Set CSP like we do for dev/stage/prod, but also allow GA over http + www subdomain +# for local development. HTTP_GA_SRC = 'http://www.google-analytics.com' -CSP_IMG_SRC += (HTTP_GA_SRC,) -CSP_SCRIPT_SRC += (HTTP_GA_SRC, "'self'") + +CSP_CONNECT_SRC += (SITE_URL,) +CSP_FONT_SRC += (STATIC_URL,) +CSP_IMG_SRC += (MEDIA_URL, STATIC_URL, HTTP_GA_SRC) +CSP_SCRIPT_SRC += (STATIC_URL, HTTP_GA_SRC) +CSP_STYLE_SRC += (STATIC_URL,) # Auth token required to authorize inbound email. INBOUND_EMAIL_SECRET_KEY = 'totally-unsecure-secret-string' diff --git a/src/olympia/amo/tests/test_csp_headers.py b/src/olympia/amo/tests/test_csp_headers.py index aa530de28d..7d8fabd7ed 100644 --- a/src/olympia/amo/tests/test_csp_headers.py +++ b/src/olympia/amo/tests/test_csp_headers.py @@ -78,13 +78,19 @@ class TestCSPHeaders(TestCase): """Check frame-src directive has same settings as child-src""" assert base_settings.CSP_FRAME_SRC == base_settings.CSP_CHILD_SRC - def test_prod_cdn_in_common_settings(self): + def test_prod_static_url_in_common_settings(self): """Make sure prod cdn is specified by default for statics.""" - prod_cdn_host = base_settings.PROD_CDN_HOST - assert prod_cdn_host in base_settings.CSP_FONT_SRC - assert prod_cdn_host in base_settings.CSP_IMG_SRC - assert prod_cdn_host in base_settings.CSP_SCRIPT_SRC - assert prod_cdn_host in base_settings.CSP_STYLE_SRC + prod_static_url = base_settings.PROD_STATIC_URL + assert prod_static_url in base_settings.CSP_FONT_SRC + assert prod_static_url in base_settings.CSP_IMG_SRC + assert prod_static_url in base_settings.CSP_SCRIPT_SRC + assert prod_static_url in base_settings.CSP_STYLE_SRC + + prod_media_url = base_settings.PROD_MEDIA_URL + assert prod_media_url not in base_settings.CSP_FONT_SRC + assert prod_media_url in base_settings.CSP_IMG_SRC + assert prod_media_url not in base_settings.CSP_SCRIPT_SRC + assert prod_media_url not in base_settings.CSP_STYLE_SRC def test_self_in_common_settings(self): """Check 'self' is defined for common settings.""" diff --git a/src/olympia/conf/prod/settings.py b/src/olympia/conf/prod/settings.py index 72a7c70d2d..445f32cf0d 100644 --- a/src/olympia/conf/prod/settings.py +++ b/src/olympia/conf/prod/settings.py @@ -16,7 +16,6 @@ ENV = env('ENV') API_THROTTLING = True -CDN_HOST = 'https://addons.cdn.mozilla.net' DOMAIN = env('DOMAIN', default='addons.mozilla.org') SERVER_EMAIL = 'zprod@addons.mozilla.org' SITE_URL = 'https://' + DOMAIN @@ -24,8 +23,12 @@ INTERNAL_SITE_URL = env('INTERNAL_SITE_URL', default='https://addons.mozilla.org EXTERNAL_SITE_URL = env('EXTERNAL_SITE_URL', default='https://addons.mozilla.org') SERVICES_URL = env('SERVICES_URL', default='https://services.addons.mozilla.org') CODE_MANAGER_URL = env('CODE_MANAGER_URL', default='https://code.addons.mozilla.org') -STATIC_URL = '%s/static/' % CDN_HOST -MEDIA_URL = '%s/user-media/' % CDN_HOST +CDN_HOST = 'https://addons.cdn.mozilla.net' +STATIC_URL = PROD_STATIC_URL +MEDIA_URL = PROD_MEDIA_URL +# user_media_url('addons') will use ADDONS_URL setting if present to build URLs +# to xpi files. We want those on the dedicated CDN domain. +ADDONS_URL = '%s/user-media/addons/' % CDN_HOST SESSION_COOKIE_DOMAIN = '.%s' % DOMAIN diff --git a/src/olympia/conf/stage/settings.py b/src/olympia/conf/stage/settings.py index a19b5744ab..1253731d54 100644 --- a/src/olympia/conf/stage/settings.py +++ b/src/olympia/conf/stage/settings.py @@ -1,17 +1,6 @@ from olympia.lib.settings_base import * # noqa -CSP_BASE_URI += ( - # Required for the legacy discovery pane. - 'https://addons.allizom.org', -) -CDN_HOST = 'https://addons-stage-cdn.allizom.org' -CSP_CONNECT_SRC += (CDN_HOST,) -CSP_FONT_SRC += (CDN_HOST,) -CSP_IMG_SRC += (CDN_HOST,) -CSP_SCRIPT_SRC += (CDN_HOST,) -CSP_STYLE_SRC += (CDN_HOST,) - ENGAGE_ROBOTS = False EMAIL_URL = env.email_url('EMAIL_URL') @@ -32,8 +21,20 @@ INTERNAL_SITE_URL = env('INTERNAL_SITE_URL', default='https://addons.allizom.org EXTERNAL_SITE_URL = env('EXTERNAL_SITE_URL', default='https://addons.allizom.org') SERVICES_URL = env('SERVICES_URL', default='https://services.addons.allizom.org') CODE_MANAGER_URL = env('CODE_MANAGER_URL', default='https://code.addons.allizom.org') -STATIC_URL = '%s/static/' % CDN_HOST -MEDIA_URL = '%s/user-media/' % CDN_HOST +CDN_HOST = 'https://addons-stage-cdn.allizom.org' +STATIC_URL = '%s/static-server/' % EXTERNAL_SITE_URL +MEDIA_URL = '%s/user-media/' % EXTERNAL_SITE_URL +# user_media_url('addons') will use ADDONS_URL setting if present to build URLs +# to xpi files. We want those on the dedicated CDN domain. +ADDONS_URL = '%s/user-media/addons/' % CDN_HOST + +CSP_CONNECT_SRC += (SITE_URL,) +CSP_FONT_SRC += (STATIC_URL,) +# CSP_IMG_SRC already contains 'self', but we could be on reviewers or admin +# domain and want to load things from the regular domain. +CSP_IMG_SRC += (MEDIA_URL, STATIC_URL) +CSP_SCRIPT_SRC += (STATIC_URL,) +CSP_STYLE_SRC += (STATIC_URL,) SESSION_COOKIE_DOMAIN = '.%s' % DOMAIN diff --git a/src/olympia/lib/settings_base.py b/src/olympia/lib/settings_base.py index 1c2d073720..c6b6c4428f 100644 --- a/src/olympia/lib/settings_base.py +++ b/src/olympia/lib/settings_base.py @@ -220,6 +220,11 @@ SERVICES_URL = 'http://%s' % SERVICES_DOMAIN # https://github.com/mozilla/addons-code-manager CODE_MANAGER_URL = f'https://code.{DOMAIN}' +# Static and media URL for prod are hardcoded here to allow them to be set in +# the base CSP shared by all envs. +PROD_STATIC_URL = 'https://addons.mozilla.org/static/' +PROD_MEDIA_URL = 'https://addons.mozilla.org/user-media/' + # Filter IP addresses of allowed clients that can post email through the API. ALLOWED_CLIENTS_EMAIL_API = env.list('ALLOWED_CLIENTS_EMAIL_API', default=[]) # Auth token required to authorize inbound email. @@ -1263,7 +1268,6 @@ LOGGING = { # CSP Settings -PROD_CDN_HOST = 'https://addons.cdn.mozilla.net' ANALYTICS_HOST = 'https://www.google-analytics.com' CSP_REPORT_URI = '/__cspreport__' @@ -1273,21 +1277,16 @@ CSP_EXCLUDE_URL_PREFIXES = () # NOTE: CSP_DEFAULT_SRC MUST be set otherwise things not set # will default to being open to anything. CSP_DEFAULT_SRC = ("'self'",) -CSP_BASE_URI = ( - "'self'", - # Required for the legacy discovery pane. - 'https://addons.mozilla.org', -) +CSP_BASE_URI = ("'self'",) CSP_CONNECT_SRC = ( "'self'", 'https://sentry.prod.mozaws.net', ANALYTICS_HOST, - PROD_CDN_HOST, ) CSP_FORM_ACTION = ("'self'",) CSP_FONT_SRC = ( "'self'", - PROD_CDN_HOST, + PROD_STATIC_URL, ) CSP_CHILD_SRC = ( "'self'", @@ -1299,7 +1298,8 @@ CSP_IMG_SRC = ( "'self'", 'data:', # Used in inlined mobile css. 'blob:', # Needed for image uploads. - PROD_CDN_HOST, + PROD_STATIC_URL, + PROD_MEDIA_URL, 'https://static.addons.mozilla.net', # CDN origin server. 'https://sentry.prod.mozaws.net', ) @@ -1312,12 +1312,12 @@ CSP_SCRIPT_SRC = ( 'https://www.recaptcha.net/recaptcha/', 'https://www.gstatic.com/recaptcha/', 'https://www.gstatic.cn/recaptcha/', - PROD_CDN_HOST, + PROD_STATIC_URL, ) CSP_STYLE_SRC = ( "'self'", "'unsafe-inline'", - PROD_CDN_HOST, + PROD_STATIC_URL, ) RESTRICTED_DOWNLOAD_CSP = {