折腾 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 中找到。

系列

相关推荐
布说在见16 分钟前
魅力标签云,奇幻词云图 —— 数据可视化新境界
信息可视化·数据挖掘·数据分析
Tianyanxiao1 小时前
如何利用探商宝精准营销,抓住行业机遇——以AI技术与大数据推动企业信息精准筛选
大数据·人工智能·科技·数据分析·深度优先·零售
招风的黑耳1 小时前
Axure大屏可视化模板:赋能各行各业的数据展示与管理
axure·数据可视化·大屏模板
FIT2CLOUD飞致云2 小时前
仪表板展示|DataEase看中国:历年双十一电商销售数据分析
数据分析·开源·数据可视化·dataease·双十一
皓7413 小时前
服饰电商行业知识管理的创新实践与知识中台的重要性
大数据·人工智能·科技·数据分析·零售
菜鸟的人工智能之路4 小时前
桑基图在医学数据分析中的更复杂应用示例
python·数据分析·健康医疗
阡之尘埃10 小时前
Python数据分析案例61——信贷风控评分卡模型(A卡)(scorecardpy 全面解析)
人工智能·python·机器学习·数据分析·智能风控·信贷风控
布说在见13 小时前
层次与网络的视觉对话:树图与力引导布局的双剑合璧
信息可视化·数据挖掘·数据分析
全栈开发圈19 小时前
新书速览|Spark SQL大数据分析快速上手
sql·数据分析·spark
spssau19 小时前
多分类logistic回归分析案例教程
分类·数据挖掘·数据分析·回归·回归分析·logistic回归·spssau