diff --git a/apps/node_man/apps.py b/apps/node_man/apps.py index 08e5a9b42..5bc86c94e 100644 --- a/apps/node_man/apps.py +++ b/apps/node_man/apps.py @@ -11,7 +11,6 @@ from blueapps.utils.esbclient import get_client_by_user from django.apps import AppConfig from django.conf import settings -from django.core.management import call_command from django.db import ProgrammingError, connection from common.log import logger @@ -27,65 +26,55 @@ def ready(self): 初始化部分配置,主要目的是为了SaaS和后台共用部分配置 """ - # 判断 APIGW 的表是否存在,不存在先跳过 - from apigw_manager.apigw.models import Context - - if Context._meta.db_table not in connection.introspection.table_names(): - # 初次部署表不存在时跳过 DB 写入操作 - logger.info(f"[ESB][JWT] {Context._meta.db_table} not exists, skip fetch_esb_api_key before migrate.") - else: - logger.info(f"[ESB][JWT] {Context._meta.db_table} exist, start to fetch_esb_api_key.") - self.fetch_esb_api_key() - try: + self.fetch_component_api_public_key() self.init_settings() except ProgrammingError as e: logger.info(f"init settings failed, err_msg -> {e}.") return True - def fetch_esb_api_key(self): + @classmethod + def fetch_component_api_public_key(cls): """ 获取JWT公钥并存储到全局配置中 """ - # 当环境整体使用 APIGW 时,尝试通过 apigw-manager 获取 esb & apigw 公钥 - if settings.BKPAAS_MAJOR_VERSION == env_constants.BkPaaSVersion.V3.value: - try: - call_command("fetch_apigw_public_key") - except Exception: - logger.info("[ESB][JWT] fetch apigw public key error") - else: - logger.info("[ESB][JWT] fetch apigw public key success") - - try: - call_command("fetch_esb_public_key") - except Exception: - logger.info("[ESB][JWT] fetch esb public key error") - else: - logger.info("[ESB][JWT] fetch esb public key success") + # 以下几种情况任一成立则不同步 + # 1.PaaSV3 情况下通过 manage.py 执行同步 + # 2.后台情况下,交由 SaaS 执行同步 + if any( + [ + settings.BKPAAS_MAJOR_VERSION == env_constants.BkPaaSVersion.V3.value, + settings.BK_BACKEND_CONFIG, + ] + ): + logger.info("[JWT] skip fetch component api public key") + return + + from apigw_manager.apigw.models import Context + + # 当依赖表暂未创建时,视为 migrate 尚未执行的阶段, 暂不同步 + # 后置这个检查,减少 DB IO + if Context._meta.db_table not in connection.introspection.table_names(): + logger.info("[JWT] skip fetch component api public key") + return client = get_client_by_user(user_or_username=settings.SYSTEM_USE_API_ACCOUNT) esb_result = client.esb.get_api_public_key() if not esb_result["result"]: - logger.error(f'[ESB][JWT] get esb api public key error:{esb_result["message"]}') + logger.error(f'[JWT][ESB] get esb api public key error:{esb_result["message"]}') return from apigw_manager.apigw.helper import PublicKeyManager api_public_key = esb_result["data"]["public_key"] - # esb-ieod-clouds / bk-esb / apigw 为各个环境的约定值,由 ESB 调用时解析 jwt header 的 kid 属性获取 - # Refer:site-packages/apigw_manager/apigw/providers.py - if settings.RUN_VER == "ieod": - # ieod 环境需要额外注入 esb 公钥,从而支持 ESB & APIGW - PublicKeyManager().set("esb-ieod-clouds", api_public_key) - logger.info("[ESB][JWT] get esb api public key and save to esb-ieod-clouds") - elif settings.BKPAAS_MAJOR_VERSION != env_constants.BkPaaSVersion.V3.value: - # V2 环境没有 APIGW,手动注入 - PublicKeyManager().set("bk-esb", api_public_key) - PublicKeyManager().set("apigw", api_public_key) - logger.info("[ESB][JWT] get esb api public key and save to bk-esb & apigw") - - def init_settings(self): + # V2 环境没有 APIGW,手动注入 + PublicKeyManager().set("bk-esb", api_public_key) + PublicKeyManager().set("apigw", api_public_key) + logger.info("[JWT][ESB] get api public key and save to bk-esb & apigw") + + @classmethod + def init_settings(cls): """ 初始化配置,读取DB后写入settings内存中,避免多次查表 """ diff --git a/apps/node_man/management/commands/fetch_component_api_public_key.py b/apps/node_man/management/commands/fetch_component_api_public_key.py new file mode 100644 index 000000000..cbc633b50 --- /dev/null +++ b/apps/node_man/management/commands/fetch_component_api_public_key.py @@ -0,0 +1,57 @@ +# coding: utf-8 +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-节点管理(BlueKing-BK-NODEMAN) available. +Copyright (C) 2017-2022 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 https://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 apigw_manager.apigw.helper import PublicKeyManager +from blueapps.utils.esbclient import get_client_by_user +from django.conf import settings +from django.core.management import call_command +from django.core.management.base import BaseCommand + +from common.log import logger +from env import constants as env_constants + + +class Command(BaseCommand): + """ + 拉取 ESB / APIGW 公钥 + 这块不放在 apps init 中,减少进程启动数据,防止容器化部署情况下,Probe 探针在 app 未就绪情况下探活失败引起容器反复重启 + 依赖 migrate 后执行 + """ + + def handle(self, **kwargs): + + # 当环境整体使用 APIGW 时,尝试通过 apigw-manager 获取 esb & apigw 公钥 + if settings.BKPAAS_MAJOR_VERSION == env_constants.BkPaaSVersion.V3.value: + + for component_name in ["esb", "apigw"]: + try: + call_command(f"fetch_{component_name}_public_key") + except Exception: + logger.info(f"[JWT][{component_name.upper()}] fetch {component_name} public key error") + else: + logger.info(f"[JWT][{component_name.upper()}] fetch {component_name} public key success") + + client = get_client_by_user(user_or_username=settings.SYSTEM_USE_API_ACCOUNT) + esb_result = client.esb.get_api_public_key() + if not esb_result["result"]: + logger.error(f'[JWT][ESB] get esb api public key error:{esb_result["message"]}') + return + + api_public_key = esb_result["data"]["public_key"] + # esb-ieod-clouds / bk-esb / apigw 为各个环境的约定值,由 ESB 调用时解析 jwt header 的 kid 属性获取 + # Refer:site-packages/apigw_manager/apigw/providers.py + if settings.RUN_VER == "ieod": + # ieod 环境需要额外注入 esb 公钥,从而支持 ESB & APIGW + PublicKeyManager().set("esb-ieod-clouds", api_public_key) + logger.info("[JWT] get esb public key and save to esb-ieod-clouds") + + logger.info("[JWT] fetch component api public key success.") diff --git a/bin/hooks/migrate-db b/bin/hooks/migrate-db index 10a58f3aa..351d99c68 100755 --- a/bin/hooks/migrate-db +++ b/bin/hooks/migrate-db @@ -1,3 +1,4 @@ #!/bin/bash python manage.py createcachetable django_cache python manage.py migrate +python manage.py fetch_component_api_public_key diff --git a/bin/post_compile b/bin/post_compile index 2b2894fdf..9f4745b6d 100644 --- a/bin/post_compile +++ b/bin/post_compile @@ -1,4 +1,5 @@ #!/bin/bash python manage.py createcachetable django_cache python manage.py migrate +python manage.py fetch_component_api_public_key python manage.py copy_file_to_nginx diff --git a/bin/pre-release b/bin/pre-release index 2b2894fdf..9f4745b6d 100755 --- a/bin/pre-release +++ b/bin/pre-release @@ -1,4 +1,5 @@ #!/bin/bash python manage.py createcachetable django_cache python manage.py migrate +python manage.py fetch_component_api_public_key python manage.py copy_file_to_nginx