diff --git a/cmdb-api/Pipfile b/cmdb-api/Pipfile index 2cc3fb4..b8dbf52 100644 --- a/cmdb-api/Pipfile +++ b/cmdb-api/Pipfile @@ -25,6 +25,7 @@ supervisor = "==4.0.3" Flask-Login = "==0.4.1" Flask-Bcrypt = "==0.7.1" Flask-Cors = ">=3.0.8" +python-ldap = "==3.2.0" # Caching Flask-Caching = ">=1.0.0" # Environment variable parsing diff --git a/cmdb-api/api/lib/perm/auth.py b/cmdb-api/api/lib/perm/auth.py index 5020dbf..4257f41 100644 --- a/cmdb-api/api/lib/perm/auth.py +++ b/cmdb-api/api/lib/perm/auth.py @@ -13,8 +13,8 @@ from flask import request from flask import session from flask_login import login_user -from api.models.acl import User from api.lib.perm.acl.cache import UserCache +from api.models.acl import User def _auth_with_key(): diff --git a/cmdb-api/api/models/acl.py b/cmdb-api/api/models/acl.py index 98eeae5..aec6194 100644 --- a/cmdb-api/api/models/acl.py +++ b/cmdb-api/api/models/acl.py @@ -5,6 +5,7 @@ import copy import hashlib from datetime import datetime +import ldap from flask import current_app from flask_sqlalchemy import BaseQuery @@ -50,6 +51,32 @@ class UserQuery(BaseQuery): return user, authenticated + def authenticate_with_ldap(self, username, password): + ldap_conn = ldap.initialize(current_app.config.get('LDAP_SERVER')) + ldap_conn.protocol_version = 3 + ldap_conn.set_option(ldap.OPT_REFERRALS, 0) + if '@' in username: + who = '{0}@{1}'.format(username.split('@')[0], current_app.config.get('LDAP_DOMAIN')) + else: + who = '{0}@{1}'.format(username, current_app.config.get('LDAP_DOMAIN')) + + username = username.split('@')[0] + user = self.get_by_username(username) + try: + + if not password: + raise ldap.INVALID_CREDENTIALS + + ldap_conn.simple_bind_s(who, password) + + if not user: + from api.lib.perm.acl.user import UserCRUD + user = UserCRUD.add(username=username, email=who) + + return user, True + except ldap.INVALID_CREDENTIALS: + return user, False + def search(self, key): query = self.filter(db.or_(User.email == key, User.nickname.ilike('%' + key + '%'), diff --git a/cmdb-api/api/views/account.py b/cmdb-api/api/views/account.py index df7c22a..37ed17b 100644 --- a/cmdb-api/api/views/account.py +++ b/cmdb-api/api/views/account.py @@ -26,7 +26,10 @@ class LoginView(APIView): def post(self): username = request.values.get("username") or request.values.get("email") password = request.values.get("password") - user, authenticated = User.query.authenticate(username, password) + if current_app.config.get('AUTH_WITH_LDAP'): + user, authenticated = User.query.authenticate_with_ldap(username, password) + else: + user, authenticated = User.query.authenticate(username, password) if not user: return abort(403, "User <{0}> does not exist".format(username)) if not authenticated: diff --git a/cmdb-api/requirements.txt b/cmdb-api/requirements.txt index 476b050..34153b0 100644 --- a/cmdb-api/requirements.txt +++ b/cmdb-api/requirements.txt @@ -20,6 +20,7 @@ supervisor == 4.0.3 Flask-Login == 0.4.1 Flask-Bcrypt == 0.7.1 Flask-Cors >= 3.0.8 +python-ldap == 3.2.0 # Caching Flask-Caching >= 1.0.0 # Environment variable parsing diff --git a/cmdb-api/settings.py.example b/cmdb-api/settings.py.example index 593fbbc..b28c568 100644 --- a/cmdb-api/settings.py.example +++ b/cmdb-api/settings.py.example @@ -69,6 +69,11 @@ CAS_VALIDATE_ROUTE = "/cas/serviceValidate" CAS_AFTER_LOGIN = "/" DEFAULT_SERVICE = "http://127.0.0.1:8000" +# # ldap +AUTH_WITH_LDAP = False +LDAP_SERVER = '' +LDAP_DOMAIN = '' + # # pagination DEFAULT_PAGE_COUNT = 50