dpgaspar / Flask-AppBuilder

Simple and rapid application development framework, built on top of Flask. includes detailed security, auto CRUD generation for your models, google charts and much more. Demo (login with guest/welcome) - http://flaskappbuilder.pythonanywhere.com/
BSD 3-Clause "New" or "Revised" License
4.65k stars 1.36k forks source link

Airflow Active Directory auth with sAMAccountName attribute #2084

Closed scobit closed 1 year ago

scobit commented 1 year ago

Hello! Could someone explain me, how to configure AD authentication with sAMAccountName attribute? I'm testing Airflow in k8s, authentication provided by FAB. Below "AD auth conf" - this configuration working with cn atrribute in AUTH_LDAP_USERNAME_FORMAT and AUTH_LDAP_UID_FIELD.

But when I'm trying to switch it to sAMAccountName I got error:

[2023-07-14T03:47:44.408+0000] {manager.py:1178} INFO - Login Failed for user: sAMAccountName=FirstName.LastName,OU=Users,OU=yyy,DC=example,DC=com

The reason why I want to use sAMAccountName - because when I'am using cn, user should input his login with space FirstName LastName

Using sAMAccountName users can input their login in a more familiar way with dot.

FirstName.LastName

I have tried to use different documentation, especially this: https://flask-appbuilder.readthedocs.io/en/latest/security.html#authentication-ldap

But most of them use cn or uid attributes. Which is strange, because uid and cn more relevant to OpenLDAP or FreeIPA instances.

AD auth conf

import os
from airflow import configuration as conf
from flask_appbuilder.security.manager import AUTH_LDAP
AUTH_TYPE = AUTH_LDAP
AUTH_LDAP_SERVER = "ldap://example.com:389"
AUTH_LDAP_USE_TLS = False

AUTH_USER_REGISTRATION = True  
AUTH_USER_REGISTRATION_ROLE = "Public"  
AUTH_LDAP_FIRSTNAME_FIELD = "givenName"
AUTH_LDAP_LASTNAME_FIELD = "sn"
AUTH_LDAP_EMAIL_FIELD = "mail"  

AUTH_LDAP_USERNAME_FORMAT = "cn=%s,OU=Users,OU=yyy,OU=yyy,DC=example,DC=com" 

AUTH_LDAP_SEARCH = "OU=Users,OU=yyy,OU=yyy,DC=example,DC=com" 

AUTH_LDAP_UID_FIELD = "cn" 

AUTH_ROLES_MAPPING = {
  "CN=viewer-group,OU=yyy,DC=example,DC=com": ["User"],
  "CN=admin-group,OU=yyy,DC=example,DC=com": ["Admin"],
}

AUTH_LDAP_GROUP_FIELD = "memberOf"
AUTH_ROLES_SYNC_AT_LOGIN = True

PERMANENT_SESSION_LIFETIME = 1800

Environment

$ flask --version Python 3.7.17 Flask 2.2.5 Werkzeug 2.2.3

$ pip freeze

adal==1.2.7 aiobotocore==2.5.0 aiofiles==23.1.0 aiohttp==3.8.4 aioitertools==0.11.0 aiosignal==1.3.1 alembic==1.11.1 amqp==5.1.1 anyio==3.7.0 apache-airflow==2.6.2 apache-airflow-providers-amazon==8.1.0 apache-airflow-providers-celery==3.2.0 apache-airflow-providers-cncf-kubernetes==7.0.0 apache-airflow-providers-common-sql==1.5.1 apache-airflow-providers-docker==3.7.0 apache-airflow-providers-elasticsearch==4.5.0 apache-airflow-providers-ftp==3.4.1 apache-airflow-providers-google==10.1.1 apache-airflow-providers-grpc==3.2.0 apache-airflow-providers-hashicorp==3.4.0 apache-airflow-providers-http==4.4.1 apache-airflow-providers-imap==3.2.1 apache-airflow-providers-microsoft-azure==6.1.1 apache-airflow-providers-mysql==5.1.0 apache-airflow-providers-odbc==3.3.0 apache-airflow-providers-postgres==5.5.0 apache-airflow-providers-redis==3.2.0 apache-airflow-providers-sendgrid==3.2.0 apache-airflow-providers-sftp==4.3.0 apache-airflow-providers-slack==7.3.0 apache-airflow-providers-snowflake==4.1.0 apache-airflow-providers-sqlite==3.4.1 apache-airflow-providers-ssh==3.7.0 apispec==5.2.2 argcomplete==3.1.1 asgiref==3.7.2 asn1crypto==1.5.1 async-timeout==4.0.2 asynctest==0.13.0 attrs==23.1.0 Authlib==1.2.0 azure-batch==14.0.0 azure-common==1.1.28 azure-core==1.27.1 azure-cosmos==4.4.0 azure-datalake-store==0.0.53 azure-identity==1.13.0 azure-keyvault-secrets==4.7.0 azure-kusto-data==0.0.45 azure-mgmt-containerinstance==1.5.0 azure-mgmt-core==1.4.0 azure-mgmt-datafactory==1.1.0 azure-mgmt-datalake-nspkg==3.0.1 azure-mgmt-datalake-store==0.5.0 azure-mgmt-nspkg==3.0.2 azure-mgmt-resource==23.0.1 azure-nspkg==3.0.2 azure-servicebus==7.11.0 azure-storage-blob==12.16.0 azure-storage-common==2.1.0 azure-storage-file==2.1.0 azure-storage-file-datalake==12.11.0 azure-synapse-spark==0.7.0 Babel==2.12.1 backoff==1.10.0 bcrypt==4.0.1 beautifulsoup4==4.12.2 billiard==3.6.4.0 blinker==1.6.2 boto3==1.26.76 botocore==1.29.76 cached-property==1.5.2 cachelib==0.9.0 cachetools==5.3.1 cattrs==23.1.2 celery==5.2.7 certifi==2023.5.7 cffi==1.15.1 chardet==5.1.0 charset-normalizer==3.1.0 click==8.1.3 click-didyoumean==0.3.0 click-plugins==1.1.1 click-repl==0.2.0 clickclick==20.10.2 cloudpickle==2.2.1 colorama==0.4.6 colorlog==4.8.0 ConfigUpdater==3.1.1 connexion==2.14.2 cron-descriptor==1.4.0 croniter==1.3.15 cryptography==40.0.2 dask==2022.2.0 db-dtypes==1.1.1 decorator==5.1.1 Deprecated==1.2.14 dill==0.3.1.1 distlib==0.3.6 distributed==2022.2.0 dnspython==2.3.0 docker==6.1.3 docutils==0.20.1 elasticsearch==7.13.4 elasticsearch-dbapi==0.2.10 elasticsearch-dsl==7.4.1 email-validator==1.3.1 eventlet==0.33.3 exceptiongroup==1.1.1 filelock==3.12.2 Flask==2.2.5 Flask-AppBuilder==4.3.1 Flask-Babel==2.0.0 Flask-Caching==2.0.2 Flask-JWT-Extended==4.5.2 Flask-Limiter==3.3.1 Flask-Login==0.6.2 Flask-Session==0.5.0 Flask-SQLAlchemy==2.5.1 Flask-WTF==1.1.1 flower==1.2.0 frozenlist==1.3.3 fsspec==2023.1.0 future==0.18.3 gcloud-aio-auth==4.2.1 gcloud-aio-bigquery==6.3.0 gcloud-aio-storage==8.2.0 gevent==22.10.2 google-ads==21.2.0 google-api-core==2.11.0 google-api-python-client==2.89.0 google-auth==2.20.0 google-auth-httplib2==0.1.0 google-auth-oauthlib==1.0.0 google-cloud-aiplatform==1.26.0 google-cloud-appengine-logging==1.3.0 google-cloud-audit-log==0.2.5 google-cloud-automl==2.11.1 google-cloud-bigquery==3.11.1 google-cloud-bigquery-datatransfer==3.11.1 google-cloud-bigquery-storage==2.20.0 google-cloud-bigtable==2.19.0 google-cloud-build==3.16.0 google-cloud-compute==1.11.0 google-cloud-container==2.24.0 google-cloud-core==2.3.2 google-cloud-datacatalog==3.13.0 google-cloud-dataflow-client==0.8.3 google-cloud-dataform==0.5.1 google-cloud-dataplex==1.5.0 google-cloud-dataproc==5.4.1 google-cloud-dataproc-metastore==1.11.0 google-cloud-dlp==3.12.1 google-cloud-kms==2.17.0 google-cloud-language==2.10.0 google-cloud-logging==3.5.0 google-cloud-memcache==1.7.1 google-cloud-monitoring==2.15.0 google-cloud-orchestration-airflow==1.9.0 google-cloud-os-login==2.9.1 google-cloud-pubsub==2.17.1 google-cloud-redis==2.13.0 google-cloud-resource-manager==1.10.1 google-cloud-secret-manager==2.16.1 google-cloud-spanner==3.36.0 google-cloud-speech==2.20.0 google-cloud-storage==2.9.0 google-cloud-tasks==2.13.1 google-cloud-texttospeech==2.14.1 google-cloud-translate==3.11.1 google-cloud-videointelligence==2.11.2 google-cloud-vision==3.4.2 google-cloud-workflows==1.10.1 google-crc32c==1.5.0 google-resumable-media==2.5.0 googleapis-common-protos==1.59.1 graphviz==0.20.1 greenlet==2.0.2 grpc-google-iam-v1==0.12.6 grpcio==1.54.2 grpcio-gcp==0.2.2 grpcio-status==1.54.2 gunicorn==20.1.0 h11==0.14.0 HeapDict==1.0.1 httpcore==0.16.3 httplib2==0.22.0 httpx==0.23.3 humanize==4.6.0 hvac==1.1.0 idna==3.4 importlib-metadata==4.13.0 importlib-resources==5.12.0 inflection==0.5.1 isodate==0.6.1 itsdangerous==2.1.2 Jinja2==3.1.2 jmespath==0.10.0 json-merge-patch==0.2 jsonpath-ng==1.5.3 jsonschema==4.17.3 kombu==5.2.4 kubernetes==23.6.0 kubernetes-asyncio==24.2.3 lazy-object-proxy==1.9.0 ldap3==2.9.1 limits==3.5.0 linkify-it-py==2.0.2 locket==1.0.0 lockfile==0.12.2 looker-sdk==23.8.1 lxml==4.9.2 Mako==1.2.4 Markdown==3.4.3 markdown-it-py==2.2.0 MarkupSafe==2.1.3 marshmallow==3.19.0 marshmallow-enum==1.5.1 marshmallow-oneofschema==3.0.1 marshmallow-sqlalchemy==0.26.1 mdit-py-plugins==0.3.5 mdurl==0.1.2 msal==1.22.0 msal-extensions==1.0.0 msgpack==1.0.5 msrest==0.7.1 msrestazure==0.6.4 multidict==6.0.4 mypy-boto3-appflow==1.26.145 mypy-boto3-rds==1.26.144 mypy-boto3-redshift-data==1.26.109 mypy-boto3-s3==1.26.153 mysqlclient==2.1.1 numpy==1.21.6 oauthlib==3.2.2 ordered-set==4.1.0 oscrypto==1.3.0 packaging==21.3 pandas==1.3.5 pandas-gbq==0.19.2 paramiko==3.2.0 partd==1.4.0 pathspec==0.9.0 pendulum==2.1.2 pkgutil_resolve_name==1.3.10 platformdirs==3.5.3 pluggy==1.0.0 ply==3.11 portalocker==2.7.0 prison==0.2.1 prometheus-client==0.17.0 prompt-toolkit==3.0.38 proto-plus==1.22.2 protobuf==4.23.2 psutil==5.9.5 psycopg2-binary==2.9.6 pyarrow==11.0.0 pyasn1==0.4.8 pyasn1-modules==0.2.8 pycparser==2.21 pycryptodomex==3.18.0 pydantic==1.10.9 pydata-google-auth==1.8.0 Pygments==2.15.1 pyhcl==0.4.4 PyJWT==2.7.0 PyNaCl==1.5.0 pyodbc==4.0.39 pyOpenSSL==23.2.0 pyparsing==3.0.9 pyrsistent==0.19.3 python-daemon==3.0.1 python-dateutil==2.8.2 python-dotenv==0.21.1 python-http-client==3.3.7 python-ldap==3.4.3 python-nvd3==0.15.0 python-slugify==8.0.1 pytz==2023.3 pytzdata==2020.1 PyYAML==6.0 redis==4.5.5 redshift-connector==2.0.911 requests==2.31.0 requests-oauthlib==1.3.1 requests-toolbelt==1.0.0 rfc3339-validator==0.1.4 rfc3986==1.5.0 rich==13.4.2 rich_argparse==1.1.1 rsa==4.9 s3transfer==0.6.1 scramp==1.4.4 sendgrid==6.10.0 setproctitle==1.3.2 Shapely==1.8.5.post1 six==1.16.0 slack-sdk==3.21.3 sniffio==1.3.0 snowflake-connector-python==3.0.4 snowflake-sqlalchemy==1.4.7 sortedcontainers==2.4.0 soupsieve==2.4.1 SQLAlchemy==1.4.48 sqlalchemy-bigquery==1.6.1 SQLAlchemy-JSONField==1.0.1.post0 sqlalchemy-redshift==0.8.14 SQLAlchemy-Utils==0.41.1 sqlparse==0.4.4 sshtunnel==0.4.0 starkbank-ecdsa==2.2.0 statsd==4.0.1 tabulate==0.9.0 tblib==1.7.0 tenacity==8.2.2 termcolor==2.3.0 text-unidecode==1.3 toolz==0.12.0 tornado==6.2 typing_extensions==4.6.3 uc-micro-py==1.0.2 unicodecsv==0.14.1 uritemplate==4.1.1 urllib3==1.26.16 vine==5.0.0 virtualenv==20.21.1 watchtower==2.0.1 wcwidth==0.2.6 websocket-client==1.5.3 Werkzeug==2.2.3 wrapt==1.15.0 WTForms==3.0.1 yarl==1.9.2 zict==2.2.0 zipp==3.15.0 zope.event==4.6 zope.interface==6.0

scobit commented 1 year ago

any ideas?, or could someone give me advice where I can get help (forum, github page etc)

dpgaspar commented 1 year ago

troubleshoot with ldapsearch and change AUTH_LDAP_USERNAME_FORMAT and AUTH_LDAP_UID_FIELD

take a look at: https://github.com/dpgaspar/Flask-AppBuilder/issues/800 https://github.com/dpgaspar/Flask-AppBuilder/issues/573 https://itsecureadmin.com/2019/02/05/apache-airflow-1-10-2-active-directory-authentication-via-ldaps/

scobit commented 1 year ago

Thank you, after several test actions it works. In case of someone is interested, final config for local airflow deployment v 2.2.4 below.

import os

from airflow import configuration as conf from flask_appbuilder.security.manager import AUTH_LDAP AUTH_TYPE = AUTH_LDAP AUTH_LDAP_SERVER = "ldap://example.com:389" AUTH_LDAP_USE_TLS = False

AUTH_USER_REGISTRATION = True
AUTH_USER_REGISTRATION_ROLE = "Public"
AUTH_LDAP_FIRSTNAME_FIELD = "givenName" AUTH_LDAP_LASTNAME_FIELD = "sn" AUTH_LDAP_EMAIL_FIELD = "mail"

AUTH_LDAP_USERNAME_FORMAT = "cn=%s,OU=Users,DC=example,DC=com"

AUTH_LDAP_SEARCH = "cn=%s,OU=Users,DC=example,DC=com" AUTH_LDAP_UID_FIELD = "samAccountName"

AUTH_LDAP_BIND_USER = "samAccountName=PeterParker,OU=Users,DC=example,DC=com" AUTH_LDAP_BIND_PASSWORD = "ParkerPassword"

AUTH_ROLES_MAPPING = { "CN=airflow-admin,OU=Groups,DC=example,DC=com": ["Admin"], }

AUTH_LDAP_GROUP_FIELD = "memberOf" AUTH_ROLES_SYNC_AT_LOGIN = True

PERMANENT_SESSION_LIFETIME = 1800