mirror of
https://github.com/apache/superset.git
synced 2026-06-01 05:39:17 +00:00
fix(embedding): require non-default JWT secret when embedded dashboards are enabled (#39999)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -51,7 +51,7 @@ from sqlalchemy.orm.query import Query
|
||||
from superset.advanced_data_type.plugins.internet_address import internet_address
|
||||
from superset.advanced_data_type.plugins.internet_port import internet_port
|
||||
from superset.advanced_data_type.types import AdvancedDataType
|
||||
from superset.constants import CHANGE_ME_SECRET_KEY
|
||||
from superset.constants import CHANGE_ME_GUEST_TOKEN_JWT_SECRET, CHANGE_ME_SECRET_KEY
|
||||
from superset.jinja_context import BaseTemplateProcessor
|
||||
from superset.key_value.types import JsonKeyValueCodec
|
||||
from superset.stats_logger import DummyStatsLogger
|
||||
@@ -2354,7 +2354,7 @@ GLOBAL_ASYNC_QUERIES_CACHE_BACKEND = {
|
||||
|
||||
# Embedded config options
|
||||
GUEST_ROLE_NAME = "Public"
|
||||
GUEST_TOKEN_JWT_SECRET = "test-guest-secret-change-me" # noqa: S105
|
||||
GUEST_TOKEN_JWT_SECRET = CHANGE_ME_GUEST_TOKEN_JWT_SECRET
|
||||
GUEST_TOKEN_JWT_ALGO = "HS256" # noqa: S105
|
||||
GUEST_TOKEN_HEADER_NAME = "X-GuestToken" # noqa: S105
|
||||
GUEST_TOKEN_JWT_EXP_SECONDS = 300 # 5 minutes
|
||||
|
||||
@@ -28,6 +28,7 @@ NULL_STRING = "<NULL>"
|
||||
EMPTY_STRING = "<empty string>"
|
||||
|
||||
CHANGE_ME_SECRET_KEY = "CHANGE_ME_TO_A_COMPLEX_RANDOM_SECRET" # noqa: S105
|
||||
CHANGE_ME_GUEST_TOKEN_JWT_SECRET = "test-guest-secret-change-me" # noqa: S105
|
||||
|
||||
# UUID for the examples database
|
||||
EXAMPLES_DB_UUID = "a2dc77af-e654-49bb-b321-40f6b559a1ee"
|
||||
|
||||
@@ -37,7 +37,7 @@ from flask_compress import Compress
|
||||
from flask_session import Session
|
||||
from werkzeug.middleware.proxy_fix import ProxyFix
|
||||
|
||||
from superset.constants import CHANGE_ME_SECRET_KEY
|
||||
from superset.constants import CHANGE_ME_GUEST_TOKEN_JWT_SECRET, CHANGE_ME_SECRET_KEY
|
||||
from superset.databases.utils import make_url_safe
|
||||
from superset.extensions import (
|
||||
_event_logger,
|
||||
@@ -634,12 +634,17 @@ class SupersetAppInitializer: # pylint: disable=too-many-public-methods
|
||||
|
||||
self.init_all_dependencies_and_extensions()
|
||||
|
||||
@staticmethod
|
||||
def _log_config_warning(message: str) -> None:
|
||||
top_banner = 80 * "-" + "\n" + 36 * " " + "WARNING\n" + 80 * "-"
|
||||
bottom_banner = 80 * "-" + "\n" + 80 * "-"
|
||||
logger.warning(top_banner)
|
||||
logger.warning(message)
|
||||
logger.warning(bottom_banner)
|
||||
|
||||
def check_secret_key(self) -> None:
|
||||
def log_default_secret_key_warning() -> None:
|
||||
top_banner = 80 * "-" + "\n" + 36 * " " + "WARNING\n" + 80 * "-"
|
||||
bottom_banner = 80 * "-" + "\n" + 80 * "-"
|
||||
logger.warning(top_banner)
|
||||
logger.warning(
|
||||
if self.config["SECRET_KEY"] == CHANGE_ME_SECRET_KEY:
|
||||
warning = (
|
||||
"A Default SECRET_KEY was detected, please use superset_config.py "
|
||||
"to override it.\n"
|
||||
"Use a strong complex alphanumeric string and use a tool to help"
|
||||
@@ -648,21 +653,44 @@ class SupersetAppInitializer: # pylint: disable=too-many-public-methods
|
||||
"For more info, see: https://superset.apache.org/docs/"
|
||||
"configuration/configuring-superset#specifying-a-secret_key"
|
||||
)
|
||||
logger.warning(bottom_banner)
|
||||
|
||||
if self.config["SECRET_KEY"] == CHANGE_ME_SECRET_KEY:
|
||||
if (
|
||||
self.superset_app.debug
|
||||
or self.superset_app.config["TESTING"]
|
||||
or is_test()
|
||||
):
|
||||
logger.warning("Debug mode identified with default secret key")
|
||||
log_default_secret_key_warning()
|
||||
self._log_config_warning(warning)
|
||||
return
|
||||
log_default_secret_key_warning()
|
||||
self._log_config_warning(warning)
|
||||
logger.error("Refusing to start due to insecure SECRET_KEY")
|
||||
sys.exit(1)
|
||||
|
||||
def check_guest_token_secret(self) -> None:
|
||||
"""Refuse to start with default guest JWT secret when embedding is enabled."""
|
||||
if not feature_flag_manager.is_feature_enabled("EMBEDDED_SUPERSET"):
|
||||
return
|
||||
if (
|
||||
self.config.get("GUEST_TOKEN_JWT_SECRET")
|
||||
!= CHANGE_ME_GUEST_TOKEN_JWT_SECRET
|
||||
):
|
||||
return
|
||||
self._log_config_warning(
|
||||
"EMBEDDED_SUPERSET is enabled but GUEST_TOKEN_JWT_SECRET has not "
|
||||
"been changed from its default value.\n"
|
||||
"The default value is publicly known and must be replaced before "
|
||||
"running in production.\n"
|
||||
"Set a strong random value in superset_config.py:\n"
|
||||
" GUEST_TOKEN_JWT_SECRET = "
|
||||
"'<output of: openssl rand -base64 42>'"
|
||||
)
|
||||
if self.superset_app.debug or self.superset_app.config["TESTING"] or is_test():
|
||||
return
|
||||
logger.error(
|
||||
"Refusing to start: insecure GUEST_TOKEN_JWT_SECRET "
|
||||
"with EMBEDDED_SUPERSET enabled"
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
def configure_session(self) -> None:
|
||||
if self.config["SESSION_SERVER_SIDE"]:
|
||||
Session(self.superset_app)
|
||||
@@ -747,6 +775,7 @@ class SupersetAppInitializer: # pylint: disable=too-many-public-methods
|
||||
# Configuration of feature_flags must be done first to allow init features
|
||||
# conditionally
|
||||
self.configure_feature_flags()
|
||||
self.check_guest_token_secret()
|
||||
self.configure_db_encrypt()
|
||||
self.setup_db()
|
||||
|
||||
|
||||
@@ -3529,14 +3529,14 @@ class SupersetSecurityManager( # pylint: disable=too-many-public-methods
|
||||
r for r in user.resources if r["type"] == GuestTokenResourceType.DASHBOARD
|
||||
]
|
||||
|
||||
if not dashboard.embedded:
|
||||
return False
|
||||
|
||||
# TODO (embedded): remove this check once uuids are rolled out
|
||||
for resource in dashboards:
|
||||
if str(resource["id"]) == str(dashboard.id):
|
||||
return True
|
||||
|
||||
if not dashboard.embedded:
|
||||
return False
|
||||
|
||||
for resource in dashboards:
|
||||
if str(resource["id"]) == str(dashboard.embedded[0].uuid):
|
||||
return True
|
||||
|
||||
Reference in New Issue
Block a user