This commit is contained in:
even 2025-07-05 21:32:10 +08:00
commit 9e13497a1d
15 changed files with 1107 additions and 105 deletions

View File

@ -1,6 +1,8 @@
package cd.casic.ci.api; package cd.casic.ci.api;
import cd.casic.ci.process.dto.req.aflManager.AflManagerReq; import cd.casic.ci.process.dto.req.aflManager.AflManagerReq;
import cd.casic.ci.process.dto.resp.aflManager.AflCrashesInfoResp;
import cd.casic.ci.process.dto.resp.aflManager.AflInfoResp;
import cd.casic.ci.process.dto.resp.aflManager.SeedsCountResp; import cd.casic.ci.process.dto.resp.aflManager.SeedsCountResp;
import cd.casic.ci.process.process.service.aflManager.AflCrashesInfoService; import cd.casic.ci.process.process.service.aflManager.AflCrashesInfoService;
import cd.casic.ci.process.process.service.aflManager.AflInfoService; import cd.casic.ci.process.process.service.aflManager.AflInfoService;
@ -39,18 +41,45 @@ public class AflManagerController {
@PostMapping(path="/saveAflInfo") @PostMapping(path="/saveAflInfo")
public CommonResult<String> saveAflInfo(@RequestBody @Valid AflManagerReq req) throws SftpUploadUtil.SftpUploadException { public CommonResult<String> saveAflInfo(@RequestBody @Valid AflManagerReq req) throws SftpUploadUtil.SftpUploadException {
String aflInfoId = aflInfoService.saveAflInfo(req); String groupIdentifier = aflInfoService.saveAflInfo(req);
return CommonResult.success(aflInfoId); return CommonResult.success(groupIdentifier);
}
@PostMapping(path="/findAflInfo")
public CommonResult<AflInfoResp> findAflInfo(@RequestBody @Valid AflManagerReq req) throws SftpUploadUtil.SftpUploadException {
AflInfoResp resp = aflInfoService.findAflInfo(req);
return CommonResult.success(resp);
}
@PostMapping(path="/findAflInfoList")
public CommonResult<List<AflInfoResp>> findAflInfoList(@RequestBody @Valid AflManagerReq req){
List<AflInfoResp> respList = aflInfoService.findPipelineList(req);
return CommonResult.success(respList);
} }
@PostMapping(path="/saveAflCrashesInfo") @PostMapping(path="/saveAflCrashesInfo")
public CommonResult<Void> saveAflCrashesInfo(@RequestBody @Valid AflManagerReq req) throws SftpUploadUtil.SftpUploadException { public CommonResult<String> saveAflCrashesInfo(@RequestBody @Valid AflManagerReq req) throws SftpUploadUtil.SftpUploadException {
aflCrashesInfoService.saveAflCrashesInfo(req); String groupIdentifier = aflCrashesInfoService.saveAflCrashesInfo(req);
return CommonResult.success(); return CommonResult.success(groupIdentifier);
}
@PostMapping(path="/findAflCrashesInfoList")
public CommonResult<List<AflCrashesInfoResp>> findAflCrashesInfoList(@RequestBody @Valid AflManagerReq req){
List<AflCrashesInfoResp> respList = aflCrashesInfoService.findPipelineList(req);
return CommonResult.success(respList);
} }

View File

@ -4,9 +4,12 @@ import lombok.Data;
@Data @Data
public class AflManagerReq { public class AflManagerReq {
private String id;
private String pipelineId; private String pipelineId;
private String pipelineHistoryId; private String pipelineHistoryId;
private String taskId; private String taskId;
//分组唯一标识
private String groupIdentifier;
/** /**
* 主机地址 * 主机地址

View File

@ -0,0 +1,275 @@
package cd.casic.ci.process.dto.resp.aflManager;
import lombok.Data;
/**
* @ClassName ReportResp
* @Author hopeli
* @Date 2025/5/10 10:53
* @Version 1.0
*/
@Data
public class AflCrashesInfoResp {
private String id;
private String pipelineId;
private String pipelineHistoryId;
private String taskId;
//分组唯一标识
private String groupIdentifier;
/**
* 模糊测试进程的开始时间
*/
private String startTime;
/**
* 最后一次更新时间戳
*/
private String lastUpdate;
/**
* 总运行时间
*/
private String runTime;
/**
* 模糊器的进程 ID
*/
private String fuzzerPid;
/**
* 已完成的循环次数
*/
private String cyclesDone;
/**
* 未发现新内容的循环次数
*/
private String cyclesWoFinds;
/**
* 未发现新内容的时间
*/
private String timeWoFinds;
/**
* 模糊测试所用时间
*/
private String fuzzTime;
/**
* 校准时间
*/
private String calibrationTime;
/**
* 比较日志时间
*/
private String cmplogTime;
/**
* 同步时间
*/
private String syncTime;
/**
* 裁剪时间
*/
private String trimTime;
/**
* 已执行的次数
*/
private String execsDone;
/**
* 每秒执行次数
*/
private String execsPerSec;
/**
* 上一分钟内的每秒执行次数
*/
private String execsPsLastMin;
/**
* 语料库中的条目数量
*/
private String corpusCount;
/**
* 语料库中被优先选择的条目
*/
private String corpusFavored;
/**
* 语料库中发现的条目
*/
private String corpusFound;
/**
* 导入到语料库的条目
*/
private String corpusImported;
/**
* 语料库中的可变条目
*/
private String corpusVariable;
/**
* 达到的最大深度
*/
private String maxDepth;
/**
* 当前处理的条目索引
*/
private String curItem;
/**
* 待处理的优先条目数
*/
private String pendingFavs;
/**
* 总待处理条目数
*/
private String pendingTotal;
/**
* 稳定性百分比
*/
private String stability;
/**
* 位图覆盖率百分比
*/
private String bitmapCvg;
/**
* 保存的崩溃次数
*/
private String savedCrashes;
/**
* 保存的挂起次数
*/
private String savedHangs;
/**
* 总超时次数
*/
private String totalTmout;
/**
* 上次发现的时间戳
*/
private String lastFind;
/**
* 上次崩溃的时间戳
*/
private String lastCrash;
/**
* 上次挂起的时间戳
*/
private String lastHang;
/**
* 自上次崩溃以来的执行次数
*/
private String execsSinceCrash;
/**
* 执行超时值
*/
private String execTimeout;
/**
* 最慢执行时间毫秒
*/
private String slowestExecMs;
/**
* 峰值 RSS 内存使用量MB
*/
private String peakRssMb;
/**
* CPU 亲和性设置
*/
private String cpuAffinity;
/**
* 发现的边数edges
*/
private String edgesFound;
/**
* 总可用边数edges
*/
private String totalEdges;
/**
* 可变字节计数
*/
private String varByteCount;
/**
* Havoc 扩展因子
*/
private String havocExpansion;
/**
* 自动词典条目数
*/
private String autoDictEntries;
/**
* 测试缓存大小
*/
private String testcacheSize;
/**
* 测试缓存条目数
*/
private String testcacheCount;
/**
* 测试缓存驱逐次数
*/
private String testcacheEvict;
/**
* 目标程序 banner
*/
private String aflBanner;
/**
* 使用的 AFL 版本
*/
private String aflVersion;
/**
* 目标模式配置
*/
private String targetMode;
/**
* 执行使用的命令行
*/
private String commandLine;
/**
* 文件二进制内容
*/
private String contentId;
/**
* 文件地址路径
*/
private String filePath;
}

View File

@ -0,0 +1,275 @@
package cd.casic.ci.process.dto.resp.aflManager;
import lombok.Data;
/**
* @ClassName ReportResp
* @Author hopeli
* @Date 2025/5/10 10:53
* @Version 1.0
*/
@Data
public class AflInfoResp {
private String id;
private String pipelineId;
private String pipelineHistoryId;
private String taskId;
//分组唯一标识
private String groupIdentifier;
/**
* 模糊测试进程的开始时间
*/
private String startTime;
/**
* 最后一次更新时间戳
*/
private String lastUpdate;
/**
* 总运行时间
*/
private String runTime;
/**
* 模糊器的进程 ID
*/
private String fuzzerPid;
/**
* 已完成的循环次数
*/
private String cyclesDone;
/**
* 未发现新内容的循环次数
*/
private String cyclesWoFinds;
/**
* 未发现新内容的时间
*/
private String timeWoFinds;
/**
* 模糊测试所用时间
*/
private String fuzzTime;
/**
* 校准时间
*/
private String calibrationTime;
/**
* 比较日志时间
*/
private String cmplogTime;
/**
* 同步时间
*/
private String syncTime;
/**
* 裁剪时间
*/
private String trimTime;
/**
* 已执行的次数
*/
private String execsDone;
/**
* 每秒执行次数
*/
private String execsPerSec;
/**
* 上一分钟内的每秒执行次数
*/
private String execsPsLastMin;
/**
* 语料库中的条目数量
*/
private String corpusCount;
/**
* 语料库中被优先选择的条目
*/
private String corpusFavored;
/**
* 语料库中发现的条目
*/
private String corpusFound;
/**
* 导入到语料库的条目
*/
private String corpusImported;
/**
* 语料库中的可变条目
*/
private String corpusVariable;
/**
* 达到的最大深度
*/
private String maxDepth;
/**
* 当前处理的条目索引
*/
private String curItem;
/**
* 待处理的优先条目数
*/
private String pendingFavs;
/**
* 总待处理条目数
*/
private String pendingTotal;
/**
* 稳定性百分比
*/
private String stability;
/**
* 位图覆盖率百分比
*/
private String bitmapCvg;
/**
* 保存的崩溃次数
*/
private String savedCrashes;
/**
* 保存的挂起次数
*/
private String savedHangs;
/**
* 总超时次数
*/
private String totalTmout;
/**
* 上次发现的时间戳
*/
private String lastFind;
/**
* 上次崩溃的时间戳
*/
private String lastCrash;
/**
* 上次挂起的时间戳
*/
private String lastHang;
/**
* 自上次崩溃以来的执行次数
*/
private String execsSinceCrash;
/**
* 执行超时值
*/
private String execTimeout;
/**
* 最慢执行时间毫秒
*/
private String slowestExecMs;
/**
* 峰值 RSS 内存使用量MB
*/
private String peakRssMb;
/**
* CPU 亲和性设置
*/
private String cpuAffinity;
/**
* 发现的边数edges
*/
private String edgesFound;
/**
* 总可用边数edges
*/
private String totalEdges;
/**
* 可变字节计数
*/
private String varByteCount;
/**
* Havoc 扩展因子
*/
private String havocExpansion;
/**
* 自动词典条目数
*/
private String autoDictEntries;
/**
* 测试缓存大小
*/
private String testcacheSize;
/**
* 测试缓存条目数
*/
private String testcacheCount;
/**
* 测试缓存驱逐次数
*/
private String testcacheEvict;
/**
* 目标程序 banner
*/
private String aflBanner;
/**
* 使用的 AFL 版本
*/
private String aflVersion;
/**
* 目标模式配置
*/
private String targetMode;
/**
* 执行使用的命令行
*/
private String commandLine;
/**
* 文件二进制内容
*/
private String contentId;
/**
* 文件地址路径
*/
private String filePath;
}

View File

@ -0,0 +1,29 @@
package cd.casic.ci.process.process.converter;
import cd.casic.ci.process.dto.resp.aflManager.AflCrashesInfoResp;
import cd.casic.ci.process.dto.resp.aflManager.AflInfoResp;
import cd.casic.ci.process.process.dataObject.aflManager.AflCrashesInfo;
import cd.casic.ci.process.process.dataObject.aflManager.AflInfo;
import org.mapstruct.Mapper;
import org.mapstruct.NullValuePropertyMappingStrategy;
import org.mapstruct.factory.Mappers;
import java.util.List;
/**
* @author HopeLi
* @version v1.0
* @ClassName PipelineConverter
* @Date: 2025/5/13 14:39
* @Description:
*/
@Mapper(componentModel = "spring",nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
public interface AflManagerConverter {
AflManagerConverter INSTANCE = Mappers.getMapper(AflManagerConverter.class);
AflInfoResp toAflInfoResp(AflInfo aflInfo);
List<AflInfoResp> toAflInfoRespList(List<AflInfo> aflInfos);
List<AflCrashesInfoResp> toAflCrashesInfoRespList(List<AflCrashesInfo> aflCrashesInfos);
}

View File

@ -17,6 +17,8 @@ public class AflCrashesInfo extends PipBaseElement {
private String pipelineHistoryId; private String pipelineHistoryId;
private String taskId; private String taskId;
//分组唯一标识
private String groupIdentifier;
/** /**

View File

@ -12,6 +12,8 @@ public class AflInfo extends PipBaseElement {
private String pipelineId; private String pipelineId;
private String pipelineHistoryId; private String pipelineHistoryId;
private String taskId; private String taskId;
//分组唯一标识
private String groupIdentifier;
/** /**
* 模糊测试进程的开始时间 * 模糊测试进程的开始时间

View File

@ -18,9 +18,11 @@ public class AflSeedInfo extends PipBaseElement {
private String pipelineId; private String pipelineId;
private String pipelineHistoryId; private String pipelineHistoryId;
private String taskId; private String taskId;
//分组唯一标识
private String groupIdentifier;
/** /**
* 最后一次更新时间戳 * 生成种子数量
*/ */
private String seedAmount; private String seedAmount;
@ -29,4 +31,10 @@ public class AflSeedInfo extends PipBaseElement {
*/ */
private String filePath; private String filePath;
/**
* 执行分钟数
*/
private Integer minutesDifference;
} }

View File

@ -1,10 +1,13 @@
package cd.casic.ci.process.process.service.aflManager; package cd.casic.ci.process.process.service.aflManager;
import cd.casic.ci.process.dto.req.aflManager.AflManagerReq; import cd.casic.ci.process.dto.req.aflManager.AflManagerReq;
import cd.casic.ci.process.dto.resp.aflManager.AflCrashesInfoResp;
import cd.casic.ci.process.process.dataObject.aflManager.AflCrashesInfo; import cd.casic.ci.process.process.dataObject.aflManager.AflCrashesInfo;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import java.util.List;
/** /**
* @author HopeLi * @author HopeLi
* @version v1.0 * @version v1.0
@ -14,5 +17,9 @@ import jakarta.validation.Valid;
*/ */
public interface AflCrashesInfoService extends IService<AflCrashesInfo> { public interface AflCrashesInfoService extends IService<AflCrashesInfo> {
void saveAflCrashesInfo(@Valid AflManagerReq req); String saveAflCrashesInfo(@Valid AflManagerReq req);
void updateHistoryPipelineIdByAflCrashesInfo(@Valid AflManagerReq req);
List<AflCrashesInfoResp> findPipelineList(@Valid AflManagerReq req);
} }

View File

@ -1,11 +1,14 @@
package cd.casic.ci.process.process.service.aflManager; package cd.casic.ci.process.process.service.aflManager;
import cd.casic.ci.process.dto.req.aflManager.AflManagerReq; import cd.casic.ci.process.dto.req.aflManager.AflManagerReq;
import cd.casic.ci.process.dto.resp.aflManager.AflInfoResp;
import cd.casic.ci.process.process.dataObject.aflManager.AflInfo; import cd.casic.ci.process.process.dataObject.aflManager.AflInfo;
import cd.casic.ci.process.util.SftpUploadUtil; import cd.casic.ci.process.util.SftpUploadUtil;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import java.util.List;
/** /**
* @author HopeLi * @author HopeLi
* @version v1.0 * @version v1.0
@ -16,4 +19,10 @@ import jakarta.validation.Valid;
public interface AflInfoService extends IService<AflInfo> { public interface AflInfoService extends IService<AflInfo> {
String saveAflInfo(@Valid AflManagerReq req) throws SftpUploadUtil.SftpUploadException; String saveAflInfo(@Valid AflManagerReq req) throws SftpUploadUtil.SftpUploadException;
void updateHistoryPipelineIdByAflInfo(@Valid AflManagerReq req);
AflInfoResp findAflInfo(@Valid AflManagerReq req) throws SftpUploadUtil.SftpUploadException;
List<AflInfoResp> findPipelineList(@Valid AflManagerReq req);
} }

View File

@ -21,4 +21,6 @@ public interface AflSeedInfoService extends IService<AflSeedInfo> {
List<SeedsCountResp> findSeedsCount(@Valid AflManagerReq req) throws SftpUploadUtil.SftpUploadException; List<SeedsCountResp> findSeedsCount(@Valid AflManagerReq req) throws SftpUploadUtil.SftpUploadException;
void saveAflSeedInfo(@Valid AflManagerReq req); void saveAflSeedInfo(@Valid AflManagerReq req);
void updateHistoryPipelineIdByAflSeedInfo(@Valid AflManagerReq req);
} }

View File

@ -1,18 +1,33 @@
package cd.casic.ci.process.process.service.aflManager.impl; package cd.casic.ci.process.process.service.aflManager.impl;
import cd.casic.ci.process.dto.req.aflManager.AflManagerReq; import cd.casic.ci.process.dto.req.aflManager.AflManagerReq;
import cd.casic.ci.process.dto.resp.aflManager.AflCrashesInfoResp;
import cd.casic.ci.process.dto.resp.resource.ResourceFindResp;
import cd.casic.ci.process.engine.constant.PipelineVariableConstant;
import cd.casic.ci.process.engine.manager.RunContextManager;
import cd.casic.ci.process.engine.runContext.BaseRunContext;
import cd.casic.ci.process.process.converter.AflManagerConverter;
import cd.casic.ci.process.process.dao.aflManager.AflCrashesInfoDao; import cd.casic.ci.process.process.dao.aflManager.AflCrashesInfoDao;
import cd.casic.ci.process.process.dataObject.aflManager.AflCrashesInfo; import cd.casic.ci.process.process.dataObject.aflManager.AflCrashesInfo;
import cd.casic.ci.process.process.dataObject.resource.PipResourceMachine;
import cd.casic.ci.process.process.service.aflManager.AflCrashesInfoService; import cd.casic.ci.process.process.service.aflManager.AflCrashesInfoService;
import cd.casic.ci.process.process.service.resource.ResourceManagerService;
import cd.casic.ci.process.util.SftpUploadUtil; import cd.casic.ci.process.util.SftpUploadUtil;
import cd.casic.framework.commons.exception.ServiceException;
import cd.casic.framework.commons.exception.enums.GlobalErrorCodeConstants;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import de.danielbechler.util.Collections;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID;
/** /**
* @author HopeLi * @author HopeLi
@ -28,18 +43,42 @@ public class AflCrashesInfoServiceImpl extends ServiceImpl<AflCrashesInfoDao, Af
private static final String remoteFilePath = "/home/casic/706/yunqi/"; private static final String remoteFilePath = "/home/casic/706/yunqi/";
private static final String crashesFilePath = "/ai_afl/default/crashes/"; private static final String crashesFilePath = "/ai_afl/default/crashes/";
@Resource
private RunContextManager runContextManager;
@Resource
private ResourceManagerService resourceManagerService;
@Override @Override
public void saveAflCrashesInfo(AflManagerReq req) { public String saveAflCrashesInfo(AflManagerReq req) {
if (StringUtils.isEmpty(req.getPipelineId()) || StringUtils.isEmpty(req.getTaskId())){
throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"pipelineId或者taskId不能为空");
}
String uuid = UUID.randomUUID().toString();
BaseRunContext runContext = runContextManager.getContext(req.getPipelineId());
String resourceId = runContext.getGlobalVariables().get(PipelineVariableConstant.AFL_RESOURCE_MANAGER_ID_KEY) instanceof String ? ((String) runContext.getGlobalVariables().get(PipelineVariableConstant.AFL_RESOURCE_MANAGER_ID_KEY)) : null;
if (StringUtils.isEmpty(resourceId)){
throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"未找到资源");
}
ResourceFindResp resourceById = resourceManagerService.findResourceById(resourceId);
if (resourceById == null || resourceById.getResourceMachine() == null) {
throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"资源信息错误");
}
PipResourceMachine resourceMachine = resourceById.getResourceMachine();
try { try {
// 步骤1列出源目录下的所有文件 // 步骤1列出源目录下的所有文件
List<String> files = SftpUploadUtil.listFilesInRemoteDirectory( List<String> files = SftpUploadUtil.listFilesInRemoteDirectory(
req.getMachineHost(), Integer.parseInt(req.getSshPort()), req.getUsername(), req.getPassword(), null, remoteFilePath + "PIP_" + req.getPipelineId() + crashesFilePath); resourceMachine.getMachineHost(), Integer.parseInt(resourceMachine.getSshPort()), resourceMachine.getUsername(), resourceMachine.getPassword(), null, remoteFilePath + "PIP_" + req.getPipelineId() + crashesFilePath);
if (!CollectionUtils.isEmpty(files)) { if (!CollectionUtils.isEmpty(files)) {
// 步骤2批量复制文件到目标目录 // 步骤2批量复制文件到目标目录
List<String> copiedFiles = SftpUploadUtil.copyRemoteFile( List<String> copiedFiles = SftpUploadUtil.copyRemoteFilesToLocal(
req.getMachineHost(), Integer.parseInt(req.getSshPort()), req.getUsername(), req.getPassword(), null, files, remoteFilePath + "PIP_" + req.getPipelineId() + "/crashes_result/"); resourceMachine.getMachineHost(), Integer.parseInt(resourceMachine.getSshPort()), resourceMachine.getUsername(), resourceMachine.getPassword(), null, files, "/home/ops/opsFile/crashes_result/" + UUID.randomUUID() + "/");
System.out.println("共复制 " + copiedFiles.size() + " 个文件"); System.out.println("共复制 " + copiedFiles.size() + " 个文件");
if (!CollectionUtils.isEmpty(copiedFiles)){ if (!CollectionUtils.isEmpty(copiedFiles)){
@ -55,6 +94,7 @@ public class AflCrashesInfoServiceImpl extends ServiceImpl<AflCrashesInfoDao, Af
if (!StringUtils.isEmpty(req.getPipelineHistoryId())){ if (!StringUtils.isEmpty(req.getPipelineHistoryId())){
aflCrashesInfo.setPipelineHistoryId(req.getPipelineHistoryId()); aflCrashesInfo.setPipelineHistoryId(req.getPipelineHistoryId());
} }
aflCrashesInfo.setGroupIdentifier(uuid);
aflCrashesInfos.add(aflCrashesInfo); aflCrashesInfos.add(aflCrashesInfo);
}); });
baseMapper.insertBatch(aflCrashesInfos); baseMapper.insertBatch(aflCrashesInfos);
@ -63,9 +103,56 @@ public class AflCrashesInfoServiceImpl extends ServiceImpl<AflCrashesInfoDao, Af
// 步骤3删除旧目录 // 步骤3删除旧目录
SftpUploadUtil.clearRemoteDirectoryFiles(req.getMachineHost(), Integer.parseInt(req.getSshPort()), req.getUsername(), req.getPassword(), null, remoteFilePath + "PIP_" + req.getPipelineId() + crashesFilePath); SftpUploadUtil.clearRemoteDirectoryFiles(req.getMachineHost(), Integer.parseInt(req.getSshPort()), req.getUsername(), req.getPassword(), null, remoteFilePath + "PIP_" + req.getPipelineId() + crashesFilePath);
System.out.println("crashes目录下文件已删除: " + remoteFilePath + "PIP_" + req.getPipelineId() + crashesFilePath); System.out.println("crashes目录下文件已删除: " + remoteFilePath + "PIP_" + req.getPipelineId() + crashesFilePath);
return uuid;
}else {
return null;
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"crashes入库失败");
} }
} }
@Override
public void updateHistoryPipelineIdByAflCrashesInfo(AflManagerReq req) {
if (!StringUtils.isEmpty(req.getGroupIdentifier())){
throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"groupIdentifier不能为空");
}
QueryWrapper<AflCrashesInfo> wrapper = new QueryWrapper<>();
wrapper.eq("group_identifier", req.getGroupIdentifier());
List<AflCrashesInfo> aflCrashesInfos = baseMapper.selectList(wrapper);
if (!Collections.isEmpty(aflCrashesInfos)){
aflCrashesInfos.forEach(o->{
o.setPipelineHistoryId(req.getPipelineHistoryId());
});
}
baseMapper.updateBatch(aflCrashesInfos);
}
@Override
public List<AflCrashesInfoResp> findPipelineList(AflManagerReq req) {
QueryWrapper<AflCrashesInfo> wrapper = new QueryWrapper<>();
if (!ObjectUtils.isEmpty(req.getId())){
wrapper.eq("id",req.getId());
}
if (!ObjectUtils.isEmpty(req.getPipelineId())){
wrapper.eq("pipeline_id",req.getPipelineId());
}
if (!ObjectUtils.isEmpty(req.getPipelineHistoryId())){
wrapper.eq("pipeline_history_id",req.getPipelineHistoryId());
}
if (!ObjectUtils.isEmpty(req.getTaskId())){
wrapper.eq("task_id",req.getTaskId());
}
if (!ObjectUtils.isEmpty(req.getGroupIdentifier())){
wrapper.eq("group_identifier",req.getGroupIdentifier());
}
List<AflCrashesInfo> aflCrashesInfos = baseMapper.selectList(wrapper);
if (ObjectUtils.isEmpty(aflCrashesInfos)){
return new ArrayList<>(0);
}
return AflManagerConverter.INSTANCE.toAflCrashesInfoRespList(aflCrashesInfos);
}
} }

View File

@ -1,17 +1,28 @@
package cd.casic.ci.process.process.service.aflManager.impl; package cd.casic.ci.process.process.service.aflManager.impl;
import cd.casic.ci.process.dto.req.aflManager.AflManagerReq; import cd.casic.ci.process.dto.req.aflManager.AflManagerReq;
import cd.casic.ci.process.dto.resp.aflManager.AflInfoResp;
import cd.casic.ci.process.dto.resp.resource.ResourceFindResp;
import cd.casic.ci.process.engine.constant.PipelineVariableConstant;
import cd.casic.ci.process.engine.manager.RunContextManager;
import cd.casic.ci.process.engine.runContext.BaseRunContext;
import cd.casic.ci.process.process.converter.AflManagerConverter;
import cd.casic.ci.process.process.dao.aflManager.AflInfoDao; import cd.casic.ci.process.process.dao.aflManager.AflInfoDao;
import cd.casic.ci.process.process.dataObject.aflManager.AflInfo; import cd.casic.ci.process.process.dataObject.aflManager.AflInfo;
import cd.casic.ci.process.process.dataObject.resource.PipResourceMachine; import cd.casic.ci.process.process.dataObject.resource.PipResourceMachine;
import cd.casic.ci.process.process.service.aflManager.AflInfoService; import cd.casic.ci.process.process.service.aflManager.AflInfoService;
import cd.casic.ci.process.process.service.resource.ResourceManagerService;
import cd.casic.ci.process.util.SftpUploadUtil; import cd.casic.ci.process.util.SftpUploadUtil;
import cd.casic.framework.commons.exception.ServiceException; import cd.casic.framework.commons.exception.ServiceException;
import cd.casic.framework.commons.exception.enums.GlobalErrorCodeConstants; import cd.casic.framework.commons.exception.enums.GlobalErrorCodeConstants;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import de.danielbechler.util.Collections;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -29,22 +40,37 @@ import java.util.UUID;
public class AflInfoServiceImpl extends ServiceImpl<AflInfoDao, AflInfo> implements AflInfoService { public class AflInfoServiceImpl extends ServiceImpl<AflInfoDao, AflInfo> implements AflInfoService {
private static final String remoteFilePath = "/home/casic/706/yunqi/"; private static final String remoteFilePath = "/home/casic/706/yunqi/";
@Resource
private RunContextManager runContextManager;
@Resource
private ResourceManagerService resourceManagerService;
@Override @Override
public String saveAflInfo(AflManagerReq req) throws SftpUploadUtil.SftpUploadException { public String saveAflInfo(AflManagerReq req) throws SftpUploadUtil.SftpUploadException {
if (StringUtils.isEmpty(req.getPipelineId())){ if (StringUtils.isEmpty(req.getPipelineId()) || StringUtils.isEmpty(req.getTaskId())){
throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"pipelineId不能为空"); throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"pipelineId或者taskId不能为空");
} }
PipResourceMachine pipResourceMachine = new PipResourceMachine();
pipResourceMachine.setMachineHost(req.getMachineHost()); BaseRunContext runContext = runContextManager.getContext(req.getPipelineId());
pipResourceMachine.setSshPort(req.getSshPort()); String resourceId = runContext.getGlobalVariables().get(PipelineVariableConstant.AFL_RESOURCE_MANAGER_ID_KEY) instanceof String ? ((String) runContext.getGlobalVariables().get(PipelineVariableConstant.AFL_RESOURCE_MANAGER_ID_KEY)) : null;
pipResourceMachine.setUsername(req.getUsername()); if (StringUtils.isEmpty(resourceId)){
pipResourceMachine.setPassword(req.getPassword()); throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"未找到资源");
AflInfo aflInfo = SftpUploadUtil.downloadFileSftpForInputStreamAndSetAflInfo(req.getMachineHost(), Integer.parseInt(req.getSshPort()), req.getUsername(), req.getPassword(),null, remoteFilePath + "PIP_" + req.getPipelineId() + "/ai_afl/default/fuzzer_stats"); }
//创建一个新文件夹将远程文件复制一份过去
ResourceFindResp resourceById = resourceManagerService.findResourceById(resourceId);
if (resourceById == null || resourceById.getResourceMachine() == null) {
throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"资源信息错误");
}
PipResourceMachine resourceMachine = resourceById.getResourceMachine();
AflInfo aflInfo = SftpUploadUtil.downloadFileSftpForInputStreamAndSetAflInfo(resourceMachine.getMachineHost(), Integer.parseInt(resourceMachine.getSshPort()), resourceMachine.getUsername(), resourceMachine.getPassword(),null, remoteFilePath + "PIP_" + req.getPipelineId() + "/ai_afl/default/fuzzer_stats");
//在本地创建一个新文件夹将远程文件复制一份过去
List<String> sourceFilePaths = new ArrayList<>(); List<String> sourceFilePaths = new ArrayList<>();
sourceFilePaths.add(remoteFilePath + "PIP_" + req.getPipelineId() + "/ai_afl/default/fuzzer_stats"); sourceFilePaths.add(remoteFilePath + "PIP_" + req.getPipelineId() + "/ai_afl/default/fuzzer_stats");
List<String> strings = SftpUploadUtil.copyRemoteFile(pipResourceMachine.getMachineHost(), Integer.parseInt(pipResourceMachine.getSshPort()), pipResourceMachine.getUsername(), pipResourceMachine.getPassword(), null, sourceFilePaths, remoteFilePath + "PIP_" + req.getPipelineId() + "/fuzzer/" + UUID.randomUUID() + "/"); List<String> strings = SftpUploadUtil.copyRemoteFilesToLocal(resourceMachine.getMachineHost(), Integer.parseInt(resourceMachine.getSshPort()), resourceMachine.getUsername(), resourceMachine.getPassword(), null, sourceFilePaths, "/home/ops/opsFile/fuzzer_result/" + UUID.randomUUID() + "/");
aflInfo.setFilePath(strings.get(0)); aflInfo.setFilePath(strings.get(0));
aflInfo.setPipelineId(req.getPipelineId()); aflInfo.setPipelineId(req.getPipelineId());
@ -54,11 +80,77 @@ public class AflInfoServiceImpl extends ServiceImpl<AflInfoDao, AflInfo> impleme
if (!StringUtils.isEmpty(req.getPipelineHistoryId())){ if (!StringUtils.isEmpty(req.getPipelineHistoryId())){
aflInfo.setPipelineHistoryId(req.getPipelineHistoryId()); aflInfo.setPipelineHistoryId(req.getPipelineHistoryId());
} }
aflInfo.setGroupIdentifier(UUID.randomUUID().toString());
baseMapper.insert(aflInfo); baseMapper.insert(aflInfo);
return aflInfo.getId(); return aflInfo.getGroupIdentifier();
} }
@Override
public void updateHistoryPipelineIdByAflInfo(AflManagerReq req) {
if (!StringUtils.isEmpty(req.getGroupIdentifier())){
throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"groupIdentifier不能为空");
}
QueryWrapper<AflInfo> wrapper = new QueryWrapper<>();
wrapper.eq("group_identifier", req.getGroupIdentifier());
List<AflInfo> aflInfos = baseMapper.selectList(wrapper);
if (!Collections.isEmpty(aflInfos)){
aflInfos.forEach(o->{
o.setPipelineHistoryId(req.getPipelineHistoryId());
});
}
baseMapper.updateBatch(aflInfos);
}
@Override
public AflInfoResp findAflInfo(AflManagerReq req) throws SftpUploadUtil.SftpUploadException {
if (StringUtils.isEmpty(req.getPipelineId()) || StringUtils.isEmpty(req.getTaskId())){
throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"pipelineId或者taskId不能为空");
}
BaseRunContext runContext = runContextManager.getContext(req.getPipelineId());
String resourceId = runContext.getGlobalVariables().get(PipelineVariableConstant.AFL_RESOURCE_MANAGER_ID_KEY) instanceof String ? ((String) runContext.getGlobalVariables().get(PipelineVariableConstant.AFL_RESOURCE_MANAGER_ID_KEY)) : null;
if (StringUtils.isEmpty(resourceId)){
throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"未找到资源");
}
ResourceFindResp resourceById = resourceManagerService.findResourceById(resourceId);
if (resourceById == null || resourceById.getResourceMachine() == null) {
throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"资源信息错误");
}
PipResourceMachine resourceMachine = resourceById.getResourceMachine();
AflInfo aflInfo = SftpUploadUtil.downloadFileSftpForInputStreamAndSetAflInfo(resourceMachine.getMachineHost(), Integer.parseInt(resourceMachine.getSshPort()), resourceMachine.getUsername(), resourceMachine.getPassword(),null, remoteFilePath + "PIP_" + req.getPipelineId() + "/ai_afl/default/fuzzer_stats");
return AflManagerConverter.INSTANCE.toAflInfoResp(aflInfo);
}
@Override
public List<AflInfoResp> findPipelineList(AflManagerReq req) {
QueryWrapper<AflInfo> wrapper = new QueryWrapper<>();
if (!ObjectUtils.isEmpty(req.getId())){
wrapper.eq("id",req.getId());
}
if (!ObjectUtils.isEmpty(req.getPipelineId())){
wrapper.eq("pipeline_id",req.getPipelineId());
}
if (!ObjectUtils.isEmpty(req.getPipelineHistoryId())){
wrapper.eq("pipeline_history_id",req.getPipelineHistoryId());
}
if (!ObjectUtils.isEmpty(req.getTaskId())){
wrapper.eq("task_id",req.getTaskId());
}
if (!ObjectUtils.isEmpty(req.getGroupIdentifier())){
wrapper.eq("group_identifier",req.getGroupIdentifier());
}
List<AflInfo> aflInfos = baseMapper.selectList(wrapper);
if (ObjectUtils.isEmpty(aflInfos)){
return new ArrayList<>(0);
}
return AflManagerConverter.INSTANCE.toAflInfoRespList(aflInfos);
}
/** /**

View File

@ -2,15 +2,21 @@ package cd.casic.ci.process.process.service.aflManager.impl;
import cd.casic.ci.process.dto.req.aflManager.AflManagerReq; import cd.casic.ci.process.dto.req.aflManager.AflManagerReq;
import cd.casic.ci.process.dto.resp.aflManager.SeedsCountResp; import cd.casic.ci.process.dto.resp.aflManager.SeedsCountResp;
import cd.casic.ci.process.dto.resp.resource.ResourceFindResp;
import cd.casic.ci.process.engine.constant.PipelineVariableConstant;
import cd.casic.ci.process.engine.manager.RunContextManager; import cd.casic.ci.process.engine.manager.RunContextManager;
import cd.casic.ci.process.engine.runContext.BaseRunContext; import cd.casic.ci.process.engine.runContext.BaseRunContext;
import cd.casic.ci.process.process.dao.aflManager.AflSeedInfoDao; import cd.casic.ci.process.process.dao.aflManager.AflSeedInfoDao;
import cd.casic.ci.process.process.dataObject.aflManager.AflSeedInfo; import cd.casic.ci.process.process.dataObject.aflManager.AflSeedInfo;
import cd.casic.ci.process.process.dataObject.resource.PipResourceMachine;
import cd.casic.ci.process.process.service.aflManager.AflSeedInfoService; import cd.casic.ci.process.process.service.aflManager.AflSeedInfoService;
import cd.casic.ci.process.process.service.resource.ResourceManagerService;
import cd.casic.ci.process.util.SftpUploadUtil; import cd.casic.ci.process.util.SftpUploadUtil;
import cd.casic.framework.commons.exception.ServiceException; import cd.casic.framework.commons.exception.ServiceException;
import cd.casic.framework.commons.exception.enums.GlobalErrorCodeConstants; import cd.casic.framework.commons.exception.enums.GlobalErrorCodeConstants;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import de.danielbechler.util.Collections;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -23,6 +29,7 @@ import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID;
/** /**
* @author HopeLi * @author HopeLi
@ -38,6 +45,9 @@ public class AflSeedInfoServiceImpl extends ServiceImpl<AflSeedInfoDao, AflSeedI
@Resource @Resource
private RunContextManager runContextManager; private RunContextManager runContextManager;
@Resource
private ResourceManagerService resourceManagerService;
private static final String remoteFilePath = "/home/casic/706/yunqi/"; private static final String remoteFilePath = "/home/casic/706/yunqi/";
private static final String seedFilePath = "/ai_afl/default/queue/"; private static final String seedFilePath = "/ai_afl/default/queue/";
@ -50,7 +60,21 @@ public class AflSeedInfoServiceImpl extends ServiceImpl<AflSeedInfoDao, AflSeedI
if (StringUtils.isEmpty(req.getPipelineId())){ if (StringUtils.isEmpty(req.getPipelineId())){
throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"pipelineId不能为空"); throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"pipelineId不能为空");
} }
List<String> resultList = SftpUploadUtil.findSeedCount(req.getMachineHost(), Integer.parseInt(req.getSshPort()), req.getUsername(), req.getPassword(), null, remoteFilePath + "PIP_" + req.getPipelineId() + "/ai_afl/default/queue/");
BaseRunContext pipelineRunContext = runContextManager.getContext(req.getPipelineId());
String resourceId = pipelineRunContext.getGlobalVariables().get(PipelineVariableConstant.AFL_RESOURCE_MANAGER_ID_KEY) instanceof String ? ((String) pipelineRunContext.getGlobalVariables().get(PipelineVariableConstant.AFL_RESOURCE_MANAGER_ID_KEY)) : null;
if (StringUtils.isEmpty(resourceId)){
throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"未找到资源");
}
ResourceFindResp resourceById = resourceManagerService.findResourceById(resourceId);
if (resourceById == null || resourceById.getResourceMachine() == null) {
throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"资源信息错误");
}
PipResourceMachine resourceMachine = resourceById.getResourceMachine();
List<String> resultList = SftpUploadUtil.findSeedCount(resourceMachine.getMachineHost(), Integer.parseInt(resourceMachine.getSshPort()), resourceMachine.getUsername(), resourceMachine.getPassword(), null, remoteFilePath + "PIP_" + req.getPipelineId() + "/ai_afl/default/queue/");
//解析resultList //解析resultList
@ -89,8 +113,8 @@ public class AflSeedInfoServiceImpl extends ServiceImpl<AflSeedInfoDao, AflSeedI
LocalDateTime createDateTime = zonedDateTime.toLocalDateTime(); LocalDateTime createDateTime = zonedDateTime.toLocalDateTime();
// 获取开始时间 // 获取开始时间
BaseRunContext runContext = runContextManager.getContext(req.getTaskId()); BaseRunContext taskRunContext = runContextManager.getContext(req.getTaskId());
LocalDateTime startTime = runContext.getStartTime(); LocalDateTime startTime = taskRunContext.getStartTime();
// 计算时间差分钟 // 计算时间差分钟
Duration duration = Duration.between(startTime, createDateTime); Duration duration = Duration.between(startTime, createDateTime);
@ -133,15 +157,33 @@ public class AflSeedInfoServiceImpl extends ServiceImpl<AflSeedInfoDao, AflSeedI
@Override @Override
public void saveAflSeedInfo(AflManagerReq req) { public void saveAflSeedInfo(AflManagerReq req) {
if (StringUtils.isEmpty(req.getPipelineId()) || StringUtils.isEmpty(req.getTaskId())){
throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"pipelineId或者taskId不能为空");
}
String uuid = UUID.randomUUID().toString();
BaseRunContext runContext = runContextManager.getContext(req.getPipelineId());
String resourceId = runContext.getGlobalVariables().get(PipelineVariableConstant.AFL_RESOURCE_MANAGER_ID_KEY) instanceof String ? ((String) runContext.getGlobalVariables().get(PipelineVariableConstant.AFL_RESOURCE_MANAGER_ID_KEY)) : null;
if (StringUtils.isEmpty(resourceId)){
throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"未找到资源");
}
ResourceFindResp resourceById = resourceManagerService.findResourceById(resourceId);
if (resourceById == null || resourceById.getResourceMachine() == null) {
throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"资源信息错误");
}
PipResourceMachine resourceMachine = resourceById.getResourceMachine();
try { try {
// 步骤1列出源目录下的所有文件 // 步骤1列出源目录下的所有文件
List<String> files = SftpUploadUtil.listFilesInRemoteDirectory( List<String> files = SftpUploadUtil.listFilesInRemoteDirectory(
req.getMachineHost(), Integer.parseInt(req.getSshPort()), req.getUsername(), req.getPassword(), null, remoteFilePath + "PIP_" + req.getPipelineId() + seedFilePath); resourceMachine.getMachineHost(), Integer.parseInt(resourceMachine.getSshPort()), resourceMachine.getUsername(), resourceMachine.getPassword(), null, remoteFilePath + "PIP_" + req.getPipelineId() + seedFilePath);
if (!CollectionUtils.isEmpty(files)) { if (!CollectionUtils.isEmpty(files)) {
// 步骤2批量复制文件到目标目录 // 步骤2批量复制文件到目标目录
List<String> copiedFiles = SftpUploadUtil.copyRemoteFile( List<String> copiedFiles = SftpUploadUtil.copyRemoteFilesToLocal(
req.getMachineHost(), Integer.parseInt(req.getSshPort()), req.getUsername(), req.getPassword(), null, files, remoteFilePath + "PIP_" + req.getPipelineId() + "/seed_result/"); resourceMachine.getMachineHost(), Integer.parseInt(resourceMachine.getSshPort()), resourceMachine.getUsername(), resourceMachine.getPassword(), null, files, "/home/ops/opsFile/seed_result/" + UUID.randomUUID() + "/");
System.out.println("共复制 " + copiedFiles.size() + " 个文件"); System.out.println("共复制 " + copiedFiles.size() + " 个文件");
if (!CollectionUtils.isEmpty(copiedFiles)){ if (!CollectionUtils.isEmpty(copiedFiles)){
@ -150,9 +192,12 @@ public class AflSeedInfoServiceImpl extends ServiceImpl<AflSeedInfoDao, AflSeedI
copiedFiles.forEach(o->{ copiedFiles.forEach(o->{
AflSeedInfo aflSeedInfo = new AflSeedInfo(); AflSeedInfo aflSeedInfo = new AflSeedInfo();
// 提取文件名部分queue/之后的内容 // 提取文件名部分seed_result/之后的内容
String fileNamePart = o.substring(o.indexOf("seed_result/") + 12); String fileNamePart = o.substring(o.indexOf("seed_result/") + 12);
//截取最后一个斜杠后的内容即文件信息部分
fileNamePart = fileNamePart.substring(fileNamePart.lastIndexOf("/") + 1);
// 使用正则匹配 id: 开头的内容 // 使用正则匹配 id: 开头的内容
java.util.regex.Pattern patternId = java.util.regex.Pattern.compile("id:([^,]+)"); java.util.regex.Pattern patternId = java.util.regex.Pattern.compile("id:([^,]+)");
java.util.regex.Matcher matcherId = patternId.matcher(fileNamePart); java.util.regex.Matcher matcherId = patternId.matcher(fileNamePart);
@ -179,6 +224,7 @@ public class AflSeedInfoServiceImpl extends ServiceImpl<AflSeedInfoDao, AflSeedI
aflSeedInfo.setPipelineHistoryId(req.getPipelineHistoryId()); aflSeedInfo.setPipelineHistoryId(req.getPipelineHistoryId());
} }
aflSeedInfo.setPipelineId(req.getPipelineId()); aflSeedInfo.setPipelineId(req.getPipelineId());
aflSeedInfo.setGroupIdentifier(uuid);
aflSeedInfos.add(aflSeedInfo); aflSeedInfos.add(aflSeedInfo);
}); });
@ -190,4 +236,20 @@ public class AflSeedInfoServiceImpl extends ServiceImpl<AflSeedInfoDao, AflSeedI
e.printStackTrace(); e.printStackTrace();
} }
} }
@Override
public void updateHistoryPipelineIdByAflSeedInfo(AflManagerReq req) {
if (!StringUtils.isEmpty(req.getGroupIdentifier())){
throw new ServiceException(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"groupIdentifier不能为空");
}
QueryWrapper<AflSeedInfo> wrapper = new QueryWrapper<>();
wrapper.eq("group_identifier", req.getGroupIdentifier());
List<AflSeedInfo> aflSeedInfos = baseMapper.selectList(wrapper);
if (!Collections.isEmpty(aflSeedInfos)){
aflSeedInfos.forEach(o->{
o.setPipelineHistoryId(req.getPipelineHistoryId());
});
}
baseMapper.updateBatch(aflSeedInfos);
}
} }

View File

@ -485,7 +485,6 @@ public class SftpUploadUtil {
currentDir.append("/").append(dir); currentDir.append("/").append(dir);
try { try {
channelSftp.cd(currentDir.toString()); channelSftp.cd(currentDir.toString());
// System.out.println("目录已存在: " + currentDir.toString());
} catch (SftpException e) { } catch (SftpException e) {
if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) { if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {
// 目录不存在创建它 // 目录不存在创建它
@ -1011,75 +1010,6 @@ public class SftpUploadUtil {
} }
private static AflInfo setAflinfo(Map<String, String> statsMap) {
//映射到 AflInfo 实体
AflInfo aflInfo = new AflInfo();
aflInfo.setStartTime(statsMap.get("start_time"));
aflInfo.setLastUpdate(statsMap.get("last_update"));
aflInfo.setRunTime(statsMap.get("run_time"));
aflInfo.setFuzzerPid(statsMap.get("fuzzer_pid"));
aflInfo.setCyclesDone(statsMap.get("cycles_done"));
aflInfo.setCyclesWoFinds(statsMap.get("cycles_wo_finds"));
aflInfo.setTimeWoFinds(statsMap.get("time_wo_finds"));
aflInfo.setFuzzTime(statsMap.get("fuzz_time"));
aflInfo.setCalibrationTime(statsMap.get("calibration_time"));
aflInfo.setCmplogTime(statsMap.get("cmplog_time"));
aflInfo.setSyncTime(statsMap.get("sync_time"));
aflInfo.setTrimTime(statsMap.get("trim_time"));
aflInfo.setExecsDone(statsMap.get("execs_done"));
aflInfo.setExecsPerSec(statsMap.get("execs_per_sec"));
aflInfo.setExecsPsLastMin(statsMap.get("execs_ps_last_min"));
aflInfo.setCorpusCount(statsMap.get("corpus_count"));
aflInfo.setCorpusFavored(statsMap.get("corpus_favored"));
aflInfo.setCorpusFound(statsMap.get("corpus_found"));
aflInfo.setCorpusImported(statsMap.get("corpus_imported"));
aflInfo.setCorpusVariable(statsMap.get("corpus_variable"));
aflInfo.setMaxDepth(statsMap.get("max_depth"));
aflInfo.setCurItem(statsMap.get("cur_item"));
aflInfo.setPendingFavs(statsMap.get("pending_favs"));
aflInfo.setPendingTotal(statsMap.get("pending_total"));
aflInfo.setStability(statsMap.get("stability"));
aflInfo.setBitmapCvg(statsMap.get("bitmap_cvg"));
aflInfo.setSavedCrashes(statsMap.get("saved_crashes"));
aflInfo.setSavedHangs(statsMap.get("saved_hangs"));
aflInfo.setTotalTmout(statsMap.get("total_tmout"));
aflInfo.setLastFind(statsMap.get("last_find"));
aflInfo.setLastCrash(statsMap.get("last_crash"));
aflInfo.setLastHang(statsMap.get("last_hang"));
aflInfo.setExecsSinceCrash(statsMap.get("execs_since_crash"));
aflInfo.setExecTimeout(statsMap.get("exec_timeout"));
aflInfo.setSlowestExecMs(statsMap.get("slowest_exec_ms"));
aflInfo.setPeakRssMb(statsMap.get("peak_rss_mb"));
aflInfo.setCpuAffinity(statsMap.get("cpu_affinity"));
aflInfo.setEdgesFound(statsMap.get("edges_found"));
aflInfo.setTotalEdges(statsMap.get("total_edges"));
aflInfo.setVarByteCount(statsMap.get("var_byte_count"));
aflInfo.setHavocExpansion(statsMap.get("havoc_expansion"));
aflInfo.setAutoDictEntries(statsMap.get("auto_dict_entries"));
aflInfo.setTestcacheSize(statsMap.get("testcache_size"));
aflInfo.setTestcacheCount(statsMap.get("testcache_count"));
aflInfo.setTestcacheEvict(statsMap.get("testcache_evict"));
aflInfo.setAflBanner(statsMap.get("afl_banner"));
aflInfo.setAflVersion(statsMap.get("afl_version"));
aflInfo.setTargetMode(statsMap.get("target_mode"));
aflInfo.setCommandLine(statsMap.get("command_line"));
return aflInfo;
}
private static boolean thisDirectory(ChannelSftp channelSftp, String fullPath) {
try {
SftpATTRS attrs = channelSftp.lstat(fullPath);
return attrs.isDir();
} catch (SftpException e) {
return false;
}
}
public static List<String> findSeedCount(String remoteHost, public static List<String> findSeedCount(String remoteHost,
Integer remotePort, Integer remotePort,
String username, String username,
@ -1193,6 +1123,196 @@ public class SftpUploadUtil {
} }
public static List<String> copyRemoteFilesToLocal(String remoteHost,
Integer remotePort,
String username,
String password,
String sshKeyPath,
List<String> remoteFilePaths,
String localDir) throws SftpUploadException {
List<String> copiedLocalPaths = new ArrayList<>();
Session session = null;
Channel channel = null;
ChannelSftp channelSftp = null;
InputStream inputStream = null;
try {
JSch jsch = new JSch();
// 1. 添加身份认证信息 (密码或密钥)
if (sshKeyPath != null && !sshKeyPath.trim().isEmpty()) {
// 使用 SSH Key 认证
File sshKeyFile = new File(sshKeyPath);
if (!sshKeyFile.exists() || !sshKeyFile.isFile()) {
throw new SftpUploadException("SSH Key 文件不存在或不是一个有效文件: " + sshKeyPath);
}
jsch.addIdentity(sshKeyPath);
System.out.println("使用 SSH Key 认证: " + sshKeyPath);
} else if (password == null || password.trim().isEmpty()) {
// 如果没有提供密码或密钥路径则认证信息不全
throw new SftpUploadException("必须提供密码或 SSH Key 路径进行 SFTP 认证.");
}
// 如果提供了密码将在 getSession 后设置因为 getSession 需要用户名主机和端口先建立连接意图
// 2. 获取 Session
int port = (remotePort != null && remotePort > 0) ? remotePort : DEFAULT_SFTP_PORT;
session = jsch.getSession(username, remoteHost, port);
System.out.println("尝试连接 SFTP 服务器: " + username + "@" + remoteHost + ":" + port);
// 如果使用密码认证且提供了密码
if (password != null && !password.trim().isEmpty() && (sshKeyPath == null || sshKeyPath.trim().isEmpty())) {
session.setPassword(password);
System.out.println("使用密码认证.");
}
// 设置连接不进行主机密钥检查 (生产环境不推荐应该配置 known_hosts)
// 在实际应用中应该引导用户信任主机密钥或提前将主机密钥加入 known_hosts
java.util.Properties config = new java.util.Properties();
config.put("StrictHostKeyChecking", "no"); // !!! 生产环境请谨慎使用或配置正确的主机密钥检查 !!!
session.setConfig(config);
// 3. 连接 Session
session.connect();
System.out.println("SFTP Session 连接成功.");
// 4. 打开 SFTP Channel
channel = session.openChannel("sftp");
channel.connect();
System.out.println("SFTP Channel 打开成功.");
channelSftp = (ChannelSftp) channel;
// 创建本地目录
File localDirectory = new File(localDir);
if (!localDirectory.exists()) {
localDirectory.mkdirs();
}
// 遍历远程文件路径并下载
for (String remoteFile : remoteFilePaths) {
String fileName = new File(remoteFile).getName();
String localFilePath = localDir + File.separator + fileName;
try (InputStream in = channelSftp.get(remoteFile);
FileOutputStream out = new FileOutputStream(localFilePath)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(buffer)) > 0) {
out.write(buffer, 0, bytesRead);
}
copiedLocalPaths.add(localFilePath); // 添加本地路径
} catch (Exception e) {
throw new RuntimeException("文件复制失败: " + remoteFile, e);
}
}
return copiedLocalPaths;
} catch (JSchException e) {
throw new SftpUploadException("SFTP 连接或认证失败: " + e.getMessage(), e);
} catch (SftpUploadException e) {
// 重新抛出自定义异常
throw e;
} catch (Exception e) {
// 捕获其他未知异常
throw new SftpUploadException("SFTP 上传过程中发生未知异常: " + e.getMessage(), e);
} finally {
// 9. 关闭资源 (确保在任何情况下都关闭)
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
System.err.println("关闭本地文件流失败: " + e.getMessage());
e.printStackTrace(); // 打印堆栈以便调试
}
}
if (channelSftp != null) {
channelSftp.disconnect();
System.out.println("SFTP Channel 已断开.");
}
if (channel != null) {
channel.disconnect();
System.out.println("SFTP Channel 资源已释放.");
}
if (session != null) {
session.disconnect();
System.out.println("SFTP Session 已断开.");
}
}
}
private static AflInfo setAflinfo(Map<String, String> statsMap) {
//映射到 AflInfo 实体
AflInfo aflInfo = new AflInfo();
aflInfo.setStartTime(statsMap.get("start_time"));
aflInfo.setLastUpdate(statsMap.get("last_update"));
aflInfo.setRunTime(statsMap.get("run_time"));
aflInfo.setFuzzerPid(statsMap.get("fuzzer_pid"));
aflInfo.setCyclesDone(statsMap.get("cycles_done"));
aflInfo.setCyclesWoFinds(statsMap.get("cycles_wo_finds"));
aflInfo.setTimeWoFinds(statsMap.get("time_wo_finds"));
aflInfo.setFuzzTime(statsMap.get("fuzz_time"));
aflInfo.setCalibrationTime(statsMap.get("calibration_time"));
aflInfo.setCmplogTime(statsMap.get("cmplog_time"));
aflInfo.setSyncTime(statsMap.get("sync_time"));
aflInfo.setTrimTime(statsMap.get("trim_time"));
aflInfo.setExecsDone(statsMap.get("execs_done"));
aflInfo.setExecsPerSec(statsMap.get("execs_per_sec"));
aflInfo.setExecsPsLastMin(statsMap.get("execs_ps_last_min"));
aflInfo.setCorpusCount(statsMap.get("corpus_count"));
aflInfo.setCorpusFavored(statsMap.get("corpus_favored"));
aflInfo.setCorpusFound(statsMap.get("corpus_found"));
aflInfo.setCorpusImported(statsMap.get("corpus_imported"));
aflInfo.setCorpusVariable(statsMap.get("corpus_variable"));
aflInfo.setMaxDepth(statsMap.get("max_depth"));
aflInfo.setCurItem(statsMap.get("cur_item"));
aflInfo.setPendingFavs(statsMap.get("pending_favs"));
aflInfo.setPendingTotal(statsMap.get("pending_total"));
aflInfo.setStability(statsMap.get("stability"));
aflInfo.setBitmapCvg(statsMap.get("bitmap_cvg"));
aflInfo.setSavedCrashes(statsMap.get("saved_crashes"));
aflInfo.setSavedHangs(statsMap.get("saved_hangs"));
aflInfo.setTotalTmout(statsMap.get("total_tmout"));
aflInfo.setLastFind(statsMap.get("last_find"));
aflInfo.setLastCrash(statsMap.get("last_crash"));
aflInfo.setLastHang(statsMap.get("last_hang"));
aflInfo.setExecsSinceCrash(statsMap.get("execs_since_crash"));
aflInfo.setExecTimeout(statsMap.get("exec_timeout"));
aflInfo.setSlowestExecMs(statsMap.get("slowest_exec_ms"));
aflInfo.setPeakRssMb(statsMap.get("peak_rss_mb"));
aflInfo.setCpuAffinity(statsMap.get("cpu_affinity"));
aflInfo.setEdgesFound(statsMap.get("edges_found"));
aflInfo.setTotalEdges(statsMap.get("total_edges"));
aflInfo.setVarByteCount(statsMap.get("var_byte_count"));
aflInfo.setHavocExpansion(statsMap.get("havoc_expansion"));
aflInfo.setAutoDictEntries(statsMap.get("auto_dict_entries"));
aflInfo.setTestcacheSize(statsMap.get("testcache_size"));
aflInfo.setTestcacheCount(statsMap.get("testcache_count"));
aflInfo.setTestcacheEvict(statsMap.get("testcache_evict"));
aflInfo.setAflBanner(statsMap.get("afl_banner"));
aflInfo.setAflVersion(statsMap.get("afl_version"));
aflInfo.setTargetMode(statsMap.get("target_mode"));
aflInfo.setCommandLine(statsMap.get("command_line"));
return aflInfo;
}
private static boolean thisDirectory(ChannelSftp channelSftp, String fullPath) {
try {
SftpATTRS attrs = channelSftp.lstat(fullPath);
return attrs.isDir();
} catch (SftpException e) {
return false;
}
}
// 自定义异常类用于封装上传过程中的错误 // 自定义异常类用于封装上传过程中的错误
public static class SftpUploadException extends Exception { public static class SftpUploadException extends Exception {