Skip to content

Commit

Permalink
perf: expose iam exception message to user (#29)
Browse files Browse the repository at this point in the history
  • Loading branch information
narasux authored Nov 22, 2022
1 parent 68b7928 commit 49ae405
Show file tree
Hide file tree
Showing 20 changed files with 229 additions and 149 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,9 @@ apiserver/paasng/.gitignore

# apiserver: iam migration files
apiserver/paasng/support-files/iam

# migrate/sync records
**/migrate_success_records.json
**/migrate_failed_records.json
**/sync_success_records.json
**/sync_failed_records.json
6 changes: 5 additions & 1 deletion apiserver/init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -285,4 +285,8 @@ ensure-service(){
python manage.py update_remote_services_config
}

call_steps ensure-apigw ensure-runtimes-fixtures ensure-init-data ensure-service ensure-smart-image
migrate-perm(){
python manage.py migrate_bkpaas3_perm
}

call_steps ensure-apigw ensure-runtimes-fixtures ensure-init-data ensure-service ensure-smart-image migrate-perm
Empty file.
24 changes: 0 additions & 24 deletions apiserver/paasng/paasng/accessories/bk_iam/constants.py

This file was deleted.

5 changes: 5 additions & 0 deletions apiserver/paasng/paasng/accessories/iam/apigw/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@


class Group(OperationGroup):
# 查询分级管理员列表
management_grade_managers_list = bind_property(
Operation, name="management_grade_managers_list", method="GET", path="/api/v1/open/management/grade_managers/"
)

# 创建分级管理员
management_grade_managers = bind_property(
Operation, name="management_grade_managers", method="POST", path="/api/v1/open/management/grade_managers/"
Expand Down
49 changes: 45 additions & 4 deletions apiserver/paasng/paasng/accessories/iam/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,14 @@
from paasng.platform.applications.constants import ApplicationRole

from . import utils
from .constants import APP_DEFAULT_ROLES, DEFAULT_PAGE, FETCH_USER_GROUP_MEMBERS_LIMIT, ResourceType
from .constants import (
APP_DEFAULT_ROLES,
DEFAULT_PAGE,
FETCH_USER_GROUP_MEMBERS_LIMIT,
LIST_GRADE_MANAGERS_LIMIT,
IAMErrorCodes,
ResourceType,
)

logger = logging.getLogger(__name__)

Expand All @@ -54,7 +61,7 @@ def _prepare_headers(self) -> dict:

def create_grade_managers(self, app_code: str, app_name: str, creator: str) -> int:
"""
在权限中心上为应用注册分级管理员
在权限中心上为应用注册分级管理员,若已存在,则返回
:param app_code: 蓝鲸应用 ID
:param app_name: 蓝鲸应用名称
Expand All @@ -63,8 +70,8 @@ def create_grade_managers(self, app_code: str, app_name: str, creator: str) -> i
"""
data = {
'system': settings.IAM_PAAS_V3_SYSTEM_ID,
'name': utils.gen_grade_member_name(app_code),
'description': utils.gen_grade_member_desc(app_code),
'name': utils.gen_grade_manager_name(app_code),
'description': utils.gen_grade_manager_desc(app_code),
'members': [creator],
# 仅可对指定的单个应用授权
'authorization_scopes': [
Expand Down Expand Up @@ -109,11 +116,45 @@ def create_grade_managers(self, app_code: str, app_name: str, creator: str) -> i
raise BKIAMGatewayServiceError(f'create grade managers error, detail: {e}')

if resp.get('code') != 0:
if resp['code'] == IAMErrorCodes.CONFLICT:
return self.fetch_grade_manager(app_code)

logger.exception(f"create iam grade managers error, message:{resp['message']} \n data: {data}")
raise BKIAMApiError(resp['message'], resp['code'])

return resp['data']['id']

def fetch_grade_manager(self, app_code: str) -> int:
"""
根据名称查询分级管理员 ID
# TODO 权限中心 API 支持按名称过滤后,添加名称参数而不是拉回全量数据过滤
:param app_code: 蓝鲸应用 ID
:returns: 分级管理员 ID
"""
try:
resp = self.client.management_grade_managers_list(
headers=self._prepare_headers(),
params={
'system': settings.IAM_PAAS_V3_SYSTEM_ID,
'page': DEFAULT_PAGE,
'page_size': LIST_GRADE_MANAGERS_LIMIT,
},
)
except APIGatewayResponseError as e:
raise BKIAMGatewayServiceError(f'fetch grade managers error, detail: {e}')

if resp.get('code') != 0:
logger.exception(f"fetch iam grade managers error, message:{resp['message']}")
raise BKIAMApiError(resp['message'], resp['code'])

manager_name = utils.gen_grade_manager_name(app_code)
for manager in resp['data']['results']:
if manager['name'] == manager_name:
return manager['id']

raise BKIAMApiError(f'failed to find application [{app_code}] grade manager')

def fetch_grade_manager_members(self, grade_manager_id: int) -> List[str]:
"""
获取某个分级管理员的成员列表
Expand Down
13 changes: 13 additions & 0 deletions apiserver/paasng/paasng/accessories/iam/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,19 @@
# 查询用户组成员,全量查询
FETCH_USER_GROUP_MEMBERS_LIMIT = 10000

# 查询开发者中心分级管理员列表,全量查询
LIST_GRADE_MANAGERS_LIMIT = 15000


class ResourceType(str, StructuredEnum):
Application = 'application'


class IAMErrorCodes(int, StructuredEnum):
"""
iam api 返回错误码
https://bk.tencent.com/docs/document/7.0/236/39801
"""

# 资源冲突
CONFLICT = 1902409
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# -*- coding: utf-8 -*-
"""
Tencent is pleased to support the open source community by making BlueKing - PaaS System available.
Copyright (C) 2017-2022 THL A29 Limited, a Tencent company. All rights reserved.
TencentBlueKing is pleased to support the open source community by making
蓝鲸智云 - PaaS 平台 (BlueKing - PaaS System) available.
Copyright (C) 2017 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
Expand All @@ -15,59 +16,51 @@
We undertake not to change the open source license (MIT license) applicable
to the current version of the project delivered to anyone in the future.
"""

# PaaS 2.0 相关权限
import logging

from blue_krill.data_types.enum import EnumField, StructuredEnum
from django.conf import settings
from iam import IAM, Action, Request, Subject
from iam.contrib.converter.sql import SQLConverter
from iam.exceptions import AuthAPIError

from paasng.accessories.bk_iam.constants import ActionEnum

logger = logging.getLogger(__name__)


class LegacyAction(str, StructuredEnum):
DEVELOP_APP = EnumField('develop_app', label='开发 SaaS 应用及外链应用')
MANAGE_SMART = EnumField('manage_smart', label='管理 S-mart 应用')


class Permission:
def __init__(self):
self._iam = IAM(
settings.IAM_APP_CODE, settings.IAM_APP_SECRET, settings.BK_IAM_V3_INNER_URL, settings.BK_PAAS2_URL
)

def _make_request_without_resources(self, username: str, action_id: str) -> 'Request':
request = Request(
settings.IAM_SYSTEM_ID,
Subject("user", username),
Action(action_id),
None,
None,
)
return request
return Request(settings.IAM_SYSTEM_ID, Subject("user", username), Action(action_id), None, None)

def allowed_manage_smart(self, username):
"""
smart管理权限
"""
"""smart管理权限"""
try:
request = self._make_request_without_resources(username, ActionEnum.MANAGE_SMART)
request = self._make_request_without_resources(username, LegacyAction.MANAGE_SMART)
return self._iam.is_allowed_with_cache(request)
except AuthAPIError as e:
logger.exception(f"check is allowed to manage smart app error: {e}")
return False

def app_filters(self, username):
"""
用户有权限的应用列表
拉回策略, 自己算!
"""
request = self._make_request_without_resources(username, ActionEnum.DEVELOP_APP)
"""用户有权限的应用列表,拉回策略, 自己算!"""
request = self._make_request_without_resources(username, LegacyAction.DEVELOP_APP)

# 两种策略 1) 实例级别 2) 用户级别
# 只有条件 code in []
# 两种策略 1) 实例级别 2) 用户级别,只有条件 code in []
key_mapping = {"app.id": "paas_app.code"}

try:
filters = self._iam.make_filter(request, converter_class=SQLConverter, key_mapping=key_mapping)
except AuthAPIError as e:
except AuthAPIError:
return None
return filters
4 changes: 2 additions & 2 deletions apiserver/paasng/paasng/accessories/iam/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from .permissions.resources.application import AppAction


def gen_grade_member_name(app_code: str) -> str:
def gen_grade_manager_name(app_code: str) -> str:
"""
生成分级管理员名称(最大字符数限制 32)
中:开发者中心-{app_code}
Expand All @@ -35,7 +35,7 @@ def gen_grade_member_name(app_code: str) -> str:
return _('开发者中心-{}').format(app_code)


def gen_grade_member_desc(app_code: str) -> str:
def gen_grade_manager_desc(app_code: str) -> str:
"""
生成分级管理员描述
中:开发者中心应用({app_code})分级管理员,拥有审批用户加入管理者/开发者/运营者用户组权限。
Expand Down
11 changes: 10 additions & 1 deletion apiserver/paasng/paasng/accounts/permissions/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@
to the current version of the project delivered to anyone in the future.
"""
import logging
import time

from iam.exceptions import AuthAPIError
from rest_framework.exceptions import PermissionDenied
from rest_framework.permissions import BasePermission

Expand All @@ -27,6 +29,8 @@
from paasng.platform.applications.models import Application
from paasng.utils.basic import get_username_by_bkpaas_user_id

logger = logging.getLogger(__name__)


def application_perm_class(action: AppAction):
"""
Expand Down Expand Up @@ -68,4 +72,9 @@ def user_has_app_action_perm(user, application: Application, action: AppAction)
code=application.code,
username=get_username_by_bkpaas_user_id(user.pk),
)
return ApplicationPermission().get_method_by_action(action)(perm_ctx, raise_exception=False)
try:
return ApplicationPermission().get_method_by_action(action)(perm_ctx, raise_exception=False)
except AuthAPIError as e:
logger.exception(f"check user has application perm error: {e}")

return False
16 changes: 13 additions & 3 deletions apiserver/paasng/paasng/plat_admin/admin42/views/applications.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

from paasng.accessories.iam.exceptions import BKIAMGatewayServiceError
from paasng.accessories.iam.helpers import (
add_role_members,
fetch_application_members,
Expand All @@ -38,6 +39,7 @@
from paasng.platform.applications.serializers import ApplicationFeatureFlagSLZ, ApplicationMemberSLZ
from paasng.platform.applications.signals import application_member_updated
from paasng.platform.applications.tasks import sync_developers_to_sentry
from paasng.utils.error_codes import error_codes


class ApplicationListView(GenericTemplateView):
Expand Down Expand Up @@ -133,16 +135,24 @@ def list(self, request, *args, **kwargs):

def destroy(self, request, code):
application = self.get_application()
remove_user_all_roles(application.code, request.query_params["username"])
try:
remove_user_all_roles(application.code, request.query_params["username"])
except BKIAMGatewayServiceError as e:
raise error_codes.DELETE_APP_MEMBERS_ERROR.f(e.message)

self.sync_membership(application)
return Response(status=204)

def update(self, request, code):
application = self.get_application()
username, role = request.data['username'], request.data['role']

remove_user_all_roles(application.code, username)
add_role_members(application.code, ApplicationRole(role), username)
try:
remove_user_all_roles(application.code, username)
add_role_members(application.code, ApplicationRole(role), username)
except BKIAMGatewayServiceError as e:
raise error_codes.UPDATE_APP_MEMBERS_ERROR.f(e.message)

self.sync_membership(application)
return Response(status=204)

Expand Down
Loading

0 comments on commit 49ae405

Please sign in to comment.