'AnonymousUserMixin' 对象没有属性 'roles' 将 LDAP 与 Flask-AppBuilder RBAC 一起使用时,Airflow Web 服务器出现错误

'AnonymousUserMixin' object has no attribute 'roles' error in Airflow Webserver when using LDAP with Flask-AppBuilder RBAC

我正在尝试将 Airflow Web 服务器身份验证与 Airflow 1.10.0 中可用的 Flask-AppBuilder RBAC 集成,但无论我尝试何种配置设置,我都会得到 AttributeError: 'AnonymousUserMixin' object has no attribute 'roles'

之前我已经让 Airflow LDAP 身份验证后端与我组织的 LDAP Microsoft AD 服务器一起使用,但我无法获得正确的配置设置以使其与 FAB RBAC 一起使用。 Airflow 和 FAB 文档很少提及 LDAP 或对其进行故障排除。

${AIRFLOW_HOME}/webserver_config.py 文件中我有

# The authentication type
AUTH_TYPE = AUTH_LDAP

AUTH_ROLE_PUBLIC = "Public"
AUTH_USER_REGISTRATION = True
AUTH_USER_REGISTRATION_ROLE = "Public"

AUTH_LDAP_SERVER = "ldaps://ldaps.myorg.org:636"
AUTH_LDAP_BIND_USER = "CN=myuser,OU=Service Accounts,DC=myorg,DC=org"
AUTH_LDAP_BIND_PASSWORD = "relevant_password"
AUTH_LDAP_SEARCH = "DC=myorg,DC=org"
AUTH_LDAP_UID_FIELD = "sAMAccountName"
# AUTH_LDAP_ALLOW_SELF_SIGNED = True
AUTH_LDAP_USE_TLS = False
AUTH_LDAP_APPEND_DOMAIN = "myorg.org"
AUTH_ROLE_ADMIN = "Admin"

{AIRFLOW_HOME}/airflow.cfg我有

[webserver]
authenticate = True
rbac = True

我已经升级了后端 Postgres 数据库,使其具有 ab_ 个表。

当我通过 Docker Swarm 部署所有内容并转到适当的 Web 服务器 URL 时,我只得到上面列出的错误和堆栈跟踪。它从来没有给我登录的选项(我尝试清除 cookie),所以我不明白如何让它让 'anonymous' 用户甚至尝试针对 LDAP AD 进行身份验证。

是问题

如果我遗漏了任何信息,请告诉我。谢谢!

AnonymousUserMixin 是在 Flask-Login python 包中定义的混入 class。您可能遇到代码路径假定已登录用户的问题。您可以将该代码路径更改为如下所示:

if flask_login.current_user.is_authenticated():
    *code*

您可能需要考虑在您的 Flask 应用 configuration/setup 代码中添加自定义 class 作为您的匿名用户 class。

class MyCustomAnonymousUser(flask_login.AnonymousUserMixin):
    def __init__(self):
        self.roles = []

flask_app = Flask(...)  # some flask app being initialized
flask_app.login_manager.anonymous_user = MyCustomAnonymousUser

但是,抛出此错误的代码也可能需要 Flask-Security 进行配置。一窥 Flask-Security 的作用:

from flask.ext.login import AnonymousUserMixin, UserMixin as BaseUserMixin, \
LoginManager, current_user

...


class AnonymousUser(AnonymousUserMixin):
    """AnonymousUser definition"""

    def __init__(self):
        self.roles = ImmutableList()

    def has_role(self, *args):
        """Returns `False`"""
        return False

要为您的应用配置 Flask-Security,请查看其文档中的快速入门:https://pythonhosted.org/Flask-Security/quickstart.html

好吧,幸运的是我想通了并且能够回答我自己的问题,这是迄今为止第一个在 SO 上得到回答的问题。

部分原因是FAB uses用于错误处理的python-ldap包,但也有ldap3ldap包,如果你安装在特定顺序可能会干扰 python-ldap 的使用。

我还发现python-ldap有一定的build requirements

此外,我发现 FAB 还有另一个 LDAP 参数,AUTH_LDAP_SEARCH_FILTER,可以让您将可能的用户过滤到某个组,这正是我想要的,但文档中没有提到;我在 GitHub 上的软件包仓库中找到了它。

这是适合我的 webserver_config.py 文件:

# -*- coding: utf-8 -*-

import os
from airflow import configuration as conf
from flask_appbuilder.security.manager import AUTH_LDAP
basedir = os.path.abspath(os.path.dirname(__file__))

# The SQLAlchemy connection string.
SQLALCHEMY_DATABASE_URI = conf.get('core', 'SQL_ALCHEMY_CONN')

# Flask-WTF flag for CSRF
CSRF_ENABLED = True

# ------------------------------------------------------------------------------
# AUTHENTICATION CONFIG
# ------------------------------------------------------------------------------
# For details on how to set up each of the following authentications, see
# http://flask-appbuilder.readthedocs.io/en/latest/security.html# authentication-methods

# The authentication type
AUTH_TYPE = AUTH_LDAP

AUTH_ROLE_PUBLIC = "Public"
AUTH_USER_REGISTRATION = True
AUTH_USER_REGISTRATION_ROLE = "Viewer"

AUTH_LDAP_SERVER = "ldaps://ldaps.myorg.org:636"
AUTH_LDAP_BIND_USER = "CN=myuser,OU=Service Accounts,DC=myorg,DC=org"
AUTH_LDAP_BIND_PASSWORD = "relevant_password"
AUTH_LDAP_SEARCH = "DC=myorg,DC=org"  # same as BASEDN
AUTH_LDAP_SEARCH_FILTER = "(memberOf=CN=My Team,OU=My Group,DC=myorg,DC=org)"
AUTH_LDAP_UID_FIELD = AUTH_LDAP_UID_FIELD = "sAMAccountName"
AUTH_LDAP_ALLOW_SELF_SIGNED = True
AUTH_LDAP_USE_TLS = False
AUTH_LDAP_TLS_DEMAND = True
AUTH_ROLE_ADMIN = "Admin"

我将 AUTH_USER_REGISTRATION_ROLE 设置为查看者,因为默认情况下 Public 没有与之关联的权限,因此如果 AD 中的某人登录并且他们的角色默认为 Public,他们在管理员更改角色之前将无法执行任何操作。

我从我组织的 IT 部门了解到,LDAP 服务器的域控制器处理 TLS,所以我认为这就是我可以将 AUTH_LDAP_ALLOW_SELF_SIGNED 设置为 True 的原因,而我没有Docker 容器中的 TLS 证书指向 Airflow,以便将 AUTH_LDAP_USE_TLS 设置为 True。