Add enterprise level LDAP authentication
This commit is contained in:
parent
785e83b221
commit
d1ed6ddd9d
@ -38,7 +38,6 @@ def create_app() -> DifyApp:
|
|||||||
|
|
||||||
def initialize_extensions(app: DifyApp):
|
def initialize_extensions(app: DifyApp):
|
||||||
from extensions import (
|
from extensions import (
|
||||||
ext_ldap,
|
|
||||||
ext_app_metrics,
|
ext_app_metrics,
|
||||||
ext_blueprints,
|
ext_blueprints,
|
||||||
ext_celery,
|
ext_celery,
|
||||||
@ -48,6 +47,7 @@ def initialize_extensions(app: DifyApp):
|
|||||||
ext_database,
|
ext_database,
|
||||||
ext_hosting_provider,
|
ext_hosting_provider,
|
||||||
ext_import_modules,
|
ext_import_modules,
|
||||||
|
ext_ldap,
|
||||||
ext_logging,
|
ext_logging,
|
||||||
ext_login,
|
ext_login,
|
||||||
ext_mail,
|
ext_mail,
|
||||||
|
@ -5,10 +5,10 @@ from pydantic.fields import FieldInfo
|
|||||||
from pydantic_settings import BaseSettings, PydanticBaseSettingsSource, SettingsConfigDict
|
from pydantic_settings import BaseSettings, PydanticBaseSettingsSource, SettingsConfigDict
|
||||||
|
|
||||||
from .deploy import DeploymentConfig
|
from .deploy import DeploymentConfig
|
||||||
from .ldap import AuthenticationConfig
|
|
||||||
from .enterprise import EnterpriseFeatureConfig
|
from .enterprise import EnterpriseFeatureConfig
|
||||||
from .extra import ExtraServiceConfig
|
from .extra import ExtraServiceConfig
|
||||||
from .feature import FeatureConfig
|
from .feature import FeatureConfig
|
||||||
|
from .ldap import AuthenticationConfig
|
||||||
from .middleware import MiddlewareConfig
|
from .middleware import MiddlewareConfig
|
||||||
from .packaging import PackagingInfo
|
from .packaging import PackagingInfo
|
||||||
from .remote_settings_sources import RemoteSettingsSource, RemoteSettingsSourceConfig, RemoteSettingsSourceName
|
from .remote_settings_sources import RemoteSettingsSource, RemoteSettingsSourceConfig, RemoteSettingsSourceName
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
"""
|
||||||
@File : __init__.py.py
|
@File : __init__.py.py
|
||||||
@Time : 2025/3/6 {TIME}
|
@Time : 2025/3/6 {TIME}
|
||||||
@ -8,6 +7,7 @@
|
|||||||
from pydantic import Field
|
from pydantic import Field
|
||||||
from pydantic_settings import BaseSettings
|
from pydantic_settings import BaseSettings
|
||||||
|
|
||||||
|
|
||||||
class AuthenticationConfig(BaseSettings):
|
class AuthenticationConfig(BaseSettings):
|
||||||
"""LDAP authentication related configuration"""
|
"""LDAP authentication related configuration"""
|
||||||
# LDAP Authentication
|
# LDAP Authentication
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
"""
|
||||||
@File : ext_ldap.py
|
@File : ext_ldap.py
|
||||||
@Time : 2025/3/5 {TIME}
|
@Time : 2025/3/5 {TIME}
|
||||||
@Author : xxlaila
|
@Author : xxlaila
|
||||||
@Software: dify
|
@Software: dify
|
||||||
"""
|
"""
|
||||||
from flask_ldap3_login import LDAP3LoginManager
|
|
||||||
from configs import dify_config
|
|
||||||
from dify_app import DifyApp
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
from queue import Queue
|
from queue import Queue
|
||||||
from ldap3 import Server, Connection, ALL
|
|
||||||
|
from flask_ldap3_login import LDAP3LoginManager
|
||||||
|
from ldap3 import ALL, Connection, Server
|
||||||
|
|
||||||
|
from configs import dify_config
|
||||||
|
from dify_app import DifyApp
|
||||||
|
|
||||||
|
|
||||||
def is_enabled():
|
def is_enabled():
|
||||||
return getattr(dify_config, 'LDAP_ENABLED', False)
|
return getattr(dify_config, 'LDAP_ENABLED', False)
|
||||||
@ -54,7 +56,7 @@ def get_ldap_connection():
|
|||||||
return new_conn
|
return new_conn
|
||||||
raise Exception("LDAP connection reconstruction failed")
|
raise Exception("LDAP connection reconstruction failed")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"LDAP connection recovery failed: {str(e)}")
|
logging.exception(f"LDAP connection recovery failed: {e}")
|
||||||
raise
|
raise
|
||||||
return conn
|
return conn
|
||||||
|
|
||||||
@ -67,7 +69,7 @@ def release_ldap_connection(conn):
|
|||||||
conn.open() # Reopen connection without binding
|
conn.open() # Reopen connection without binding
|
||||||
LDAP_POOL.put(conn)
|
LDAP_POOL.put(conn)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Failed to recycle LDAP connection: {str(e)}")
|
logging.exception(f"Failed to recycle LDAP connection: {str(e)}")
|
||||||
conn.unbind()
|
conn.unbind()
|
||||||
|
|
||||||
def init_app(app: DifyApp):
|
def init_app(app: DifyApp):
|
||||||
|
@ -8,6 +8,8 @@ from datetime import UTC, datetime, timedelta
|
|||||||
from hashlib import sha256
|
from hashlib import sha256
|
||||||
from typing import Any, Optional, cast
|
from typing import Any, Optional, cast
|
||||||
|
|
||||||
|
from flask import current_app as app
|
||||||
|
from ldap3 import Connection, Server
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
from sqlalchemy import func
|
from sqlalchemy import func
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
@ -17,6 +19,7 @@ from configs import dify_config
|
|||||||
from constants.languages import language_timezone_mapping, languages
|
from constants.languages import language_timezone_mapping, languages
|
||||||
from events.tenant_event import tenant_was_created
|
from events.tenant_event import tenant_was_created
|
||||||
from extensions.ext_database import db
|
from extensions.ext_database import db
|
||||||
|
from extensions.ext_ldap import get_ldap_connection, release_ldap_connection
|
||||||
from extensions.ext_redis import redis_client
|
from extensions.ext_redis import redis_client
|
||||||
from libs.helper import RateLimiter, TokenManager
|
from libs.helper import RateLimiter, TokenManager
|
||||||
from libs.passport import PassportService
|
from libs.passport import PassportService
|
||||||
@ -57,10 +60,7 @@ from tasks.mail_account_deletion_task import send_account_deletion_verification_
|
|||||||
from tasks.mail_email_code_login import send_email_code_login_mail_task
|
from tasks.mail_email_code_login import send_email_code_login_mail_task
|
||||||
from tasks.mail_invite_member_task import send_invite_member_mail_task
|
from tasks.mail_invite_member_task import send_invite_member_mail_task
|
||||||
from tasks.mail_reset_password_task import send_reset_password_mail_task
|
from tasks.mail_reset_password_task import send_reset_password_mail_task
|
||||||
from extensions.ext_ldap import get_ldap_connection, release_ldap_connection
|
|
||||||
from ldap3 import Server, Connection, ALL
|
|
||||||
|
|
||||||
from flask import current_app as app
|
|
||||||
|
|
||||||
class TokenPair(BaseModel):
|
class TokenPair(BaseModel):
|
||||||
access_token: str
|
access_token: str
|
||||||
@ -217,7 +217,7 @@ class AccountService:
|
|||||||
finally:
|
finally:
|
||||||
release_ldap_connection(conn)
|
release_ldap_connection(conn)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"LDAP authentication error: {str(e)}")
|
logging.exception(f"LDAP authentication error: {str(e)}")
|
||||||
|
|
||||||
# Perform local authentication only if LDAP authentication explicitly fails
|
# Perform local authentication only if LDAP authentication explicitly fails
|
||||||
if not is_ldap_success:
|
if not is_ldap_success:
|
||||||
@ -303,7 +303,7 @@ class AccountService:
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
db.session.rollback() # Transaction rollback to prevent database pollution
|
db.session.rollback() # Transaction rollback to prevent database pollution
|
||||||
logging.error(f"Failed to create LDAP user or add to tenant: {str(e)}")
|
logging.exception(f"Failed to create LDAP user or add to tenant: {str(e)}")
|
||||||
raise AccountRegisterError("Failed to create LDAP user.")
|
raise AccountRegisterError("Failed to create LDAP user.")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
Loading…
Reference in New Issue
Block a user