mirror of
https://github.com/apache/superset.git
synced 2026-06-11 18:49:15 +00:00
141 lines
4.8 KiB
Python
141 lines
4.8 KiB
Python
# Licensed to the Apache Software Foundation (ASF) under one
|
|
# or more contributor license agreements. See the NOTICE file
|
|
# distributed with this work for additional information
|
|
# regarding copyright ownership. The ASF licenses this file
|
|
# to you under the Apache License, Version 2.0 (the
|
|
# "License"); you may not use this file except in compliance
|
|
# with the License. You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing,
|
|
# software distributed under the License is distributed on an
|
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
# KIND, either express or implied. See the License for the
|
|
# specific language governing permissions and limitations
|
|
# under the License.
|
|
"""Unit tests for the default async JWT secret startup check."""
|
|
|
|
from unittest.mock import MagicMock
|
|
|
|
import pytest
|
|
from pytest_mock import MockerFixture
|
|
|
|
from superset.constants import CHANGE_ME_GLOBAL_ASYNC_QUERIES_JWT_SECRET
|
|
from superset.initialization import SupersetAppInitializer
|
|
|
|
|
|
def _make_initializer(
|
|
secret: str,
|
|
*,
|
|
debug: bool = False,
|
|
testing: bool = False,
|
|
) -> SupersetAppInitializer:
|
|
initializer = SupersetAppInitializer.__new__(SupersetAppInitializer)
|
|
app = MagicMock()
|
|
app.debug = debug
|
|
app.config = {
|
|
"GLOBAL_ASYNC_QUERIES_JWT_SECRET": secret,
|
|
"TESTING": testing,
|
|
}
|
|
initializer.superset_app = app
|
|
initializer.config = app.config
|
|
return initializer
|
|
|
|
|
|
def test_check_async_query_secret_rejects_default_in_production(
|
|
mocker: MockerFixture,
|
|
) -> None:
|
|
"""A default async secret with GAQ enabled refuses to start in production."""
|
|
mocker.patch(
|
|
"superset.initialization.feature_flag_manager.is_feature_enabled",
|
|
return_value=True,
|
|
)
|
|
mocker.patch("superset.initialization.is_test", return_value=False)
|
|
initializer = _make_initializer(CHANGE_ME_GLOBAL_ASYNC_QUERIES_JWT_SECRET)
|
|
|
|
with pytest.raises(SystemExit):
|
|
initializer.check_async_query_secret()
|
|
|
|
|
|
def test_check_async_query_secret_allows_overridden_secret(
|
|
mocker: MockerFixture,
|
|
) -> None:
|
|
"""A non-default async secret does not block startup."""
|
|
mocker.patch(
|
|
"superset.initialization.feature_flag_manager.is_feature_enabled",
|
|
return_value=True,
|
|
)
|
|
mocker.patch("superset.initialization.is_test", return_value=False)
|
|
initializer = _make_initializer("a-strong-random-secret-value-1234567890")
|
|
|
|
# Should not raise.
|
|
initializer.check_async_query_secret()
|
|
|
|
|
|
def test_check_async_query_secret_skipped_when_gaq_disabled(
|
|
mocker: MockerFixture,
|
|
) -> None:
|
|
"""The check is a no-op when GLOBAL_ASYNC_QUERIES is disabled."""
|
|
mocker.patch(
|
|
"superset.initialization.feature_flag_manager.is_feature_enabled",
|
|
return_value=False,
|
|
)
|
|
mocker.patch("superset.initialization.is_test", return_value=False)
|
|
initializer = _make_initializer(CHANGE_ME_GLOBAL_ASYNC_QUERIES_JWT_SECRET)
|
|
|
|
# Should not raise even with the default secret.
|
|
initializer.check_async_query_secret()
|
|
|
|
|
|
def test_check_async_query_secret_warns_only_in_debug(
|
|
mocker: MockerFixture,
|
|
) -> None:
|
|
"""In debug the default secret warns but does not exit (matches SECRET_KEY)."""
|
|
mocker.patch(
|
|
"superset.initialization.feature_flag_manager.is_feature_enabled",
|
|
return_value=True,
|
|
)
|
|
mocker.patch("superset.initialization.is_test", return_value=False)
|
|
initializer = _make_initializer(
|
|
CHANGE_ME_GLOBAL_ASYNC_QUERIES_JWT_SECRET, debug=True
|
|
)
|
|
|
|
# Should not raise in debug mode.
|
|
initializer.check_async_query_secret()
|
|
|
|
|
|
def test_configure_async_queries_skips_init_with_default_secret(
|
|
mocker: MockerFixture,
|
|
) -> None:
|
|
"""In warn-only modes, async init is skipped so the short default secret cannot
|
|
crash startup via AsyncQueryManager.init_app()'s length check."""
|
|
mocker.patch(
|
|
"superset.initialization.feature_flag_manager.is_feature_enabled",
|
|
return_value=True,
|
|
)
|
|
factory = mocker.patch("superset.initialization.async_query_manager_factory")
|
|
initializer = _make_initializer(
|
|
CHANGE_ME_GLOBAL_ASYNC_QUERIES_JWT_SECRET, debug=True
|
|
)
|
|
|
|
initializer.configure_async_queries()
|
|
|
|
factory.init_app.assert_not_called()
|
|
|
|
|
|
def test_configure_async_queries_inits_with_overridden_secret(
|
|
mocker: MockerFixture,
|
|
) -> None:
|
|
"""A non-default secret proceeds to initialize the async query manager."""
|
|
mocker.patch(
|
|
"superset.initialization.feature_flag_manager.is_feature_enabled",
|
|
return_value=True,
|
|
)
|
|
factory = mocker.patch("superset.initialization.async_query_manager_factory")
|
|
initializer = _make_initializer("a-strong-random-secret-value-1234567890")
|
|
|
|
initializer.configure_async_queries()
|
|
|
|
factory.init_app.assert_called_once_with(initializer.superset_app)
|