Код: Выделить всё
import os
from flask_appbuilder.security.manager import AUTH_OAUTH
AUTH_TYPE = AUTH_OAUTH
OAUTH_PROVIDERS = [{
'name': 'keycloak',
'token_key': 'access_token',
'icon': 'fa-circle-o',
'remote_app': {
'client_id': os.getenv("AIRFLOW_OAUTH_CLIENT_ID"),
'client_secret': os.getenv("AIRFLOW_OAUTH_CLIENT_SECRET"),
'api_base_url': 'https:///realms//protocol/openid-connect',
'client_kwargs': {
'scope': 'openid profile email'
},
'access_token_url': 'https:///realms//protocol/openid-connect/token',
'authorize_url': 'https:///realms//protocol/openid-connect/auth',
'request_token_url': None,
'server_metadata_url': os.getenv("AIRFLOW_METADATA_URL"),
}
'role_keys': 'realm_access.roles',
}]
AUTH_ROLES_MAPPING = {
"Viewer": ["Viewer"],
"Admin": ["Admin"],
"User": ["User"],
"Public": ["Public"],
"Op": ["Op"],
}
# Uncomment to setup Full admin role name
AUTH_ROLE_ADMIN = "Admin"
# Uncomment to setup Public role name, no authentication needed
AUTH_ROLE_PUBLIC = "Public"
# Will allow user self registration
AUTH_USER_REGISTRATION = True
# The default user self registration role
AUTH_USER_REGISTRATION_ROLE = "Viewer"
AUTH_ROLES_SYNC_AT_LOGIN = True
< /code>
Мы также попытались настроить менеджера безопасности, чтобы переопределить картирование ролей, как это: < /p>
from airflow.providers.fab.auth_manager.security_manager.override import FabAirflowSecurityManagerOverride
from base64 import b64decode
import jwt
import requests
from cryptography.hazmat.primitives import serialization
OIDC_ISSUER = os.getenv("OIDC_ISSUER")
# Fetch public key
req = requests.get(OIDC_ISSUER)
key_der_base64 = req.json()["public_key"]
key_der = b64decode(key_der_base64.encode())
public_key = serialization.load_der_public_key(key_der)
class CustomSecurityManager(FabAirflowSecurityManagerOverride):
def get_oauth_user_info(self, provider, response):
if provider == "keycloak":
token = response["access_token"]
me = jwt.decode(token, public_key, algorithms=["HS256", "RS256"], audience=os.getenv("SSO_CLIENT_ID"))
# Extract roles from resource access
realm_access = me.get("realm_access", {})
groups = realm_access.get("roles", [])
log.info("groups: {0}".format(groups))
if not groups:
groups = ["Viewer"]
userinfo = {
"username": me.get("preferred_username"),
"email": me.get("email"),
"first_name": me.get("given_name"),
"last_name": me.get("family_name"),
"role_keys": groups,
}
log.info("user info: {0}".format(userinfo))
return userinfo
else:
return {}
SECURITY_MANAGER_CLASS = "my_module.CustomSecurityManager"
Каждому пользователю SSO присваивается роль администратора , но есть две записи для картирования ролей пользователей в таблице Postgresql AB_USER_ROLE : одна для администратора и другая для Viewer. /> Если пользователь имеет роль "Admin" в KeyCloak, он должен получить роль Admin в воздушном потоке.
Дополнительная информация:
the Keycloak Token содержит Roles in realm_access. Декодированный токен фрагмент: < /li>
< /ul>
"realm_access": {
"roles": ["offline_access", "uma_authorization", "admin"]
}
< /code>
Вопросы: < /h3>
Как мы можем правильно извлечь роли царства KeyCloak из токена и отобразить их в роли воздушного потока? Чтобы изменить Fab < /code> (Flask Appbuilder) Синхронизировать или расширить объект OAuthuserInfo?>
Подробнее здесь: https://stackoverflow.com/questions/797 ... fter-login