dpgaspar/Flask-AppBuilder

Nested Group LDAP Auth not working in Airflow FAB

ranga2crazyy opened this issue · 1 comments

Hi All,

I am currently using flask_appbuilder.security.manager in order to provide LDAP authentication for my Airflow Users.
While doing the AUTH_ROLES_MAPPING I have noticed that it only works for direct members of the AD groups not the nested groups.
Has anyone been able to get this to work for nested groups?

Example:

in my current set up

_> AUTH_ROLES_MAPPING = {"CN=DIRECTGROUP,OU=!!sample,OU=!!sample,OU=!!sample,DC=sample,DC=sample" : ["Viewer", "executer"],

User A: member of DIRECTGROUP
User B: member of NESTEDGROUP which is a member of DIRECTGROUP_

Only User A would be able to login to my airflow instance as Viewer/Executer.
User B gets assigned to default "Public" role since flask is not able to drill down to the subtree.

I have tried using the Microsoft special string via AUTH_LDAP_SEARCH_FILTER but no luck. I browsed to different options in FAB but couldn't find one which supports this.

Current config options used(webserver_config.py) in Airflow 2.3.2

import os
from airflow.www.fab_security.manager import AUTH_LDAP
basedir = os.path.abspath(os.path.dirname(file))
Flask-WTF flag for CSRF

WTF_CSRF_ENABLED = True

AUTH_LDAP_SEARCH = "dc=sample,dc=samp,dc=com" # the LDAP search base
AUTH_LDAP_UID_FIELD = "sAMAccountName"
AUTH_LDAP_BIND_USER & AUTH_LDAP_BIND_PASSWORD
AUTH_USER_REGISTRATION = True
AUTH_USER_REGISTRATION_ROLE = "Public"
AUTH_LDAP_GROUP_FIELD = "memberOf"
AUTH_LDAP_SEARCH_FILTER='(&(objectClass=user)(memberOf:1.2.840.113556.1.4.1941:=CN=DIRECTGROUP,OU=!!sample,OU=!!sample,OU=!!sample,DC=sample,DC=sample))
AUTH_ROLES_SYNC_AT_LOGIN=True
PERMANENT_SESSION_LIFETIME=1800

Environment

Flask-Appbuilder version: 3.4.5

pip freeze output:
aenum==3.1.11
aiohttp==3.8.4
aioretry==5.0.2
aiosignal==1.3.1
alembic==1.8.0
ansible==6.3.0
ansible-core==2.13.3
anyio==3.6.1
apache-airflow==2.3.2
apache-airflow-providers-ftp==2.1.2
apache-airflow-providers-http==2.1.2
apache-airflow-providers-imap==2.2.3
apache-airflow-providers-microsoft-mssql==2.1.1
apache-airflow-providers-postgres==3.0.0
apache-airflow-providers-snowflake==2.5.1
apache-airflow-providers-sqlite==2.1.3
apispec==3.3.2
appdirs==1.4.4
APScheduler==3.10.1
argcomplete==2.0.0
asn1crypto==1.5.1
async-timeout==4.0.2
attrs==20.3.0
auth-lib==1.2.0
azure-core==1.26.3
azure-storage-blob==12.15.0
Babel==2.10.1
backoff==1.11.1
bcpy==0.1.8
bcrypt==4.0.1
beautifulsoup4==4.11.1
blinker==1.4
bs4==0.0.1
cachelib==0.7.0
case-conversion==2.1.0
cattrs==1.10.0
cdsapi==0.5.1
certifi==2022.12.7
cetools==1.10.2
cffi==1.15.0
cftime==1.6.0
chardet==5.1.0
charset-normalizer==2.0.12
click==8.1.3
clickclick==20.10.2
clipboard==0.0.4
colorama==0.4.4
colorlog==4.8.0
colour==0.1.5
commonmark==0.9.1
configparser==5.3.0
connexion==2.13.1
coverage==7.2.2
crayons==0.4.0
cron-descriptor==1.2.31
croniter==1.3.5
cronitor==4.6.0
cryptography==3.4.8
cssselect==1.2.0
cursor==1.3.5
decorator==4.4.2
defusedxml==0.7.1
Deprecated==1.2.13
dill==0.3.1.1
distro==1.8.0
dnspython==2.2.1
docutils==0.18.1
email-validator==1.2.1
et-xmlfile==1.1.0
exceptiongroup==1.1.1
fake-useragent==1.1.3
Flask==1.1.2
Flask-AppBuilder==3.4.5
Flask-Babel==2.0.0
Flask-Caching==1.11.1
Flask-JWT-Extended==3.25.1
Flask-Login==0.4.1
Flask-OpenID==1.3.0
Flask-Session==0.4.0
Flask-SQLAlchemy==2.5.1
Flask-WTF==0.14.3
freezegun==1.2.2
frozenlist==1.3.3
ftfy==6.1.1
fuzzywuzzy==0.18.0
gender-guesser==0.4.0
graphviz==0.20
greenlet==1.1.2
gunicorn==20.1.0
h11==0.12.0
html-text==0.5.2
html5lib==1.1
http-constants==0.5.0
httpcore==0.15.0
httpx==0.23.0
humanize==4.6.0
idna==3.3
imageio==2.26.1
imageio-ffmpeg==0.4.8
importlib-metadata==4.11.4
importlib-resources==5.12.0
infi.systray==0.1.12
inflect==6.0.2
inflection==0.5.1
iniconfig==2.0.0
isodate==0.6.1
itsdangerous==1.1.0
Jinja2==3.0.3
jsonschema==4.5.1
kayrros-client==1.2.17
lazy-object-proxy==1.7.1
lockfile==0.12.2
lxml==4.8.0
Mako==1.2.0
Markdown==3.3.7
MarkupSafe==2.0.1
marshmallow==3.16.0
marshmallow-enum==1.5.1
marshmallow-oneofschema==3.0.1
marshmallow-sqlalchemy==0.26.1
maybe-else==0.2.1
mbstrdecoder==1.1.2
mock==5.0.1
moviepy==1.0.3
msal==1.21.0
msoffcrypto-tool==5.0.0
multidict==6.0.4
mypy-extensions==1.0.0
nest-asyncio==1.5.6
ntlm-auth==1.5.0
numpy==1.23.5
O365==2.0.21
oauthlib==3.2.2
office365==0.3.15
Office365-REST-Python-Client==2.3.16
olefile==0.46
openpyxl==3.0.7
oscrypto==1.3.0
packaging==21.3
pandas==1.1.5
pandera==0.6.5
paramiko==2.12.0
parse==1.19.0
parsedatetime==2.6
pathmagic==0.3.14
pathspec==0.9.0
pendulum==2.1.2
Pillow==9.4.0
pluggy==1.0.0
ply==3.11
polars==0.15.16
prettierfier==1.0.3
prison==0.2.1
proglog==0.1.10
psutil==5.8.0
psycopg2-binary==2.9.5
py==1.11.0
pyADW==2.9.997
pyarrow==11.0.0
pyasn1==0.4.8
pycparser==2.21
pycryptodomex==3.17
pycurl==7.45.2
pydantic==1.9.2
pydub==0.25.1
pyee==8.2.2
Pygments==2.12.0
pyinstrument==4.4.0
pyiotools==0.3.18
PyJWT==1.7.1
pykerberos==1.2.4
pymiscutils==0.3.14
pymssql==2.2.7
PyNaCl==1.5.0
pyodbc==4.0.32
pyOpenSSL==20.0.1
pyparsing==2.4.7
PyPDF2==3.0.1
pyperclip==1.8.2
pyppeteer==1.0.2
PyQt5==5.15.9
PyQt5-Qt5==5.15.2
PyQt5-sip==12.11.1
pyquery==2.0.0
pyrsistent==0.18.1
pysmb==1.2.7
PySocks==1.7.1
pysubtypes==0.3.18
pytest==7.2.2
python-daemon==2.3.0
python-dateutil==2.8.2
python-docx==0.8.11
python-nvd3==0.15.0
python-slugify==6.1.2
python3-openid==3.2.0
pytz==2022.1
pytz-deprecation-shim==0.1.0.post0
pytzdata==2020.1
pyxlsb==1.0.9
PyYAML==5.4.1
readchar==4.0.5
regex==2023.3.23
requests==2.26.0
requests-html==0.10.0
requests-kerberos==0.11.0
requests-ntlm==1.1.0
requests-oauthlib==1.3.1
responses==0.23.1
retry==0.9.2
rfc3986==1.5.0
rich==12.4.4
scipy==1.5.4
scraping-framework==2.23.506
selenium==3.141.0
selenium-stealth==1.0.6
Send2Trash==1.8.0
setproctitle==1.2.3
simplejson==3.18.4
six==1.16.0
sniffio==1.2.0
snowflake-connector-python==2.7.1
snowflake-sqlalchemy==1.4.7
soupsieve==2.4
SQLAlchemy==1.4.9
SQLAlchemy-JSONField==1.0.0
SQLAlchemy-Utils==0.38.2
statsd==4.0.1
stopwatch.py==2.0.1
stringcase==1.2.0
swagger-ui-bundle==0.0.9
sxl==0.0.1a10
synmax-api-python-client==0.0.29
tabula-py==2.3.0
tabulate==0.8.9
tenacity==8.0.1
termcolor==1.1.0
text-unidecode==1.3
tomli==2.0.1
tqdm==4.65.0
typepy==1.3.0
types-PyYAML==6.0.12.8
typing-inspect==0.8.0
typing_extensions==4.2.0
tzdata==2022.7
tzlocal==4.3
unicodecsv==0.14.1
urllib3==1.26.9
w3lib==2.1.1
wcwidth==0.2.6
webdriver-manager==3.5.3
webencodings==0.5.1
websockets==10.4
Werkzeug==1.0.1
wrapt==1.14.1
WTForms==2.3.3
xarray==0.16.2
xlrd==1.2.0
XlsxWriter==3.0.9
yarl==1.8.2
zipp==3.8.0

Describe the expected results

Users from nested groups should be assigned the roles as per the primary group role mapping configured in "AUTH_ROLES_MAPPING"

Describe the actual results

User gets assigned to the default airflow role

Paste the full traceback if there was an exception.

Steps to reproduce

Going to classify this has a feature request