Skip to content

Commit

Permalink
feat(backend): webconsole 安全控制 #8408
Browse files Browse the repository at this point in the history
  • Loading branch information
zhangzhw8 authored and iSecloud committed Dec 4, 2024
1 parent 87423dc commit a2d201f
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 3 deletions.
7 changes: 7 additions & 0 deletions dbm-ui/backend/bk_dataview/grafana/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import View

from backend import env
from backend.bk_web.exceptions import ExternalClusterIdInvalidException
from backend.configuration.constants import SystemSettingsEnum
from backend.configuration.models import SystemSettings
from backend.db_meta.enums import ClusterType
Expand Down Expand Up @@ -412,6 +414,11 @@ def _auth(self, request):
resource_meta = ResourceEnum.cluster_type_to_resource_meta(cluster.cluster_type)
resources = [[resource] for resource in resource_meta.batch_create_instances([cluster.id])]
result = IAMPermission(actions, resources).has_permission(request, "")

# 针对外部查询,需在判断是否集群是否在允许的白名单内
if env.ENABLE_EXTERNAL_PROXY and cluster.id not in SystemSettings.get_external_whitelist_cluster_ids():
raise ExternalClusterIdInvalidException(cluster_id=cluster.id)

if not result:
raise PermissionError

Expand Down
6 changes: 6 additions & 0 deletions dbm-ui/backend/bk_web/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,9 @@ class ExternalUserNotExistException(ExternalProxyBaseException):
class ExternalRouteInvalidException(ExternalProxyBaseException):
ERROR_CODE = "002"
MESSAGE = _("转发路由非法")


class ExternalClusterIdInvalidException(ExternalProxyBaseException):
ERROR_CODE = "003"
MESSAGE = _("转发集群请求非法")
MESSAGE_TPL = _("转发集群[{cluster_id}]请求非法")
17 changes: 16 additions & 1 deletion dbm-ui/backend/bk_web/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,14 @@
NON_EXTERNAL_PROXY_ROUTING,
ROUTING_WHITELIST_PATTERNS,
)
from backend.bk_web.exceptions import ExternalProxyBaseException, ExternalRouteInvalidException
from backend.bk_web.exceptions import (
ExternalClusterIdInvalidException,
ExternalProxyBaseException,
ExternalRouteInvalidException,
)
from backend.bk_web.handlers import _error
from backend.configuration.models import SystemSettings
from backend.db_services.dbbase.views import DBBaseViewSet
from backend.ticket.views import TicketViewSet
from backend.utils.local import local
from backend.utils.string import str2bool
Expand Down Expand Up @@ -166,6 +172,8 @@ def check_create_ticket():
# 目前只放开数据导出
if data["ticket_type"] not in EXTERNAL_TICKET_TYPE_WHITELIST:
raise ExternalRouteInvalidException(_("单据类型[{}]非法,未开通白名单").format(data["ticket_type"]))
if data["details"]["cluster_id"] not in SystemSettings.get_external_whitelist_cluster_ids():
raise ExternalClusterIdInvalidException(cluster_id=data["cluster_id"])

# 单据过滤校验函数
def check_list_ticket():
Expand All @@ -174,9 +182,16 @@ def check_list_ticket():
data["ticket_type__in"] = ",".join(EXTERNAL_TICKET_TYPE_WHITELIST)
request.GET = data

def check_webconsole():
data = json.loads(request.body.decode("utf-8"))
# 校验集群是否在白名单中
if data["cluster_id"] not in SystemSettings.get_external_whitelist_cluster_ids():
raise ExternalClusterIdInvalidException(cluster_id=data["cluster_id"])

check_action_func_map = {
f"{TicketViewSet.__name__}.{TicketViewSet.create.__name__}": check_create_ticket,
f"{TicketViewSet.__name__}.{TicketViewSet.list.__name__}": check_list_ticket,
f"{DBBaseViewSet.__name__}.{DBBaseViewSet.webconsole.__name__}": check_webconsole,
}
# 根据请求的视图 + 动作判断是否特殊接口,以及接口参数是否合法
try:
Expand Down
1 change: 1 addition & 0 deletions dbm-ui/backend/configuration/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ class SystemSettingsEnum(str, StructuredEnum):
# 主机默认统一转移到 DBM 业务下托管,若业务 ID 属于这个列表,则转移到对应的业务下
INDEPENDENT_HOSTING_BIZS = EnumField("INDEPENDENT_HOSTING_BIZS", _("独立托管机器的业务列表"))
BF_WHITELIST_BIZS = EnumField("BF_WHITELIST_BIZS", _("BF业务白名单"))
EXTERNAL_WHITELIST_CLUSTER_IDS = EnumField("EXTERNAL_WHITELIST_CLUSTER_IDS", _("外部访问集群ID白名单列表"))
SPEC_OFFSET = EnumField("SPEC_OFFSET", _("默认的规格参数偏移量"))
DEVICE_CLASSES = EnumField("DEVICE_CLASSES", _("机型列表"))
BKM_DUTY_NOTICE = EnumField("BKM_DUTY_NOTICE", _("轮值通知设置"))
Expand Down
13 changes: 11 additions & 2 deletions dbm-ui/backend/configuration/models/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class AbstractSettings(AuditedModel):
desc = models.CharField(_("描述"), max_length=LEN_LONG)

@classmethod
def get_setting_value(cls, key: dict, default: Optional[Any] = None) -> Union[str, Dict]:
def get_setting_value(cls, key: dict, default: Optional[Any] = None) -> Union[str, Dict, List]:
"""插入一条配置记录"""
try:
setting_value = cls.objects.get(**key).value
Expand Down Expand Up @@ -103,7 +103,7 @@ def register_system_settings(cls):
setattr(settings, system_setting.key, system_setting.value)

@classmethod
def get_setting_value(cls, key: str, default: Optional[Any] = None) -> Union[str, Dict]:
def get_setting_value(cls, key: str, default: Optional[Any] = None) -> Union[str, Dict, List]:
return super().get_setting_value(key={"key": key}, default=default)

@classmethod
Expand All @@ -116,6 +116,15 @@ def insert_setting_value(cls, key: str, value: Any, value_type: str = "str", use
desc=constants.SystemSettingsEnum.get_choice_label(key),
)

@classmethod
def get_external_whitelist_cluster_ids(cls) -> List[int]:
return [
conf["cluster_id"]
for conf in cls.get_setting_value(
key=constants.SystemSettingsEnum.EXTERNAL_WHITELIST_CLUSTER_IDS.value, default=[]
)
]


class BizSettings(AbstractSettings):
"""业务配置表"""
Expand Down

0 comments on commit a2d201f

Please sign in to comment.