def has_permission(self, request, view): if view.action == "list": if "project_id" not in request.query_params: return False project_resources = res_factory.resources_for_project(request.query_params["project_id"]) allow_or_raise_auth_failed( iam=iam, system=IAMMeta.SYSTEM_ID, subject=Subject("user", request.user.username), action=Action(IAMMeta.PROJECT_VIEW_ACTION), resources=project_resources, ) elif view.action == "create": # let serializer to handle this if "project_id" not in request.data: return True project_resources = res_factory.resources_for_project(request.data["project_id"]) allow_or_raise_auth_failed( iam=iam, system=IAMMeta.SYSTEM_ID, subject=Subject("user", request.user.username), action=Action(IAMMeta.PROJECT_EDIT_ACTION), resources=project_resources, ) return True
def process(self, request, *args, **kwargs): if request.is_trust: return params = json.loads(request.body) template_source = params.get("template_source", PROJECT) template_id = kwargs["template_id"] subject = Subject("user", request.user.username) if template_source in NON_COMMON_TEMPLATE_TYPES: action = Action(IAMMeta.FLOW_CREATE_TASK_ACTION) resources = res_factory.resources_for_flow(template_id) allow_or_raise_auth_failed(iam, IAMMeta.SYSTEM_ID, subject, action, resources, cache=True) else: action = Action(IAMMeta.COMMON_FLOW_CREATE_TASK_ACTION) resources = [ res_factory.resources_for_common_flow(template_id)[0], res_factory.resources_for_project_obj(request.project)[0], ] allow_or_raise_auth_failed(iam, IAMMeta.SYSTEM_ID, subject, action, resources, cache=True)
def scheme_allow_or_raise_auth_failed(request, template_id=None): data = request.query_params or request.data if template_id is None: template_id = data.get("template_id") # 项目流程方案的权限控制 if "project_id" in data or data.get("template_type") != "common": # 默认进行是否有流程查看权限校验 scheme_action = IAMMeta.FLOW_VIEW_ACTION scheme_resources = res_factory.resources_for_flow(template_id) # 公共流程方案的权限控制 else: # 默认进行是否有流程查看权限校验 scheme_action = IAMMeta.COMMON_FLOW_VIEW_ACTION scheme_resources = res_factory.resources_for_common_flow( template_id) allow_or_raise_auth_failed( iam=iam, system=IAMMeta.SYSTEM_ID, subject=Subject("user", request.user.username), action=Action(scheme_action), resources=scheme_resources, ) return True
def test_allow_or_raise_auth_failed__raise(): system = "system" subject = "subject" action = "action" resources = ["r1", "r2"] iam = MagicMock() iam.is_allowed = MagicMock(return_value=False) iam.is_allowed_with_cache = MagicMock() Request = MagicMock() with patch("iam.shortcuts.Request", Request): try: allow_or_raise_auth_failed(iam, system, subject, action, resources) except AuthFailedException as e: assert e.system == system assert e.subject == subject assert e.action == action assert e.resources == resources else: assert False, "allow_or_raise_auth_failed did not raise" iam.is_allowed.assert_called() iam.is_allowed_with_cache.assert_not_called() Request.assert_called_once_with(system, subject, action, resources, None)
def process(self, request, *args, **kwargs): if request.is_trust: return template_source = request.GET.get("template_source", PROJECT) template_id = kwargs["template_id"] subject = Subject("user", request.user.username) if template_source in NON_COMMON_TEMPLATE_TYPES: action = Action(IAMMeta.FLOW_VIEW_ACTION) resources = res_factory.resources_for_flow(template_id) allow_or_raise_auth_failed(iam, IAMMeta.SYSTEM_ID, subject, action, resources, cache=True) else: action = Action(IAMMeta.COMMON_FLOW_VIEW_ACTION) resources = res_factory.resources_for_common_flow(template_id) allow_or_raise_auth_failed(iam, IAMMeta.SYSTEM_ID, subject, action, resources, cache=True)
def process(self, request, *args, **kwargs): if request.is_trust: return subject = Subject("user", request.user.username) action = Action(IAMMeta.FUNCTION_VIEW_ACTION) resources = [] allow_or_raise_auth_failed(iam, IAMMeta.SYSTEM_ID, subject, action, resources, cache=True)
def iam_auth_check(request, action, resources): allow_or_raise_auth_failed( iam=iam, system=IAMMeta.SYSTEM_ID, subject=Subject("user", request.user.username), action=Action(action), resources=resources, )
def process(self, request, *args, **kwargs): if request.is_trust: return task_id = kwargs["task_id"] subject = Subject("user", request.user.username) action = Action(IAMMeta.TASK_CLAIM_ACTION) resources = res_factory.resources_for_task(task_id) allow_or_raise_auth_failed(iam, IAMMeta.SYSTEM_ID, subject, action, resources, cache=True)
def has_object_permission(self, request, view, obj): project_resources = res_factory.resources_for_project(obj.project_id) allow_or_raise_auth_failed( iam=iam, system=IAMMeta.SYSTEM_ID, subject=Subject("user", request.user.username), action=Action(IAMMeta.PROJECT_EDIT_ACTION), resources=project_resources, ) return True
def list(self, request, *args, **kwargs): project_id = request.query_params.get("project_id") if not project_id: raise ValidationException("project_id should be provided.") allow_or_raise_auth_failed( iam=iam, system=IAMMeta.SYSTEM_ID, subject=Subject("user", request.user.username), action=Action(IAMMeta.PROJECT_VIEW_ACTION), resources=res_factory.resources_for_project(project_id), ) return super(NewLabelViewSet, self).list(request, *args, **kwargs)
def has_permission(self, request, view): task_id = view.kwargs["task_id"] task_resources = res_factory.resources_for_task(task_id) allow_or_raise_auth_failed( iam=iam, system=IAMMeta.SYSTEM_ID, subject=Subject("user", request.user.username), action=Action(IAMMeta.TASK_VIEW_ACTION), resources=task_resources, ) return True
def update(self, request, *args, **kwargs): label = self.get_object() if label.is_default: raise ValidationException("default label cannot be updated.") project_id = label.project_id allow_or_raise_auth_failed( iam=iam, system=IAMMeta.SYSTEM_ID, subject=Subject("user", request.user.username), action=Action(IAMMeta.PROJECT_EDIT_ACTION), resources=res_factory.resources_for_project(project_id), ) return super(NewLabelViewSet, self).update(request, *args, **kwargs)
def has_permission(self, request, view): project_id = view.kwargs["pk"] action = IAMMeta.PROJECT_VIEW_ACTION if view.action in [ "retrieve" ] else IAMMeta.PROJECT_EDIT_ACTION allow_or_raise_auth_failed( iam=iam, system=IAMMeta.SYSTEM_ID, subject=Subject("user", request.user.username), action=Action(action), resources=res_factory.resources_for_project(project_id), ) return True
def destroy(self, request, *args, **kwargs): label = self.get_object() if label.is_default: raise ValidationException("default label cannot be deleted.") project_id = label.project_id allow_or_raise_auth_failed( iam=iam, system=IAMMeta.SYSTEM_ID, subject=Subject("user", request.user.username), action=Action(IAMMeta.PROJECT_EDIT_ACTION), resources=res_factory.resources_for_project(project_id), ) self.perform_destroy(label) return Response({"result": True, "message": "success"})
def process(self, request, *args, **kwargs): if request.is_trust: return template_id = kwargs["template_id"] subject = Subject("user", request.user.username) action = Action(IAMMeta.COMMON_FLOW_VIEW_ACTION) resources = res_factory.resources_for_common_flow(template_id) allow_or_raise_auth_failed(iam, IAMMeta.SYSTEM_ID, subject, action, resources, cache=True)
def test_allow_or_raise_auth_failed__allowed(): system = "system" subject = "subject" action = "action" resources = ["r1", "r2"] iam = MagicMock() iam.is_allowed = MagicMock(return_value=True) Request = MagicMock() with patch("iam.shortcuts.Request", Request): allow_or_raise_auth_failed(iam, system, subject, action, resources) Request.assert_called_once_with(system, subject, action, resources, None)
def process(self, request, *args, **kwargs): if request.is_trust: return project = request.project subject = Subject("user", request.user.username) action = Action(IAMMeta.PROJECT_VIEW_ACTION) resources = res_factory.resources_for_project_obj(project) allow_or_raise_auth_failed(iam, IAMMeta.SYSTEM_ID, subject, action, resources, cache=True)
def _fetch_label_or_template_ids(request, fetch_label): base_id_name = "template_ids" if fetch_label else "label_ids" if fetch_label: fetch_func = TemplateLabelRelation.objects.fetch_templates_labels else: fetch_func = TemplateLabelRelation.objects.fetch_label_template_ids base_ids = request.query_params.get(base_id_name) if not base_ids: raise ValidationException( "{} must be provided.".format(base_id_name)) project_id = request.query_params.get("project_id") allow_or_raise_auth_failed( iam=iam, system=IAMMeta.SYSTEM_ID, subject=Subject("user", request.user.username), action=Action(IAMMeta.PROJECT_VIEW_ACTION), resources=res_factory.resources_for_project(project_id), ) base_ids = [int(base_id) for base_id in base_ids.strip().split(",")] return Response(fetch_func(base_ids))
def list_with_default_labels(self, request, *args, **kwargs): """ 获取某个项目下的标签(包括默认标签) param: project_id: 项目ID, integer, query, required """ project_id = request.query_params.get("project_id") if not project_id: raise ValidationException("project_id should be provided.") allow_or_raise_auth_failed( iam=iam, system=IAMMeta.SYSTEM_ID, subject=Subject("user", request.user.username), action=Action(IAMMeta.PROJECT_VIEW_ACTION), resources=res_factory.resources_for_project(project_id), ) queryset = Label.objects.filter( Q(project_id=project_id) | Q(is_default=True)) serializer = self.get_serializer(queryset, many=True) return Response(serializer.data)
def process(self, request, *args, **kwargs): if request.is_trust: return project = request.project subject = Subject("user", request.user.username) action = Action(IAMMeta.PROJECT_FAST_CREATE_TASK_ACTION) resources = res_factory.resources_for_project_obj(project) allow_or_raise_auth_failed(iam, IAMMeta.SYSTEM_ID, subject, action, resources, cache=True) params = request.params_json has_common_subprocess = params.get("has_common_subprocess", False) templates_in_task = set() pipeline_tree = params["pipeline_tree"] for activity in pipeline_tree["activities"].values(): if "template_id" in activity: templates_in_task.add(activity["template_id"]) if not has_common_subprocess: action = Action(IAMMeta.FLOW_VIEW_ACTION) resources_list = res_factory.resources_list_for_flows( list(templates_in_task)) else: action = Action(IAMMeta.COMMON_FLOW_VIEW_ACTION) resources_list = res_factory.resources_list_for_common_flows( list(templates_in_task)) allow_or_raise_immediate_response_for_resources_list( iam=iam, system=IAMMeta.SYSTEM_ID, subject=subject, action=action, resources_list=resources_list, )
def save_app_maker(self, project_id, app_params, fake=False): """ @summary: @param project_id: 项目 ID @param app_params: App maker参数 @param fake: 为True则不会真正调用API创建轻应用 @return: """ from gcloud.iam_auth import res_factory logger.info("save_app_maker params: %s" % app_params) app_id = app_params["id"] if app_id == "0" or not app_id: app_id = None template_id = app_params["template_id"] app_params["name"] = standardize_name(app_params["name"], 20) app_params["desc"] = standardize_name(app_params.get("desc", ""), 30) proj = Project.objects.get(id=project_id) try: task_template = TaskTemplate.objects.get(pk=template_id, project_id=project_id, is_deleted=False) except TaskTemplate.DoesNotExist: return False, _("保存失败,引用的流程模板不存在!") if not app_id: subject = Subject("user", app_params["username"]) action = Action(IAMMeta.FLOW_CREATE_MINI_APP_ACTION) resources = res_factory.resources_for_flow_obj(task_template) allow_or_raise_auth_failed(iam=iam, system=IAMMeta.SYSTEM_ID, subject=subject, action=action, resources=resources) fields = { "project": proj, "name": app_params["name"], "code": "", "desc": app_params["desc"], "logo_url": "", "link": app_params["link_prefix"], "creator": app_params["username"], "editor": app_params["username"], "task_template": task_template, # 生成一个删除状态的对象,以便拼接轻应用访问链接 "is_deleted": True, } if app_params.get("category"): fields["category"] = app_params["category"] if app_params.get("template_scheme_id"): fields["template_scheme_id"] = app_params["template_scheme_id"] app_maker_obj = AppMaker.objects.create(**fields) # update app link app_id = app_maker_obj.id app_link = "{appmaker_prefix}{app_id}/newtask/{project_id}/selectnode/?template_id={template_id}".format( appmaker_prefix=app_params["link_prefix"], app_id=app_id, project_id=project_id, template_id=template_id) app_maker_obj.link = app_link if fake: app_maker_obj.code = "%s%s" % (settings.APP_CODE, time_now_str()) app_maker_obj.is_deleted = False app_maker_obj.save() return True, app_maker_obj # create app on blueking desk app_create_result = create_maker_app( app_params["username"], app_params["name"], app_link, app_params["username"], app_params.get("category") or task_template.category, app_params["desc"], ) if not app_create_result["result"]: return False, _("创建轻应用失败:%s") % app_create_result["message"] app_code = app_create_result["data"]["bk_light_app_code"] app_maker_obj.code = app_code app_maker_obj.is_deleted = False # edit appmaker else: try: app_maker_obj = AppMaker.objects.get( id=app_id, project_id=project_id, task_template__id=template_id, is_deleted=False) except AppMaker.DoesNotExist: return False, _("保存失败,当前操作的轻应用不存在或已删除!") subject = Subject("user", app_params["username"]) action = Action(IAMMeta.MINI_APP_EDIT_ACTION) resources = res_factory.resources_for_mini_app_obj(app_maker_obj) allow_or_raise_auth_failed(iam=iam, system=IAMMeta.SYSTEM_ID, subject=subject, action=action, resources=resources) app_code = app_maker_obj.code creator = app_maker_obj.creator # app_params["link_prefix"]: current_host.com/appmaker, link_prefix: current_host.com/ link_prefix = app_params["link_prefix"][:app_params["link_prefix"]. rfind("appmaker")] # app_maker_obj.link: old_host.com/appmaker/xxx, link_suffix: appmaker/xxx link_suffix = app_maker_obj.link[app_maker_obj.link. rfind("appmaker"):] # 只保留app_maker_obj.link的后缀,使用环境当前域名作为前缀 app_link = f"{link_prefix}{link_suffix}" app_maker_obj.link = app_link if not fake: # edit app on blueking app_edit_result = edit_maker_app( creator, app_code, app_params["name"], app_link, creator, app_params.get("category") or task_template.category, app_params["desc"], ) if not app_edit_result["result"]: return False, _("编辑轻应用失败:%s") % app_edit_result["message"] app_maker_obj.name = app_params["name"] app_maker_obj.desc = app_params["desc"] app_maker_obj.editor = app_params["username"] if "category" in app_params: app_maker_obj.category = app_params["category"] if "template_scheme_id" in app_params: app_maker_obj.template_scheme_id = app_params[ "template_scheme_id"] # upload app logo if not fake and app_params["logo_content"]: logo = base64.b64encode(app_params["logo_content"]) app_logo_result = modify_app_logo(app_maker_obj.creator, app_code, logo) if not app_logo_result["result"]: logger.error("AppMaker[id=%s] upload logo failed: %s" % (app_maker_obj.id, app_logo_result["message"])) # update app maker info app_maker_obj.logo_url = get_app_logo_url(app_code=app_code) app_maker_obj.save() return True, app_maker_obj