折腾 Superset 4.x,常用配置(config.py 模块暴露了数百个可配置参数)

superset_config.py

Superset 通过其 config.py 模块 暴露了数百个可配置参数。 暴露的变量和对象充当了大部分你可能想要配置、修改和交互的公共接口。 在这个 Python 模块中,你可以找到所有这些参数、合理的默认值,以及以注释形式呈现的丰富文档。

为了配置你的应用,你需要创建自己的配置模块,这样就可以覆盖其中的少量或大量参数。 不要直接修改核心模块,而是应该定义自己的模块(通常是一个名为 superset_config.py 的文件)。 将这个文件添加到你的 PYTHONPATH 中,或者创建一个环境变量 SUPERSET_CONFIG_PATH 来指定 superset_config.py 的完整路径。

例如,如果你在基于 Linux 的系统上直接部署 Superset, 并且你的 superset_config.py 文件位于 /app 目录下,你可以运行:

bash 复制代码
export SUPERSET_CONFIG_PATH=/app/superset_config.py

如果你使用自定义的 Dockerfile,并以官方的 Superset 镜像作为基础镜像, 那么你可以按照以下方式添加你的覆盖配置:

bash 复制代码
COPY --chown=superset superset_config.py /app/
ENV SUPERSET_CONFIG_PATH /app/superset_config.py

Docker Compose 部署通过特定的约定来以不同的方式处理应用程序配置。 具体细节请参考 Docker Compose 小技巧与配置

以下是在你的 superset_config.py 文件中可以设置的部分参数示例:

ini 复制代码
# Superset specific config
ROW_LIMIT = 5000

# Flask App Builder配置
# 你的应用程序密钥将用于安全地签名会话cookie
# 并加密数据库上的敏感信息
# 确保你在部署时使用一个强大的密钥更改此密钥。
# 或者,你可以使用`SUPERSET_SECRET_KEY`环境变量设置它。
# 对于生产环境,你必须设置这个密钥,否则服务器将拒绝启动,
# 并且你会在日志中看到相应的错误。
SECRET_KEY = 'YOUR_OWN_RANDOM_GENERATED_SECRET_KEY'

# 到你的数据库后端的 SQLAlchemy 连接字符串
# 此连接定义了存储你的 superset 元数据(切片、连接、表格、仪表板等)的数据库路径。
# 注意,连接到你想探索的数据源的信息直接在 web UI 中管理
# `check_same_thread=false` 属性确保 sqlite 客户端不会尝试强制执行单线程访问,
# 这在某些边缘情况下可能会有问题
SQLALCHEMY_DATABASE_URI = 'sqlite:////path/to/superset.db?check_same_thread=false'

# Flask-WTF 用于 CSRF 的功能 flag
WTF_CSRF_ENABLED = True
# 添加需要免除 CSRF 保护的端点
WTF_CSRF_EXEMPT_LIST = []
# 一个在一年后过期的 CSRF 令牌
WTF_CSRF_TIME_LIMIT = 60 * 60 * 24 * 365

# 设置此 API 密钥以启用 Mapbox 可视化
MAPBOX_API_KEY = ''

请注意,通常的做法是从核心 superset/config.py 中仅复制和粘贴你想要修改的部分,连同相关的注释,到你自己的 superset_config.py 文件中。

superset/config.py 中定义的所有参数和默认值 都可以在你的本地 superset_config.py 中进行修改。管理员需要仔细阅读该文件,了解哪些配置可以在本地进行调整,以及当前设置的默认值。

由于 superset_config.py 作为 Flask 的配置模块, 它不仅可以用来修改 Flask 自身的设置,还可以修改 Superset 所捆绑的 Flask 扩展, 如 flask-wtfflask-cachingflask-migrateflask-appbuilder。 这些扩展各自提供了复杂的可配置选项。Superset 使用的 Web 框架 Flask App Builder 同样提供了许多配置设置。 更多关于如何配置它的信息,请查阅 Flask App Builder 文档

至少,你可能需要更改 SECRET_KEYSQLALCHEMY_DATABASE_URI。继续阅读以了解更多关于这两个配置的信息。

指定一个 SECRET_KEY

添加一个初始 SECRET_KEY

Superset 需要用户指定的 SECRET_KEY 才能启动。 这一要求是在 2.1.0 版本中添加的, 目的是强制执行安全配置(阅读有关默认 SECRET_KEY 漏洞的安全更新)。 在你的 superset_config.py 文件中添加一个强度高的 SECRET_KEY,例如:

python 复制代码
SECRET_KEY = 'YOUR_OWN_RANDOM_GENERATED_SECRET_KEY'

你可以生成一个健壮的安全密钥,使用 openssl rand -base64 42 这个命令。

使用健壮的密钥
这个密钥将用于安全地签名会话 cookie 以及加密存储在 Superset 应用程序元数据数据库中的敏感信息。 你的部署必须使用一个复杂且独一无二的密钥。

轮换至新的 SECRET_KEY

如果你想更改现有的 SECRET_KEY,将现有的 SECRET_KEY 添加到你的 superset_config.py 文件中,作为 PREVIOUS_SECRET_KEY =,并将你的新密钥设置为SECRET_KEY =。你可以通过以下 命令找到你当前的 SECRET_KEY --- 如果使用 Docker 运行 Superset,从 Superset 应用容器内部执行:

python 复制代码
superset shell
from flask import current_app; print(current_app.config["SECRET_KEY"])

将带有这些值的 superset_config.py 文件保存,然后运行 superset re-encrypt-secrets

配置生产环境的元数据数据库

Superset 需要一个数据库来存储其管理的信息,比如图表、仪表板的定义,以及其他许多内容。

默认情况下,Superset 被配置为使用 SQLite, 这是一个自包含的、单文件数据库,提供了简单快速的启动方式(无需任何安装)。然而,在生产环境中, 由于安全、可扩展性和数据完整性方面的原因,强烈不建议使用 SQLite。 重要的是,只应使用受支持的数据库引擎,并考虑在单独的主机或容器上使用不同的数据库引擎。

Superset 支持以下数据库引擎/版本:

Database Engine Supported Versions
PostgreSQL 10.X, 11.X, 12.X, 13.X, 14.X, 15.X
MySQL 5.7, 8.X

使用以下数据库驱动程序和连接字符串:

Database PyPI package Connection String
PostgreSQL pip install psycopg2 postgresql://<UserName>:<DBPassword>@<Database Host>/<Database Name>
MySQL pip install mysqlclient mysql://<UserName>:<DBPassword>@<Database Host>/<Database Name>

为元数据存储设置正确是超出本指南的范围。我们建议使用托管服务,如 Amazon RDSGoogle Cloud Databases 来处理 服务支持和支持基础设施和备份策略。

superset_config 中设置 SQLALCHEMY_DATABASE_URI 配置键,以适当的连接字符串配置元数据存储。

在 WSGI HTTP 服务器上运行

虽然你可以在 NGINX 或 Apache 上运行 Superset,但我们推荐使用 Gunicorn 的异步模式。 这能够实现令人印象深刻的并发性能,而且安装和配置相对容易。 请参照你首选技术的文档,以一种在你的环境中表现良好的方式来设置这个 Flask WSGI 应用。 以下是一个在生产环境中已知表现良好的异步配置示例:

lua 复制代码
      -w 10 \
      -k gevent \
      --worker-connections 1000 \
      --timeout 120 \
      -b  0.0.0.0:6666 \
      --limit-request-line 0 \
      --limit-request-field_size 0 \
      --statsd-host localhost:8125 \
      "superset.app:create_app()"

参考Gunicorn 文档以获取更多信息。 _请注意,开发 Web 服务器(通过 superset runflask run 运行)并不适用于生产环境使用。

如果你没有使用 Gunicorn, 你可能需要在 superset_config.py 中设置 COMPRESS_REGISTER = False 来禁用 flask-compress 的使用。

目前,Google BigQuery 的 Python SDK 与 gevent 不兼容,这是因为 gevent 对 Python 核心库进行了一些动态的 monkeypatch 操作。 因此,当你在 Superset 上使用 BigQuery 数据源时,必须使用 gunicorn 工作进程类型,而不能使用 gevent

HTTPS 配置

你可以通过负载均衡器或反向代理(如nginx)在上游配置 HTTPS, 并在流量到达 Superset 应用之前完成 SSL/TLS 卸载。 在这种设置下,从 Celery worker(用于 Alerts & Reports 图表快照)产生的本地流量可以从入口点后方通过 http:// URL 访问 Superset。 如果你使用的是官方的 Superset Docker 镜像, 也可以配置Gunicorn 中的 SSL(Python Web 服务器)。

负载均衡器后的配置

如果你在负载均衡器或反向代理(例如 NGINX 或 AWS 上的 ELB)之后运行 Superset, 你可能需要利用健康检查端点,以便负载均衡器知道你的 Superset 实例是否正在运行。 这在 /health 路径下提供,如果 Web 服务器正在运行,将返回包含 "OK" 的 200 响应。

如果负载均衡器插入了 X-Forwarded-For/X-Forwarded-Proto 头, 你应该在 Superset 配置文件(superset_config.py)中设置 ENABLE_PROXY_FIX = True,以提取和使用这些头。

如果反向代理用于提供 SSL 加密,可能需要显式定义 X-Forwarded-Proto。 对于 Apache webserver,可以按照以下方式设置:

arduino 复制代码
RequestHeader set X-Forwarded-Proto "https"

自定义 OAuth2 配置

Superset 基于 Flask-AppBuilder(FAB)构建, 开箱即支持许多提供商(GitHub、Twitter、LinkedIn、Google、Azure等)。 除此之外,Superset 还可以配置以连接到其他支持 "code" 授权的 OAuth2 授权服务器实现。

确保 pip 包Authlib已安装在 webserver 上。

首先,在 Superset 的 superset_config.py 中配置授权。

python 复制代码
from flask_appbuilder.security.manager import AUTH_OAUTH

# 将认证类型设置为 OAuth
AUTH_TYPE = AUTH_OAUTH

OAUTH_PROVIDERS = [
    {   'name':'egaSSO',
        'token_key':'access_token', # access_token_url 响应中的 token 名称
        'icon':'fa-address-card',   # 提供商图标 icon
        'remote_app': {
            'client_id':'myClientId',  # 客户端 ID(标识 Superset 应用)
            'client_secret':'MySecret', # 此客户端 ID 的密钥(标识 Superset 应用)
            'client_kwargs':{
                'scope': 'read'               # 授权范围
            },
            'access_token_method':'POST',    # 调用 access_token_url 的 HTTP Method
            'access_token_params':{        # 调用 access_token_url 的附加参数
                'client_id':'myClientId'
            },
            'jwks_uri':'https://myAuthorizationServe/adfs/discovery/keys', # 可能需要用于生成 token
            'access_token_headers':{    # 调用 access_token_url 的附加 HTTP 头
                'Authorization': 'Basic Base64EncodedClientIdAndSecret'
            },
            'api_base_url':'https://myAuthorizationServer/oauth2AuthorizationServer/',
            'access_token_url':'https://myAuthorizationServer/oauth2AuthorizationServer/token',
            'authorize_url':'https://myAuthorizationServer/oauth2AuthorizationServer/authorize'
        }
    }
]

# 允许用户自助注册,允许从已授权用户创建 Flask 用户
AUTH_USER_REGISTRATION = True

# 默认用户注册的角色
AUTH_USER_REGISTRATION_ROLE = "Public"

然后,创建一个继承自 SupersetSecurityManagerCustomSsoSecurityManager 类, 并重写 oauth_user_info 方法:

python 复制代码
import logging
from superset.security import SupersetSecurityManager

class CustomSsoSecurityManager(SupersetSecurityManager):

    def oauth_user_info(self, provider, response=None):
        logging.debug("Oauth2 provider: {0}.".format(provider))
        if provider == 'egaSSO':
            # 例如,这一行请求使用带有 Bearer 认证的方式向 `base_url + '/' + userDetails` 发送 GET 请求,
            # 并期望授权服务器验证 token,并响应用户详细信息
            me = self.appbuilder.sm.oauth_remotes[provider].get('userDetails').data
            logging.debug("user_data: {0}".format(me))
            return { 'name' : me['name'], 'email' : me['email'], 'id' : me['user_name'], 'username' : me['user_name'], 'first_name':'', 'last_name':''}
    ...

此文件必须与 superset_config.py 位于同一目录下, 文件名为 custom_sso_security_manager.py。 最后,在 superset_config.py 中添加以下 2 行代码:

ini 复制代码
from custom_sso_security_manager import CustomSsoSecurityManager
CUSTOM_SECURITY_MANAGER = CustomSsoSecurityManager

注意事项

  • 当配置 OAuth2 授权提供商时,重定向 URL 将是 https://<superset-webserver>/oauth-authorized/<provider-name>。 例如,对于上述配置,重定向 URL 将是 https://<superset-webserver>/oauth-authorized/egaSSO

  • 如果 OAuth2 授权服务器支持 OpenID Connect 1.0,你可以仅配置其配置文档 URL, 无需提供 api_base_urlaccess_token_urlauthorize_url 和其他必需选项, 如用户信息端点、jwks uri 等。例如:

    python 复制代码
    OAUTH_PROVIDERS = [
      {   'name':'egaSSO',
          'token_key':'access_token', # Name of the token in the response of access_token_url
          'icon':'fa-address-card',   # Icon for the provider
          'remote_app': {
              'client_id':'myClientId',  # Client Id (Identify Superset application)
              'client_secret':'MySecret', # Secret for this Client Id (Identify Superset application)
              'server_metadata_url': 'https://myAuthorizationServer/.well-known/openid-configuration'
          }
      }
    ]

使用 Flask-OIDC 进行 Keycloak 特定配置

如果你使用 Keycloak 作为 OpenID Connect 1.0 提供商, 基于 Authlib 的上述配置可能无法正常工作。 在这种情况下,使用 Flask-OIDC 是一个可行的选项。

确保 pip 包Flask-OIDC 已安装在 Web 服务器上。 使用版本 2.2.0 成功进行了测试。此包需要 Flask-OpenID 作为依赖项。

以下代码定义了一个新的安全管理员。 将其添加到一个新文件中,文件名为 keycloak_security_manager.py, 放置在与你的 superset_config.py 文件相同的目录下。

python 复制代码
from flask_appbuilder.security.manager import AUTH_OID
from superset.security import SupersetSecurityManager
from flask_oidc import OpenIDConnect
from flask_appbuilder.security.views import AuthOIDView
from flask_login import login_user
from urllib.parse import quote
from flask_appbuilder.views import ModelView, SimpleFormView, expose
from flask import (
    redirect,
    request
)
import logging

class OIDCSecurityManager(SupersetSecurityManager):

    def __init__(self, appbuilder):
        super(OIDCSecurityManager, self).__init__(appbuilder)
        if self.auth_type == AUTH_OID:
            self.oid = OpenIDConnect(self.appbuilder.get_app)
        self.authoidview = AuthOIDCView

class AuthOIDCView(AuthOIDView):

    @expose('/login/', methods=['GET', 'POST'])
    def login(self, flag=True):
        sm = self.appbuilder.sm
        oidc = sm.oid

        @self.appbuilder.sm.oid.require_login
        def handle_login():
            user = sm.auth_user_oid(oidc.user_getfield('email'))

            if user is None:
                info = oidc.user_getinfo(['preferred_username', 'given_name', 'family_name', 'email'])
                user = sm.add_user(info.get('preferred_username'), info.get('given_name'), info.get('family_name'),
                                   info.get('email'), sm.find_role('Gamma'))

            login_user(user, remember=False)
            return redirect(self.appbuilder.get_url_for_index)

        return handle_login()

    @expose('/logout/', methods=['GET', 'POST'])
    def logout(self):
        oidc = self.appbuilder.sm.oid

        oidc.logout()
        super(AuthOIDCView, self).logout()
        redirect_url = request.url_root.strip('/') + self.appbuilder.get_url_for_login

        return redirect(
            oidc.client_secrets.get('issuer') + '/protocol/openid-connect/logout?redirect_uri=' + quote(redirect_url))

然后,在你的 superset_config.py 文件中添加:

python 复制代码
from keycloak_security_manager import OIDCSecurityManager
from flask_appbuilder.security.manager import AUTH_OID, AUTH_REMOTE_USER, AUTH_DB, AUTH_LDAP, AUTH_OAUTH
import os

AUTH_TYPE = AUTH_OID
SECRET_KEY: 'SomethingNotEntirelySecret'
OIDC_CLIENT_SECRETS =  '/path/to/client_secret.json'
OIDC_ID_TOKEN_COOKIE_SECURE = False
OIDC_OPENID_REALM: '<myRealm>'
OIDC_INTROSPECTION_AUTH_METHOD: 'client_secret_post'
CUSTOM_SECURITY_MANAGER = OIDCSecurityManager

# 允许用户自助注册,从而可以从已授权用户创建 Flask 用户
AUTH_USER_REGISTRATION = True

# 默认用户注册的角色
AUTH_USER_REGISTRATION_ROLE = 'Public'

将你的客户端特定的 OpenID 信息存储在一个名为 client_secret.json 的文件中。 在与 superset_config.py 相同的目录下创建此文件:

json 复制代码
{
    "<myOpenIDProvider>": {
        "issuer": "https://<myKeycloakDomain>/realms/<myRealm>",
        "auth_uri": "https://<myKeycloakDomain>/realms/<myRealm>/protocol/openid-connect/auth",
        "client_id": "https://<myKeycloakDomain>",
        "client_secret": "<myClientSecret>",
        "redirect_uris": [
            "https://<SupersetWebserver>/oauth-authorized/<myOpenIDProvider>"
  ],
        "userinfo_uri": "https://<myKeycloakDomain>/realms/<myRealm>/protocol/openid-connect/userinfo",
        "token_uri": "https://<myKeycloakDomain>/realms/<myRealm>/protocol/openid-connect/token",
        "token_introspection_uri": "https://<myKeycloakDomain>/realms/<myRealm>/protocol/openid-connect/token/introspect"
  }
}

LDAP 认证

FAB 支持使用 LDAP 服务器验证用户凭据。 要使用 LDAP,必须安装 python-ldap 包。 详细信息,请参阅FAB 的 LDAP 文档

将 LDAP 或 OAUTH 组映射到 Superset 角色

Flask-AppBuilder 中的 AUTH_ROLES_MAPPING 是一个字典,用于将 LDAP/OAUTH 组名映射到 FAB 角色。 它用于为使用 LDAP 或 OAuth 进行身份验证的用户分配角色。

将 OAUTH 组映射到 Superset 角色

以下 AUTH_ROLES_MAPPING 字典将把 OAUTH 组 "superset_users" 映射到 Superset 角色 "Gamma" 和 "Alpha", 以及将 OAUTH 组 "superset_admins" 映射到 Superset 角色 "Admin"。

python 复制代码
AUTH_ROLES_MAPPING = {
"superset_users": ["Gamma","Alpha"],
"superset_admins": ["Admin"],
}

将 LDAP 组映射到 Superset 角色

以下 AUTH_ROLES_MAPPING 字典将把 LDAP DN "cn=superset_users,ou=groups,dc=example,dc=com" 映射到 Superset 角色 "Gamma" 和 "Alpha", 以及将 LDAP DN "cn=superset_admins,ou=groups,dc=example,dc=com" 映射到 Superset 角色 "Admin"。

python 复制代码
AUTH_ROLES_MAPPING = {
"cn=superset_users,ou=groups,dc=example,dc=com": ["Gamma","Alpha"],
"cn=superset_admins,ou=groups,dc=example,dc=com": ["Admin"],
}

注意: 这需要设置 AUTH_LDAP_SEARCH。更多详情,请参阅 FAB 安全文档

登录时同步角色

你还可以使用 AUTH_ROLES_SYNC_AT_LOGIN 配置变量 来控制 Flask-AppBuilder 与 LDAP/OAUTH 组同步用户角色的频率。 如果将 AUTH_ROLES_SYNC_AT_LOGIN 设置为 True,Flask-AppBuilder 将在 用户每次登录时同步其角色。如果将 AUTH_ROLES_SYNC_AT_LOGIN 设置为False, Flask-AppBuilder 仅在用户首次注册时同步其角色。

Flask 应用配置钩子

FLASK_APP_MUTATOR 是在你的环境中提供的一个配置函数, 它接收 app 对象并可以以任何方式修改它。 例如,在你的 superset_config.py 中添加 FLASK_APP_MUTATOR 以将 会话 cookie 过期时间设置为 24 小时:

python 复制代码
from flask import session
from flask import Flask


def make_session_permanent():
    '''
    Enable maxAge for the cookie 'session'
    '''
    session.permanent = True

# 设置 session 的 max age 为 24 小时
PERMANENT_SESSION_LIFETIME = timedelta(hours=24)
def FLASK_APP_MUTATOR(app: Flask) -> None:
    app.before_request_funcs.setdefault(None, []).append(make_session_permanent)

特性标志

为了支持多样化的用户群体,Superset 有一些特性默认并未启用。 例如,一些用户有更严格的安全限制,而另一些则没有。 因此,Superset 允许用户通过配置来启用或禁用某些功能。 对于特性所有者,你可以在 Superset 中添加可选的功能,但只会影响一部分用户。

你可以从 superset_config.py 中使用 flag 来启用或禁用功能:

python 复制代码
FEATURE_FLAGS = {
    'PRESTO_EXPAND_DATA': False,
}

当前的特性标志列表可以在 RESOURCES/FEATURE_FLAGS.md 中找到。

系列

相关推荐
Narutolxy7 小时前
大模型数据分析破局之路20250512
人工智能·chatgpt·数据分析
Ai尚研修-贾莲10 小时前
Python语言在地球科学交叉领域中的应用——从数据可视化到常见数据分析方法的使用【实例操作】
python·信息可视化·数据分析·地球科学
lilye6610 小时前
精益数据分析(53/126):双边市场模式指标全解析与运营策略深度探讨
数据挖掘·数据分析
ʚɞ 短腿欧尼12 小时前
文本数据可视化
信息可视化·数据分析
安特尼15 小时前
招行数字金融挑战赛数据赛道赛题一
人工智能·python·机器学习·金融·数据分析
请你喝好果汁64117 小时前
TWASandGWAS中GBS filtering and GWAS(1)
信息可视化·数据挖掘·数据分析
Leo.yuan18 小时前
数据分析怎么做?高效的数据分析方法有哪些?
大数据·数据库·信息可视化·数据挖掘·数据分析
HsuHeinrich21 小时前
利用散点图探索宇航员特征与太空任务之间的关系
python·数据可视化
马志远的生信笔记1 天前
质控脚本来喽
linux·数据分析
intcube1 天前
集中运营、分散决策,寻找最佳财务规划的平衡点
大数据·信息可视化·数据分析·全面预算管理·财务管理·财务规划