From 23fea9fffab655a0985f30e49552f3e319cd38c1 Mon Sep 17 00:00:00 2001 From: Luc Didry Date: Tue, 18 Feb 2025 11:28:05 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20=E2=80=94=20Automatically=20reco?= =?UTF-8?q?nnect=20to=20LDAP=20if=20unreachable=20(fix=20#81)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + argos/server/main.py | 4 +--- argos/server/routes/dependencies.py | 13 +++++++++++-- argos/server/routes/views.py | 9 +++++++++ 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a110977..8d7f58d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - ✨ — No need cron tasks for DB cleaning anymore (#74 and #75) - ✨ — No need cron tasks for agents watching (#76) - ✨ — Reload configuration asynchronously (#79) +- 🐛 — Automatically reconnect to LDAP if unreachable (#81) ## 0.7.4 diff --git a/argos/server/main.py b/argos/server/main.py index 65828ee..c4623d2 100644 --- a/argos/server/main.py +++ b/argos/server/main.py @@ -39,9 +39,7 @@ def get_application() -> FastAPI: if config.general.ldap is not None: import ldap - l = ldap.initialize(config.general.ldap.uri) - l.simple_bind_s(config.general.ldap.bind_dn, config.general.ldap.bind_pwd) - appli.state.ldap = l + appli.state.ldap = ldap.initialize(config.general.ldap.uri) @appli.state.manager.user_loader() async def query_user(user: str) -> None | str | models.User: diff --git a/argos/server/routes/dependencies.py b/argos/server/routes/dependencies.py index e61b77a..ed0399a 100644 --- a/argos/server/routes/dependencies.py +++ b/argos/server/routes/dependencies.py @@ -2,6 +2,8 @@ from fastapi import Depends, HTTPException, Request from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer from fastapi_login import LoginManager +from argos.logging import logger + auth_scheme = HTTPBearer() @@ -33,12 +35,19 @@ async def verify_token( return token -async def find_ldap_user(config, ldap, user: str) -> str | None: +async def find_ldap_user(config, ldapobj, user: str) -> str | None: """Do a LDAP search for user and return its dn""" + import ldap import ldap.filter as ldap_filter from ldapurl import LDAP_SCOPE_SUBTREE - result = ldap.search_s( + try: + ldapobj.simple_bind_s(config.general.ldap.bind_dn, config.general.ldap.bind_pwd) + except ldap.LDAPError as err: # pylint: disable-msg=no-member + logger.error("LDAP error: %s", err) + return None + + result = ldapobj.search_s( config.general.ldap.user_tree, LDAP_SCOPE_SUBTREE, filterstr=ldap_filter.filter_format( diff --git a/argos/server/routes/views.py b/argos/server/routes/views.py index 3242972..3da2a6b 100644 --- a/argos/server/routes/views.py +++ b/argos/server/routes/views.py @@ -90,6 +90,15 @@ async def post_login( from ldap import INVALID_CREDENTIALS # pylint: disable-msg=no-name-in-module from argos.server.routes.dependencies import find_ldap_user + invalid_credentials = templates.TemplateResponse( + "login.html", + { + "request": request, + "msg": "Sorry, invalid username or bad password. " + "Or the LDAP server is unreachable (see logs to verify).", + }, + ) + ldap_dn = await find_ldap_user(config, request.app.state.ldap, username) if ldap_dn is None: return invalid_credentials