我想使用keycloak在我们的Superset环境中对我的用户进行身份验证。
Superset使用flask-openid,如flask-security中所实现:
要启用与常规身份验证(数据库)不同的用户身份验证,您需要在superset_config.py文件中覆盖AUTH_TYPE参数。您还需要提供对openid-connect领域的引用,并启用用户注册。据我了解,它看起来应该像这样:
from flask_appbuilder.security.manager import AUTH_OID
AUTH_TYPE = AUTH_OID
OPENID_PROVIDERS = [
{ 'name':'keycloak', 'url':'http://localhost:8080/auth/realms/superset' }
]
AUTH_USER_REGISTRATION = True
AUTH_USER_REGISTRATION_ROLE = 'Gamma'
使用此配置,登录页面将变为提示,用户可以在其中选择所需的OpenID提供程序(在我们的示例中为keycloak)。我们还有两个按钮,一个用于登录(针对现有用户),另一个用于注册为新用户。
我希望这些按钮中的任何一个都可以将我带到我的密钥库登录页面。但是,这不会发生。相反,我被直接重定向回登录页面。
如果我按下注册按钮,则会收到一条消息,提示“目前无法注册,请稍后再试”。当我按下登录按钮时,没有消息显示。“超集”日志显示加载登录页面的请求,但不显示对密钥斗篷的请求。我已经使用Google OpenID提供程序尝试了同样的方法,效果很好。
由于我没有看到对密钥斗篷的任何请求,因此使我认为我在某处缺少配置设置,或者使用了错误的设置。您能帮我弄清楚我应该使用哪些设置吗?
@sjmeyer已编写了更新的指南,该指南可与Superset 0.28.1及更高版本一起使用。我自己还没有尝试过,但是感谢@nawazxy确认此解决方案有效。
我设法解决了自己的问题。主要问题是由我对超集使用的flask-openid插件的错误假设引起的。该插件实际上支持OpenID 2.x,但不支持OpenID -Connect(由Keycloak实现的版本)。
解决方法是,我决定切换到flask-oidc插件。切换到新的身份验证提供程序实际上需要进行一些挖掘工作。要集成插件,我必须遵循以下步骤:
不幸的是,flask-oidc不支持Keycloak生成的配置格式。相反,您的配置应如下所示:
{
"web": {
"realm_public_key": "<YOUR_REALM_PUBLIC_KEY>",
"issuer": "http://<YOUR_DOMAIN>/auth/realms/<YOUR_REALM_ID>",
"auth_uri": "http://<YOUR_DOMAIN>/auth/realms/<YOUR_REALM_ID>/protocol/openid-connect/auth",
"client_id": "<YOUR_CLIENT_ID>",
"client_secret": "<YOUR_SECRET_KEY>",
"redirect_urls": [
"http://<YOUR_DOMAIN>/*"
],
"userinfo_uri": "http://<YOUR_DOMAIN>/auth/realms/<YOUR_REALM_ID>/protocol/openid-connect/userinfo",
"token_uri": "http://<YOUR_DOMAIN>/auth/realms/<YOUR_REALM_ID>/protocol/openid-connect/token",
"token_introspection_uri": "http://<YOUR_DOMAIN>/auth/realms/<YOUR_REALM_ID>/protocol/openid-connect/token/introspect"
}
}
Flask-oidc希望该配置位于文件中。我把我的东西存放在了client_secret.json
。您可以在中配置配置文件的路径superset_config.py
。
首先,您要确保烧瓶停止使用flask-openid,而广告开始使用flask-oidc。为此,您将需要创建自己的安全管理器,以将flask-oidc配置为其身份验证提供程序。我已经实现了我的安全管理器,如下所示:
from flask_appbuilder.security.manager import AUTH_OID
from flask_appbuilder.security.sqla.manager import SecurityManager
from flask_oidc import OpenIDConnect
class OIDCSecurityManager(SecurityManager):
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
要在Superset中启用OpenID,您以前必须将身份验证类型设置为AUTH_OID。我的安全管理器仍然执行超类的所有行为,但是使用OpenIDConnect对象覆盖oid属性。此外,它用自定义视图替换默认的OpenID身份验证视图。我已经像这样实现了我的:
from flask_appbuilder.security.views import AuthOIDView
from flask_login import login_user
from urllib import quote
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))
我的视图覆盖了/ login和/ logout端点上的行为。登录时,将运行handle_login方法。它要求用户由OIDC提供程序进行身份验证。在我们的例子中,这意味着用户将首先被重定向到Keycloak进行登录。
进行身份验证时,用户将被重定向回Superset。接下来,我们查询是否可以识别用户。如果没有,我们将基于其OIDC用户信息创建用户。最后,我们将用户登录到Superset,然后将他们重定向到登录页面。
注销时,我们将使这些cookie无效:
默认情况下,Superset只处理第一个。扩展的注销方法可以处理所有这三点。
最后,我们需要在中添加一些参数superset_config.py
。这是我配置我的方式:
'''
AUTHENTICATION
'''
AUTH_TYPE = AUTH_OID
OIDC_CLIENT_SECRETS = 'client_secret.json'
OIDC_ID_TOKEN_COOKIE_SECURE = False
OIDC_REQUIRE_VERIFIED_EMAIL = False
CUSTOM_SECURITY_MANAGER = OIDCSecurityManager
AUTH_USER_REGISTRATION = True
AUTH_USER_REGISTRATION_ROLE = 'Gamma'
嗨,非常感谢您,但是您是否愿意分享更多有关如何精确地完成上述操作的信息,特别是如果要使用诸如amancevice / superset:0.24.0 plese之类的图像工作时?
更具体地说,在哪里可以替换/覆盖现有文件,或者可能有一种更清洁的解决方案,例如要使用更新的软件包或系统或映像?
我不确定使用Docker时如何执行此操作。我们将添加的内容部署为运行超集的服务器上python模块的一部分。然后,我们如上所述更改了superset_config.py。我的建议是查看有关创建自定义版本的超集文档:superset.incubator.apache.org/…
嗨@thijsfranck谢谢您的解决方案!我正在尝试实施它,但是遇到了问题。我将安全管理器替代代码保存在一个名为auth_manager.py的文件中,并将视图保存在auth_view.py中,并将它们都存储在appbuilder软件包的/ security /目录中。当我运行超集时,它说不能对OIDCSecurityManager进行罚款。还尝试将其放在/ superset /中,也没有用。是否有使应用程序获取文件的特定方法,或将其放置的特定位置?
对于我的项目,我在
superset_config.py
存储我的文件夹下创建了一个新包。我将代码放在__init__.py
文件中,但这不是必需的。根据放置代码的位置,您将需要更改superset_config.py
文件中的导入。