使用 dex (oauth / openid connect) 连接到超集并将 dex 组映射到角色
Connect to superset using dex (oauth / openid connect) and mapping dex groups to roles
我一直在广泛查看文档和 stackover 流程,以获取有关如何使用 helm chart 使此设置正常工作的示例。
我一直在努力使 OAuth 和组角色映射正常工作
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'
}
}
]
此示例配置无法将用户信息响应从 dex 映射到登录名。
我已经建立了自己的答案
https://gist.github.com/nelaaro/a2ef6f2a268d5a8a7caf6676e2ef2bb5
我只展示了对我有用的相关部分
这就是我 values.yaml
中的内容
# Install additional packages and do any other bootstrap configuration in this script
# For production clusters it's recommended to build own image with this step done in CI
bootstrapScript: |
#!/bin/bash
rm -rf /var/lib/apt/lists/* && \
pip install \
psycopg2==2.8.5 \
redis==3.2.1 \
thrift \
sasl \
thrift_sasl \
pyhive \
elasticsearch-dbapi \
Authlib \
JMESPath \
sqlalchemy-trino && \
if [ ! -f ~/bootstrap ]; then echo "Running Superset with uid {{ .Values.runAsUser }}" > ~/bootstrap; fi
extraSecrets:
custom_sso_security_manager.py: |-
import logging
from superset.security import SupersetSecurityManager
class CustomSsoSecurityManager(SupersetSecurityManager):
def oauth_user_info(self, provider, response=None):
userinfo = {}
logging.debug("Oauth2 provider: {0}.".format(provider))
if provider == 'dex':
# As example, this line request a GET to base_url + '/' + userDetails with Bearer Authentication,
# and expects that authorization server checks the token, and response with user details
me = self.appbuilder.sm.oauth_remotes[provider].get('userinfo').json()
# logging.debug("user_data me: {0}".format(me))
# logging.debug("user_data me[name]: {0}".format(me['name']))
# logging.debug("user_data me[groups]: {0}".format(me['groups']))
role_map = {'datascience': 'Gamma',
'data-engineering': 'Alpha',
'data-platform-admin': 'Admin'}
roles = [role_map[key] for key in me['groups'] if key in role_map]
logging.debug("user_data roles: {0}".format(roles))
userinfo = {
'name' : me['name'],
'email' : me['email'],
'id' : me['preferred_username'],
'username' : me['preferred_username'],
'first_name': me['name'].split()[0],
'last_name': me['name'].split()[-1],
'groups': me['groups'],
'role_keys': roles
}
logging.debug("user_info: {0}".format(userinfo))
return userinfo
else:
return userinfo
# A dictionary of overrides to append at the end of superset_config.py - the name does not matter
# WARNING: the order is not guaranteed
configOverrides:
a_override_proxy: |
# https://superset.apache.org/docs/installation/running-on-kubernetes#superset_configpy
# This will make sure the redirect_uri is properly computed, even with SSL offloading
ENABLE_PROXY_FIX = True
FEATURE_FLAGS = {
"DYNAMIC_PLUGINS": True
}
#
#
# https://superset.apache.org/docs/installation/configuring-superset
# https://flask-appbuilder.readthedocs.io/en/latest/security.html#authentication-oauth
# https://flask-appbuilder.readthedocs.io/en/latest/config.html full config reference
# https://docs.authlib.org/en/latest/client/flask.html
# https://github.com/apache/superset/issues/13806
enable_oauth: |
from flask_appbuilder.security.manager import (AUTH_DB, AUTH_OAUTH, AUTH_OID)
from custom_sso_security_manager import CustomSsoSecurityManager
CUSTOM_SECURITY_MANAGER = CustomSsoSecurityManager
AUTH_TYPE = AUTH_OAUTH
OAUTH_PROVIDERS = [
{ "name":"dex",
"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":"superset-auth", # Client Id (Identify Superset application)
"client_secret":"some lone secure secret", # Secret for this Client Id (Identify Superset application)
"server_metadata_url": "https://dex.somedomain.net/.well-known/openid-configuration",
"api_base_url": "https://dex.somedomain.net/", # required for the custom security manager to work CUSTOM_SECURITY_MANAGER
# "access_token_url": "https://dex.somedomain.net/token",
# "authorize_url": "https://dex.somedomain.net/auth",
# "redirect_uri":"https://superset.somedomain.net/oauth-authorized/dex",
"client_kwargs":{
"scope": "openid profile email groups" # Scope for the Authorization
}
}
}
]
# Will allow user self registration, allowing to create Flask users from Authorized User
AUTH_USER_REGISTRATION = True
PUBLIC_ROLE_LIKE = "Gamma" # allow access to dashboard for users not logged in.
# Map Authlib roles to superset roles
# AUTH_ROLE_ADMIN = "Admin"
AUTH_ROLE_PUBLIC = "Public"
# The default user self registration role or use AUTH_USER_REGISTRATION_ROLE_JMESPATH below
# AUTH_USER_REGISTRATION_ROLE = "Admin"
# AUTH_USER_REGISTRATION_ROLE = "Public"
# if we should replace ALL the user's roles each login, or only on registration
AUTH_ROLES_SYNC_AT_LOGIN = True
# https://flask-appbuilder.readthedocs.io/en/latest/config.html#jmespath-examples
# https://flask-appbuilder.readthedocs.io/en/latest/security.html#role-based
# https://apache.github.io/superset/security.html
# https://api.gopipeline.io/jmespath-tester
AUTH_USER_REGISTRATION_ROLE_JMESPATH = "sort(role_keys)[0] || 'Gamma'"
这里重要的是角色如何映射到超集使用的角色。
AUTH_USER_REGISTRATION_ROLE_JMESPATH = "sort(role_keys)[0] || 'Gamma'"
上述方法有效,因为我在我的 dex oauth 响应中发送了我的 ldap 组。
role_map = {'datascience': 'Gamma',
'data-engineering': 'Alpha',
'data-platform-admin': 'Admin'}
roles = [role_map[key] for key in me['groups'] if key in role_map]
我一直在广泛查看文档和 stackover 流程,以获取有关如何使用 helm chart 使此设置正常工作的示例。
我一直在努力使 OAuth 和组角色映射正常工作
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'
}
}
]
此示例配置无法将用户信息响应从 dex 映射到登录名。
我已经建立了自己的答案 https://gist.github.com/nelaaro/a2ef6f2a268d5a8a7caf6676e2ef2bb5
我只展示了对我有用的相关部分
这就是我 values.yaml
# Install additional packages and do any other bootstrap configuration in this script
# For production clusters it's recommended to build own image with this step done in CI
bootstrapScript: |
#!/bin/bash
rm -rf /var/lib/apt/lists/* && \
pip install \
psycopg2==2.8.5 \
redis==3.2.1 \
thrift \
sasl \
thrift_sasl \
pyhive \
elasticsearch-dbapi \
Authlib \
JMESPath \
sqlalchemy-trino && \
if [ ! -f ~/bootstrap ]; then echo "Running Superset with uid {{ .Values.runAsUser }}" > ~/bootstrap; fi
extraSecrets:
custom_sso_security_manager.py: |-
import logging
from superset.security import SupersetSecurityManager
class CustomSsoSecurityManager(SupersetSecurityManager):
def oauth_user_info(self, provider, response=None):
userinfo = {}
logging.debug("Oauth2 provider: {0}.".format(provider))
if provider == 'dex':
# As example, this line request a GET to base_url + '/' + userDetails with Bearer Authentication,
# and expects that authorization server checks the token, and response with user details
me = self.appbuilder.sm.oauth_remotes[provider].get('userinfo').json()
# logging.debug("user_data me: {0}".format(me))
# logging.debug("user_data me[name]: {0}".format(me['name']))
# logging.debug("user_data me[groups]: {0}".format(me['groups']))
role_map = {'datascience': 'Gamma',
'data-engineering': 'Alpha',
'data-platform-admin': 'Admin'}
roles = [role_map[key] for key in me['groups'] if key in role_map]
logging.debug("user_data roles: {0}".format(roles))
userinfo = {
'name' : me['name'],
'email' : me['email'],
'id' : me['preferred_username'],
'username' : me['preferred_username'],
'first_name': me['name'].split()[0],
'last_name': me['name'].split()[-1],
'groups': me['groups'],
'role_keys': roles
}
logging.debug("user_info: {0}".format(userinfo))
return userinfo
else:
return userinfo
# A dictionary of overrides to append at the end of superset_config.py - the name does not matter
# WARNING: the order is not guaranteed
configOverrides:
a_override_proxy: |
# https://superset.apache.org/docs/installation/running-on-kubernetes#superset_configpy
# This will make sure the redirect_uri is properly computed, even with SSL offloading
ENABLE_PROXY_FIX = True
FEATURE_FLAGS = {
"DYNAMIC_PLUGINS": True
}
#
#
# https://superset.apache.org/docs/installation/configuring-superset
# https://flask-appbuilder.readthedocs.io/en/latest/security.html#authentication-oauth
# https://flask-appbuilder.readthedocs.io/en/latest/config.html full config reference
# https://docs.authlib.org/en/latest/client/flask.html
# https://github.com/apache/superset/issues/13806
enable_oauth: |
from flask_appbuilder.security.manager import (AUTH_DB, AUTH_OAUTH, AUTH_OID)
from custom_sso_security_manager import CustomSsoSecurityManager
CUSTOM_SECURITY_MANAGER = CustomSsoSecurityManager
AUTH_TYPE = AUTH_OAUTH
OAUTH_PROVIDERS = [
{ "name":"dex",
"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":"superset-auth", # Client Id (Identify Superset application)
"client_secret":"some lone secure secret", # Secret for this Client Id (Identify Superset application)
"server_metadata_url": "https://dex.somedomain.net/.well-known/openid-configuration",
"api_base_url": "https://dex.somedomain.net/", # required for the custom security manager to work CUSTOM_SECURITY_MANAGER
# "access_token_url": "https://dex.somedomain.net/token",
# "authorize_url": "https://dex.somedomain.net/auth",
# "redirect_uri":"https://superset.somedomain.net/oauth-authorized/dex",
"client_kwargs":{
"scope": "openid profile email groups" # Scope for the Authorization
}
}
}
]
# Will allow user self registration, allowing to create Flask users from Authorized User
AUTH_USER_REGISTRATION = True
PUBLIC_ROLE_LIKE = "Gamma" # allow access to dashboard for users not logged in.
# Map Authlib roles to superset roles
# AUTH_ROLE_ADMIN = "Admin"
AUTH_ROLE_PUBLIC = "Public"
# The default user self registration role or use AUTH_USER_REGISTRATION_ROLE_JMESPATH below
# AUTH_USER_REGISTRATION_ROLE = "Admin"
# AUTH_USER_REGISTRATION_ROLE = "Public"
# if we should replace ALL the user's roles each login, or only on registration
AUTH_ROLES_SYNC_AT_LOGIN = True
# https://flask-appbuilder.readthedocs.io/en/latest/config.html#jmespath-examples
# https://flask-appbuilder.readthedocs.io/en/latest/security.html#role-based
# https://apache.github.io/superset/security.html
# https://api.gopipeline.io/jmespath-tester
AUTH_USER_REGISTRATION_ROLE_JMESPATH = "sort(role_keys)[0] || 'Gamma'"
这里重要的是角色如何映射到超集使用的角色。
AUTH_USER_REGISTRATION_ROLE_JMESPATH = "sort(role_keys)[0] || 'Gamma'"
上述方法有效,因为我在我的 dex oauth 响应中发送了我的 ldap 组。
role_map = {'datascience': 'Gamma',
'data-engineering': 'Alpha',
'data-platform-admin': 'Admin'}
roles = [role_map[key] for key in me['groups'] if key in role_map]