Esempio n. 1
0
    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)
Esempio n. 2
0
class TemplatePermissionMixin:
    """
    两种Template统一的鉴权逻辑,需要通过template_type区分
    """

    iam_mapping_config = {
        "project": {
            "delete_action": Action(IAMMeta.FLOW_DELETE_ACTION),
            "resources_list_func": res_factory.resources_list_for_flows,
        },
        "common": {
            "delete_action": Action(IAMMeta.COMMON_FLOW_DELETE_ACTION),
            "resources_list_func": res_factory.resources_list_for_common_flows,
        },
    }

    def has_permission(self, request, view):
        if view.action == "batch_delete":
            self.check_batch_delete_permission(request, view)
        return True

    def check_batch_delete_permission(self, request, view):
        template_ids = request.data.get("template_ids") or []
        action = self.iam_mapping_config[self.template_type]["delete_action"]
        resources_list = self.iam_mapping_config[
            self.template_type]["resources_list_func"](template_ids)
        allow_or_raise_immediate_response_for_resources_list(
            iam=iam,
            system=IAMMeta.SYSTEM_ID,
            subject=Subject("user", request.user.username),
            action=action,
            resources_list=resources_list,
        )
Esempio n. 3
0
    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
Esempio n. 4
0
    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)
Esempio n. 5
0
def check_project_or_admin_view_action_for_user(project_id, username):
    iam = get_iam_client()
    action = Action(IAMMeta.PROJECT_VIEW_ACTION) if project_id else Action(IAMMeta.ADMIN_VIEW_ACTION)
    resources = res_factory.resources_for_project(project_id) if project_id else []
    allow_or_raise_immediate_response(
        iam=iam,
        system=IAMMeta.SYSTEM_ID,
        subject=Subject("user", username),
        action=action,
        resources=resources,
    )
Esempio n. 6
0
    def create_detail(self, object_list, bundle):
        system = self.helper.system
        subject = self.helper.get_subject(bundle)
        action = Action(self.helper.create_action)
        resources = self.helper.get_create_detail_resources(bundle)

        request = Request(
            system,
            subject,
            action,
            resources,
            self.helper.get_create_detail_environment(bundle),
        )

        allowed = self.iam.is_allowed(request)
        logger.debug(
            "tastypie create_detail is_allowed request({}) result: {}".format(
                request.to_dict(), allowed))

        if not allowed:
            raise ImmediateHttpResponse(
                IAMAuthFailedResponse(
                    AuthFailedException(system, subject, action, resources)))

        return allowed
Esempio n. 7
0
    def alter_detail_data_to_serialize(self, request, data):
        helper = getattr(self._meta, "iam_resource_helper", None)
        if not helper:
            return data

        bundle = data

        # 1. get resources
        resources = helper.get_resources(bundle)

        # 2. make request
        request = MultiActionRequest(
            helper.system,
            helper.get_subject_for_alter_detail(request, data),
            [Action(action) for action in helper.actions],
            resources,
            helper.get_environment_for_alter_detail(request, data),
        )

        actions_allowed = helper.iam.resource_multi_actions_allowed(request)
        logger.debug(
            "tastypie alter_detail_data_to_serialize resource_multi_actions_allowed request({}) result: {}".format(
                request.to_dict(), actions_allowed
            )
        )

        # 3. assemble action allowed data
        bundle.data["auth_actions"] = [action for action, allowed in actions_allowed.items() if allowed]

        return data
Esempio n. 8
0
    def obj_get_list(self, bundle, **kwargs):

        allow_or_raise_immediate_response(
            iam=iam,
            system=IAMMeta.SYSTEM_ID,
            subject=Subject("user", bundle.request.user.username),
            action=Action(IAMMeta.ADMIN_VIEW_ACTION),
            resources=[],
        )

        filters = {}

        if hasattr(bundle.request, "GET"):
            # Grab a mutable copy.
            filters = bundle.request.GET.copy()

        # Update with the provided kwargs.
        filters.update(kwargs)
        applicable_filters = self.build_filters(filters=filters)

        try:
            objects = self.apply_filters(bundle.request, applicable_filters)
            return self.authorized_read_list(objects, bundle)
        except ValueError:
            raise BadRequest("Invalid resource lookup params provided")
Esempio n. 9
0
 def _check_user_scheme_permission(username, template_id, project_id=None):
     if project_id is None:
         try:
             template = TaskTemplate.objects.get(pk=template_id)
         except TaskTemplate.DoesNotExist:
             message = "flow template[id={template_id}] does not exist".format(template_id=template_id)
             logger.error(message)
             raise BadRequest(message)
     else:
         try:
             template = TaskTemplate.objects.get(pk=template_id, project_id=project_id)
         except TaskTemplate.DoesNotExist:
             message = "flow template[id={template_id}] in project[id={project_id}] does not exist".format(
                 template_id=template_id, project_id=project_id
             )
             logger.error(message)
             raise BadRequest(message)
     allow_or_raise_immediate_response(
         iam=iam,
         system=IAMMeta.SYSTEM_ID,
         subject=Subject("user", username),
         action=Action(IAMMeta.FLOW_EDIT_ACTION),
         resources=res_factory.resources_for_flow_obj(template),
     )
     return True, template
Esempio n. 10
0
    def process(self, request, *args, **kwargs):

        data = request.data
        template_id_list = data["template_id_list"]

        subject = Subject("user", request.user.username)
        action = Action(IAMMeta.FLOW_VIEW_ACTION)
        resources_list = res_factory.resources_list_for_flows(template_id_list)

        if not resources_list:
            return

        resources_map = {}
        for resources in resources_list:
            resources_map[resources[0].id] = resources

        request = Request(IAMMeta.SYSTEM_ID, subject, action, [], {})
        result = iam.batch_is_allowed(request, resources_list)

        if not result:
            raise MultiAuthFailedException(IAMMeta.SYSTEM_ID, subject, action,
                                           resources_list)

        not_allowed_list = []
        for tid, allow in result.items():
            if not allow:
                not_allowed_list.append(resources_map[tid])

        if not_allowed_list:
            raise MultiAuthFailedException(IAMMeta.SYSTEM_ID, subject, action,
                                           not_allowed_list)
Esempio n. 11
0
    def obj_create(self, bundle, **kwargs):
        try:
            project_id = bundle.data.pop("project__id")
            template_id = bundle.data.pop("template_id")
            common_template = CommonTemplate.objects.get(pk=template_id)
        except Exception:
            raise BadRequest("common template does not exist")

        allow_or_raise_immediate_response(
            iam=iam,
            system=IAMMeta.SYSTEM_ID,
            subject=Subject("user", bundle.request.user.username),
            action=Action(IAMMeta.COMMON_FLOW_EDIT_ACTION),
            resources=res_factory.resources_for_common_flow_obj(
                common_template),
        )

        bundle.data["name"] = standardize_name(bundle.data["name"],
                                               TEMPLATE_NODE_NAME_MAX_LENGTH)
        kwargs["unique_id"] = "%s-%s-%s" % (project_id, template_id,
                                            bundle.data["name"])
        if TemplateScheme.objects.filter(
                unique_id=kwargs["unique_id"]).exists():
            raise BadRequest(
                "common template scheme name has existed, please change the name"
            )
        kwargs["template"] = common_template.pipeline_template
        return super(CommonTemplateSchemeResource,
                     self).obj_create(bundle, **kwargs)
Esempio n. 12
0
def get_resources_allowed_actions_for_user(username, system_id, actions, resources_list):
    subject = Subject("user", username)
    actions = [Action(act) for act in actions]
    request = MultiActionRequest(system_id, subject, actions, [], {})

    iam = get_iam_client()
    return iam.batch_resource_multi_actions_allowed(request, resources_list)
Esempio n. 13
0
    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
Esempio n. 14
0
    def obj_create(self, bundle, **kwargs):

        allow_or_raise_immediate_response(
            iam=iam,
            system=IAMMeta.SYSTEM_ID,
            subject=Subject("user", bundle.request.user.username),
            action=Action(IAMMeta.ADMIN_EDIT_ACTION),
            resources=[],
        )

        model = bundle.obj.__class__

        if model.objects.filter(status=RUNNING).exists():
            raise BadRequest(
                "There is already a running sync task, please wait for it to complete and try again"
            )
        if not CachePackageSource.objects.all().exists():
            raise BadRequest(
                "No cache package found, please add cache package in Backend Manage"
            )
        if len(PackageSourceResource.get_all_source_objects()) <= 1:
            raise BadRequest(
                "No original packages found, please add original packages in Backend Manage"
            )
        return super(SyncTaskResource, self).obj_create(bundle, **kwargs)
Esempio n. 15
0
    def iam_get_instance_auth_actions(self, request, instance):
        helper = getattr(self, "iam_resource_helper", None)
        if not helper:
            return None

        # 1. get resources
        resources = helper.get_resources(instance)

        # 2. make request
        request = MultiActionRequest(
            helper.system,
            helper.get_subject_for_alter_detail(request, instance),
            [Action(action) for action in helper.actions],
            resources,
            helper.get_environment_for_alter_detail(request, instance),
        )

        actions_allowed = helper.iam.resource_multi_actions_allowed(request)
        iam_logger.debug(
            "[drf iam_get_instance_auth_actions] resource_multi_actions_allowed request({}) result: {}"
            .format(request.to_dict(), actions_allowed))

        # 3. assemble action allowed data
        auth_actions = [
            action for action, allowed in actions_allowed.items() if allowed
        ]

        return auth_actions
Esempio n. 16
0
    def obj_create(self, bundle, **kwargs):

        allow_or_raise_immediate_response(
            iam=iam,
            system=IAMMeta.SYSTEM_ID,
            subject=Subject("user", bundle.request.user.username),
            action=Action(IAMMeta.ADMIN_EDIT_ACTION),
            resources=[],
        )

        try:
            origins = bundle.data.pop("origins")
            caches = bundle.data.pop("caches")
        except KeyError:
            raise BadRequest("Invalid params, please check origins and caches")

        with transaction.atomic():
            # collect packages of all origin to cache
            cache_packages = {}
            for origin in origins:
                try:
                    jsonschema.validate(origin, ADD_SOURCE_SCHEMA)
                except jsonschema.ValidationError as e:
                    message = "Invalid origin source params: %s" % e
                    logger.error(message)
                    raise BadRequest(message)
                cache_packages.update(origin["packages"])

            # create cache first if caches exist
            for cache in caches:
                try:
                    jsonschema.validate(cache, ADD_SOURCE_SCHEMA)
                except jsonschema.ValidationError as e:
                    message = "Invalid cache source params: %s" % e
                    logger.error(message)
                    raise BadRequest(message)
                try:
                    CachePackageSource.objects.add_cache_source(
                        cache["name"], cache["type"], cache_packages,
                        cache.get("desc", ""), **cache["details"])
                except exceptions.GcloudExternalPluginsError as e:
                    message = "Create cache source raise error: %s" % e
                    logger.error(message)
                    raise BadRequest(message)

            # create origins after
            for origin in origins:
                source_type = origin["type"]
                details = origin["details"]
                # divide details into two parts,base_kwargs mains fields in base model(e.g. fields of
                # pipeline.contrib.external_plugins.models.GitRepoSource)
                # original_kwargs mains field in origin model but not in base model(e.g. repo_address、desc)
                source_model = source_cls_factory[source_type]
                original_kwargs, base_kwargs = source_model.objects.divide_details_parts(
                    source_type, details)
                original_kwargs["desc"] = origin.get("desc", "")
                source_model.objects.add_original_source(
                    origin["name"], source_type, origin["packages"],
                    original_kwargs, **base_kwargs)
Esempio n. 17
0
 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

        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)
Esempio n. 19
0
 def _make_request(self, username: str, action_id: str, resources: Optional[List[Resource]] = None) -> Request:
     return Request(
         settings.BK_IAM_SYSTEM_ID,
         Subject("user", username),
         Action(action_id),
         resources,
         None,
     )
Esempio n. 20
0
    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)
Esempio n. 21
0
    def obj_get_list(self, bundle, **kwargs):
        allow_or_raise_immediate_response(
            iam=iam,
            system=IAMMeta.SYSTEM_ID,
            subject=Subject("user", bundle.request.user.username),
            action=Action(IAMMeta.ADMIN_VIEW_ACTION),
            resources=[],
        )

        return super(SyncTaskResource, self).obj_get_list(bundle, **kwargs)
Esempio n. 22
0
def iam_resource_auth_or_raise(username, action, resource_id=None, get_resource_func=None):
    iam = get_iam_client()
    action = Action(action)
    subject = Subject("user", username)
    resources = None
    if get_resource_func:
        resources = getattr(res_factory, get_resource_func)(resource_id)
    request = Request(IAMMeta.SYSTEM_ID, subject, action, resources or [], {})
    if not iam.is_allowed(request):
        raise AuthFailedException(IAMMeta.SYSTEM_ID, subject, action, resources or [])
Esempio n. 23
0
    def process(self, request, *args, **kwargs):

        subject = Subject("user", request.user.username)
        action = Action(self.action)

        request = Request(IAMMeta.SYSTEM_ID, subject, action, [], {})
        allowed = iam.is_allowed(request)

        if not allowed:
            raise AuthFailedException(IAMMeta.SYSTEM_ID, subject, action, [])
Esempio n. 24
0
    def resource_inst_multi_actions_allowed(self, username, actions_ids,
                                            resource_id):
        resource = Resource(settings.APP_ID, self.resource_type_id,
                            resource_id, {})
        actions = [Action(action_id) for action_id in actions_ids]

        request = MultiActionRequest(settings.APP_ID,
                                     Subject("user", username), actions,
                                     [resource], None)
        return self.iam.resource_multi_actions_allowed(request)
Esempio n. 25
0
 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
Esempio n. 26
0
 def batch_resource_multi_actions_allowed(
     self, username: str, action_ids: List[str], resources: List[Resource]
 ) -> Dict[str, Dict[str, bool]]:
     """
     判断用户对某些资源是否具有多个指定操作的权限. 当前sdk仅支持同类型的资源
     :return 示例 {'0ad86c25363f4ef8adcb7ac67a483837': {'project_view': True, 'project_edit': False}}
     """
     actions = [Action(action_id) for action_id in action_ids]
     request = MultiActionRequest(settings.BK_IAM_SYSTEM_ID, Subject("user", username), actions, [], None)
     resources_list = [[res] for res in resources]
     return self.iam.batch_resource_multi_actions_allowed(request, resources_list)
Esempio n. 27
0
 def _make_request_with_resources(self,
                                  username,
                                  action_id,
                                  resources=None):
     request = Request(
         settings.APP_ID,
         Subject("user", username),
         Action(action_id),
         resources,
         None,
     )
     return request
Esempio n. 28
0
    def process(self, request, *args, **kwargs):
        task_id = self.get_task_id(request, *args, **kwargs)

        subject = Subject("user", request.user.username)
        action = Action(self.action)
        resources = res_factory.resources_for_task(task_id)

        request = Request(IAMMeta.SYSTEM_ID, subject, action, resources, {})
        allowed = iam.is_allowed_with_cache(request)

        if not allowed:
            raise AuthFailedException(IAMMeta.SYSTEM_ID, subject, action, resources)
Esempio n. 29
0
 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)
Esempio n. 30
0
    def resource_inst_multi_actions_allowed(
        self, username: str, action_ids: List[str], resources: List[Resource]
    ) -> Dict[str, bool]:
        """
        判断用户对某个(单个)资源实例是否具有多个操作的权限.
        note: 权限判断与资源实例有关,如更新某个具体资源

        :return 示例 {'project_view': True, 'project_edit': False}
        """
        actions = [Action(action_id) for action_id in action_ids]
        request = MultiActionRequest(settings.BK_IAM_SYSTEM_ID, Subject("user", username), actions, resources, None)
        return self.iam.resource_multi_actions_allowed(request)