diff --git a/flask-consul/manager.py b/flask-consul/manager.py index 321daa0..0279a15 100755 --- a/flask-consul/manager.py +++ b/flask-consul/manager.py @@ -7,7 +7,7 @@ skey_path = 'ConsulManager/assets/secret/skey' if consul_kv.get_kv_dict(skey_path) == {}: consul_kv.put_kv(skey_path,{'sk':''.join(str(uuid.uuid4()).split('-'))}) -from views import login, blackbox, consul, jobs, nodes, selfnode, selfrds, avd, exp, jms, edit_cloud +from views import login, blackbox, consul, jobs, nodes, selfnode, selfrds, avd, exp, jms, edit_cloud, ldap from views.prom import cloud_mysql_metrics from units.cloud import huaweicloud,alicloud,tencent_cloud from units.avd import avd_list @@ -29,6 +29,7 @@ app.register_blueprint(exp.blueprint) app.register_blueprint(jms.blueprint) app.register_blueprint(edit_cloud.blueprint) app.register_blueprint(cloud_mysql_metrics.blueprint) +app.register_blueprint(ldap.blueprint) class Config(object): JOBS = [] diff --git a/flask-consul/requirements.txt b/flask-consul/requirements.txt index 0c5b61c..ec9d27c 100644 --- a/flask-consul/requirements.txt +++ b/flask-consul/requirements.txt @@ -10,6 +10,7 @@ xlrd==1.2.0 #pyDes==2.0.1 pycryptodome==3.14.1 beautifulsoup4==4.11.1 +ldap3==2.9.1 huaweicloudsdkcore==3.1.8 huaweicloudsdkecs==3.1.8 huaweicloudsdkeps==3.1.8 diff --git a/flask-consul/units/json_response.py b/flask-consul/units/json_response.py new file mode 100644 index 0000000..1abbd1e --- /dev/null +++ b/flask-consul/units/json_response.py @@ -0,0 +1,11 @@ +""" +自定义返回数据格式 +""" + +def JsonResponse(data:str=None,msg:str=None,success:bool=None,code:int=200): + """ + An HttpResponse that allows its data to be rendered into + arbitrary media types. + """ + data = {"data": data, "msg": msg, "success": success, "code": code} + return data diff --git a/flask-consul/units/ldap/LdapUser.py b/flask-consul/units/ldap/LdapUser.py new file mode 100644 index 0000000..f61fc02 --- /dev/null +++ b/flask-consul/units/ldap/LdapUser.py @@ -0,0 +1,91 @@ +""" +ldap 用户认证 +""" + +from ldap3 import Server, Connection, ALL + +from units.ldap.ldap_consul import Ldap_Consul + + +class Ldap(object): + def __init__(self,**args): + self.ldap_url,self.port,self.rule,self.password = Ldap_Consul.get_consul_args(**args) + server = Server(self.ldap_url,port=self.port, get_info=ALL,connect_timeout=5) + self.conn = Connection(server, user=self.rule, password=self.password, auto_bind=True) + + + + #校验登录 + def authpass(self, username, password): + server = Server(self.ldap_url,port=self.port, get_info=ALL,connect_timeout=5) + conn = Connection(server, user="uid={0},xxxxxxxxxxxxx".format(username), + password="{0}".format(password), + check_names=True, lazy=False, raise_exceptions=False) + try: + conn.bind() + except Exception: + conn.bind() + + if conn.result["description"] == "success": + data = True + else: + data = False + + return data + + + #连接 + def conn_ldap(self): + self.conn.search('dc=lishicloud,dc=com', '(objectclass=person)', + attributes=['cn', 'displayName', 'departmentNumber']) + entry = self.conn.response + return entry + + + #获取用户 + def get_user(self,username=None,all=False): + ldap_user = [] + if all == False: + try: + result = self.conn_ldap() + except Exception: + result = self.conn_ldap() + + for user in result: + users = user.get("raw_attributes").get("cn")[0].decode("utf8") + if users == username: + try: + users = user.get("raw_attributes").get("displayName")[0].decode("utf-8") + return users + except Exception as e: + return False + else: + result = self.conn_ldap() + for user in result: + users = user.get("raw_attributes").get("cn")[0].decode("utf8") + ldap_user.append(users) + return ldap_user + + #创建用户 + def create_user(self): + objectclass = ['top', 'inetOrgPerson', 'posixAccount'] + c = self.conn.add('uid=user1,ou=People,dc=xxx,dc=com',objectclass, + {'cn': "user1", 'sn': 'user1',"employeeType":"developer", + 'gidNumber': 501, 'homeDirectory': '/home/users/{0}', 'uidNumber': 5000,"givenName":"user1", + "loginShell":"/bin/bash",'displayName': "测试用户",'userPassword': "111111", 'mail': 'user1@qq.com'}), + print(c) + + + #删除用户 + def delete_user(self): + c = self.conn.delete('cn=xxx,ou=People,dc=xxx,dc=com') + print(c) + + # def __del__(self): + # self.conn.delete() + + +if __name__ == '__main__': + ldap = Ldap() + result = ldap.delete_user() + print(result) diff --git a/flask-consul/units/ldap/ldap_consul.py b/flask-consul/units/ldap/ldap_consul.py new file mode 100644 index 0000000..eb7e129 --- /dev/null +++ b/flask-consul/units/ldap/ldap_consul.py @@ -0,0 +1,34 @@ +""" +截取前端ldap信息存入consul +""" +from units import consul_kv + + +class Ldap_Consul(): + + """ + 存储ldap信息 + """ + @staticmethod + def set_consul_args(**kwargs): + kwargs['port'] = int(kwargs.get("port")) + result = consul_kv.put_kv(f'ConsulManager/ldap/report', {**kwargs}) + if result: + return True + return False + + + """ + 获取ldap信息进行链接服务端 + """ + @staticmethod + def get_consul_args(**kwargs): + result = consul_kv.get_kv_dict("ConsulManager/ldap/report") + try: + result.get("ConsulManager/ldap/report").get("ldap_url") + except Exception: + return False + return result.get("ConsulManager/ldap/report").get("ldap_url"),\ + result.get("ConsulManager/ldap/report").get("port"),\ + result.get("ConsulManager/ldap/report").get("rule"),\ + result.get("ConsulManager/ldap/report").get("password") diff --git a/flask-consul/views/ldap.py b/flask-consul/views/ldap.py new file mode 100644 index 0000000..21572f6 --- /dev/null +++ b/flask-consul/views/ldap.py @@ -0,0 +1,40 @@ +""" +ldap信息填写 +""" +from flask import Blueprint +from flask_restful import reqparse, Resource, Api +import sys + +from units.json_response import JsonResponse +from units.ldap.ldap_consul import Ldap_Consul + +sys.path.append("..") +from units import token_auth, consul_kv +from itsdangerous import TimedJSONWebSignatureSerializer + +secret_key = consul_kv.get_value('ConsulManager/assets/secret/skey')['sk'] +s = TimedJSONWebSignatureSerializer(secret_key,expires_in=28800) + +blueprint = Blueprint('ldap',__name__) +api = Api(blueprint) +parser = reqparse.RequestParser() + +parser.add_argument('ldap_url',type=str) +parser.add_argument('password',type=str) +parser.add_argument('port',type=str) +parser.add_argument('rule',type=str) + + + + +class LdapView(Resource): + """ + 封装了公共返回格式 + {"code": code,"success": success, "message": msg, "data": data} + """ + def post(self,): + args = parser.parse_args() + Ldap_Consul.set_consul_args(**args) + return JsonResponse(data="", code=20000, success=True, msg="添加统一认证成功") + +api.add_resource(LdapView, '/api/ldap/config') diff --git a/flask-consul/views/login.py b/flask-consul/views/login.py index 1df652a..7c969e0 100644 --- a/flask-consul/views/login.py +++ b/flask-consul/views/login.py @@ -5,6 +5,7 @@ import sys sys.path.append("..") from config import admin_passwd from units import token_auth, consul_kv +from units.ldap.LdapUser import Ldap secret_key = consul_kv.get_value('ConsulManager/assets/secret/skey')['sk'] s = TimedJSONWebSignatureSerializer(secret_key,expires_in=28800) @@ -14,6 +15,7 @@ api = Api(blueprint) parser = reqparse.RequestParser() parser.add_argument('username',type=str) parser.add_argument('password',type=str) +parser.add_argument('ldap',type=str) class User(Resource): @token_auth.auth.login_required @@ -23,16 +25,29 @@ class User(Resource): "code": 20000, "data": {"roles": ["admin"],"name": "admin","avatar": "/sl.png"}} def post(self, user_opt): - if user_opt == 'login': - args = parser.parse_args() - username = args.get('username') - password = args.get('password') - if password == admin_passwd: - token = str(s.dumps(admin_passwd),encoding="utf-8") - return {"code": 20000,"data": {"token": "Bearer " + token}} - else: - return {"code": 40000, "data": "密码错误!"} - elif user_opt == 'logout': - return {"code": 20000,"data": "success"} + args = parser.parse_args() + username = args.get('username') + password = args.get('password') + ldap = args.get('ldap') + #ldap认证 + if user_opt == 'login' and ldap == "True": + print("ldap") + ldap_obj = Ldap() + ldap_result = ldap_obj.authpass(username,password) + if ldap_result: + token = str(s.dumps(admin_passwd), encoding="utf-8") + return {"code": 20000, "data": {"token": "Bearer " + token,"username":username}} + return {"code": 40000, "data": "ldap校验失败!"} + else: + if user_opt == 'login': + print("非ldap") + if password == admin_passwd: + token = str(s.dumps(admin_passwd),encoding="utf-8") + return {"code": 20000,"data": {"token": "Bearer " + token,"username":username}} + else: + return {"code": 40000, "data": "密码错误!"} + + elif user_opt == 'logout': + return {"code": 20000,"data": "success"} api.add_resource(User, '/api/user/') diff --git a/vue-consul/src/api/ldap.js b/vue-consul/src/api/ldap.js new file mode 100644 index 0000000..083f654 --- /dev/null +++ b/vue-consul/src/api/ldap.js @@ -0,0 +1,9 @@ +import request from '@/utils/request-ops' + +export function setldap(data) { + return request({ + url: '/api/ldap/config', + method: 'post', + data: data + }) +} diff --git a/vue-consul/src/main.js b/vue-consul/src/main.js index ba7d371..f951abf 100644 --- a/vue-consul/src/main.js +++ b/vue-consul/src/main.js @@ -46,7 +46,7 @@ Object.keys(filters).forEach(key => { }) Vue.config.productionTip = false -Vue.prototype.VER = 'v0.9.7' +Vue.prototype.VER = 'v0.10.0-alpha' new Vue({ el: '#app', diff --git a/vue-consul/src/router/index.js b/vue-consul/src/router/index.js index 89972be..fc9dd30 100644 --- a/vue-consul/src/router/index.js +++ b/vue-consul/src/router/index.js @@ -234,6 +234,16 @@ export const constantRoutes = [ meta: { title: '漏洞通知', icon: 'el-icon-chat-line-square' } }] }, + { + path: '/settings', + component: Layout, + children: [{ + path: 'index', + name: '全局配置', + component: () => import('@/views/ldap/index'), + meta: { title: '全局配置', icon: 'el-icon-chat-line-square' } + }] + }, { path: '/link', component: Layout, diff --git a/vue-consul/src/store/modules/user.js b/vue-consul/src/store/modules/user.js index 37f41cd..44a203d 100644 --- a/vue-consul/src/store/modules/user.js +++ b/vue-consul/src/store/modules/user.js @@ -30,9 +30,9 @@ const mutations = { const actions = { // user login login({ commit }, userInfo) { - const { username, password } = userInfo + const { username, password, Ldapchecked } = userInfo return new Promise((resolve, reject) => { - login({ username: username.trim(), password: password }).then(response => { + login({ username: username.trim(), password: password, ldap: Ldapchecked }).then(response => { const { data } = response commit('SET_TOKEN', data.token) setToken(data.token) diff --git a/vue-consul/src/views/ldap/index.vue b/vue-consul/src/views/ldap/index.vue new file mode 100644 index 0000000..8c639db --- /dev/null +++ b/vue-consul/src/views/ldap/index.vue @@ -0,0 +1,85 @@ + + + + diff --git a/vue-consul/src/views/login/index.vue b/vue-consul/src/views/login/index.vue index 04c64ba..030bb87 100644 --- a/vue-consul/src/views/login/index.vue +++ b/vue-consul/src/views/login/index.vue @@ -41,7 +41,7 @@ - + 登 录 @@ -52,13 +52,12 @@