Skip to content

Commit

Permalink
feat: 支持触发全局扫描任务 TencentBlueKing#877 (TencentBlueKing#1301)
Browse files Browse the repository at this point in the history
  • Loading branch information
cnlkl authored Nov 28, 2023
1 parent 76035e0 commit 98c59e8
Show file tree
Hide file tree
Showing 27 changed files with 338 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,15 @@ enum class ScannerMessageCode(
SCAN_TASK_COUNT_EXCEED_LIMIT("scanner.task.count.exceed-limit", 5),
SCAN_TASK_NAME_BATCH_SCAN("scanner.task.name.manual", 6),
SCAN_TASK_NAME_SINGLE_SCAN("scanner.task.name.manual.single", 7),
SCAN_REPORT_NOTIFY_MESSAGE_SCANNED("scanner.report.notify.message.scanned",8),
SCAN_REPORT_NOTIFY_MESSAGE_CVE("scanner.report.notify.message.cve",10),
SCAN_REPORT_NOTIFY_MESSAGE_DETAIL("scanner.report.notify.message.detail",14),
SCAN_REPORT_NOTIFY_MESSAGE_SCANNED("scanner.report.notify.message.scanned", 8),
SCAN_REPORT_NOTIFY_MESSAGE_CVE("scanner.report.notify.message.cve", 10),
SCAN_REPORT_NOTIFY_MESSAGE_DETAIL("scanner.report.notify.message.detail", 14),
SCAN_REPORT_NOTIFY_MESSAGE_TITLE("scanner.report.notify.message.title", 15),
SCAN_REPORT_NOTIFY_MESSAGE_TRIGGER_TIME("scanner.report.notify.message.trigger.time", 16),
SCAN_REPORT_NOTIFY_MESSAGE_TRIGGER_USER("scanner.report.notify.message.trigger.user", 17),
LICENSE_NOT_FOUND("license.not-found",18),
SCAN_REPORT_NOTIFY_MESSAGE_LICENSE("scanner.report.notify.message.license",19),
SCAN_REPORT_NOTIFY_MESSAGE_SENSITIVE("scanner.report.notify.message.sensitive",20),
LICENSE_NOT_FOUND("license.not-found", 18),
SCAN_REPORT_NOTIFY_MESSAGE_LICENSE("scanner.report.notify.message.license", 19),
SCAN_REPORT_NOTIFY_MESSAGE_SENSITIVE("scanner.report.notify.message.sensitive", 20),
EXPORT_REPORT_FAIL("export.report.fail", 21),
EXPORT_REPORT_STATUS_INIT("export.report.status.init", 22),
EXPORT_REPORT_STATUS_RUNNING("export.report.status.running", 23),
Expand All @@ -59,7 +59,8 @@ enum class ScannerMessageCode(
EXPORT_REPORT_STATUS_QUALITY_PASS("export.report.status.quality.pass", 27),
EXPORT_REPORT_STATUS_QUALITY_UN_PASS("export.report.status.quality.un.pass", 28),
EXPORT_REPORT_STATUS_FAILED("export.report.status.failed", 29),
ANALYST_ARTIFACT_DELETED("analyst.artifact.deleted", 30);
ANALYST_ARTIFACT_DELETED("analyst.artifact.deleted", 30),
ANALYST_TASK_EXCEED_MAX_GLOBAL_TASK_COUNT("analyst.task.global.count.exceed", 31);

override fun getBusinessCode() = businessCode
override fun getKey() = key
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@ data class ScanTask(
val name: String? = null,
@ApiModelProperty("任务id")
val taskId: String,
@ApiModelProperty("项目id")
@ApiModelProperty("项目id,只扫描单个项目时有值")
val projectId: String?,
@ApiModelProperty("项目id")
val projectIds: Set<String>,
@ApiModelProperty("触发者")
val createdBy: String,
@ApiModelProperty("最后修改时间")
Expand Down Expand Up @@ -79,4 +81,6 @@ data class ScanTask(
val force: Boolean = false,
@ApiModelProperty("扫描任务元数据")
val metadata: List<TaskMetadata>
)
) {
fun isGlobal() = metadata.any { it.key == TaskMetadata.TASK_METADATA_GLOBAL && it.value == "true" }
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,10 @@ data class TaskMetadata(
* 指定任务使用哪个分发器分发子任务
*/
const val TASK_METADATA_DISPATCHER = "DISPATCHER"

/**
* 标记任务是否为全局扫描任务
*/
const val TASK_METADATA_GLOBAL = "GLOBAL"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available.
*
* Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved.
*
* BK-CI 蓝鲸持续集成平台 is licensed under the MIT license.
*
* A copy of the MIT License is included in this file.
*
*
* Terms of the MIT License:
* ---------------------------------------------------
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of
* the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
* LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

package com.tencent.bkrepo.analyst.pojo.request

import com.tencent.bkrepo.analyst.pojo.TaskMetadata
import com.tencent.bkrepo.common.query.model.Rule
import com.tencent.bkrepo.repository.pojo.project.ProjectMetadata
import io.swagger.annotations.ApiModel
import io.swagger.annotations.ApiModelProperty

@ApiModel("全局扫描请求")
data class GlobalScanRequest(
@ApiModelProperty("扫描器名")
val scanner: String,
@ApiModelProperty("扫描文件匹配规则")
val rule: Rule,
@ApiModelProperty("是否强制扫描,为true时无论是否存在扫描结果都会执行扫描")
val force: Boolean = false,
@ApiModelProperty("项目元数据,用于筛选待扫描项目")
val projectMetadata: List<ProjectMetadata> = emptyList(),
@ApiModelProperty("任务元数据")
val metadata: List<TaskMetadata> = emptyList()
)
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import io.swagger.annotations.ApiModelProperty
@ApiModel("获取扫描任务")
data class ScanTaskQuery(
@ApiModelProperty("任务所属项目")
val projectId: String,
val projectId: String? = null,
@ApiModelProperty("任务名前缀")
val namePrefix: String? = null,
@ApiModelProperty("扫描方案id")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import com.tencent.bkrepo.common.security.permission.Principal
import com.tencent.bkrepo.common.security.util.SecurityUtils
import com.tencent.bkrepo.common.service.util.HttpContextHolder
import com.tencent.bkrepo.analyst.model.SubScanTaskDefinition
import com.tencent.bkrepo.common.security.permission.PrincipalType
import org.springframework.context.annotation.Primary
import org.springframework.stereotype.Component
import org.springframework.web.servlet.HandlerMapping
Expand All @@ -62,6 +63,10 @@ class ScannerPermissionCheckHandler(
permissionManager.checkPrincipal(userId, principal.type)
}

fun checkPrincipal(userId: String, principal: PrincipalType) {
permissionManager.checkPrincipal(userId, principal)
}

fun checkProjectPermission(
projectId: String,
action: PermissionAction,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ data class ScannerProperties(
* 生成的制品临时下载链接超时时间允许下载的次数
*/
var tempDownloadUrlPermits: Int? = null,
/**
* 最大全局扫描任务数量
*/
var maxGlobalTaskCount: Int = 1,
) {
companion object {
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ package com.tencent.bkrepo.analyst.controller.user

import com.tencent.bkrepo.analyst.pojo.ScanTask
import com.tencent.bkrepo.analyst.pojo.ScanTriggerType
import com.tencent.bkrepo.analyst.pojo.request.GlobalScanRequest
import com.tencent.bkrepo.analyst.pojo.request.PipelineScanRequest
import com.tencent.bkrepo.auth.pojo.enums.PermissionAction
import com.tencent.bkrepo.auth.pojo.enums.ResourceType
Expand All @@ -49,6 +50,8 @@ import com.tencent.bkrepo.analyst.pojo.response.SubtaskResultOverview
import com.tencent.bkrepo.analyst.service.ScanService
import com.tencent.bkrepo.analyst.service.ScanTaskService
import com.tencent.bkrepo.analyst.utils.ScanPlanConverter
import com.tencent.bkrepo.common.security.permission.Principal
import com.tencent.bkrepo.common.security.permission.PrincipalType
import io.swagger.annotations.Api
import io.swagger.annotations.ApiOperation
import io.swagger.annotations.ApiParam
Expand All @@ -69,6 +72,13 @@ class UserScanController @Autowired constructor(
private val scanTaskService: ScanTaskService
) {

@ApiOperation("手动创建全局扫描任务")
@PostMapping("/global")
@Principal(PrincipalType.ADMIN)
fun globalScan(@RequestBody scanRequest: GlobalScanRequest): Response<ScanTask> {
return ResponseBuilder.success(scanService.globalScan(scanRequest))
}

@ApiOperation("手动创建扫描任务")
@PostMapping
fun scan(@RequestBody scanRequest: ScanRequest): Response<ScanTask> {
Expand Down Expand Up @@ -117,6 +127,16 @@ class UserScanController @Autowired constructor(
return ResponseBuilder.success(scanService.stopTask(projectId, taskId))
}

@ApiOperation("中止制品扫描")
@PostMapping("/tasks/{taskId}/stop")
@Principal(PrincipalType.ADMIN)
fun stopTask(
@ApiParam(value = "任务id")
@PathVariable("taskId") taskId: String
): Response<Boolean> {
return ResponseBuilder.success(scanService.stopTask(null, taskId))
}

@ApiOperation("获取扫描任务信息")
@GetMapping("/tasks/{taskId}")
fun task(@PathVariable("taskId") taskId: String): Response<ScanTask> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ package com.tencent.bkrepo.analyst.dao
import com.mongodb.client.result.UpdateResult
import com.tencent.bkrepo.analyst.model.TScanTask
import com.tencent.bkrepo.analyst.pojo.ScanTaskStatus
import com.tencent.bkrepo.analyst.pojo.TaskMetadata
import com.tencent.bkrepo.analyst.pojo.request.ScanTaskQuery
import com.tencent.bkrepo.common.api.pojo.Page
import com.tencent.bkrepo.common.api.util.ofTimestamp
Expand All @@ -41,6 +42,7 @@ import org.springframework.data.mongodb.core.query.Criteria
import org.springframework.data.mongodb.core.query.Query
import org.springframework.data.mongodb.core.query.Update
import org.springframework.data.mongodb.core.query.and
import org.springframework.data.mongodb.core.query.elemMatch
import org.springframework.data.mongodb.core.query.inValues
import org.springframework.data.mongodb.core.query.isEqualTo
import org.springframework.stereotype.Repository
Expand Down Expand Up @@ -180,12 +182,10 @@ class ScanTaskDao : ScannerSimpleMongoDao<TScanTask>() {
return find(Query(Criteria.where(ID).inValues(ids)))
}

fun findByProjectIdAndId(projectId: String, id: String): TScanTask? {
return findOne(
Query(
TScanTask::projectId.isEqualTo(projectId).and(ID).isEqualTo(id)
)
)
fun findByProjectIdAndId(projectId: String?, id: String): TScanTask? {
val criteria = projectId?.let { TScanTask::projectId.isEqualTo(it).and(ID).isEqualTo(id) }
?: Criteria().and(ID).isEqualTo(id).and(TScanTask::metadata.name).elemMatch(buildGlobalTaskCriteria())
return findOne(Query(criteria))
}

fun findUnFinished(projectId: String, planId: String): List<TScanTask> {
Expand All @@ -200,7 +200,8 @@ class ScanTaskDao : ScannerSimpleMongoDao<TScanTask>() {
fun find(scanTaskQuery: ScanTaskQuery, pageLimit: PageLimit): Page<TScanTask> {
val criteria = Criteria()
with(scanTaskQuery) {
criteria.and(TScanTask::projectId.name).isEqualTo(projectId)
projectId?.let { criteria.and(TScanTask::projectId.name).isEqualTo(projectId) }
?: criteria.and(TScanTask::metadata.name).elemMatch(buildGlobalTaskCriteria())
namePrefix?.let { criteria.and(TScanTask::name.name).regex("^$it") }
planId?.let { criteria.and(TScanTask::planId.name).isEqualTo(it) }
triggerType?.let { criteria.and(TScanTask::triggerType.name).isEqualTo(it) }
Expand Down Expand Up @@ -230,6 +231,15 @@ class ScanTaskDao : ScannerSimpleMongoDao<TScanTask>() {
return count(Query(TScanTask::status.isEqualTo(status.name)))
}

fun countGlobalTask(status: List<ScanTaskStatus>): Long {
val criteria = TScanTask::metadata.elemMatch(buildGlobalTaskCriteria())
.and(TScanTask::status.name).inValues(status)
return count(Query(criteria))
}

private fun buildGlobalTaskCriteria() =
TaskMetadata::key.isEqualTo(TaskMetadata.TASK_METADATA_GLOBAL).and(TaskMetadata::value.name).isEqualTo("true")

private fun buildQuery(taskId: String) = Query(Criteria.where(ID).isEqualTo(taskId))

private fun buildUpdate(lastModifiedDate: LocalDateTime = LocalDateTime.now()): Update =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,13 @@ class SubScanTaskDao(
/**
* 获取项目[projectId]扫描中的任务数量
*/
fun scanningCount(projectId: String): Long {
fun scanningCount(projectId: String, includeGlobal: Boolean = false): Long {
val criteria = Criteria
.where(TSubScanTask::projectId.name).isEqualTo(projectId)
.and(TSubScanTask::status.name).inValues(SubScanTaskStatus.RUNNING_STATUS)
if (!includeGlobal) {
criteria.and("${TSubScanTask::metadata.name}.key").ne(TaskMetadata.TASK_METADATA_GLOBAL)
}
return count(Query(criteria))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,13 @@ data class TScanTask(
*/
val planId: String? = null,
/**
* 扫描的项目
* 扫描的项目,扫描单个项目时有值
*/
val projectId: String? = null,
/**
* 扫描的项目列表
*/
val projectIds: Set<String> = emptySet(),
/**
* 任务状态
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,5 +81,5 @@ interface ProjectScanConfigurationService {
*
* @return 项目扫描配置
*/
fun findProjectOrGlobalScanConfiguration(projectId: String): ProjectScanConfiguration?
fun findProjectOrGlobalScanConfiguration(projectId: String? = null): ProjectScanConfiguration?
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ package com.tencent.bkrepo.analyst.service
import com.tencent.bkrepo.analyst.pojo.ScanTask
import com.tencent.bkrepo.analyst.pojo.ScanTriggerType
import com.tencent.bkrepo.analyst.pojo.SubScanTask
import com.tencent.bkrepo.analyst.pojo.request.GlobalScanRequest
import com.tencent.bkrepo.analyst.pojo.request.PipelineScanRequest
import com.tencent.bkrepo.analyst.pojo.request.ReportResultRequest
import com.tencent.bkrepo.analyst.pojo.request.ScanRequest
Expand All @@ -38,6 +39,15 @@ import com.tencent.bkrepo.analyst.pojo.request.ScanRequest
* 扫描服务
*/
interface ScanService {
/**
* 触发全局扫描
*
* @param request 全局扫描请求
*
* @return 创建的扫描任务
*/
fun globalScan(request: GlobalScanRequest): ScanTask

/**
* 创建扫描任务,启动扫描
*
Expand Down Expand Up @@ -90,7 +100,7 @@ interface ScanService {
*
* @return true 停止成功,false 停止失败
*/
fun stopTask(projectId: String, taskId: String): Boolean
fun stopTask(projectId: String?, taskId: String): Boolean

/**
* 扫描结果上报
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,10 @@ class ProjectScanConfigurationServiceImpl(
?: throw NotFoundException(CommonMessageCode.RESOURCE_NOT_FOUND)
}

override fun findProjectOrGlobalScanConfiguration(projectId: String): ProjectScanConfiguration? {
val configuration = projectScanConfigurationDao.findByProjectId(projectId)
?: projectScanConfigurationDao.findByProjectId(GLOBAL_PROJECT_ID)
override fun findProjectOrGlobalScanConfiguration(projectId: String?): ProjectScanConfiguration? {
val configuration = projectId?.let {
projectScanConfigurationDao.findByProjectId(it)
} ?: projectScanConfigurationDao.findByProjectId(GLOBAL_PROJECT_ID)
return configuration?.let { Converter.convert(it) }
}

Expand Down
Loading

0 comments on commit 98c59e8

Please sign in to comment.