mirror of
https://github.com/open-webui/open-webui.git
synced 2026-09-14 23:22:44 +00:00
ldap.server.use_ad_sid
This commit is contained in:
parent
1c5e84ddf2
commit
2c7df30241
4 changed files with 85 additions and 2 deletions
|
|
@ -4010,6 +4010,10 @@ LDAP_VALIDATE_CERT = PersistentConfig(
|
|||
|
||||
LDAP_CIPHERS = PersistentConfig('LDAP_CIPHERS', 'ldap.server.ciphers', os.environ.get('LDAP_CIPHERS', 'ALL'))
|
||||
|
||||
LDAP_USE_AD_SID = PersistentConfig(
|
||||
"LDAP_USE_AD_SID", "ldap.server.use_ad_sid", os.environ.get("LDAP_USE_AD_SID", "False").lower() == "true"
|
||||
)
|
||||
|
||||
# For LDAP Group Management
|
||||
ENABLE_LDAP_GROUP_MANAGEMENT = PersistentConfig(
|
||||
'ENABLE_LDAP_GROUP_MANAGEMENT',
|
||||
|
|
|
|||
|
|
@ -425,6 +425,7 @@ from open_webui.config import (
|
|||
LDAP_CA_CERT_FILE,
|
||||
LDAP_VALIDATE_CERT,
|
||||
LDAP_CIPHERS,
|
||||
LDAP_USE_AD_SID,
|
||||
# LDAP Group Management
|
||||
ENABLE_LDAP_GROUP_MANAGEMENT,
|
||||
ENABLE_LDAP_GROUP_CREATION,
|
||||
|
|
@ -914,6 +915,7 @@ app.state.config.LDAP_USE_TLS = LDAP_USE_TLS
|
|||
app.state.config.LDAP_CA_CERT_FILE = LDAP_CA_CERT_FILE
|
||||
app.state.config.LDAP_VALIDATE_CERT = LDAP_VALIDATE_CERT
|
||||
app.state.config.LDAP_CIPHERS = LDAP_CIPHERS
|
||||
app.state.config.LDAP_USE_AD_SID = LDAP_USE_AD_SID
|
||||
|
||||
# For LDAP Group Management
|
||||
app.state.config.ENABLE_LDAP_GROUP_MANAGEMENT = ENABLE_LDAP_GROUP_MANAGEMENT
|
||||
|
|
|
|||
|
|
@ -97,12 +97,11 @@ class AuthsTable:
|
|||
role: str = 'pending',
|
||||
oauth: Optional[dict] = None,
|
||||
db: Optional[Session] = None,
|
||||
id: Optional[str] = str(uuid.uuid4()),
|
||||
) -> Optional[UserModel]:
|
||||
with get_db_context(db) as db:
|
||||
log.info('insert_new_auth')
|
||||
|
||||
id = str(uuid.uuid4())
|
||||
|
||||
auth = AuthModel(**{'id': id, 'email': email, 'password': password, 'active': True})
|
||||
result = Auth(**auth.model_dump())
|
||||
db.add(result)
|
||||
|
|
|
|||
78
backend/open_webui/routers/auths.py
Normal file → Executable file
78
backend/open_webui/routers/auths.py
Normal file → Executable file
|
|
@ -302,6 +302,58 @@ async def update_password(
|
|||
raise HTTPException(400, detail=ERROR_MESSAGES.INVALID_CRED)
|
||||
|
||||
|
||||
############################
|
||||
# LDAP Helper Functions
|
||||
############################
|
||||
|
||||
|
||||
def convert_ad_sid_to_string(sid_bytes):
|
||||
"""
|
||||
Convert Active Directory binary SID to string format.
|
||||
|
||||
Args:
|
||||
sid_bytes: Binary SID from AD (objectSid attribute)
|
||||
|
||||
Returns:
|
||||
String representation like "S-1-5-21-3396494274-2626632863-120886085-599475"
|
||||
or None if conversion fails
|
||||
"""
|
||||
if not sid_bytes or not isinstance(sid_bytes, bytes):
|
||||
return None
|
||||
|
||||
try:
|
||||
# SID structure: S-Revision-IdentifierAuthority-SubAuthority1-SubAuthority2-...
|
||||
# Revision (1 byte)
|
||||
revision = sid_bytes[0]
|
||||
|
||||
# Number of SubAuthorities (1 byte)
|
||||
sub_auth_count = sid_bytes[1]
|
||||
|
||||
# IdentifierAuthority (6 bytes, big-endian)
|
||||
identifier_authority = int.from_bytes(sid_bytes[2:8], byteorder='big')
|
||||
|
||||
# SubAuthorities (4 bytes each, little-endian)
|
||||
sub_authorities = []
|
||||
for i in range(sub_auth_count):
|
||||
offset = 8 + (i * 4)
|
||||
sub_auth = int.from_bytes(
|
||||
sid_bytes[offset:offset + 4],
|
||||
byteorder='little'
|
||||
)
|
||||
sub_authorities.append(str(sub_auth))
|
||||
|
||||
# Construct SID string
|
||||
sid_string = f"S-{revision}-{identifier_authority}"
|
||||
if sub_authorities:
|
||||
sid_string += "-" + "-".join(sub_authorities)
|
||||
|
||||
return sid_string
|
||||
|
||||
except Exception as e:
|
||||
log.error(f"Failed to convert AD SID to string: {str(e)}")
|
||||
return None
|
||||
|
||||
|
||||
############################
|
||||
# LDAP Authentication
|
||||
############################
|
||||
|
|
@ -336,6 +388,7 @@ async def ldap_auth(
|
|||
LDAP_CA_CERT_FILE = request.app.state.config.LDAP_CA_CERT_FILE
|
||||
LDAP_VALIDATE_CERT = CERT_REQUIRED if request.app.state.config.LDAP_VALIDATE_CERT else CERT_NONE
|
||||
LDAP_CIPHERS = request.app.state.config.LDAP_CIPHERS if request.app.state.config.LDAP_CIPHERS else 'ALL'
|
||||
LDAP_USE_AD_SID = request.app.state.config.LDAP_USE_AD_SID
|
||||
|
||||
try:
|
||||
tls = Tls(
|
||||
|
|
@ -378,6 +431,9 @@ async def ldap_auth(
|
|||
if ENABLE_LDAP_GROUP_MANAGEMENT:
|
||||
search_attributes.append(f'{LDAP_ATTRIBUTE_FOR_GROUPS}')
|
||||
log.info(f'LDAP Group Management enabled. Adding {LDAP_ATTRIBUTE_FOR_GROUPS} to search attributes')
|
||||
if LDAP_USE_AD_SID:
|
||||
search_attributes.append('objectSid')
|
||||
log.info('LDAP AD SID usage enabled. Adding objectSid to search attributes')
|
||||
log.info(f'LDAP search attributes: {search_attributes}')
|
||||
|
||||
search_success = await asyncio.to_thread(
|
||||
|
|
@ -412,6 +468,22 @@ async def ldap_auth(
|
|||
cn = str(entry['cn']) # common name
|
||||
user_dn = entry.entry_dn # user distinguished name
|
||||
|
||||
# Extract and convert AD SID if enabled
|
||||
user_id = None
|
||||
if LDAP_USE_AD_SID and "objectSid" in entry:
|
||||
try:
|
||||
sid_bytes = entry["objectSid"].value
|
||||
if sid_bytes:
|
||||
user_id = convert_ad_sid_to_string(sid_bytes)
|
||||
if user_id:
|
||||
log.info(f"Successfully extracted AD SID for user {username_list}: {user_id}")
|
||||
else:
|
||||
log.warning(f"Failed to convert AD SID for user {username_list}, will use UUID fallback")
|
||||
except Exception as e:
|
||||
log.warning(f"Error extracting AD SID for user {username_list}: {str(e)}, will use UUID fallback")
|
||||
elif LDAP_USE_AD_SID:
|
||||
log.warning(f"LDAP_USE_AD_SID enabled but objectSid not found for user {username_list}, will use UUID fallback")
|
||||
|
||||
user_groups = []
|
||||
if ENABLE_LDAP_GROUP_MANAGEMENT and LDAP_ATTRIBUTE_FOR_GROUPS in entry:
|
||||
group_dns = entry[LDAP_ATTRIBUTE_FOR_GROUPS]
|
||||
|
|
@ -481,12 +553,18 @@ async def ldap_auth(
|
|||
try:
|
||||
role = 'admin' if not Users.has_users(db=db) else request.app.state.config.DEFAULT_USER_ROLE
|
||||
|
||||
kwargs = {}
|
||||
if user_id:
|
||||
log.info(f"Creating LDAP user with AD SID as ID: {user_id}")
|
||||
kwargs["id"] = user_id
|
||||
|
||||
user = Auths.insert_new_auth(
|
||||
email=email,
|
||||
password=str(uuid.uuid4()),
|
||||
name=cn,
|
||||
role=role,
|
||||
db=db,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
if not user:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue