mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-10-07 11:18:11 +08:00
Fixes from frontend/backend url separation (#1829)
* Fixes from frontend/backend url separation This fixes the CORS and CSP headers. Also, in thie commit, I removed the cors_supports_credentials config parameter, which was recently introduced. Instead, the logic determines the need to use CORS headers if the web_page_url is set. #1778
This commit is contained in:
@@ -341,9 +341,6 @@ def handle_api_base_url(app, app_config):
|
|||||||
if not api_base_url:
|
if not api_base_url:
|
||||||
return
|
return
|
||||||
|
|
||||||
if api_base_url.endswith("/"):
|
|
||||||
api_base_url = api_base_url[:-1]
|
|
||||||
|
|
||||||
sha256 = hashlib.sha256(api_base_url.encode()).hexdigest()
|
sha256 = hashlib.sha256(api_base_url.encode()).hexdigest()
|
||||||
script_name = f"api_base_url-{sha256}.js"
|
script_name = f"api_base_url-{sha256}.js"
|
||||||
script_path = os.path.join(app.root_path, "../common/web/templates", script_name)
|
script_path = os.path.join(app.root_path, "../common/web/templates", script_name)
|
||||||
|
|||||||
@@ -296,7 +296,7 @@ class CliLaunchServer(Server):
|
|||||||
"application/octet-stream",
|
"application/octet-stream",
|
||||||
]
|
]
|
||||||
Compress(app)
|
Compress(app)
|
||||||
if app_config.server_config.app__cors_supports_credentials or app_config.server_config.app__debug:
|
if app_config.server_config.app__debug:
|
||||||
CORS(app, supports_credentials=True)
|
CORS(app, supports_credentials=True)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -435,7 +435,6 @@ class ServerConfig(BaseConfig):
|
|||||||
self.app__generate_cache_control_headers = dc["app"]["generate_cache_control_headers"]
|
self.app__generate_cache_control_headers = dc["app"]["generate_cache_control_headers"]
|
||||||
self.app__server_timing_headers = dc["app"]["server_timing_headers"]
|
self.app__server_timing_headers = dc["app"]["server_timing_headers"]
|
||||||
self.app__csp_directives = dc["app"]["csp_directives"]
|
self.app__csp_directives = dc["app"]["csp_directives"]
|
||||||
self.app__cors_supports_credentials = dc["app"]["cors_supports_credentials"]
|
|
||||||
self.app__api_base_url = dc["app"]["api_base_url"]
|
self.app__api_base_url = dc["app"]["api_base_url"]
|
||||||
self.app__web_base_url = dc["app"]["web_base_url"]
|
self.app__web_base_url = dc["app"]["web_base_url"]
|
||||||
|
|
||||||
@@ -506,7 +505,6 @@ class ServerConfig(BaseConfig):
|
|||||||
self.check_attr("app__flask_secret_key", (type(None), str))
|
self.check_attr("app__flask_secret_key", (type(None), str))
|
||||||
self.check_attr("app__generate_cache_control_headers", bool)
|
self.check_attr("app__generate_cache_control_headers", bool)
|
||||||
self.check_attr("app__server_timing_headers", bool)
|
self.check_attr("app__server_timing_headers", bool)
|
||||||
self.check_attr("app__cors_supports_credentials", bool)
|
|
||||||
self.check_attr("app__csp_directives", (type(None), dict))
|
self.check_attr("app__csp_directives", (type(None), dict))
|
||||||
self.check_attr("app__api_base_url", (type(None), str))
|
self.check_attr("app__api_base_url", (type(None), str))
|
||||||
self.check_attr("app__web_base_url", (type(None), str))
|
self.check_attr("app__web_base_url", (type(None), str))
|
||||||
@@ -758,6 +756,8 @@ class ServerConfig(BaseConfig):
|
|||||||
def get_api_base_url(self):
|
def get_api_base_url(self):
|
||||||
if self.app__api_base_url == "local":
|
if self.app__api_base_url == "local":
|
||||||
return f"http://{self.app__host}:{self.app__port}"
|
return f"http://{self.app__host}:{self.app__port}"
|
||||||
|
if self.app__api_base_url and self.app__api_base_url.endswith("/"):
|
||||||
|
return self.app__api_base_url[:-1]
|
||||||
return self.app__api_base_url
|
return self.app__api_base_url
|
||||||
|
|
||||||
def get_web_base_url(self):
|
def get_web_base_url(self):
|
||||||
@@ -765,7 +765,9 @@ class ServerConfig(BaseConfig):
|
|||||||
return f"http://{self.app__host}:{self.app__port}"
|
return f"http://{self.app__host}:{self.app__port}"
|
||||||
if self.app__web_base_url is None:
|
if self.app__web_base_url is None:
|
||||||
return self.get_api_base_url()
|
return self.get_api_base_url()
|
||||||
return self.app__web_base_url
|
if self.app__web_base_url.endswith("/"):
|
||||||
|
return self.app__web_base_url[:-1]
|
||||||
|
return self.api__web_base_url
|
||||||
|
|
||||||
|
|
||||||
class DatasetConfig(BaseConfig):
|
class DatasetConfig(BaseConfig):
|
||||||
|
|||||||
@@ -14,11 +14,6 @@ server:
|
|||||||
server_timing_headers: false
|
server_timing_headers: false
|
||||||
csp_directives: null
|
csp_directives: null
|
||||||
|
|
||||||
# CORS: Cross Origin Resource Sharing. If true, this allow users to make
|
|
||||||
# authenticated requests. This allows cookies and credentials to be submitted
|
|
||||||
# across domains
|
|
||||||
cors_supports_credentials: false
|
|
||||||
|
|
||||||
# By default, cellxgene will serve api requests from the same base url as the webpage.
|
# By default, cellxgene will serve api requests from the same base url as the webpage.
|
||||||
# In general api_base_url and web_base_url will not need to be set.
|
# In general api_base_url and web_base_url will not need to be set.
|
||||||
# There are two reasons to set these parameters:
|
# There are two reasons to set these parameters:
|
||||||
|
|||||||
+18
-2
@@ -4,10 +4,11 @@ import sys
|
|||||||
import os
|
import os
|
||||||
import hashlib
|
import hashlib
|
||||||
import base64
|
import base64
|
||||||
|
from urllib.parse import urlparse
|
||||||
from flask import json
|
from flask import json
|
||||||
import logging
|
import logging
|
||||||
from flask_talisman import Talisman
|
from flask_talisman import Talisman
|
||||||
|
from flask_cors import CORS
|
||||||
from server.common.aws_secret_utils import handle_config_from_secret
|
from server.common.aws_secret_utils import handle_config_from_secret
|
||||||
from server.common.errors import SecretKeyRetrievalError
|
from server.common.errors import SecretKeyRetrievalError
|
||||||
|
|
||||||
@@ -41,6 +42,14 @@ class WSGIServer(Server):
|
|||||||
def _before_adding_routes(app, app_config):
|
def _before_adding_routes(app, app_config):
|
||||||
script_hashes = WSGIServer.get_csp_hashes(app, app_config)
|
script_hashes = WSGIServer.get_csp_hashes(app, app_config)
|
||||||
server_config = app_config.server_config
|
server_config = app_config.server_config
|
||||||
|
|
||||||
|
# add the api_base_url to the connect_src csp header.
|
||||||
|
extra_connect_src = []
|
||||||
|
api_base_url = server_config.get_api_base_url()
|
||||||
|
if api_base_url:
|
||||||
|
parse_api_base_url = urlparse(api_base_url)
|
||||||
|
extra_connect_src = [f"{parse_api_base_url.scheme}://{parse_api_base_url.netloc}"]
|
||||||
|
|
||||||
# This hash should be in sync with the script within
|
# This hash should be in sync with the script within
|
||||||
# `client/configuration/webpack/obsoleteHTMLTemplate.html`
|
# `client/configuration/webpack/obsoleteHTMLTemplate.html`
|
||||||
|
|
||||||
@@ -51,7 +60,7 @@ class WSGIServer(Server):
|
|||||||
obsolete_browser_script_hash = ["'sha256-/rmgOi/skq9MpiZxPv6lPb1PNSN+Uf4NaUHO/IjyfwM='"]
|
obsolete_browser_script_hash = ["'sha256-/rmgOi/skq9MpiZxPv6lPb1PNSN+Uf4NaUHO/IjyfwM='"]
|
||||||
csp = {
|
csp = {
|
||||||
"default-src": ["'self'"],
|
"default-src": ["'self'"],
|
||||||
"connect-src": ["'self'"],
|
"connect-src": ["'self'"] + extra_connect_src,
|
||||||
"script-src": ["'self'", "'unsafe-eval'"]
|
"script-src": ["'self'", "'unsafe-eval'"]
|
||||||
+ obsolete_browser_script_hash + script_hashes,
|
+ obsolete_browser_script_hash + script_hashes,
|
||||||
"style-src": ["'self'", "'unsafe-inline'"],
|
"style-src": ["'self'", "'unsafe-inline'"],
|
||||||
@@ -70,6 +79,13 @@ class WSGIServer(Server):
|
|||||||
v = [v]
|
v = [v]
|
||||||
csp[k] = csp.get(k, []) + v
|
csp[k] = csp.get(k, []) + v
|
||||||
|
|
||||||
|
# Add the web_base_url to the CORS header
|
||||||
|
web_base_url = server_config.get_web_base_url()
|
||||||
|
if web_base_url:
|
||||||
|
web_base_url_parse = urlparse(web_base_url)
|
||||||
|
allowed_origin = f"{web_base_url_parse.scheme}://{web_base_url_parse.netloc}"
|
||||||
|
CORS(app, supports_credentials=True, origins=allowed_origin)
|
||||||
|
|
||||||
Talisman(
|
Talisman(
|
||||||
app, force_https=server_config.app__force_https, frame_options="DENY", content_security_policy=csp,
|
app, force_https=server_config.app__force_https, frame_options="DENY", content_security_policy=csp,
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user