Compare commits

...

18 Commits

Author SHA1 Message Date
weishao 00c214a473 rm \ 2023-03-09 19:13:18 +08:00
youys 45a2f5be9b 添加注释 2023-03-09 18:10:53 +08:00
youys c657b31416 缺陷>代码详情接口v2版本 2023-03-09 17:35:00 +08:00
youys 7e387eb37a 缺陷>代码详情接口v2版本 2023-03-09 17:34:12 +08:00
weishao 69d126b2f6 扫描文件路径 2023-03-09 16:43:08 +08:00
weishao bd0c90a496 静态扫描扫描逻辑 2023-03-09 16:14:29 +08:00
weishao 0421776f81 静态扫描扫描逻辑 2023-03-09 15:32:02 +08:00
jshixiong 5099a0a90a 组件漏洞 2023-03-09 15:04:34 +08:00
jshixiong 38d1a432a7 fix 2023-03-08 15:08:41 +08:00
jshixiong dd5f1f7fc3 概览 漏洞指标 2023-03-08 15:08:40 +08:00
jshixiong 2f368a2a44 fix:漏洞和组件 2023-03-07 16:01:48 +08:00
jshixiong a40dfb387a 漏洞和组件 2023-03-07 15:45:42 +08:00
weishao d72dba7f01 组件漏洞 2023-03-02 18:09:59 +08:00
weishao 88b3b4cd91 漏洞分页 2023-03-02 15:47:22 +08:00
weishao a0b77d21d6 漏洞详情 2023-03-02 15:09:32 +08:00
weishao 172def1186 漏洞 2023-03-02 14:44:08 +08:00
weishao 53428dc4ac 漏洞 2023-03-02 14:13:13 +08:00
weishao f968d9c668 漏洞 2023-03-02 10:39:18 +08:00
35 changed files with 1686 additions and 242 deletions

View File

@ -26,6 +26,7 @@ public class DynamicDataSourceConfig {
public static final String MASTER = "master";
public static final String READONLY = "readonly";
public static final String GITEA = "gitea";
public static final String SAST = "sast";
private static final List INIT_SQLS = Arrays.asList("SET NAMES utf8mb4");
@ -133,6 +134,41 @@ public class DynamicDataSourceConfig {
@Value("${spring.datasource.gitea.druid.test-while-idle}")
private boolean giteaTestWhileIdle;
// --------------------------sast----------------------------------
@Value("${spring.datasource.sast.driver-class-name}")
private String sastDriverClass;
@Value("${spring.datasource.sast.url}")
private String sastUrl;
@Value("${spring.datasource.sast.username}")
private String sastUsername;
@Value("${spring.datasource.sast.password}")
private String sastPassword;
@Value("${spring.datasource.sast.druid.initial-size}")
private Integer sastInitialSize;
@Value("${spring.datasource.sast.druid.max-active}")
private Integer sastMaxActive;
@Value("${spring.datasource.sast.druid.min-idle}")
private Integer sastMinIdle;
@Value("${spring.datasource.sast.druid.validation-query}")
private String sastValidationQuery;
@Value("${spring.datasource.sast.druid.test-on-borrow}")
private boolean sastTestOnBorrow;
@Value("${spring.datasource.sast.druid.test-on-return}")
private boolean sastTestOnReturn;
@Value("${spring.datasource.sast.druid.test-while-idle}")
private boolean sastTestWhileIdle;
@Bean("master")
public DataSource masterDataSource() {
DruidDataSource masterDataSource = new DruidDataSource();
@ -201,6 +237,28 @@ public class DynamicDataSourceConfig {
return giteaDataSource;
}
@Bean("sast")
public DataSource sastDataSource() {
DruidDataSource sastDataSource = new DruidDataSource();
sastDataSource.setDriverClassName(sastDriverClass);
sastDataSource.setUrl(sastUrl);
sastDataSource.setUsername(sastUsername);
sastDataSource.setPassword(sastPassword);
sastDataSource.setMinIdle(sastMinIdle);
sastDataSource.setMaxActive(sastMaxActive);
sastDataSource.setMinIdle(sastMinIdle);
sastDataSource.setTestOnBorrow(sastTestOnBorrow);
sastDataSource.setTestOnReturn(sastTestOnReturn);
sastDataSource.setTestWhileIdle(sastTestWhileIdle);
sastDataSource.setValidationQuery(sastValidationQuery);
// 连接失败后中断---重试10次
sastDataSource.setBreakAfterAcquireFailure(true);
sastDataSource.setConnectionErrorRetryAttempts(10);
// 快速失败
sastDataSource.setFailFast(true);
return sastDataSource;
}
@Bean
@Primary
@ -209,6 +267,7 @@ public class DynamicDataSourceConfig {
dataSourceMap.put(MASTER, masterDataSource());
dataSourceMap.put(READONLY, slaveDataSource());
dataSourceMap.put(GITEA, giteaDataSource());
dataSourceMap.put(SAST, sastDataSource());
//设置动态数据源
DynamicDataSource dynamicDataSource = new DynamicDataSource();
dynamicDataSource.setTargetDataSources(dataSourceMap);

View File

@ -36,4 +36,7 @@ public class PropertiesConfig {
@Value("${nil.jarPath}")
private String nilJarPath;
@Value("${sast.driver}")
private String sastDriver;
}

View File

@ -0,0 +1,35 @@
package net.educoder.quality.common.config;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import tk.mybatis.spring.annotation.MapperScan;
import javax.sql.DataSource;
@Configuration
@MapperScan(basePackages = "net.educoder.quality.mapper.sast", sqlSessionFactoryRef = "sqlSessionFactorySastDataSource")
public class SastDatasourceConfig {
@Bean(name = "sqlSessionFactorySastDataSource")
public SqlSessionFactory sqlSessionFactoryDdsDataSource(@Qualifier("sast") DataSource sastDataSource) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(sastDataSource);
factoryBean.setTypeAliasesPackage("net.educoder.quality.entity.sast");
factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:sast.mapper/*Mapper.xml"));
return factoryBean.getObject();
}
@Bean(name = "sastPlatformTransactionManager")
public PlatformTransactionManager platformTransactionManager(@Qualifier("sast") DataSource sastDataSource) {
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(sastDataSource);
return dataSourceTransactionManager;
}
}

View File

@ -1,11 +1,14 @@
package net.educoder.quality.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.github.pagehelper.PageInfo;
import net.educoder.quality.common.util.R;
import net.educoder.quality.dto.*;
import net.educoder.quality.entity.mysql.ComponentParseRecordDetail;
import net.educoder.quality.service.ComponentService;
import net.educoder.quality.vo.PageVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
@ -60,6 +63,7 @@ public class ComponentController {
for (ComponentParseRecordDetail componentParseRecordDetail : componentListDTOPageInfo.getList()) {
ComponentListDTO componentListDTO = new ComponentListDTO();
BeanUtils.copyProperties(componentParseRecordDetail, componentListDTO);
componentListDTO.setVulnerabilities(StringUtils.isNotEmpty(componentParseRecordDetail.getVulnerabilities()) ? JSON.parseArray(componentParseRecordDetail.getVulnerabilities()) : new JSONArray());
resultList.add(componentListDTO);
}
PageInfo<ComponentListDTO> pageInfo = new PageInfo<>();

View File

@ -5,9 +5,11 @@ import com.github.pagehelper.PageInfo;
import net.educoder.quality.common.annotations.OperateLogAnnotation;
import net.educoder.quality.common.util.R;
import net.educoder.quality.dto.*;
import net.educoder.quality.entity.mysql.ComponentParseRecordDetail;
import net.educoder.quality.entity.mysql.Projects;
import net.educoder.quality.service.ProjectService;
import net.educoder.quality.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@ -15,6 +17,7 @@ import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -178,6 +181,8 @@ public class ProjectController {
return R.success(projectBugCenterDTOPageInfo);
}
/**
* 缺陷列表导出
*
@ -210,153 +215,16 @@ public class ProjectController {
/**
* 漏洞统计信息
* 缺陷中心> 代码详情
* V2版本
*
* @param projectId
* @return
*/
@GetMapping("/projects/{projectId}/vulnerability")
public R<ProjectVulnerabilityDTO> projectVulnerability(@PathVariable Long projectId) {
ProjectVulnerabilityDTO projectVulnerabilityDTO = projectService.projectVulnerability(projectId);
return R.success(projectVulnerabilityDTO);
@GetMapping("/projects/v2/{projectId}/bug/center/codeDetail")
public R<ProjectBugCenterCodeDetailV2DTO> projectBugCenterCodeDetailV2(@PathVariable Long projectId, @RequestParam("ruleId") Integer id) {
ProjectBugCenterCodeDetailV2DTO codeDetailV2DTO = projectService.projectBugCenterCodeDetailV2(projectId, id);
return R.success(codeDetailV2DTO);
}
/**
* 漏洞列表
*
* @param projectId
* @return
*/
@GetMapping("/projects/{projectId}/vulnerability/list")
public R<PageInfo> projectVulnerabilityList(@PathVariable Long projectId, @Valid PageVO pageVO) {
PageInfo<ProjectVulnerabilityListDTO> projectVulnerabilityListDTOPageInfo = projectService.projectVulnerabilityList(projectId, pageVO);
return R.success(projectVulnerabilityListDTOPageInfo);
}
/**
* 漏洞列表导出
*
* @param projectId
* @return
*/
@GetMapping("/projects/{projectId}/vulnerability/export")
public void projectVulnerabilityExport(@PathVariable Long projectId, @Valid CommonVO commonVO, HttpServletResponse response) throws Exception {
List<ProjectVulnerabilityListDTO> vulnerabilityListDTOS = projectService.projectVulnerabilityExport(projectId, commonVO);
Projects projects = projectService.getProjectById(projectId);
response.setCharacterEncoding("utf-8");
String fileName = new String(projects.getProjectName().getBytes("utf-8"), "ISO8859-1");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
response.setContentType("application/octet-stream");
EasyExcel.write(response.getOutputStream(), ProjectVulnerabilityListDTO.class).sheet().doWrite(vulnerabilityListDTOS);
}
/**
* 漏洞详情
*
* @param projectId
* @return
*/
@GetMapping("/projects/{projectId}/vulnerability/detail")
public R<ProjectVulnerabilityDetailDTO> projectVulnerabilityDetail(@PathVariable Long projectId, @RequestParam("uuid") String uuid) {
ProjectVulnerabilityDetailDTO detailDTO = projectService.projectVulnerabilityDetail(projectId, uuid);
return R.success(detailDTO);
}
/**
* 许可证总计
*
* @param projectId
* @return
*/
@GetMapping("/projects/{projectId}/licence/overview")
public R<LicenceOverviewDTO> projectLicenceOverview(@PathVariable("projectId") Long projectId) {
return R.success(projectService.projectLicenceOverview(projectId));
}
/**
* 许可证兼容风险总计
*
* @param projectId
* @return
*/
@GetMapping("/projects/{projectId}/licence/risk")
public R<LicenceRiskDTO> projectLicenceRiskOverview(@PathVariable("projectId") Long projectId) {
return R.success(projectService.projectLicenceRiskOverview(projectId));
}
/**
* 许可证分页
*
* @param projectId
* @param vo
* @return
*/
@GetMapping("/projects/{projectId}/licence/page")
public R<PageInfo<LicenceListDTO>> licencePage(@PathVariable("projectId") Long projectId, ProjectLicencePageVO vo) {
return R.success(projectService.licencePage(projectId, vo));
}
/**
* 许可证文件或组件列表
* vo.fileType : 1文件2组件
*
* @param projectId
* @param vo
* @return
*/
@GetMapping("/projects/{projectId}/licence/files")
public R<List<LicenceFileDTO>> licenceFileList(@PathVariable("projectId") Long projectId, @Valid LicenceFileVO vo) {
return R.success(projectService.licenceFileList(projectId, vo));
}
/**
* 许可证版权信息分页
*
* @param projectId
* @param vo
* @return
*/
@GetMapping("/projects/{projectId}/licenceCopyright/page")
public R<PageInfo<LicenceCopyrightDTO>> licenceCopyrightList(@PathVariable("projectId") Long projectId, PageVO vo) {
return R.success(projectService.licenceCopyrightList(projectId, vo));
}
/**
* 许可证兼容分析分页
*
* @param projectId
* @param vo
* @return
*/
@GetMapping("/projects/{projectId}/licenceCompatible/page")
public R<PageInfo<LicenceCompatibleDTO>> licenceCompatibleList(@PathVariable("projectId") Long projectId, PageVO vo) {
return R.success(projectService.licenceCompatibleList(projectId, vo));
}
/**
* 许可证版权信息篡改分析分页
*
* @param projectId
* @param vo
* @return
*/
@GetMapping("/projects/{projectId}/licenceCopyrightDistort/page")
public R<PageInfo<LicenceCopyrightDTO>> licenceCopyrightDistortList(@PathVariable("projectId") Long projectId, PageVO vo) {
return R.success(projectService.licenceCopyrightDistortList(projectId, vo));
}
/**
* 许可证篡改分析分页
*
* @param projectId
* @param vo
* @return
*/
@GetMapping("/projects/{projectId}/licenceDistort/page")
public R<PageInfo<LicenceDistortDTO>> licenceDistortList(@PathVariable("projectId") Long projectId, PageVO vo) {
return R.success(projectService.licenceDistortList(projectId, vo));
}
}

View File

@ -0,0 +1,63 @@
package net.educoder.quality.controller;
import com.github.pagehelper.PageInfo;
import net.educoder.quality.common.util.R;
import net.educoder.quality.dto.ProjectVulnerabilityDTO;
import net.educoder.quality.dto.ProjectVulnerabilityDetailDTO;
import net.educoder.quality.service.VulnerabilityService;
import net.educoder.quality.vo.PageVO;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.validation.Valid;
/**
* 克隆检测控制器
*/
@RestController
public class VulnerabilityController {
@Resource
private VulnerabilityService vulnerabilityService;
/**
* 漏洞统计信息
*
* @param projectId
* @return
*/
@GetMapping("/projects/{projectId}/vulnerability")
public R<ProjectVulnerabilityDTO> projectVulnerability(@PathVariable Long projectId) {
ProjectVulnerabilityDTO projectVulnerabilityDTO = vulnerabilityService.vulnerabilityStatistics(projectId);
return R.success(projectVulnerabilityDTO);
}
/**
* 漏洞列表
*
* @param projectId
* @return
*/
@GetMapping("/projects/{projectId}/vulnerability/list")
public R<PageInfo> projectVulnerabilityList(@PathVariable Long projectId, @Valid PageVO pageVO) {
PageInfo<ProjectVulnerabilityDetailDTO> vulnerabilityList = vulnerabilityService.vulnerabilityList(projectId, pageVO);
return R.success(vulnerabilityList);
}
/**
* 漏洞详情
*
* @param projectId
* @return
*/
@GetMapping("/projects/{projectId}/vulnerability/detail")
public R<ProjectVulnerabilityDetailDTO> projectVulnerabilityDetail(@PathVariable Long projectId, @RequestParam("uuid") String uuid) {
ProjectVulnerabilityDetailDTO detailDTO = vulnerabilityService.vulnerabilityDetail(projectId, uuid);
return R.success(detailDTO);
}
}

View File

@ -1,5 +1,6 @@
package net.educoder.quality.dto;
import com.alibaba.fastjson.JSONArray;
import lombok.Data;
/**
@ -28,6 +29,10 @@ public class ComponentListDTO {
* 漏洞
*/
private String vulnerability;
/**
* 漏洞详情
*/
private JSONArray vulnerabilities;
/**
* 依赖方式
*/

View File

@ -1,6 +1,8 @@
package net.educoder.quality.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Author: youys
@ -8,6 +10,8 @@ import lombok.Data;
* @Description:
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class FileSourceDTO {
private Integer rowNumber;

View File

@ -0,0 +1,44 @@
package net.educoder.quality.dto;
import lombok.Data;
import java.util.List;
/**
* @Author: youys
* @Date: 2023/3/9
* @Description: 缺陷中心>查看详情 v2版本
*/
@Data
public class ProjectBugCenterCodeDetailV2DTO {
private String filePath;
/**
* 代码行号
*/
private Integer line;
/**
* 缺陷名称
*/
private String bugName;
/**
* 缺陷描述
*/
private String description;
/**
* 正确代码示例
*/
private String example;
/**
* 错误代码示例
*/
private String errorExample;
/**
* 代码所属错误分类
*/
private String parentBugCatalog;
/**
* 代码
*/
private List<FileSourceDTO> codes;
}

View File

@ -11,6 +11,7 @@ import java.util.Date;
*/
@Data
public class ProjectVulnerabilityDetailDTO {
private String uuid;
/**
* 漏洞编号

View File

@ -25,6 +25,5 @@ public class ReportDetailDTO {
private List<PgIssues> bugIssues;
// private List<PgIssues> vulnerabilityIssues;
private List<ComponentParseRecordDetailDTO> parseRecordDetails;
}

View File

@ -0,0 +1,14 @@
package net.educoder.quality.dto;
import lombok.Data;
@Data
public class SastBugDTO {
private Long bugId;
private String bugType;
private int line;
private String filePath;
private String message;
private String methodName;
private String variable;
}

View File

@ -1,6 +1,8 @@
package net.educoder.quality.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Author: youys
@ -9,6 +11,4 @@ import lombok.Data;
*/
@Data
public class VulnerabilityResultDTO extends CompareBaseResultDTO{
}

View File

@ -0,0 +1,91 @@
package net.educoder.quality.entity.mysql;
import lombok.Data;
import net.educoder.quality.common.util.AbstractDO;
import javax.persistence.Table;
import java.util.Objects;
@Data
@Table(name = "project_vulnerability_detail")
public class ProjectVulnerabilityDetail extends AbstractDO {
/**
* 漏洞编号
*/
private String vulnerabilityNumber;
/**
* 漏洞名称
*/
private String vulnerabilityName;
/**
* 风险等级
*/
private Integer riskLevel;
/**
* 发布日期
*/
private String publishDate;
/**
* 利用难度
*/
private Integer difficulty;
/**
* 攻击类型远程
*/
private String attackType;
/**
* 漏洞描述
*/
private String description;
/**
* 修复建议
*/
private String repairSuggestions;
/**
* 组件ID
*/
private Long componentId;
/**
* 工程ID
*/
private Long projectId;
@Override
public boolean equals(Object o) {
if (this == o){
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ProjectVulnerabilityDetail that = (ProjectVulnerabilityDetail) o;
return strEquals(vulnerabilityNumber,that.vulnerabilityNumber) && strEquals(vulnerabilityName,that.vulnerabilityName) && intEquals(riskLevel, that.riskLevel) && strEquals(publishDate, that.publishDate) && intEquals(difficulty, that.difficulty) && strEquals(attackType, that.attackType) && strEquals(description, that.description) && strEquals(repairSuggestions, that.repairSuggestions);
}
private boolean strEquals(String a,String b){
if (a==null || "".equals(a)){
return b == null || "".equals(b);
}
return a.equals(b);
}
private boolean intEquals(Integer a,Integer b){
if (a==null){
return b == null;
}
return a.equals(b);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), vulnerabilityNumber, vulnerabilityName, riskLevel, publishDate, difficulty, attackType, description, repairSuggestions);
}
}

View File

@ -0,0 +1,208 @@
package net.educoder.quality.entity.mysql;
import java.util.Date;
import javax.persistence.*;
import lombok.Data;
import net.educoder.quality.common.util.AbstractDO;
@Data
@Table(name = "sast_analysis_detail")
public class SastAnalysisDetail extends AbstractDO {
/**
* bug分类
*/
@Column(name = "bug_catalog")
private String bugCatalog;
/**
* bug大分类
*/
@Column(name = "parent_bug_catalog")
private String parentBugCatalog;
/**
* bug类型编号
*/
@Column(name = "bug_no")
private String bugNo;
/**
* bug名称
*/
@Column(name = "bug_name")
private String bugName;
/**
* bug类型父级编号
*/
@Column(name = "parent_bug_no")
private String parentBugNo;
/**
* bug类型号
*/
@Column(name = "bug_type")
private String bugType;
/**
* bug类型名
*/
@Column(name = "bug_type_name")
private String bugTypeName;
/**
* bug级别
*/
@Column(name = "bug_level")
private String bugLevel;
/**
* 常见后果关键词
*/
@Column(name = "frequent_result_keyword")
private String frequentResultKeyword;
/**
* 创建时间
*/
@Column(name = "create_time")
private Date createTime;
/**
* 更新时间
*/
@Column(name = "update_time")
private Date updateTime;
/**
* 工程id
*/
@Column(name = "project_id")
private Long projectId;
/**
* 任务id
*/
@Column(name = "task_id")
private String taskId;
/**
* 简介
*/
private String synopsis;
/**
* 描述
*/
private String description;
/**
* 常见后果
*/
@Column(name = "frequent_result")
private String frequentResult;
/**
* 修复意见
*/
@Column(name = "repair_opinion")
private String repairOpinion;
/**
* 示例
*/
private String example;
/**
* 错误示例
*/
@Column(name = "error_example")
private String errorExample;
@Column(name = "method_name")
private String methodName;
private String variable;
private Integer line;
@Column(name = "file_path")
private String filePath;
public static final String ID = "id";
public static final String DB_ID = "id";
public static final String BUG_CATALOG = "bugCatalog";
public static final String DB_BUG_CATALOG = "bug_catalog";
public static final String BUG_NO = "bugNo";
public static final String DB_BUG_NO = "bug_no";
public static final String BUG_NAME = "bugName";
public static final String DB_BUG_NAME = "bug_name";
public static final String PARENT_BUG_NO = "parentBugNo";
public static final String DB_PARENT_BUG_NO = "parent_bug_no";
public static final String BUG_TYPE = "bugType";
public static final String DB_BUG_TYPE = "bug_type";
public static final String BUG_TYPE_NAME = "bugTypeName";
public static final String DB_BUG_TYPE_NAME = "bug_type_name";
public static final String BUG_LEVEL = "bugLevel";
public static final String DB_BUG_LEVEL = "bug_level";
public static final String FREQUENT_RESULT_KEYWORD = "frequentResultKeyword";
public static final String DB_FREQUENT_RESULT_KEYWORD = "frequent_result_keyword";
public static final String CREATE_TIME = "createTime";
public static final String DB_CREATE_TIME = "create_time";
public static final String UPDATE_TIME = "updateTime";
public static final String DB_UPDATE_TIME = "update_time";
public static final String PROJECT_ID = "projectId";
public static final String DB_PROJECT_ID = "project_id";
public static final String TASK_ID = "taskId";
public static final String DB_TASK_ID = "task_id";
public static final String SYNOPSIS = "synopsis";
public static final String DB_SYNOPSIS = "synopsis";
public static final String DESCRIPTION = "description";
public static final String DB_DESCRIPTION = "description";
public static final String FREQUENT_RESULT = "frequentResult";
public static final String DB_FREQUENT_RESULT = "frequent_result";
public static final String REPAIR_OPINION = "repairOpinion";
public static final String DB_REPAIR_OPINION = "repair_opinion";
public static final String EXAMPLE = "example";
public static final String DB_EXAMPLE = "example";
public static final String ERROR_EXAMPLE = "errorExample";
public static final String DB_ERROR_EXAMPLE = "error_example";
}

View File

@ -0,0 +1,216 @@
package net.educoder.quality.entity.sast;
import java.util.Date;
import javax.persistence.*;
import lombok.Data;
@Data
@Table(name = "biz_knowledge_bug")
public class BizKnowledgeBug {
/**
* 知识库BUG类型ID
*/
@Id
@Column(name = "OID_KNOWLEDGE_BUG_ID")
private String oidKnowledgeBugId;
/**
* 知识库目录ID
*/
@Column(name = "OID_KNOWLEDGE_CATALOG_ID")
private String oidKnowledgeCatalogId;
/**
* BUG类型编号
*/
@Column(name = "BUG_NO")
private String bugNo;
/**
* BUG名称
*/
@Column(name = "BUG_NAME")
private String bugName;
/**
* BUG类型父级编号
*/
@Column(name = "PARENT_BUG_NO")
private String parentBugNo;
/**
* BUG类型号
*/
@Column(name = "BUG_TYPE")
private String bugType;
/**
* BUG类型名
*/
@Column(name = "BUG_TYPE_NAME")
private String bugTypeName;
/**
* BUG级别
*/
@Column(name = "BUG_LEVEL")
private String bugLevel;
/**
* 常见后果关键词
*/
@Column(name = "FREQUENT_RESULT_KEYWORD")
private String frequentResultKeyword;
/**
* 删除FLG
*/
@Column(name = "DEL_FLG")
private String delFlg;
/**
* 作成者ID
*/
@Column(name = "INS_USER_ID")
private String insUserId;
/**
* 作成日
*/
@Column(name = "INS_DATE")
private Date insDate;
/**
* 更新者ID
*/
@Column(name = "UPD_USER_ID")
private String updUserId;
/**
* 更新日
*/
@Column(name = "UPD_DATE")
private Date updDate;
/**
* 简介
*/
@Column(name = "SYNOPSIS")
private String synopsis;
/**
* 描述
*/
@Column(name = "DESCRIPTION")
private String description;
/**
* 常见后果
*/
@Column(name = "FREQUENT_RESULT")
private String frequentResult;
/**
* 修复意见
*/
@Column(name = "REPAIR_OPINION")
private String repairOpinion;
/**
* 示例
*/
@Column(name = "EXAMPLE")
private String example;
/**
* 错误示例
*/
@Column(name = "ERROR_EXAMPLE")
private String errorExample;
@Transient
private String bugCatalog;
@Transient
private String parentBugCatalog;
public static final String OID_KNOWLEDGE_BUG_ID = "oidKnowledgeBugId";
public static final String DB_OID_KNOWLEDGE_BUG_ID = "OID_KNOWLEDGE_BUG_ID";
public static final String OID_KNOWLEDGE_CATALOG_ID = "oidKnowledgeCatalogId";
public static final String DB_OID_KNOWLEDGE_CATALOG_ID = "OID_KNOWLEDGE_CATALOG_ID";
public static final String BUG_NO = "bugNo";
public static final String DB_BUG_NO = "BUG_NO";
public static final String BUG_NAME = "bugName";
public static final String DB_BUG_NAME = "BUG_NAME";
public static final String PARENT_BUG_NO = "parentBugNo";
public static final String DB_PARENT_BUG_NO = "PARENT_BUG_NO";
public static final String BUG_TYPE = "bugType";
public static final String DB_BUG_TYPE = "BUG_TYPE";
public static final String BUG_TYPE_NAME = "bugTypeName";
public static final String DB_BUG_TYPE_NAME = "BUG_TYPE_NAME";
public static final String BUG_LEVEL = "bugLevel";
public static final String DB_BUG_LEVEL = "BUG_LEVEL";
public static final String FREQUENT_RESULT_KEYWORD = "frequentResultKeyword";
public static final String DB_FREQUENT_RESULT_KEYWORD = "FREQUENT_RESULT_KEYWORD";
public static final String DEL_FLG = "delFlg";
public static final String DB_DEL_FLG = "DEL_FLG";
public static final String INS_USER_ID = "insUserId";
public static final String DB_INS_USER_ID = "INS_USER_ID";
public static final String INS_DATE = "insDate";
public static final String DB_INS_DATE = "INS_DATE";
public static final String UPD_USER_ID = "updUserId";
public static final String DB_UPD_USER_ID = "UPD_USER_ID";
public static final String UPD_DATE = "updDate";
public static final String DB_UPD_DATE = "UPD_DATE";
public static final String SYNOPSIS = "synopsis";
public static final String DB_SYNOPSIS = "SYNOPSIS";
public static final String DESCRIPTION = "description";
public static final String DB_DESCRIPTION = "DESCRIPTION";
public static final String FREQUENT_RESULT = "frequentResult";
public static final String DB_FREQUENT_RESULT = "FREQUENT_RESULT";
public static final String REPAIR_OPINION = "repairOpinion";
public static final String DB_REPAIR_OPINION = "REPAIR_OPINION";
public static final String EXAMPLE = "example";
public static final String DB_EXAMPLE = "EXAMPLE";
public static final String ERROR_EXAMPLE = "errorExample";
public static final String DB_ERROR_EXAMPLE = "ERROR_EXAMPLE";
}

View File

@ -4,7 +4,21 @@ package net.educoder.quality.mapper.mysql;
import net.educoder.quality.common.util.BaseMapper;
import net.educoder.quality.entity.mysql.ComponentParseRecord;
import java.util.List;
public interface ComponentParseRecordMapper extends BaseMapper<ComponentParseRecord> {
/**
* 项目最近的一次组件分析记录
* @param projectId
* @return
*/
ComponentParseRecord getByProjectId(Long projectId);
/**
* 项目所有分析记录
* @param projectId
* @return
*/
List<ComponentParseRecord> quaryByProjectId(Long projectId);
}

View File

@ -0,0 +1,7 @@
package net.educoder.quality.mapper.mysql;
import net.educoder.quality.common.util.BaseMapper;
import net.educoder.quality.entity.mysql.ProjectVulnerabilityDetail;
public interface ProjectVulnerabilityDetailMapper extends BaseMapper<ProjectVulnerabilityDetail> {
}

View File

@ -0,0 +1,7 @@
package net.educoder.quality.mapper.mysql;
import net.educoder.quality.common.util.BaseMapper;
import net.educoder.quality.entity.mysql.SastAnalysisDetail;
public interface SastAnalysisDetailMapper extends BaseMapper<SastAnalysisDetail> {
}

View File

@ -67,8 +67,8 @@ public interface PgProjectMapper {
/**
* 根据issueType查询出现的次数
* issueType2 漏洞
* issueType3 缺陷
* issueType2 缺陷
* issueType3 漏洞
*
* @param projectName
* @param issueType

View File

@ -0,0 +1,10 @@
package net.educoder.quality.mapper.sast;
import net.educoder.quality.common.util.BaseMapper;
import net.educoder.quality.entity.sast.BizKnowledgeBug;
import java.util.List;
public interface BizKnowledgeBugMapper {
List<BizKnowledgeBug> selectBugAndCatalogByTypes(List<String> bugTypes);
}

View File

@ -146,6 +146,15 @@ public interface ProjectService {
*/
ProjectBugCenterCodeDetailDTO projectBugCenterCodeDetail(Long projectId, ProjectBugCenterCodeDetailVO centerCodeDetailVO);
/**
* 获取缺陷中心代码详情 V2版本
* @param projectId
* @param id
* @return
*/
ProjectBugCenterCodeDetailV2DTO projectBugCenterCodeDetailV2(Long projectId, Integer id);
/**
* 许可证总计
*
@ -232,6 +241,15 @@ public interface ProjectService {
*/
PageInfo<ProjectVulnerabilityListDTO> projectVulnerabilityList(Long projectId, PageVO pageVO);
/**
* 项目漏洞列表
*
* @param projectId
* @param pageVO
* @return
*/
PageInfo<ProjectVulnerabilityListDTO> getProjectVulnerabilityList(Long projectId, PageVO pageVO);
/**
* 项目漏洞详情
*
@ -249,4 +267,5 @@ public interface ProjectService {
* @return
*/
List<ProjectVulnerabilityListDTO> projectVulnerabilityExport(Long projectId, CommonVO commonVO);
}

View File

@ -0,0 +1,12 @@
package net.educoder.quality.service;
import net.educoder.quality.entity.mysql.SastAnalysisDetail;
public interface SastService {
void analysis(Long projectId, String taskId);
SastAnalysisDetail findById(Long id);
}

View File

@ -0,0 +1,26 @@
package net.educoder.quality.service;
import com.github.pagehelper.PageInfo;
import net.educoder.quality.dto.ProjectVulnerabilityDTO;
import net.educoder.quality.dto.ProjectVulnerabilityDetailDTO;
import net.educoder.quality.vo.PageVO;
public interface VulnerabilityService {
/**
* 漏洞列表
*/
PageInfo<ProjectVulnerabilityDetailDTO> vulnerabilityList(Long projectId, PageVO pageVO);
/**
* 漏洞详情
*/
ProjectVulnerabilityDetailDTO vulnerabilityDetail(Long projectId, String uuid);
/**
* 漏洞统计
* @param projectId
* @return
*/
ProjectVulnerabilityDTO vulnerabilityStatistics(Long projectId);
}

View File

@ -1,8 +1,10 @@
package net.educoder.quality.service.impl;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
@ -15,19 +17,14 @@ import net.educoder.quality.common.exception.BusinessException;
import net.educoder.quality.common.util.GitUtil;
import net.educoder.quality.common.util.ShellUtil;
import net.educoder.quality.common.util.mdc.MdcTaskDecorator;
import net.educoder.quality.dto.ComponentDetailDTO;
import net.educoder.quality.dto.ComponentParseRecordDetailDTO;
import net.educoder.quality.dto.ComponentStatisticsDTO;
import net.educoder.quality.dto.DependComponentDTO;
import net.educoder.quality.entity.mysql.ComponentLibrary;
import net.educoder.quality.entity.mysql.ComponentParseRecord;
import net.educoder.quality.entity.mysql.ComponentParseRecordDetail;
import net.educoder.quality.entity.mysql.Projects;
import net.educoder.quality.dto.*;
import net.educoder.quality.entity.mysql.*;
import net.educoder.quality.entity.gitea.PgCodeLicense;
import net.educoder.quality.mapper.mysql.ComponentLibraryMapper;
import net.educoder.quality.mapper.mysql.ComponentParseRecordDetailMapper;
import net.educoder.quality.mapper.mysql.ComponentParseRecordMapper;
import net.educoder.quality.mapper.gitea.PgCodeLicenseMapper;
import net.educoder.quality.mapper.mysql.ProjectVulnerabilityDetailMapper;
import net.educoder.quality.service.ComponentService;
import net.educoder.quality.service.ProjectService;
import net.educoder.quality.task.ComponentParseRunnable;
@ -40,7 +37,9 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;
import javax.annotation.Resource;
import java.nio.charset.Charset;
import java.util.*;
@ -71,6 +70,9 @@ public class ComponentServiceImpl implements ComponentService {
@Autowired
private PgCodeLicenseMapper pgCodeLicenseMapper;
@Resource
private ProjectVulnerabilityDetailMapper projectVulnerabilityDetailMapper;
@Autowired
@Qualifier("parseComponentThreadPool")
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@ -104,57 +106,170 @@ public class ComponentServiceImpl implements ComponentService {
}
// 克隆之后执行组件分析
ComponentParseRecord query = new ComponentParseRecord();
query.setProjectId(projectId);
ComponentParseRecord componentParseRecord = componentParseRecordMapper.selectOne(query);
ComponentParseRecord componentParseRecord;
Set<ComponentParseRecordDetail> parseRecordDetailSet = new HashSet<>(200);
// 未解析
if (componentParseRecord == null) {
String outPath = fullPath + "/output.json";
String url = "http://opensca.xmirror.cn:8003";
String token = "6cb2f6fb-cf87-463d-b5a3-d242eb97d7c1";
String command = StringUtils.join(openScaCliPath," -url "
, url, " -token ", token, " -path ", fullPath, " -out ", outPath);
ShellResult shellResult = ShellUtil.executeAndGetExitStatus(command);
log.info("command:{}, result:{}", command, shellResult);
if (shellResult.getExitStatus() == 0) {
String output = FileUtil.readString(outPath, Charset.defaultCharset());
//每次都重新分析
String outPath = fullPath + "/output.json";
String url = "http://opensca.xmirror.cn:8003";
String token = "6cb2f6fb-cf87-463d-b5a3-d242eb97d7c1";
String command = StringUtils.join(openScaCliPath," -url "
, url, " -token ", token, " -path ", fullPath, " -out ", outPath);
ShellResult shellResult = ShellUtil.executeAndGetExitStatus(command);
log.info("command:{}, result:{}", command, shellResult);
componentParseRecord = new ComponentParseRecord();
componentParseRecord.setProjectId(projectId);
componentParseRecord.setCreateTime(new Date());
componentParseRecord.setUpdateTime(new Date());
componentParseRecord = new ComponentParseRecord();
componentParseRecord.setProjectId(projectId);
componentParseRecord.setResult(output);
componentParseRecord.setCreateTime(new Date());
componentParseRecord.setUpdateTime(new Date());
componentParseRecordMapper.insertSelective(componentParseRecord);
if (shellResult.getExitStatus() == 0) {
String output = FileUtil.readString(outPath, Charset.defaultCharset());
parseResult(componentParseRecord.getResult(), componentParseRecord.getId(), parseRecordDetailSet);
componentParseRecord.setResult(output);
componentParseRecordMapper.insertSelective(componentParseRecord);
log.info("if需要插入的组件详情数据有{}条", parseRecordDetailSet.size());
if (CollectionUtils.isNotEmpty(parseRecordDetailSet)) {
List<ComponentParseRecordDetail> batchList = new ArrayList<>(parseRecordDetailSet);
componentParseRecordDetailMapper.insertList(batchList);
}
}
} else {
log.info("projectId:{},组件已解析", projectId);
ComponentParseRecordDetail detailQuery = new ComponentParseRecordDetail();
detailQuery.setComponentId(componentParseRecord.getId());
int count = componentParseRecordDetailMapper.selectCount(detailQuery);
if (count > 0) {
log.info("projectId:{},组件已解析,并且已入库", projectId);
return;
}
parseResult(componentParseRecord.getResult(), componentParseRecord.getId(), parseRecordDetailSet);
String result = componentParseRecord.getResult();
parseResult(result, componentParseRecord.getId(), parseRecordDetailSet);
log.info("else需要插入的组件详情数据有{}条", parseRecordDetailSet.size());
log.info("parseComponent需要插入的组件详情数据有{}条", parseRecordDetailSet.size());
if (CollectionUtils.isNotEmpty(parseRecordDetailSet)) {
List<ComponentParseRecordDetail> batchList = new ArrayList<>(parseRecordDetailSet);
componentParseRecordDetailMapper.insertList(batchList);
}
}else {
componentParseRecord.setResult("");
componentParseRecordMapper.insertSelective(componentParseRecord);
}
// } else {
// log.info("projectId:{},组件已解析", projectId);
// ComponentParseRecordDetail detailQuery = new ComponentParseRecordDetail();
// detailQuery.setComponentId(componentParseRecord.getId());
// int count = componentParseRecordDetailMapper.selectCount(detailQuery);
// if (count > 0) {
// log.info("projectId:{},组件已解析,并且已入库", projectId);
// return;
// }
//
// String result = componentParseRecord.getResult();
// parseResult(result, componentParseRecord.getId(), parseRecordDetailSet);
// log.info("else需要插入的组件详情数据有{}条", parseRecordDetailSet.size());
// if (CollectionUtils.isNotEmpty(parseRecordDetailSet)) {
// List<ComponentParseRecordDetail> batchList = new ArrayList<>(parseRecordDetailSet);
// componentParseRecordDetailMapper.insertList(batchList);
// }
// }
// 插入漏洞
log.info("开始插入漏洞");
try{
batchInsertVulnerability(parseRecordDetailSet, projectId,componentParseRecord.getId());
log.info("插入漏洞成功");
}catch (Exception e){
log.info("插入漏洞失败");
e.printStackTrace();
}
}
/**
* 批量插入漏洞增量
*/
private void batchInsertVulnerability(Set<ComponentParseRecordDetail> parseRecordDetailSet, Long projectId, Long componentId) {
List<ProjectVulnerabilityDetail> projectVulnerabilityDetailList = new ArrayList<>();
for (ComponentParseRecordDetail componentParseRecordDetail : parseRecordDetailSet) {
String vulnerabilities = componentParseRecordDetail.getVulnerabilities();
if (StringUtils.isNotEmpty(vulnerabilities)) {
JSONArray vuls = JSON.parseArray(vulnerabilities);
for (int i = 0; i < vuls.size(); i++) {
ProjectVulnerabilityDetail pvd = new ProjectVulnerabilityDetail();
JSONObject vul = vuls.getJSONObject(i);
pvd.setVulnerabilityNumber(StringUtils.firstNonBlank(vul.getString("cwe_id"), vul.getString("id").replaceAll("XMIRROR-", "")));
pvd.setDescription(vul.getString("description"));
pvd.setAttackType(vul.getString("attack_type"));
pvd.setDifficulty(vul.getInteger("exploit_level_id"));
pvd.setRiskLevel(vul.getInteger("security_level_id"));
pvd.setPublishDate(vul.getString("release_date"));
pvd.setRepairSuggestions(vul.getString("suggestion"));
pvd.setVulnerabilityName(vul.getString("name"));
pvd.setComponentId(componentId);
pvd.setProjectId(projectId);
pvd.setCreateTime(DateTime.now());
pvd.setUpdateTime(DateTime.now());
projectVulnerabilityDetailList.add(pvd);
}
}
}
//新漏洞排除已有旧漏洞
List<ComponentParseRecord> parseRecords = componentParseRecordMapper.quaryByProjectId(projectId);
List<ProjectVulnerabilityDetail> oldVulnerabilityList = new ArrayList<>();
if (parseRecords.size()>=2){
Long oldComponentId = parseRecords.get(1).getId();
ProjectVulnerabilityDetail projectVulnerabilityDetail = new ProjectVulnerabilityDetail();
projectVulnerabilityDetail.setComponentId(oldComponentId);
oldVulnerabilityList = projectVulnerabilityDetailMapper.select(projectVulnerabilityDetail);
}
if (oldVulnerabilityList.size()>0){
Iterator<ProjectVulnerabilityDetail> it = projectVulnerabilityDetailList.iterator();
while (it.hasNext()){
ProjectVulnerabilityDetail newVulnerability = it.next();
for (ProjectVulnerabilityDetail oldVulnerability:oldVulnerabilityList) {
if (newVulnerability.equals(oldVulnerability)){
it.remove();
break;
}
}
}
//新漏洞加上所有旧漏洞
for (ProjectVulnerabilityDetail oldVulnerability:oldVulnerabilityList) {
oldVulnerability.setId(null);
oldVulnerability.setComponentId(componentId);
oldVulnerability.setProjectId(projectId);
oldVulnerability.setCreateTime(new Date());
oldVulnerability.setUpdateTime(new Date());
}
projectVulnerabilityDetailList.addAll(oldVulnerabilityList);
}
log.info("本次漏洞数据有{}条", projectVulnerabilityDetailList.size());
if (CollectionUtils.isNotEmpty(projectVulnerabilityDetailList)) {
projectVulnerabilityDetailMapper.insertList(projectVulnerabilityDetailList);
}
}
/**
* 批量插入漏洞全量
*/
private void batchInsertVulnerabilityAll(Set<ComponentParseRecordDetail> parseRecordDetailSet, Long projectId) {
List<ProjectVulnerabilityDetail> projectVulnerabilityDetailList = new ArrayList<>();
for (ComponentParseRecordDetail componentParseRecordDetail : parseRecordDetailSet) {
String vulnerabilities = componentParseRecordDetail.getVulnerabilities();
Long componentId = componentParseRecordDetail.getComponentId();
if (StringUtils.isNotEmpty(vulnerabilities)) {
JSONArray vuls = JSON.parseArray(vulnerabilities);
for (int i = 0; i < vuls.size(); i++) {
ProjectVulnerabilityDetail pvd = new ProjectVulnerabilityDetail();
JSONObject vul = vuls.getJSONObject(i);
pvd.setVulnerabilityNumber(StringUtils.firstNonBlank(vul.getString("cwe_id"), vul.getString("id").replaceAll("XMIRROR-", "")));
pvd.setDescription(vul.getString("description"));
pvd.setAttackType(vul.getString("attack_type"));
pvd.setDifficulty(vul.getInteger("exploit_level_id"));
pvd.setRiskLevel(vul.getInteger("security_level_id"));
pvd.setPublishDate(vul.getString("release_date"));
pvd.setRepairSuggestions(vul.getString("suggestion"));
pvd.setVulnerabilityName(vul.getString("name"));
pvd.setComponentId(componentId);
pvd.setProjectId(projectId);
pvd.setCreateTime(DateTime.now());
pvd.setUpdateTime(DateTime.now());
projectVulnerabilityDetailList.add(pvd);
}
}
}
log.info("本次漏洞数据有{}条", projectVulnerabilityDetailList.size());
if (CollectionUtils.isNotEmpty(projectVulnerabilityDetailList)) {
projectVulnerabilityDetailMapper.insertList(projectVulnerabilityDetailList);
}
}
@ -166,9 +281,7 @@ public class ComponentServiceImpl implements ComponentService {
}
ComponentStatisticsDTO statisticsDTO = new ComponentStatisticsDTO();
ComponentParseRecord query = new ComponentParseRecord();
query.setProjectId(projectId);
ComponentParseRecord componentParseRecord = componentParseRecordMapper.selectOne(query);
ComponentParseRecord componentParseRecord = componentParseRecordMapper.getByProjectId(projectId);
if (componentParseRecord == null) {
statisticsDTO.setComponentRisk(new ComponentStatisticsDTO.ComponentRisk());
@ -209,9 +322,7 @@ public class ComponentServiceImpl implements ComponentService {
@Override
public PageInfo<ComponentParseRecordDetailDTO> componentList(Long projectId, PageVO pageVO) {
ComponentParseRecord query = new ComponentParseRecord();
query.setProjectId(projectId);
ComponentParseRecord componentParseRecord = componentParseRecordMapper.selectOne(query);
ComponentParseRecord componentParseRecord = componentParseRecordMapper.getByProjectId(projectId);
if (componentParseRecord == null) {
return new PageInfo<>(new ArrayList<>(0));
@ -301,11 +412,13 @@ public class ComponentServiceImpl implements ComponentService {
detail.setComponentName(StringUtils.isNotBlank(json.getString("vendor")) ? json.getString("vendor") + ":" + json.getString("name"): json.getString("name"));
detail.setLanguage(json.getString("language"));
detail.setRiskLevel(randomRiskLevel(detail.getComponentName()));
detail.setRiskLevel("低危");
if(json.containsKey("vulnerabilities")){
int size = json.getJSONArray("vulnerabilities").size();
JSONArray vulnerabilities = json.getJSONArray("vulnerabilities");
int size = vulnerabilities.size();
detail.setVulnerability(String.valueOf(size));
detail.setVulnerabilities(json.getJSONArray("vulnerabilities").toJSONString());
detail.setVulnerabilities(vulnerabilities.toJSONString());
detail.setRiskLevel(size > 5 ? "严重" : size > 3 ? "高危" : "中危");
}else{
detail.setVulnerability("0");
}

View File

@ -22,14 +22,12 @@ import net.educoder.quality.entity.postgres.PgRule;
import net.educoder.quality.mapper.mysql.*;
import net.educoder.quality.protobuf.DbFileSources;
import net.educoder.quality.protobuf.DbIssues;
import net.educoder.quality.service.ComponentService;
import net.educoder.quality.service.DetectionConfigService;
import net.educoder.quality.service.ProjectService;
import net.educoder.quality.service.SonarService;
import net.educoder.quality.service.*;
import net.educoder.quality.service.postgres.PgProjectsService;
import net.educoder.quality.task.SonarDetectionRunnable;
import net.educoder.quality.vo.*;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
@ -39,6 +37,9 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.*;
/**
@ -95,6 +96,12 @@ public class ProjectServiceImpl implements ProjectService {
@Autowired
private ComponentService componentService;
@Autowired
private ComponentParseRecordMapper componentParseRecordMapper;
@Resource
private SastService sastService;
@Override
public PageInfo<ProjectsDTO> getProjectList(ProjectsVO projectsVO) {
@ -212,6 +219,14 @@ public class ProjectServiceImpl implements ProjectService {
}
});
// 静态分析
sonarQueryResultThreadPool.execute(new Runnable() {
@Override
public void run() {
sastService.analysis(projects.getId(), taskInfo.getTaskId());
}
});
// 更新projects状态为检测中
Projects updateProjects = new Projects();
@ -331,11 +346,18 @@ public class ProjectServiceImpl implements ProjectService {
String projectName = String.format("%s-%s", projectDetectionTaskInfo.getProjectName(), projectDetectionTaskInfo.getRandomStr());
// 缺陷&漏洞
BugResultDTO bug = pgProjectsService.getBug(projectName);
VulnerabilityResultDTO vulnerability = pgProjectsService.getNewComponentVulnerability(projectId);
projectOverviewDTO.setBugDetail(bug);
projectOverviewDTO.setVulnerabilityDetail(vulnerability);
// 获取缺陷漏洞
ProjectMetricsDTO projectMetrics = pgProjectsService.getProjectMetrics(projectName);
projectOverviewDTO.setBug(new ProjectOverviewDTO.Metres(projectMetrics.getBugNumber(), 0));
projectOverviewDTO.setVulnerability(new ProjectOverviewDTO.Metres(projectMetrics.getVulnerabilityNumber(), 0));
projectOverviewDTO.setVulnerability(new ProjectOverviewDTO.Metres(vulnerability.getTotal().intValue(), 0));
projectOverviewDTO.setComponent(new ProjectOverviewDTO.Metres());
projectOverviewDTO.setLicense(new ProjectOverviewDTO.Metres());
@ -346,15 +368,6 @@ public class ProjectServiceImpl implements ProjectService {
detectContent.setFileNumber(projects.getTargetFileNum());
projectOverviewDTO.setDetectContent(detectContent);
// 缺陷&漏洞
BugResultDTO bug = pgProjectsService.getBug(projectName);
VulnerabilityResultDTO vulnerability = pgProjectsService.getVulnerability(projectName);
projectOverviewDTO.setBugDetail(bug);
projectOverviewDTO.setVulnerabilityDetail(vulnerability);
} else {
ProjectDetectionTaskInfo projectDetectionTaskInfo = projectDetectionTaskInfos.get(0);
ProjectDetectionTaskInfo projectDetectionTaskInfo2 = projectDetectionTaskInfos.get(1);
@ -362,14 +375,22 @@ public class ProjectServiceImpl implements ProjectService {
String projectName = String.format("%s-%s", projectDetectionTaskInfo.getProjectName(), projectDetectionTaskInfo.getRandomStr());
String projectName2 = String.format("%s-%s", projectDetectionTaskInfo2.getProjectName(), projectDetectionTaskInfo2.getRandomStr());
// 缺陷&漏洞
BugResultDTO bug = pgProjectsService.getBug(projectName);
VulnerabilityResultDTO vulnerability = pgProjectsService.getNewComponentVulnerability(projectId);
VulnerabilityResultDTO vulnerability2 = pgProjectsService.getOldComponentVulnerability(projectId);
projectOverviewDTO.setBugDetail(bug);
projectOverviewDTO.setVulnerabilityDetail(vulnerability);
// 获取缺陷漏洞
ProjectMetricsDTO projectMetrics = pgProjectsService.getProjectMetrics(projectName);
ProjectMetricsDTO projectMetrics2 = pgProjectsService.getProjectMetrics(projectName2);
projectOverviewDTO.setBug(new ProjectOverviewDTO.Metres(projectMetrics2.getBugNumber(),
projectMetrics.getBugNumber() - projectMetrics2.getBugNumber()));
projectOverviewDTO.setVulnerability(new ProjectOverviewDTO.Metres(projectMetrics2.getVulnerabilityNumber(),
projectMetrics.getVulnerabilityNumber() - projectMetrics2.getVulnerabilityNumber()));
projectOverviewDTO.setVulnerability(new ProjectOverviewDTO.Metres(vulnerability.getTotal().intValue(),
vulnerability.getTotal().intValue() - vulnerability2.getTotal().intValue()));
projectOverviewDTO.setComponent(new ProjectOverviewDTO.Metres());
projectOverviewDTO.setLicense(new ProjectOverviewDTO.Metres());
@ -380,13 +401,6 @@ public class ProjectServiceImpl implements ProjectService {
detectContent.setFileNumber(projects.getTargetFileNum());
projectOverviewDTO.setDetectContent(detectContent);
// 缺陷&漏洞
BugResultDTO bug = pgProjectsService.getBug(projectName);
VulnerabilityResultDTO vulnerability = pgProjectsService.getVulnerability(projectName);
projectOverviewDTO.setBugDetail(bug);
projectOverviewDTO.setVulnerabilityDetail(vulnerability);
}
return projectOverviewDTO;
@ -444,9 +458,9 @@ public class ProjectServiceImpl implements ProjectService {
BugResultDTO bug = pgProjectsService.getBug(projectName);
PgProjectMeasures projectMeasures = pgProjectsService.getProjectMeasureByMetricId(projectName, 1);
if(projectMeasures != null) {
if (projectMeasures != null) {
detectResult.setCodeNumber(projectMeasures.getValue().intValue());
}else{
} else {
detectResult.setCodeNumber(0);
}
@ -591,6 +605,40 @@ public class ProjectServiceImpl implements ProjectService {
return projectBugCenterCodeDetailDTO;
}
@Override
public ProjectBugCenterCodeDetailV2DTO projectBugCenterCodeDetailV2(Long projectId, Integer id){
SastAnalysisDetail sastAnalysisDetail = sastService.findById(Long.valueOf(id));
if(sastAnalysisDetail == null){
throw new BusinessException(ErrorCodeEnum.PARAM_ERROR);
}
ProjectBugCenterCodeDetailV2DTO codeDetailV2DTO = new ProjectBugCenterCodeDetailV2DTO();
BeanUtils.copyProperties(sastAnalysisDetail, codeDetailV2DTO);
String filePath = sastAnalysisDetail.getFilePath();
File file = new File(filePath);
if(file.exists()){
try {
List<String> codeStr = FileUtils.readLines(file, "UTF-8");
List<FileSourceDTO> codes = new ArrayList();
for (int i = 0; i < codeStr.size(); i++) {
codes.add(new FileSourceDTO(i+1, codeStr.get(i)));
}
codeDetailV2DTO.setCodes(codes);
} catch (IOException e) {
log.error("projectBugCenterCodeDetailV2 读文件异常", e);
codeDetailV2DTO.setCodes(new ArrayList<>());
}
}else{
codeDetailV2DTO.setCodes(new ArrayList<>());
}
return codeDetailV2DTO;
}
@Override
public LicenceOverviewDTO projectLicenceOverview(Long projectId) {
//TODO:暂用假数据
@ -763,6 +811,17 @@ public class ProjectServiceImpl implements ProjectService {
return pageInfo;
}
@Override
public PageInfo<ProjectVulnerabilityListDTO> getProjectVulnerabilityList(Long projectId, PageVO pageVO) {
ProjectDetectionTaskInfo projectDetectionTaskInfo = projectDetectionTaskInfoMapper.selectLastSuccessByProjectId(projectId);
if (projectDetectionTaskInfo == null) {
throw new BusinessException(ErrorCodeEnum.PROJECT_NOT_SUCCESS);
}
return null;
}
@Override
public ProjectVulnerabilityDetailDTO projectVulnerabilityDetail(Long projectId, String uuid) {
@ -840,7 +899,7 @@ public class ProjectServiceImpl implements ProjectService {
sonarScannerParam.setLanguage(contains ? QualityConstants.C : QualityConstants.OTHER);
boolean useNet = detectionTemplate.getLanguage().toLowerCase().contains(QualityConstants.NET);
if (useNet){
if (useNet) {
sonarScannerParam.setLanguage(QualityConstants.NET);
}
sonarScannerParam.setWorkspace(workspace);
@ -879,6 +938,7 @@ public class ProjectServiceImpl implements ProjectService {
* @return
*/
private CompareResultDTO<?> processCompareResult(DetectResultCompareEnum detectResultCompareEnum, List<ProjectDetectionTaskInfo> projectDetectionTaskInfos) {
Long projectId = projectDetectionTaskInfos.get(0).getProjectId();
if (DetectResultCompareEnum.COMPONENT.getType().equals(detectResultCompareEnum.getType())) {
CompareResultDTO<ComponentResultDTO> resultDTO = new CompareResultDTO();
resultDTO.setFirstDetect(new ComponentResultDTO());
@ -887,14 +947,14 @@ public class ProjectServiceImpl implements ProjectService {
} else if (DetectResultCompareEnum.VULNERABILITY.getType().equals(detectResultCompareEnum.getType())) {
CompareResultDTO<VulnerabilityResultDTO> resultDTO = new CompareResultDTO();
ProjectDetectionTaskInfo projectDetectionTaskInfo = projectDetectionTaskInfos.get(0);
ProjectDetectionTaskInfo projectDetectionTaskInfo2 = projectDetectionTaskInfos.get(1);
// ProjectDetectionTaskInfo projectDetectionTaskInfo = projectDetectionTaskInfos.get(0);
// ProjectDetectionTaskInfo projectDetectionTaskInfo2 = projectDetectionTaskInfos.get(1);
//
// String projectName = projectDetectionTaskInfo.getProjectName() + "-" + projectDetectionTaskInfo.getRandomStr();
// String projectName2 = projectDetectionTaskInfo2.getProjectName() + "-" + projectDetectionTaskInfo2.getRandomStr();
String projectName = projectDetectionTaskInfo.getProjectName() + "-" + projectDetectionTaskInfo.getRandomStr();
String projectName2 = projectDetectionTaskInfo2.getProjectName() + "-" + projectDetectionTaskInfo2.getRandomStr();
resultDTO.setFirstDetect(pgProjectsService.getVulnerability(projectName2));
resultDTO.setSecondDetect(pgProjectsService.getVulnerability(projectName));
resultDTO.setFirstDetect(pgProjectsService.getOldComponentVulnerability(projectId));
resultDTO.setSecondDetect(pgProjectsService.getNewComponentVulnerability(projectId));
return resultDTO;
} else if (DetectResultCompareEnum.BUG.getType().equals(detectResultCompareEnum.getType())) {
@ -924,17 +984,17 @@ public class ProjectServiceImpl implements ProjectService {
/**
* 处理giturl
* @param gitUrl http://118.31.13.117:64300/wangwei/jwebssh/analysis Or http://118.31.13.117:64300/wangwei/jwebssh/analysis/
*
* @param gitUrl http://118.31.13.117:64300/wangwei/jwebssh/analysis Or http://118.31.13.117:64300/wangwei/jwebssh/analysis/
* @return
*/
private String processGitUrl(String gitUrl){
private String processGitUrl(String gitUrl) {
String router = gitUrl.substring(gitUrl.lastIndexOf("/"));
if ("/".equals(router) || StringUtils.isBlank(router)) {
String newGitUrl = gitUrl.substring(0, gitUrl.length() - 1);
router = newGitUrl.substring(newGitUrl.lastIndexOf("/"));
return newGitUrl.replaceAll(router,"") + ".git";
return newGitUrl.replaceAll(router, "") + ".git";
}
return gitUrl.replaceAll(router,"") + ".git";
return gitUrl.replaceAll(router, "") + ".git";
}
}

View File

@ -0,0 +1,184 @@
package net.educoder.quality.service.impl;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import net.educoder.quality.common.bean.ShellResult;
import net.educoder.quality.common.config.PropertiesConfig;
import net.educoder.quality.common.enums.ErrorCodeEnum;
import net.educoder.quality.common.exception.BusinessException;
import net.educoder.quality.common.util.GitUtil;
import net.educoder.quality.common.util.ShellUtil;
import net.educoder.quality.dto.SastBugDTO;
import net.educoder.quality.entity.mysql.Projects;
import net.educoder.quality.entity.mysql.SastAnalysisDetail;
import net.educoder.quality.entity.sast.BizKnowledgeBug;
import net.educoder.quality.mapper.mysql.SastAnalysisDetailMapper;
import net.educoder.quality.mapper.sast.BizKnowledgeBugMapper;
import net.educoder.quality.service.ProjectService;
import net.educoder.quality.service.SastService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@Service
@Slf4j
public class SastServiceImpl implements SastService {
private Pattern p = Pattern.compile("[\\s\\S]*(\\{[\\s\\S]*Result.[\\s\\S]*\\})[\\s\\S]*");
@Autowired
private PropertiesConfig propertiesConfig;
@Autowired
private ProjectService projectService;
@Autowired
private BizKnowledgeBugMapper bizKnowledgeBugMapper;
@Autowired
private SastAnalysisDetailMapper sastAnalysisDetailMapper;
@Override
public void analysis(Long projectId, String taskId) {
Projects projects = projectService.getProjectById(projectId);
if (projects == null) {
throw new BusinessException(ErrorCodeEnum.PROJECT_NOT_EXISTS);
}
String fullPath = propertiesConfig.getWorkspace() + "/" + DateUtil.formatDate(new Date()) + "/" + RandomUtil.randomString(10);
ShellResult gitCloneResult = GitUtil.gitClone(projects.getGitUrl(), projects.getBranch(), propertiesConfig.getGitUsername(), propertiesConfig.getGitPassword(), fullPath);
if (gitCloneResult.getExitStatus() != 0) {
log.info("projectId:{}克隆代码失败,终止执行", projectId);
return;
}
// 执行检测
Map<String, String> paramMap = new HashMap<>();
paramMap.put("driver", propertiesConfig.getSastDriver());
paramMap.put("outputDir", "/tmp/" + RandomUtil.randomString(10));
paramMap.put("targetDir", fullPath);
List<SastBugDTO> sastResult = execute(paramMap);
log.info("SAST结果: {}, projectId: {}, taskId: {}", sastResult, projectId, taskId);
List<String> bugTypes = sastResult.stream().map(SastBugDTO::getBugType).collect(Collectors.toList());
// 取结果封装详情入库
List<BizKnowledgeBug> bizKnowledgeBugs = bizKnowledgeBugMapper.selectBugAndCatalogByTypes(bugTypes);
List<SastAnalysisDetail> sastAnalysisDetails = new ArrayList<>();
for (SastBugDTO sastBugDTO : sastResult) {
SastAnalysisDetail sastAnalysisDetail = new SastAnalysisDetail();
BeanUtils.copyProperties(sastBugDTO, sastAnalysisDetail);
BizKnowledgeBug bizKnowledgeBug = bizKnowledgeBugs.stream().filter(bug -> bug.getBugType().equals(sastBugDTO.getBugType())).findFirst().get();
BeanUtils.copyProperties(bizKnowledgeBug, sastAnalysisDetail);
sastAnalysisDetail.setProjectId(projectId);
sastAnalysisDetail.setTaskId(taskId);
sastAnalysisDetail.setFilePath(fullPath + sastBugDTO.getFilePath());
sastAnalysisDetail.setCreateTime(DateTime.now());
sastAnalysisDetail.setUpdateTime(DateTime.now());
sastAnalysisDetails.add(sastAnalysisDetail);
}
sastAnalysisDetailMapper.insertList(sastAnalysisDetails);
log.info("SAST结果入库完成, projectId: {}, taskId: {}", sastResult, projectId, taskId);
}
public List<SastBugDTO> execute(Map<String, String> paramMap) {
List<SastBugDTO> sastBugDTOS = new ArrayList<>();
String separator = "/|\\\\";
String driver = paramMap.get("driver");
String buildFileType = paramMap.get("buildFileType");
String outputDir1 = paramMap.get("outputDir");
String outputDir2 = outputDir1.replace(separator, "/");
Path outputDir = Paths.get(outputDir2, new String[0]);
String targetDir1 = paramMap.get("targetDir");
String targetDir2 = targetDir1.replace(separator, "/");
Path targetDir = Paths.get(targetDir2, new String[0]);
String examiningMode = paramMap.get("examiningMode");
String examiningFrame = paramMap.get("examiningFrame");
String examiningLanguage = paramMap.get("examiningLanguage");
String source = paramMap.get("source");
String forceAutoBuild = paramMap.get("forceAutoBuild");
String incrementFlg = paramMap.get("incrementFlg");
String incrementFilePath = paramMap.get("incrementFilePath");
StringBuffer sb = new StringBuffer();
sb.append(driver);
if (!StringUtils.isEmpty(examiningFrame)) {
for (String frame : examiningFrame.split(","))
sb.append(" -" + frame);
} else {
sb.append(" -OC");
}
if ("1".equals(forceAutoBuild))
sb.append(" -build ");
if ("1".equals(examiningMode)) {
sb.append(" -l 2");
} else if ("2".equals(examiningMode)) {
sb.append(" -l 3");
} else {
sb.append(" -l 1");
}
if ("1".equals(source) &&
"1".equals(incrementFlg) && !StringUtils.isEmpty(incrementFilePath))
sb.append(" --increment-file " + incrementFilePath);
sb.append(" --merge-json ");
if (!StringUtils.isEmpty(examiningLanguage))
for (String language : examiningLanguage.split(",")) {
if (!StringUtils.isEmpty(language))
sb.append(" -L " + language);
}
sb.append(" -p WK_ALL");
if (!StringUtils.isEmpty(buildFileType))
sb.append(" --BFT " + buildFileType);
sb.append(" -o");
sb.append(" ");
sb.append(outputDir);
sb.append(" ");
sb.append(targetDir);
// TODO 临时
sb.append("'");
ShellUtil.execute("sshpass -pWk_20230306wk scp -r -P40022 -o StrictHostKeyChecking=no " + targetDir + " root@118.178.181.154:" + targetDir);
ShellUtil.execute(sb.toString());
String analysisResult = ShellUtil.execute("sshpass -pWk_20230306wk ssh -p40022 -o StrictHostKeyChecking=no root@118.178.181.154 " +
"'cat " + outputDir + "/mergedJson'");
log.info("SAST扫描命令: {}, 结果: {}", sb.toString(), analysisResult);
Matcher matcher = p.matcher(analysisResult);
if (matcher.find()) {
analysisResult = matcher.group(1);
JSONArray result = JSON.parseObject(analysisResult).getJSONArray("Result");
for (int i = 0; i < result.size(); i++) {
JSONObject ele = result.getJSONObject(i);
SastBugDTO sastBugDTO = new SastBugDTO();
sastBugDTO.setBugId(ele.getLong("bug_id"));
sastBugDTO.setBugType(ele.getString("bug_type"));
sastBugDTO.setFilePath(ele.getString("file_path"));
sastBugDTO.setLine(ele.getInteger("line"));
sastBugDTO.setMessage(ele.getString("message"));
sastBugDTO.setMethodName(ele.getString("methodName"));
sastBugDTO.setVariable(ele.getString("variable"));
sastBugDTOS.add(sastBugDTO);
}
}
return sastBugDTOS;
}
@Override
public SastAnalysisDetail findById(Long id) {
return sastAnalysisDetailMapper.selectByPrimaryKey(id);
}
}

View File

@ -0,0 +1,155 @@
package net.educoder.quality.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import net.educoder.quality.dto.ProjectVulnerabilityDTO;
import net.educoder.quality.dto.ProjectVulnerabilityDetailDTO;
import net.educoder.quality.entity.mysql.ComponentParseRecord;
import net.educoder.quality.entity.mysql.ProjectVulnerabilityDetail;
import net.educoder.quality.mapper.mysql.ComponentParseRecordMapper;
import net.educoder.quality.mapper.mysql.ProjectVulnerabilityDetailMapper;
import net.educoder.quality.service.VulnerabilityService;
import net.educoder.quality.vo.PageVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Slf4j
@Service
public class VulnerabilityServiceImpl implements VulnerabilityService {
@Resource
private ProjectVulnerabilityDetailMapper projectVulnerabilityDetailMapper;
@Autowired
private ComponentParseRecordMapper componentParseRecordMapper;
@Override
public PageInfo<ProjectVulnerabilityDetailDTO> vulnerabilityList(Long projectId, PageVO pageVO) {
PageHelper.startPage(pageVO.getPageNum(), pageVO.getPageSize());
ProjectVulnerabilityDetail projectVulnerabilityDetail = new ProjectVulnerabilityDetail();
projectVulnerabilityDetail.setProjectId(projectId);
List<ProjectVulnerabilityDetail> details = projectVulnerabilityDetailMapper.select(projectVulnerabilityDetail);
PageInfo<ProjectVulnerabilityDetail> doPageInfo = new PageInfo<>(details);
List<ProjectVulnerabilityDetailDTO> dtos = new ArrayList<>();
for (ProjectVulnerabilityDetail detail : details) {
dtos.add(convertToDTO(detail));
}
PageInfo<ProjectVulnerabilityDetailDTO> result = new PageInfo<>();
BeanUtil.copyProperties(doPageInfo, result);
result.setList(dtos);
return result;
}
private static ProjectVulnerabilityDetailDTO convertToDTO(ProjectVulnerabilityDetail detail) {
ProjectVulnerabilityDetailDTO dto = new ProjectVulnerabilityDetailDTO();
dto.setVulnerabilityName(detail.getVulnerabilityName());
dto.setVulnerabilityNumber(detail.getVulnerabilityNumber());
Map<Object, Object> difficultyMap = MapUtil.builder().put(0, "简单").put(1, "困难").build();
dto.setDifficulty((String) difficultyMap.get(detail.getDifficulty()));
Map<Object, Object> riskMap = MapUtil.builder().put(0, "未知").put(1, "低危").put(2, "中危").put(3, "高危").put(4, "严重").build();
dto.setRiskLevel((String) riskMap.get(detail.getRiskLevel()));
dto.setPublishDate(detail.getPublishDate());
dto.setAttackType(detail.getAttackType());
dto.setRepairSuggestions(detail.getRepairSuggestions());
dto.setDescription(detail.getDescription());
dto.setUuid(String.valueOf(detail.getId()));
return dto;
}
@Override
public ProjectVulnerabilityDetailDTO vulnerabilityDetail(Long projectId, String uuid) {
ProjectVulnerabilityDetail projectVulnerabilityDetail = new ProjectVulnerabilityDetail();
projectVulnerabilityDetail.setProjectId(projectId);
projectVulnerabilityDetail.setId(Long.parseLong(uuid));
projectVulnerabilityDetail = projectVulnerabilityDetailMapper.selectOne(projectVulnerabilityDetail);
return convertToDTO(projectVulnerabilityDetail);
}
@Override
public ProjectVulnerabilityDTO vulnerabilityStatistics(Long projectId) {
ProjectVulnerabilityDTO result = new ProjectVulnerabilityDTO();
List<ComponentParseRecord> recordList = componentParseRecordMapper.quaryByProjectId(projectId);
if (recordList.size() <= 0){
return result;
}
ComponentParseRecord newRecord = recordList.get(0);
ProjectVulnerabilityDetail projectVulnerabilityDetail = new ProjectVulnerabilityDetail();
projectVulnerabilityDetail.setComponentId(newRecord.getId());
List<ProjectVulnerabilityDetail> details = projectVulnerabilityDetailMapper.select(projectVulnerabilityDetail);
result.setTotal((long)details.size());
for (ProjectVulnerabilityDetail detail : details) {
switch (detail.getRiskLevel()) {
case 0:
result.setUnKnow(result.getUnKnow() + 1);
break;
case 1:
result.setLow(result.getLow() + 1);
break;
case 2:
result.setMiddle(result.getMiddle() + 1);
break;
case 3:
result.setHigh(result.getHigh() + 1);
break;
case 4:
result.setCritical(result.getCritical() + 1);
break;
default:
break;
}
}
//根据上次检测结果过滤出最近新增的Vulnerability数量
ComponentParseRecord componentParseRecord = null;
if (recordList.size() >= 2){
componentParseRecord = recordList.get(1);
}
if (componentParseRecord!=null){
Long componentId = componentParseRecord.getId();
projectVulnerabilityDetail.setComponentId(componentId);
List<ProjectVulnerabilityDetail> collects = projectVulnerabilityDetailMapper.select(projectVulnerabilityDetail);
for (ProjectVulnerabilityDetail detail : collects) {
switch (detail.getRiskLevel()) {
case 0:
result.setNewUnKnow(result.getNewUnKnow() + 1);
break;
case 1:
result.setNewLow(result.getNewLow() + 1);
break;
case 2:
result.setNewMiddle(result.getNewMiddle() + 1);
break;
case 3:
result.setNewHigh(result.getNewHigh() + 1);
break;
case 4:
result.setNewCritical(result.getNewCritical() + 1);
break;
default:
break;
}
}
result.setNewUnKnow(result.getUnKnow() - result.getNewUnKnow());
result.setNewLow(result.getLow() - result.getNewLow());
result.setNewMiddle(result.getMiddle() - result.getNewMiddle());
result.setNewHigh(result.getHigh() - result.getNewHigh());
result.setNewCritical(result.getCritical() - result.getNewCritical());
}
return result;
}
}

View File

@ -11,10 +11,13 @@ import net.educoder.quality.common.enums.*;
import net.educoder.quality.common.exception.BusinessException;
import net.educoder.quality.common.util.WordUtil;
import net.educoder.quality.dto.*;
import net.educoder.quality.entity.mysql.ComponentParseRecord;
import net.educoder.quality.entity.mysql.ComponentParseRecordDetail;
import net.educoder.quality.entity.mysql.ProjectVulnerabilityDetail;
import net.educoder.quality.entity.postgres.*;
import net.educoder.quality.mapper.mysql.ComponentParseRecordDetailMapper;
import net.educoder.quality.mapper.mysql.ComponentParseRecordMapper;
import net.educoder.quality.mapper.mysql.ProjectVulnerabilityDetailMapper;
import net.educoder.quality.mapper.mysql.ProjectsMapper;
import net.educoder.quality.mapper.postgres.PgCeActivityMapper;
import net.educoder.quality.mapper.postgres.PgProjectMapper;
@ -27,6 +30,7 @@ import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -55,6 +59,11 @@ public class PgProjectsService {
@Autowired
private ProjectsMapper mysqlProjectMapper;
@Resource
private ProjectVulnerabilityDetailMapper projectVulnerabilityDetailMapper;
@Autowired
private ComponentParseRecordMapper componentParseRecordMapper;
public PgProjects getProjectsByProjectName(String projectName) {
PgProjects project = projectMapper.findByName(projectName);
@ -215,6 +224,7 @@ public class PgProjectsService {
* @param projectName
* @return
*/
@Deprecated
public VulnerabilityResultDTO getVulnerability(String projectName) {
VulnerabilityResultDTO resultDTO = new VulnerabilityResultDTO();
@ -239,6 +249,95 @@ public class PgProjectsService {
return resultDTO;
}
/**
* 最新一次组件漏洞指标
* @param projectId
* @return
*/
public VulnerabilityResultDTO getNewComponentVulnerability(Long projectId) {
VulnerabilityResultDTO result = new VulnerabilityResultDTO();
List<ComponentParseRecord> recordList = componentParseRecordMapper.quaryByProjectId(projectId);
if (recordList.size() <= 0){
return result;
}
ComponentParseRecord newRecord = recordList.get(0);
ProjectVulnerabilityDetail projectVulnerabilityDetail = new ProjectVulnerabilityDetail();
projectVulnerabilityDetail.setComponentId(newRecord.getId());
List<ProjectVulnerabilityDetail> details = projectVulnerabilityDetailMapper.select(projectVulnerabilityDetail);
result.setTotal((long)details.size());
for (ProjectVulnerabilityDetail detail : details) {
switch (detail.getRiskLevel()) {
case 1:
result.setLow(result.getLow() + 1);
break;
case 2:
result.setMiddle(result.getMiddle() + 1);
break;
case 3:
result.setHigh(result.getHigh() + 1);
break;
case 4:
result.setCritical(result.getCritical() + 1);
break;
default:
break;
}
}
return result;
}
/**
* 通过组件检测记录id获取漏洞指标
* @param componentId
* @return
*/
public VulnerabilityResultDTO getVulnerabilityByComponentId(Long componentId) {
VulnerabilityResultDTO result = new VulnerabilityResultDTO();
ProjectVulnerabilityDetail projectVulnerabilityDetail = new ProjectVulnerabilityDetail();
projectVulnerabilityDetail.setComponentId(componentId);
List<ProjectVulnerabilityDetail> details = projectVulnerabilityDetailMapper.select(projectVulnerabilityDetail);
result.setTotal((long)details.size());
for (ProjectVulnerabilityDetail detail : details) {
switch (detail.getRiskLevel()) {
case 1:
result.setLow(result.getLow() + 1);
break;
case 2:
result.setMiddle(result.getMiddle() + 1);
break;
case 3:
result.setHigh(result.getHigh() + 1);
break;
case 4:
result.setCritical(result.getCritical() + 1);
break;
default:
break;
}
}
return result;
}
/**
* 上一次组件漏洞检测结果
* @param projectId
* @return
*/
public VulnerabilityResultDTO getOldComponentVulnerability(Long projectId) {
List<ComponentParseRecord> recordList = componentParseRecordMapper.quaryByProjectId(projectId);
VulnerabilityResultDTO vulnerability;
if (recordList.size() <= 1){
vulnerability = new VulnerabilityResultDTO();
}else {
Long oldComponentId = recordList.get(1).getId();
vulnerability = getVulnerabilityByComponentId(oldComponentId);
}
return vulnerability;
}
/**
* 获取缺陷指标
*

View File

@ -6,9 +6,11 @@ openi:
sonar:
# serverUrl: http://117.50.14.123:9000
serverUrl: http://127.0.0.1:9000
workspace: /opt/workspace
workspace: /tmp/workspace
donet:
serverUrl: http://139.159.227.131:7788/donet/sonar/scan
sast:
driver: sshpass -pWk_20230306wk ssh -p40022 -o StrictHostKeyChecking=no root@118.178.181.154 'source /etc/profile; /home/wukong/docroot/wk/wukong-driver
download:
tempDir: /tmp/quality
# opensca-cli命令路径

View File

@ -55,6 +55,21 @@ spring:
test-on-borrow: false
test-on-return: false
test-while-idle: true
# sast
sast:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://118.178.181.154:43306/zktq_wukong?useUnicode=true&characterEncoding=utf8&autoReconnect=true&failOverReadOnly=false
username: root
password: Wk_20230306wk
type: com.alibaba.druid.pool.DruidDataSource
druid:
initial-size: 20
max-active: 40
min-idle: 20
validation-query: select 1
test-on-borrow: false
test-on-return: false
test-while-idle: true
# redis配置
redis:
host: 127.0.0.1

View File

@ -9,6 +9,19 @@
component_parse_record
where
project_id=#{projectId}
order by
create_time desc
limit 1
</select>
<select id="quaryByProjectId" resultType="net.educoder.quality.entity.mysql.ComponentParseRecord">
select
id,project_id,result
from
component_parse_record
where
project_id=#{projectId}
order by
create_time desc
</select>
</mapper>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="net.educoder.quality.mapper.mysql.ProjectVulnerabilityDetailMapper">
</mapper>

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="net.educoder.quality.mapper.mysql.SastAnalysisDetailMapper" >
<resultMap id="BaseResultMap" type="net.educoder.quality.entity.mysql.SastAnalysisDetail" >
<!--
WARNING - @mbg.generated
-->
<id column="id" property="id" jdbcType="BIGINT" />
<result column="bug_catalog" property="bugCatalog" jdbcType="VARCHAR" />
<result column="parent_bug_catalog" property="parentBugCatalog" jdbcType="VARCHAR" />
<result column="bug_no" property="bugNo" jdbcType="VARCHAR" />
<result column="bug_name" property="bugName" jdbcType="VARCHAR" />
<result column="parent_bug_no" property="parentBugNo" jdbcType="VARCHAR" />
<result column="bug_type" property="bugType" jdbcType="VARCHAR" />
<result column="bug_type_name" property="bugTypeName" jdbcType="VARCHAR" />
<result column="bug_level" property="bugLevel" jdbcType="CHAR" />
<result column="frequent_result_keyword" property="frequentResultKeyword" jdbcType="VARCHAR" />
<result column="create_time" property="createTime" jdbcType="TIMESTAMP" />
<result column="update_time" property="updateTime" jdbcType="TIMESTAMP" />
<result column="project_id" property="projectId" jdbcType="BIGINT" />
<result column="task_id" property="taskId" jdbcType="VARCHAR" />
<result column="synopsis" property="synopsis" jdbcType="LONGVARCHAR" />
<result column="description" property="description" jdbcType="LONGVARCHAR" />
<result column="frequent_result" property="frequentResult" jdbcType="LONGVARCHAR" />
<result column="repair_opinion" property="repairOpinion" jdbcType="LONGVARCHAR" />
<result column="example" property="example" jdbcType="LONGVARCHAR" />
<result column="error_example" property="errorExample" jdbcType="LONGVARCHAR" />
<result column="method_name" property="methodName" jdbcType="VARCHAR" />
<result column="variable" property="variable" jdbcType="VARCHAR" />
<result column="line" property="line" jdbcType="INTEGER" />
<result column="file_path" property="filePath" jdbcType="VARCHAR" />
</resultMap>
</mapper>

View File

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="net.educoder.quality.mapper.sast.BizKnowledgeBugMapper">
<resultMap id="BaseResultMap" type="net.educoder.quality.entity.sast.BizKnowledgeBug">
<!--
WARNING - @mbg.generated
-->
<id column="OID_KNOWLEDGE_BUG_ID" jdbcType="VARCHAR" property="oidKnowledgeBugId"/>
<result column="OID_KNOWLEDGE_CATALOG_ID" jdbcType="VARCHAR" property="oidKnowledgeCatalogId"/>
<result column="BUG_NO" jdbcType="VARCHAR" property="bugNo"/>
<result column="BUG_NAME" jdbcType="VARCHAR" property="bugName"/>
<result column="PARENT_BUG_NO" jdbcType="VARCHAR" property="parentBugNo"/>
<result column="BUG_TYPE" jdbcType="VARCHAR" property="bugType"/>
<result column="BUG_TYPE_NAME" jdbcType="VARCHAR" property="bugTypeName"/>
<result column="BUG_LEVEL" jdbcType="CHAR" property="bugLevel"/>
<result column="FREQUENT_RESULT_KEYWORD" jdbcType="VARCHAR" property="frequentResultKeyword"/>
<result column="DEL_FLG" jdbcType="CHAR" property="delFlg"/>
<result column="INS_USER_ID" jdbcType="VARCHAR" property="insUserId"/>
<result column="INS_DATE" jdbcType="TIMESTAMP" property="insDate"/>
<result column="UPD_USER_ID" jdbcType="VARCHAR" property="updUserId"/>
<result column="UPD_DATE" jdbcType="TIMESTAMP" property="updDate"/>
<result column="SYNOPSIS" jdbcType="LONGVARCHAR" property="synopsis"/>
<result column="DESCRIPTION" jdbcType="LONGVARCHAR" property="description"/>
<result column="FREQUENT_RESULT" jdbcType="LONGVARCHAR" property="frequentResult"/>
<result column="REPAIR_OPINION" jdbcType="LONGVARCHAR" property="repairOpinion"/>
<result column="EXAMPLE" jdbcType="LONGVARCHAR" property="example"/>
<result column="ERROR_EXAMPLE" jdbcType="LONGVARCHAR" property="errorExample"/>
</resultMap>
<select id="selectBugAndCatalogByTypes" resultType="net.educoder.quality.entity.sast.BizKnowledgeBug"
parameterType="java.util.ArrayList">
select bug.BUG_NO as bugNo,
bug.BUG_NAME as bugName,
bug.BUG_TYPE as bugType,
bug.BUG_TYPE_NAME as bugTypeName,
bug.BUG_LEVEL as bugLevel,
bug.FREQUENT_RESULT_KEYWORD as frequentResultKeyword,
bug.INS_DATE as insDate,
bug.SYNOPSIS as synopsis,
bug.DESCRIPTION as description,
bug.FREQUENT_RESULT as frequentResult,
bug.REPAIR_OPINION as repairOpinion,
bug.EXAMPLE as example,
bug.ERROR_EXAMPLE as errorExample,
cata.FULL_NAME as bugCatalog,
catap.FULL_NAME as parentBugCatalog
from biz_knowledge_bug bug left join biz_knowledge_catalog cata on
bug.OID_KNOWLEDGE_CATALOG_ID = cata.OID_KNOWLEDGE_CATALOG_ID
left join biz_knowledge_catalog catap on cata.PARENT_ID = catap.OID_KNOWLEDGE_CATALOG_ID
<where>
bug.BUG_TYPE in (
<foreach collection="list" item="type" index="index" separator=",">
#{type}
</foreach>
)
</where>
</select>
</mapper>