From ac6f66b08341db7ede38840891b2e836e1d658f7 Mon Sep 17 00:00:00 2001 From: Guillaume GILL Date: Wed, 8 Nov 2017 00:35:38 +0100 Subject: [PATCH] Make LDAP auth fonctionnal --- octoprint_auth_ldap/__init__.py | 82 ++++++++++++++++++++++++++++----- requirements.txt | 3 ++ setup.py | 8 ++-- 3 files changed, 77 insertions(+), 16 deletions(-) diff --git a/octoprint_auth_ldap/__init__.py b/octoprint_auth_ldap/__init__.py index efc21c8..fdefa49 100644 --- a/octoprint_auth_ldap/__init__.py +++ b/octoprint_auth_ldap/__init__.py @@ -1,49 +1,107 @@ # coding=utf-8 from __future__ import absolute_import -from octoprint.users import FilebasedUserManager +from octoprint.users import FilebasedUserManager, User from octoprint.settings import settings import ldap import uuid class LDAPUserManager(FilebasedUserManager): + #Login phase : + # - findUser called, if it return a user + # - chaeckPassword called, if it return True + # - login_user called with User returned by previous findUser + def checkPassword(self, username, password): ldap_server = settings().get(["accessControl", "ldap_uri"]) ldap_search_base = settings().get(["accessControl", "ldap_search_base"]) + ldap_verifypeer = settings().get(["accessControl", "ldap_tls_reqcert"]) + self._logger.debug(ldap_server) + self._logger.debug(ldap_search_base) if ldap_server is None or ldap_search_base is None: - self._logger.debug("LDAP conf error") + self._logger.error("LDAP conf error") return False - dn = "uid=" + username + ",ou=users," + ldap_search_base + + #@TODO Voir pour sortir le groupe "smile" de là... + group = "ou=smile,ou=users" + dn = "uid=" + username + "," + group + "," + ldap_search_base try: connection = ldap.initialize(ldap_server) - connection.start_tls_s() + if (ldap_server.startswith('ldaps://')): + verifypeer = ldap.OPT_X_TLS_NEVER + if ldap_verifypeer == 'demand': + verifypeer = ldap.OPT_X_TLS_DEMAND + connection.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, verifypeer) + try: + connection.start_tls_s() + except: + pass + connection.bind_s(dn, password) + connection.unbind_s() - user = self.findUser(username) + user = FilebasedUserManager.findUser(self, username) if not user: - self.addUser(username, uuid.uuid4(), True) + self.addUser(username, str(uuid.uuid4()), True) return True except ldap.INVALID_CREDENTIALS: - self._logger.debug("LDAP : Your username or password is incorrect.") + self._logger.error("LDAP : Your username or password is incorrect.") return FilebasedUserManager.checkPassword(self, username, password) except ldap.LDAPError, e: if type(e.message) == dict: for (k, v) in e.message.iteritems(): - self._logger.debug("%s: %sn" % (k, v)) + self._logger.error("%s: %sn" % (k, v)) else: - self._logger.debug(e.message) + self._logger.error(e.message) return False -def changeUserPassword(self, username, password): - pass + def changeUserPassword(self, username, password): + pass + + def findUser(self, userid=None, session=None): + local_user = FilebasedUserManager.findUser(self, userid, session) + #If user not exists in local database, search it on LDAP + if userid and not local_user: + ldap_server = settings().get(["accessControl", "ldap_uri"]) + ldap_search_base = settings().get(["accessControl", "ldap_search_base"]) + ldap_verifypeer = settings().get(["accessControl", "ldap_tls_reqcert"]) + + try: + connection = ldap.initialize(ldap_server) + if (ldap_server.startswith('ldaps://')): + verifypeer = ldap.OPT_X_TLS_NEVER + if ldap_verifypeer == 'demand': + verifypeer = ldap.OPT_X_TLS_DEMAND + connection.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, verifypeer) + try: + connection.start_tls_s() + except: + pass + + result = connection.search_s(ldap_search_base, ldap.SCOPE_SUBTREE, "uid="+userid) + connection.unbind_s() + if (result is None or len(result) == 0): + return None + + #Return a fake user instance + return User(userid, str(uuid.uuid4()), True, ["user"]) + + except ldap.LDAPError, e: + if type(e.message) == dict: + for (k, v) in e.message.iteritems(): + self._logger.error("%s: %sn" % (k, v)) + else: + self._logger.error(e.message) + return None + else : + return local_user def ldap_user_factory(components, settings, *args, **kwargs): return LDAPUserManager(); __plugin_name__ = "Auth LDAP" __plugin_version__ = "1.0.0" -__plugin_description__ = "LDAP authentication" def __plugin_load__(): global __plugin_hooks__ diff --git a/requirements.txt b/requirements.txt index 3175f72..2b4328b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,4 +7,7 @@ # variables INSTALL_REQUIRES and EXTRA_REQUIRES. ### +## To install correctly python-ldap you need : +# apt-get install libsasl2-dev python-dev libldap2-dev libssl-dev + . diff --git a/setup.py b/setup.py index 2dfc210..707b622 100644 --- a/setup.py +++ b/setup.py @@ -14,11 +14,11 @@ plugin_package = "octoprint_%s" % plugin_identifier plugin_name = "OctoPrint-LDAP" # The plugin's version. Can be overwritten within OctoPrint's internal data via __plugin_version__ in the plugin module -plugin_version = "0.1" +plugin_version = "1.0.0" # The plugin's description. Can be overwritten within OctoPrint's internal data via __plugin_description__ in the plugin # module -plugin_description = "TODO" +plugin_description = "LDAP Auth provider" # The plugin's author. Can be overwritten within OctoPrint's internal data via __plugin_author__ in the plugin module plugin_author = "Guillaume GILL" @@ -27,13 +27,13 @@ plugin_author = "Guillaume GILL" plugin_author_email = "guillaume.gill@petitchinois.net" # The plugin's homepage URL. Can be overwritten within OctoPrint's internal data via __plugin_url__ in the plugin module -plugin_url = "TODO" +plugin_url = "https://github.com/gillg/OctoPrint-LDAP" # The plugin's license. Can be overwritten within OctoPrint's internal data via __plugin_license__ in the plugin module plugin_license = "AGPLv3" # Any additional requirements besides OctoPrint should be listed here -plugin_requires = ["ldap","uuid"] +plugin_requires = ["python-ldap","uuid"] # Additional package data to install for this plugin. The subfolders "templates", "static" and "translations" will # already be installed automatically if they exist.