Skip to content

Commit

Permalink
Merge pull request #828 from wklken/ft_login_use_esb_api
Browse files Browse the repository at this point in the history
Ft login use esb api
  • Loading branch information
wklken authored Mar 31, 2022
2 parents d655cab + b77d24b commit ea9bdde
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 58 deletions.
2 changes: 1 addition & 1 deletion paas2/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.13.37
2.14.0
87 changes: 87 additions & 0 deletions paas2/paas/components/esb.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# -*- coding: utf-8 -*-
"""
Tencent is pleased to support the open source community by making 蓝鲸智云PaaS平台社区版 (BlueKing PaaS
Community Edition) available.
Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved.
Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
You may obtain a copy of the License at http://opensource.org/licenses/MIT
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
"""

from __future__ import unicode_literals

import copy

from django.conf import settings
from common.log import logger

def _call_esb_api(http_func, url_path, data, timeout=30):
# 默认请求头
headers = {
"Content-Type": "application/json",
}

# Note: 目前企业版ESB调用的鉴权信息都是与接口的参数一起的,并非在header头里
common_params = {
"bk_app_code": "bk_paas",
"bk_app_secret": settings.ESB_TOKEN,
"bk_username": "admin", # 存在后台任务,无法使用登录态的方式
# 兼容TE版
"app_code": "bk_paas",
"app_secret": settings.ESB_TOKEN,
}
data.update(common_params)

url = "http://{}{}".format(settings.PAAS_INNER_DOMAIN, url_path)

ok, resp_data = http_func(url, data, headers=headers)
if not ok:
message = resp_data["error"]
logger.error(
"call esb api failed! %s %s, data: %s, error: %s",
http_func.__name__,
url,
_remove_sensitive_info(data),
message,
)
return False, -1, message, None

code = resp_data.get("code", -1)
message = resp_data.get("message", "unknown")

# code may be string or int, and login v1 the code is "00"
try:
code = int(code)
except Exception: # pylint: disable=broad-except
pass
if code in ("0", 0, "00"):
return True, 0, "ok", resp_data["data"]

logger.error(
"call esb api error! %s %s, data: %s, code: %s, message: %s",
http_func.__name__,
url,
_remove_sensitive_info(data),
code,
message,
)

return False, code, message, None


def _remove_sensitive_info(info):
"""
去除敏感信息
"""
if info is None:
return ""

data = copy.copy(info)
sensitive_info_keys = ["bk_token", "bk_app_secret", "app_secret"]

for key in sensitive_info_keys:
if key in data:
data[key] = data[key][:6] + "******"
return str(data)
2 changes: 2 additions & 0 deletions paas2/paas/components/esb_usermgr.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
APP_SECRET = settings.ESB_TOKEN


# FIXME: move into usermgr_api.py

def _call_esb_api(http_func, path, data, bk_token, bk_username, timeout=None):
headers = {}
data.update(
Expand Down
68 changes: 54 additions & 14 deletions paas2/paas/components/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,51 +14,83 @@
from __future__ import unicode_literals

from builtins import str
import time
from urllib.parse import urlparse

import requests
from django.conf import settings

from common.log import logger



def _gen_header():
headers = {
"Content-Type": "application/json",
}
return headers


session = requests.Session()
adapter = requests.adapters.HTTPAdapter(
pool_connections=settings.REQUESTS_POOL_CONNECTIONS, pool_maxsize=settings.REQUESTS_POOL_MAXSIZE
)
session.mount("https://", adapter)
session.mount("http://", adapter)


def _http_request(method, url, headers=None, data=None, timeout=None, verify=False, cert=None, cookies=None):
request_id = headers.get("X-Request-Id", "-") if headers else "-"
st = time.time()
try:
if method == "GET":
resp = requests.get(
resp = session.get(
url=url, headers=headers, params=data, timeout=timeout, verify=verify, cert=cert, cookies=cookies
)
elif method == "HEAD":
resp = requests.head(url=url, headers=headers, verify=verify, cert=cert, cookies=cookies)
resp = session.head(url=url, headers=headers, verify=verify, cert=cert, cookies=cookies)
elif method == "POST":
resp = requests.post(
resp = session.post(
url=url, headers=headers, json=data, timeout=timeout, verify=verify, cert=cert, cookies=cookies
)
elif method == "DELETE":
resp = requests.delete(
resp = session.delete(
url=url, headers=headers, json=data, timeout=timeout, verify=verify, cert=cert, cookies=cookies
)
elif method == "PUT":
resp = requests.put(
resp = session.put(
url=url, headers=headers, json=data, timeout=timeout, verify=verify, cert=cert, cookies=cookies
)
elif method == "PATCH":
resp = session.patch(
url=url, headers=headers, json=data, timeout=timeout, verify=verify, cert=cert, cookies=cookies
)
else:
return False, None
except requests.exceptions.RequestException:
logger.exception("http request error! method: %s, url: %s, data: %s", method, url, data)
return False, None
return False, {"error": "method not supported"}
except requests.exceptions.RequestException as e:
logger.exception("http request error! %s %s, data: %s, request_id: %s", method, url, data, request_id)
return False, {"error": str(e)}
else:
# record for /metrics
latency = int((time.time() - st) * 1000)

# greater than 100ms
if latency > 100:
logger.warning("http slow request! method: %s, url: %s, latency: %dms", method, url, latency)

if resp.status_code != 200:
content = resp.content[:100] if resp.content else ""
content = resp.content[:256] if resp.content else ""
error_msg = (
"http request fail! method: %s, url: %s, data: %s, " "response_status_code: %s, response_content: %s"
"http request fail! %s %s, data: %s, request_id: %s, response.status_code: %s, response.body: %s"
)
logger.error(error_msg % (method, url, str(data), resp.status_code, content))
return False, None
logger.error(error_msg, method, url, str(data), request_id, resp.status_code, content)

return False, {
"error": (
f"status_code is {resp.status_code}, not 200! "
f"{method} {urlparse(url).path}, request_id={request_id}, resp.body={content}"
)
}

return True, resp.json()

Expand Down Expand Up @@ -87,6 +119,14 @@ def http_put(url, data, headers=None, verify=False, cert=None, timeout=None, coo
)


def http_patch(url, data, headers=None, verify=False, cert=None, timeout=None, cookies=None):
if not headers:
headers = _gen_header()
return _http_request(
method="PATCH", url=url, headers=headers, data=data, timeout=timeout, verify=verify, cert=cert, cookies=cookies
)


def http_delete(url, data, headers=None, verify=False, cert=None, timeout=None, cookies=None):
if not headers:
headers = _gen_header()
Expand All @@ -99,4 +139,4 @@ def http_delete(url, data, headers=None, verify=False, cert=None, timeout=None,
verify=verify,
cert=cert,
cookies=cookies,
)
)
50 changes: 7 additions & 43 deletions paas2/paas/components/usermgr_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,44 +10,25 @@
specific language governing permissions and limitations under the License.
"""
from __future__ import absolute_import

from django.conf import settings

from .http import http_post
from .esb import _call_esb_api
from common.log import logger


BK_USERMGR_HOST = "%s://%s" % ("http", settings.BK_USERMGR_HOST)


def _call_usermgr_api(http_func, url, data):
# TODO: 后续添加Token Header进行服务间认证
ok, _data = http_func(url, data)
if not ok:
return False, "verify from usermgr server fail", None

if not _data.get("result"):
logger.info("_call_usermgr_api fail: url=%s, data=%s, _data=%s", url, data, _data)
return False, _data.get("message", "usermgr api fail"), None

_d = _data.get("data")

return True, "ok", _d


def batch_query_users(username_list=[], is_complete=False):
"""
批量获取用户,可以获取所有
"""
path = "/api/v1/login/profile/query/"
url = "{host}{path}".format(host=BK_USERMGR_HOST, path=path)
path = "/api/c/compapi/v1/usermanage/login/profile/query/"

data = {
"username_list": username_list,
"is_complete": is_complete,
}

ok, message, _data = _call_usermgr_api(http_post, url, data)
ok, _, message, _data = _call_esb_api(http_post, path, data)
return ok, message, _data


Expand All @@ -56,29 +37,12 @@ def upsert_user(username, **kwargs):
创建或更新用户
主要用于ee_login,企业第三方应用某些情况下需要支持将用户存储到用户管理
"""
path = "/api/v1/login/profile/"
url = "{host}{path}".format(host=BK_USERMGR_HOST, path=path)
path = "/api/c/compapi/v1/usermanage/login/profile/"

data = {
"username": username,
}
data.update(kwargs)
# for bklogin_field, usermgr_field in BKLOGIN_USERMGR_FIELD_MAP.iteritems():
# if kwargs.get(bklogin_field):
# data[usermgr_field] = kwargs[bklogin_field]
ok, message, _data = _call_usermgr_api(http_post, url, data)
return ok, message, _data


# # 用户管理与登录自身提供的用户信息字段KeyMap
# USERMGR_BKLOGIN_FIELD_MAP = {
# 'show_name': 'chname',
# 'telephone': 'phone',
# 'email': 'email',
# 'role': 'role',
# 'language': 'language',
# 'time_zone': 'time_zone',
# 'wx_id': 'wx_userid'
# }

# BKLOGIN_USERMGR_FIELD_MAP = dict((v, k) for k, v in USERMGR_BKLOGIN_FIELD_MAP.iteritems())
# ok, _, message, _data = _call_usermgr_api(http_post, url, data)
ok, _, message, _data = _call_esb_api(http_post, path, data)
return ok, message, _data
4 changes: 4 additions & 0 deletions paas2/paas/conf/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,10 @@
# API 网关文档中心地址
BK_APIGW_DOC_URL = ""

# HTTP CONNECTIONS
REQUESTS_POOL_CONNECTIONS = 20
REQUESTS_POOL_MAXSIZE = 20

##################
# ESB 信息 #
##################
Expand Down
3 changes: 3 additions & 0 deletions paas2/release.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
Release Log
===============================
# 2.14.0
- add: paas/ce call usermgr api via esb

# 2.13.37
- bugfix: esb usermgr api username missing

Expand Down

0 comments on commit ea9bdde

Please sign in to comment.