From e0ba74a542bed9274c05b2e6d33d093d0253beed Mon Sep 17 00:00:00 2001 From: Ben Reinhart Date: Wed, 7 Apr 2021 16:38:01 -0700 Subject: [PATCH 1/2] feat: Make async query JWT cookie domain configurable --- CONTRIBUTING.md | 1 + docs/installation.rst | 1 + superset/config.py | 1 + superset/utils/async_query_manager.py | 3 +++ 4 files changed, 6 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b0358add264ee..3e83ef02e208b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1278,6 +1278,7 @@ The following configuration settings are available for async queries (see config - `GLOBAL_ASYNC_QUERIES_REDIS_STREAM_LIMIT_FIREHOSE` - the maximum number of events for all users (FIFO eviction) - `GLOBAL_ASYNC_QUERIES_JWT_COOKIE_NAME` - the async query feature uses a [JWT](https://tools.ietf.org/html/rfc7519) cookie for authentication, this setting is the cookie's name - `GLOBAL_ASYNC_QUERIES_JWT_COOKIE_SECURE` - JWT cookie secure option +- `GLOBAL_ASYNC_QUERIES_JWT_COOKIE_DOMAIN` - JWT cookie domain option ([see docs for set_cookie](https://tedboy.github.io/flask/interface_api.response_object.html#flask.Response.set_cookie)) - `GLOBAL_ASYNC_QUERIES_JWT_SECRET` - JWT's use a secret key to sign and validate the contents. This value should be at least 32 bytes and have sufficient randomness for proper security - `GLOBAL_ASYNC_QUERIES_TRANSPORT` - currently the only available option is (HTTP) `polling`, but support for a WebSocket will be added in future versions - `GLOBAL_ASYNC_QUERIES_POLLING_DELAY` - the time (in ms) between polling requests diff --git a/docs/installation.rst b/docs/installation.rst index d93e7b6193503..dcbbf88f38b3e 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -1133,6 +1133,7 @@ The following configuration settings are available for async queries (see config - ``GLOBAL_ASYNC_QUERIES_REDIS_STREAM_LIMIT_FIREHOSE`` - the maximum number of events for all users (FIFO eviction) - ``GLOBAL_ASYNC_QUERIES_JWT_COOKIE_NAME`` - the async query feature uses a `JWT `_ cookie for authentication, this setting is the cookie's name - ``GLOBAL_ASYNC_QUERIES_JWT_COOKIE_SECURE`` - JWT cookie secure option +- ``GLOBAL_ASYNC_QUERIES_JWT_COOKIE_DOMAIN`` - JWT cookie domain option (`see docs for set_cookie ` - ``GLOBAL_ASYNC_QUERIES_JWT_SECRET`` - JWT's use a secret key to sign and validate the contents. This value should be at least 32 bytes and have sufficient randomness for proper security - ``GLOBAL_ASYNC_QUERIES_TRANSPORT`` - currently the only available option is (HTTP) `polling`, but support for a WebSocket will be added in future versions - ``GLOBAL_ASYNC_QUERIES_POLLING_DELAY`` - the time (in ms) between polling requests diff --git a/superset/config.py b/superset/config.py index 1d9da94df460e..09c6240fbbf4e 100644 --- a/superset/config.py +++ b/superset/config.py @@ -1141,6 +1141,7 @@ class CeleryConfig: # pylint: disable=too-few-public-methods GLOBAL_ASYNC_QUERIES_REDIS_STREAM_LIMIT_FIREHOSE = 1000000 GLOBAL_ASYNC_QUERIES_JWT_COOKIE_NAME = "async-token" GLOBAL_ASYNC_QUERIES_JWT_COOKIE_SECURE = False +GLOBAL_ASYNC_QUERIES_JWT_COOKIE_DOMAIN = None GLOBAL_ASYNC_QUERIES_JWT_SECRET = "test-secret-change-me" GLOBAL_ASYNC_QUERIES_TRANSPORT = "polling" GLOBAL_ASYNC_QUERIES_POLLING_DELAY = 500 diff --git a/superset/utils/async_query_manager.py b/superset/utils/async_query_manager.py index f005ba114cf35..08ea6c85d5f23 100644 --- a/superset/utils/async_query_manager.py +++ b/superset/utils/async_query_manager.py @@ -75,6 +75,7 @@ def __init__(self) -> None: self._stream_limit_firehose: Optional[int] self._jwt_cookie_name: str self._jwt_cookie_secure: bool = False + self._jwt_cookie_domain: Optional[str] self._jwt_secret: str def init_app(self, app: Flask) -> None: @@ -105,6 +106,7 @@ def init_app(self, app: Flask) -> None: ] self._jwt_cookie_name = config["GLOBAL_ASYNC_QUERIES_JWT_COOKIE_NAME"] self._jwt_cookie_secure = config["GLOBAL_ASYNC_QUERIES_JWT_COOKIE_SECURE"] + self._jwt_cookie_domain = config["GLOBAL_ASYNC_QUERIES_JWT_COOKIE_DOMAIN"] self._jwt_secret = config["GLOBAL_ASYNC_QUERIES_JWT_SECRET"] @app.after_request @@ -133,6 +135,7 @@ def validate_session( # pylint: disable=unused-variable value=token, httponly=True, secure=self._jwt_cookie_secure, + domain=self._jwt_cookie_domain, ) return response From e00363a468aa761753110ad627c80ba3bc10033e Mon Sep 17 00:00:00 2001 From: Ben Reinhart Date: Wed, 7 Apr 2021 16:50:59 -0700 Subject: [PATCH 2/2] Disable too many instance attributes --- superset/utils/async_query_manager.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/superset/utils/async_query_manager.py b/superset/utils/async_query_manager.py index 08ea6c85d5f23..77373b685765d 100644 --- a/superset/utils/async_query_manager.py +++ b/superset/utils/async_query_manager.py @@ -61,6 +61,8 @@ def increment_id(redis_id: str) -> str: class AsyncQueryManager: + # pylint: disable=too-many-instance-attributes + MAX_EVENT_COUNT = 100 STATUS_PENDING = "pending" STATUS_RUNNING = "running"