Browse Source

Merge pull request #76 from freedomkk-qfeng/master

refactor ldap login mode
laiwei 6 years ago
parent
commit
51e0d3423b
3 changed files with 82 additions and 15 deletions
  1. 4 1
      rrd/config.py
  2. 20 9
      rrd/view/auth/auth.py
  3. 58 5
      rrd/view/utils.py

+ 4 - 1
rrd/config.py

@@ -23,6 +23,8 @@ SITE_COOKIE = os.environ.get("SITE_COOKIE","open-falcon-ck")
 
 # Falcon+ API
 API_ADDR = os.environ.get("API_ADDR","http://127.0.0.1:8080/api/v1")
+API_USER = os.environ.get("API_USER","admin")
+API_PASS = os.environ.get("API_PASS","password")
 
 # portal database
 # TODO: read from api instead of db
@@ -44,7 +46,8 @@ ALARM_DB_NAME = os.environ.get("ALARM_DB_NAME","alarms")
 LDAP_ENABLED = os.environ.get("LDAP_ENABLED",False)
 LDAP_SERVER = os.environ.get("LDAP_SERVER","ldap.forumsys.com:389")
 LDAP_BASE_DN = os.environ.get("LDAP_BASE_DN","dc=example,dc=com")
-LDAP_BINDDN_FMT = os.environ.get("LDAP_BINDDN_FMT","uid=%s,dc=example,dc=com")
+LDAP_BINDDN = os.environ.get("LDAP_BINDDN","cn=manager,dc=example,dc=org")
+LDAP_BIND_PASS = os.environ.get("LDAP_BIND_PASS","password")
 LDAP_SEARCH_FMT = os.environ.get("LDAP_SEARCH_FMT","uid=%s")
 LDAP_ATTRS = ["cn","mail","telephoneNumber"]
 LDAP_TLS_START_TLS = False

+ 20 - 9
rrd/view/auth/auth.py

@@ -18,6 +18,8 @@ from flask import request, g, abort, render_template, redirect
 from flask.ext.babel import refresh
 import requests
 import json
+import string
+import random
 from rrd import app
 from rrd import config
 from rrd.model.user import User
@@ -26,6 +28,9 @@ from rrd.view import utils as view_utils
 from rrd.utils.logger import logging
 log = logging.getLogger(__file__)
 
+def id_generator(size=16, chars=string.ascii_uppercase + string.digits):
+   return ''.join(random.choice(chars) for _ in range(size)) 
+
 @app.route("/auth/login", methods=["GET", "POST"])
 def auth_login():
     if request.method == "GET":
@@ -48,21 +53,27 @@ def auth_login():
         if ldap == "1":
             try:
                 ldap_info = view_utils.ldap_login_user(name, password)
-
-                h = {"Content-type":"application/json"}
-                d = {
+                password = id_generator()
+                user_info = {
                     "name": name,
                     "password": password,
                     "cnname": ldap_info['cnname'],
                     "email": ldap_info['email'],
                     "phone": ldap_info['phone'],
                 }
-
-                r = requests.post("%s/user/create" %(config.API_ADDR,), \
-                        data=json.dumps(d), headers=h)
-                log.debug("%s:%s" %(r.status_code, r.text))
-
-                #TODO: update password in db if ldap password changed
+                Apitoken = view_utils.get_Apitoken(config.API_USER, config.API_PASS)
+
+                ut = view_utils.admin_login_user(name, Apitoken)
+                if not ut:
+                    view_utils.create_user(user_info)
+                    ut = view_utils.admin_login_user(name, Apitoken)
+                    #if user not exist, create user , signup must be enabled
+                ret["data"] = {
+                        "name": ut.name,
+                        "sig": ut.sig,
+                }
+                return json.dumps(ret)
+					
             except Exception as e:
                 ret["msg"] = str(e)
                 return json.dumps(ret)

+ 58 - 5
rrd/view/utils.py

@@ -116,17 +116,34 @@ def login_user(name, password):
     set_user_cookie(ut, session)
     return ut
 
+def admin_login_user(name, Apitoken):
+    params = {
+        "name": name,
+    }
+    h = {
+        "Apitoken": Apitoken
+    }
+    r = requests.post("%s/admin/login" %config.API_ADDR, data=params, headers=h)
+    log.debug("%s:%s" %(r.status_code, r.text))
+    if r.status_code != 200:
+        if json.loads(r.text)["error"] == "no such user":
+            return None
+        else:
+            raise Exception("%s : %s" %(r.status_code, r.text))
+
+    j = r.json()
+    ut = UserToken(j["name"], j["sig"])
+    set_user_cookie(ut, session)
+    return ut
 
 def ldap_login_user(name, password):
     import ldap
     if not config.LDAP_ENABLED:
         raise Exception("ldap not enabled")
 
-    bind_dn = config.LDAP_BINDDN_FMT
+    bind_dn = config.LDAP_BINDDN
+    bind_pass = config.LDAP_BIND_PASS
     base_dn = config.LDAP_BASE_DN
-    try:
-        bind_dn = config.LDAP_BINDDN_FMT %name
-    except TypeError: pass
 
     search_filter = config.LDAP_SEARCH_FMT
     try:
@@ -150,9 +167,11 @@ def ldap_login_user(name, password):
                 cli.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, config.LDAP_TLS_REQUIRE_CERT)
             if config.LDAP_TLS_CIPHER_SUITE:
                 cli.set_option(ldap.OPT_X_TLS_CIPHER_SUITE, config.LDAP_TLS_CIPHER_SUITE)
-        cli.simple_bind_s(bind_dn, password)
+        cli.bind_s(bind_dn, bind_pass, ldap.AUTH_SIMPLE)
         result = cli.search_s(base_dn, ldap.SCOPE_SUBTREE, search_filter, config.LDAP_ATTRS)
         log.debug("ldap result: %s" % result)
+        user_dn = result[0][0]
+        cli.bind_s(user_dn, password, ldap.AUTH_SIMPLE)
         d = result[0][1]
         email = d['mail'][0]
         cnname = d['cn'][0]
@@ -173,9 +192,43 @@ def ldap_login_user(name, password):
                 "phone": phone,
         }
     except ldap.LDAPError as e:
+        if "desc" in e[0]:
+            raise NameError(e[0]["desc"])
         cli and cli.unbind_s()
         raise e
     except (IndexError, KeyError) as e:
+        if str(e) == "list index out of range":
+            raise IndexError("no such user")
+            # result = [], so result out of range
         raise e
     finally:
         cli and cli.unbind_s()
+
+def get_Apitoken(name, password):
+    d = {
+        "name": name, "password": password,
+    }
+	
+    h = {"Content-type":"application/json"}
+	
+    r = requests.post("%s/user/login" %(config.API_ADDR,), \
+            data=json.dumps(d), headers=h)
+    log.debug("%s:%s" %(r.status_code, r.text))
+	
+    if r.status_code != 200:
+        raise Exception("%s %s" %(r.status_code, r.text))
+
+    sig = json.loads(r.text)["sig"]
+    return json.dumps({"name":name,"sig":sig})
+
+def create_user(user_info):
+    h = {"Content-type":"application/json"}
+	
+    r = requests.post("%s/user/create" %(config.API_ADDR,), \
+           data=json.dumps(user_info), headers=h)
+    log.debug("%s:%s" %(r.status_code, r.text))
+	
+    if r.status_code != 200:
+        raise Exception("%s %s" %(r.status_code, r.text))
+		
+    return