Merge remote-tracking branch 'origin/master'

This commit is contained in:
HopeLi 2025-07-23 17:03:28 +08:00
commit ddec4a6671
32 changed files with 591 additions and 248 deletions

View File

@ -2,10 +2,18 @@ package cd.casic.ci.api;
import cd.casic.ci.process.dto.req.resource.ResourceCreateReq;
import cd.casic.ci.process.dto.req.resource.ResourceListReq;
import cd.casic.ci.process.dto.req.resource.ResourcePageReq;
import cd.casic.ci.process.dto.req.resource.ResourceUpdateReq;
import cd.casic.ci.process.dto.resp.resource.ResourceDetailResp;
import cd.casic.ci.process.dto.resp.resource.ResourceListResp;
import cd.casic.ci.process.process.service.resource.ResourceManagerService;
import cd.casic.framework.commons.pojo.CommonResult;
import cd.casic.framework.commons.pojo.PageResult;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@ -22,7 +30,31 @@ public class ResourceManagerController {
@Resource
private ResourceManagerService resourceManagerService;
@PostMapping("/createResource")
public CommonResult<String> createResource(@RequestBody ResourceCreateReq req){
return CommonResult.success(resourceManagerService.createResource(req));
}
@PostMapping("/updateResource")
public CommonResult<String> updateResource(@RequestBody ResourceUpdateReq req){
return CommonResult.success(resourceManagerService.updateResource(req));
}
@GetMapping("/findResourceDetailById/{resourceId}")
public CommonResult<ResourceDetailResp> findResourceDetailById(@PathVariable String resourceId){
return CommonResult.success(resourceManagerService.findResourceDetailById(resourceId));
}
@PostMapping("/list")
public CommonResult<List<ResourceListResp>> list(@RequestBody ResourceListReq req){
return CommonResult.success(resourceManagerService.list(req));
}
@PostMapping("/page")
public CommonResult<PageResult<ResourceListResp>> page(@RequestBody ResourcePageReq req){
return CommonResult.success(resourceManagerService.page(req));
}
@DeleteMapping("/deleteResource/{resourceId}")
public CommonResult<Void> deleteResource(@PathVariable String resourceId){
resourceManagerService.deleteResource(resourceId);
return CommonResult.success();
}
}

View File

@ -1,6 +1,5 @@
package cd.casic.ci.api;
import cd.casic.ci.process.util.CryptogramUtil;
import cd.casic.ci.process.util.SftpUploadUtil;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

View File

@ -0,0 +1,11 @@
package cd.casic.ci.process.constant;
/**
* AI测试用例生成url常量类
* */
public class TestCaseAIGeneratorConstant {
public static final String targetUpload ="/upload-target";
public static final String taskCreate ="/create-task";
public static final String getTaskStatus ="/query-task/";
public static final String getTaskLog ="/task-log/";
public static final String downloadTestCase ="/download-case/";
}

View File

@ -0,0 +1,8 @@
package cd.casic.ci.process.dto.req.resource;
import lombok.Data;
@Data
public class ResourceListReq {
}

View File

@ -0,0 +1,10 @@
package cd.casic.ci.process.dto.req.resource;
import cd.casic.framework.commons.pojo.PageParam;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class ResourcePageReq extends PageParam {
}

View File

@ -22,4 +22,6 @@ public class ResourceUpdateReq {
* docker连接端口选填
* */
private Integer dockerPort;
private String cloudId;
}

View File

@ -0,0 +1,13 @@
package cd.casic.ci.process.dto.req.testCase;
import lombok.Data;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.util.zip.ZipOutputStream;
@Data
public class TestCaseAITargetUploadReq {
private String binaryPath;
private MultipartFile file;
}

View File

@ -0,0 +1,25 @@
package cd.casic.ci.process.dto.req.testCase;
import lombok.Data;
/**
* {
* "model_id": "gpt-4", // 可选模型ID默认值为deepseek/deepseekchat
* "api_key": "your-api-key", // 可选API密钥
* "api_base": "https://api.openai.com/v1", // 可选API基础URL默认值为
* https://api.deepseek.com
* "binary_id": "abc123def456", // 条件可选二进制文件ID, 如果未提供则需要提供
* case_format参数
* "case_format": "png", // 条件可选测试用例文件格式, 如果未提供则需要提
* 供binary_id参数
* "custom_prompt": "", // 可选测试用例生成任务的自定义提示词, "构造
* 尽可能小的png文件"
* "count": 10 // 可选生成用例数量默认10
* }
* */
@Data
public class TestCaseAITaskCreateReq {
private String binaryId;
private String caseFormat;
private String customPrompt;
private Integer count;
}

View File

@ -0,0 +1,38 @@
package cd.casic.ci.process.dto.resp.resource;
import jakarta.annotation.Resource;
import lombok.Data;
@Data
public class ResourceListResp {
/**
* docker镜像服务器信息id
*/
private String dockerId;
/**
* k8s服务器信息id
*/
private String k8sId;
/**
* 机器服务器信息id
*/
private Long machineId;
/**
* 弹性云服务器信息id
*/
private String cloudId;
/**
* 资源名称
*/
private String resourceName;
/**
* 资源类型ResourceConstant.RES_TYPE_*
* */
private String resourceType;
private String id;
}

View File

@ -11,11 +11,11 @@ import cd.casic.ci.process.process.dataObject.pipeline.PipPipeline;
import cd.casic.ci.process.process.dataObject.target.TargetVersion;
import cd.casic.ci.process.process.dataObject.task.PipTask;
import cd.casic.ci.process.process.service.target.TargetVersionService;
import cd.casic.ci.process.util.CryptogramUtil;
import cd.casic.ci.process.util.SftpUploadUtil;
import cd.casic.framework.commons.exception.ServiceException;
import cd.casic.framework.commons.exception.enums.GlobalErrorCodeConstants;
import cd.casic.module.machine.dal.dataobject.MachineInfoDO;
import cd.casic.module.machine.utils.CryptogramUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
@ -92,7 +92,7 @@ public class CustomCompilerWorker extends SshWorker {
//则默认路径写死
remoteDir = "/home/casic/706/ai_test_527";
}
SftpUploadUtil.uploadFileViaSftp(resourceMachine.getHostIp(), resourceMachine.getSshPort(),resourceMachine.getUsername(), resourceMachine.getPassword(),null,file.getAbsolutePath(),remoteDir,file.getName());
SftpUploadUtil.uploadFileViaSftp(resourceMachine.getHostIp(), resourceMachine.getSshPort(),resourceMachine.getUsername(), CryptogramUtil.doDecrypt(resourceMachine.getPassword()),null,file.getAbsolutePath(),remoteDir,file.getName());
//TODO 得改一下
statusCode = shell(resourceMachine, null,context,

View File

@ -13,6 +13,7 @@ import cd.casic.ci.process.process.service.target.TargetVersionService;
import cd.casic.ci.process.util.SftpUploadUtil;
import cd.casic.module.execute.docker.dataobject.dto.DockerEndpointDo;
import cd.casic.module.machine.dal.dataobject.MachineInfoDO;
import cd.casic.module.machine.utils.CryptogramUtil;
import com.alibaba.fastjson.JSON;
import com.jcraft.jsch.*;
import jakarta.annotation.Resource;
@ -70,7 +71,7 @@ public class AFLSlotCompileWorker extends DockerWorker {
append(context,"AFL编译上传文件路径:"+realPath);
SftpUploadUtil.uploadFileViaSftp(
machineInfo.getHostIp()
,machineInfo.getSshPort(),machineInfo.getUsername(), machineInfo.getPassword(),"",filePath,realPath,file.getName());
,machineInfo.getSshPort(),machineInfo.getUsername(), CryptogramUtil.doDecrypt(machineInfo.getPassword()),"",filePath,realPath,file.getName());
} catch (SftpUploadUtil.SftpUploadException e) {
append(context,"上传文件失败,请确认资源信息是否有误:"+JSON.toJSONString(machineInfo));
log.error("上传文件报错",e);
@ -128,10 +129,10 @@ public class AFLSlotCompileWorker extends DockerWorker {
"cd "+prefix+"\n";
return cmd;
}
if ("gz".equals(suffix)) {
if (fileName.contains(".tar")||fileName.contains(".tar.gz")) {
String cmd ="tar -zxvf "+fileName+"\n" +
"chmod -R o+rwx "+prefix+"/\n"+
"cd "+prefix+"\n";
"cd "+fileName.replace(".tar.gz","").replace(".tar","")+"\n";
return cmd;
}
return "";
@ -145,7 +146,7 @@ public class AFLSlotCompileWorker extends DockerWorker {
try {
JSch jsch = new JSch();
Session session = jsch.getSession(user, host, 22);
session.setPassword(machineInfo.getPassword());
session.setPassword(CryptogramUtil.doDecrypt(machineInfo.getPassword()));
session.setConfig("StrictHostKeyChecking", "no");
session.connect();
ChannelSftp sftpChannel = (ChannelSftp) session.openChannel("sftp");

View File

@ -115,9 +115,12 @@ public class AFLWorker extends DockerWorker {
}
}
private String cdSourceName(String fileName){
int dotIndex = fileName.lastIndexOf(".");
if (dotIndex!=-1) {
return "cd "+fileName.substring(0, dotIndex)+"\n";
if (fileName.contains(".zip")||fileName.contains(".tar")||fileName.contains(".tar.gz")) {
String cdPath = fileName
.replace(".zip","")
.replace(".tar.gz","")
.replace(".tar","");
return "cd "+cdPath+"\n";
}
return "";
}

View File

@ -2,7 +2,7 @@ package cd.casic.ci.process.engine.worker.afl;
import cd.casic.ci.process.common.WorkAtom;
import cd.casic.ci.process.dto.req.resource.ResourceQueryReq;
import cd.casic.ci.process.dto.req.testCase.TestCaseAITaskCreateReq;
import cd.casic.ci.process.dto.resp.resource.ResourceDetailResp;
import cd.casic.ci.process.engine.runContext.TaskRunContext;
import cd.casic.ci.process.engine.worker.base.DockerWorker;
@ -11,20 +11,24 @@ import cd.casic.ci.process.process.dataObject.target.TargetVersion;
import cd.casic.ci.process.process.dataObject.task.PipTask;
import cd.casic.ci.process.process.dataObject.testCase.TestCaseInfo;
import cd.casic.ci.process.process.service.target.TargetVersionService;
import cd.casic.ci.process.process.service.testCase.TestCaseAIGeneratorService;
import cd.casic.ci.process.process.service.testCase.TestCaseInfoService;
import cd.casic.ci.process.util.CryptogramUtil;
import cd.casic.ci.process.util.SftpUploadUtil;
import cd.casic.module.execute.docker.dataobject.dto.DockerEndpointDo;
import cd.casic.module.machine.dal.dataobject.MachineInfoDO;
import cd.casic.module.machine.utils.CryptogramUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jcraft.jsch.*;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.io.*;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import static cd.casic.ci.process.engine.constant.PipelineVariableConstant.*;
import static cd.casic.ci.process.engine.constant.TestCaseGenerationConstant.*;
@ -36,6 +40,8 @@ public class TestCaseGenerationWorker extends DockerWorker {
private TestCaseInfoService testCaseInfoService;
@Resource
private TargetVersionService targetVersionService;
@Resource
private TestCaseAIGeneratorService aiGeneratorService;
@Override
public void execute(TaskRunContext context) {
int statusCode = -1;
@ -45,7 +51,6 @@ public class TestCaseGenerationWorker extends DockerWorker {
String seedPath= workDir+File.separator+ AFL_DOCKER_SEED;
Map<String, Object> taskProperties = taskDef.getTaskProperties();
Object caseType = taskProperties.get(CASE_TYPE_KEY);
String binaryName = taskProperties.get(BINARY_NAME) instanceof String ? ((String) taskProperties.get("binaryName")) : null;
String managerId = getVariableNearby(context, AFL_RESOURCE_MANAGER_ID_KEY) instanceof String ? ((String) getVariableNearby(context, AFL_RESOURCE_MANAGER_ID_KEY)) : null;
Object itemListObject = taskProperties.get(ITEM_LIST);
List<String> itemList = JSON.parseArray(JSON.toJSONString(itemListObject),String.class);
@ -55,23 +60,21 @@ public class TestCaseGenerationWorker extends DockerWorker {
if (Objects.isNull(machineInfo)||Objects.isNull(dockerInfo)) {
append(context,"该资源不支持docker或者ssh");
}
PipPipeline pipeline = (PipPipeline) getContextManager().getContext(taskDef.getPipelineId()).getContextDef();
TargetVersion targetVersion = targetVersionService.getById(pipeline.getTargetVersionId());
String fileName = targetVersion.getFileName();
String imageName = getVariableNearby(context,IMAGE_NAME) instanceof String ? ((String) getVariableNearby(context,IMAGE_NAME)) : null;
//如果machineId为0则说明该节点没有配置机器则使用开始节点的机器
if (CASE_TYPE_AI.equals(caseType)) {
// 容器内部test 目录, 获取编译后的文件
String runScript = "docker run -v "+ AFL_VOLUME_WORK_DIR_PREFIX +":"+ AFL_DOCKER_BASE_DIR+" -it "+imageName+" bash\n" // 目前测试用例ai生成只有这个路径能跑
+ "cd "+ AFL_DOCKER_BASE_DIR+"\n" +
"mkdir -p "+seedPath +"\n"+
"cd "+seedPath +"\n"+
"PYTHONPATH="+AFL_DOCKER_BASE_DIR+File.separator+"CaseGenerator/src python3 "+AFL_DOCKER_BASE_DIR+File.separator+"CaseGenerator/src/CaseGenerator/main.py --work-dir "+workDir+" --binary "+workDir+File.separator+getSourceName(fileName)+File.separator+binaryName+" --output-dir "+seedPath+" --count 100";
//将节点的配置信息反编译成对象
log.info("测试用例生成-AI生成实际执行命令:{}" , runScript);
append(context,"测试用例生成-AI生成实际执行命令:"+runScript);
//获取机器
dockerRun(runScript,dockerInfo,context);
// // 容器内部test 目录, 获取编译后的文件
// String runScript = "docker run -v "+ AFL_VOLUME_WORK_DIR_PREFIX +":"+ AFL_DOCKER_BASE_DIR+" -it "+imageName+" bash\n" // 目前测试用例ai生成只有这个路径能跑
// + "cd "+ AFL_DOCKER_BASE_DIR+"\n" +
// "mkdir -p "+seedPath +"\n"+
// "cd "+seedPath +"\n"+
// "PYTHONPATH="+AFL_DOCKER_BASE_DIR+File.separator+"CaseGenerator/src python3 "+AFL_DOCKER_BASE_DIR+File.separator+"CaseGenerator/src/CaseGenerator/main.py --work-dir "+workDir+" --binary "+workDir+File.separator+getSourceName(fileName)+File.separator+binaryName+" --output-dir "+seedPath+" --count 100";
// //将节点的配置信息反编译成对象
// log.info("测试用例生成-AI生成实际执行命令:{}" , runScript);
// append(context,"测试用例生成-AI生成实际执行命令:"+runScript);
// //获取机器
// dockerRun(runScript,dockerInfo,context);
handleAIGenerator(context);
} else if (CASE_TYPE_FILE.equals(caseType)){
// 文件上传
Object filePathObj = taskProperties.get(SEED_SOURCE);
@ -90,7 +93,7 @@ public class TestCaseGenerationWorker extends DockerWorker {
try {
SftpUploadUtil.uploadFileViaSftp(
machineInfo.getHostIp()
,Integer.valueOf(machineInfo.getSshPort()),machineInfo.getUsername(),machineInfo.getPassword(),"",filePath,seedTarget,file.getName());
,machineInfo.getSshPort(),machineInfo.getUsername(), CryptogramUtil.doDecrypt(machineInfo.getPassword()),"",filePath,seedTarget,file.getName());
} catch (SftpUploadUtil.SftpUploadException e) {
append(context,"seed文件上传失败");
log.error("seed文件上传失败",e);
@ -111,7 +114,7 @@ public class TestCaseGenerationWorker extends DockerWorker {
machineInfo.getHostIp()
,machineInfo.getSshPort()
,machineInfo.getUsername()
,machineInfo.getPassword()
,CryptogramUtil.doDecrypt(machineInfo.getPassword())
,"", testFilePath,seedTarget,testCaseInfo.getFileName());
} catch (SftpUploadUtil.SftpUploadException e) {
toBadEnding();
@ -121,10 +124,122 @@ public class TestCaseGenerationWorker extends DockerWorker {
globalVariables.put(AFL_DOCKER_SEED_PATH_KEY,seedPath);
}
}
public String getSourceName(String fileName){
int dotIndex = fileName.lastIndexOf(".");
if (dotIndex!=-1) {
return fileName.substring(0, dotIndex);
public void handleAIGenerator(TaskRunContext context){
PipTask taskDef = context.getContextDef() instanceof PipTask ? ((PipTask) context.getContextDef()) : null;
Map<String, Object> taskProperties = taskDef.getTaskProperties();
String binaryName = taskProperties.get(BINARY_NAME) instanceof String ? ((String) taskProperties.get("binaryName")) : null;
PipPipeline pipeline = (PipPipeline) getContextManager().getContext(taskDef.getPipelineId()).getContextDef();
TargetVersion targetVersion = targetVersionService.getById(pipeline.getTargetVersionId());
String managerId = getVariableNearby(context, AFL_RESOURCE_MANAGER_ID_KEY) instanceof String ? ((String) getVariableNearby(context, AFL_RESOURCE_MANAGER_ID_KEY)) : null;
ResourceDetailResp resourceById = resourceManagerService.findResourceDetailById(managerId);
MachineInfoDO machineInfo = resourceById.getMachineInfo();
DockerEndpointDo dockerInfo = resourceById.getDockerInfo();
String fileName = targetVersion.getFileName();
if (Objects.isNull(machineInfo)||Objects.isNull(dockerInfo)) {
append(context,"该资源不支持docker或者ssh");
}
// TODO 需要新增的项
String prompt = "你是一个模糊测试专家,当前程序输入为文本例如 aa aaa 这种";
Integer count = 10;
// 获取编译后的文文件的inputStream
JSch jsch = new JSch();
Session session = null;
ChannelExec exec = null;
ChannelSftp sftp = null;
try {
session = jsch.getSession(machineInfo.getUsername(),machineInfo.getHostIp(), machineInfo.getSshPort());
session.setPassword( CryptogramUtil.doDecrypt(machineInfo.getPassword()));
// 跳过 host key 检查
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
sftp = (ChannelSftp) session.openChannel("sftp");
sftp.connect();
String workDir = (String)getGlobalVariable(context,AFL_DOCKER_WORK_DIR_KEY);
append(context,"AI测试用例生成开始上传目标文件。。。");
String filePath = AFL_DOCKER_BASE_DIR + File.separator + workDir+File.separator+getSourceName(fileName)+File.separator+binaryName;
append(context,"读取到目标文件路径:"+filePath);
InputStream inputStream = sftp.get(filePath);
String targetUploadRes = aiGeneratorService.targetUpload("./" + binaryName, inputStream);
append(context,"上传结果:"+targetUploadRes);
String binaryId = JSON.parseObject(targetUploadRes).getString("id");
append(context,"开始创建测试用例生成task");
// 创建task
TestCaseAITaskCreateReq req = new TestCaseAITaskCreateReq();
req.setBinaryId(binaryId);
req.setCustomPrompt(prompt);
req.setCount(count);
String taskCreateRes = aiGeneratorService.taskCreate(req);
String taskId = JSON.parseObject(taskCreateRes).getString("task_id");
append(context,"创建测试用例生成task成功开始读取task执行日志");
while (true){
// 获取状态及日志
String taskStatusRes = aiGeneratorService.getTaskStatus(taskId);
String status = JSONObject.parseObject(taskStatusRes).getString("status");
if ("success".equals(status)) {
break;
} else if("failed".equals(status)){
toBadEnding();
} else {
String logRes = aiGeneratorService.getTaskLog(taskId);
String logStr = JSON.parseObject(logRes).getString("log");
append(context,logStr);
}
append(context,"task当前执行状态"+taskStatusRes);
}
append(context,"开始下载生成的测试用例文件");
File tempFile = File.createTempFile("seed", ".zip");
tempFile.deleteOnExit();
FileOutputStream fos = new FileOutputStream(tempFile);
// 下载生成的种子
aiGeneratorService.downloadTestCase(taskId,fos);
fos.close();
append(context,"下载生成的模糊测试种子文件成功");
FileInputStream fis = new FileInputStream(tempFile);
// 上传种子zip到目标服务器
String seedPath= workDir+File.separator+ AFL_DOCKER_SEED;
String seedTarget = AFL_VOLUME_WORK_DIR_PREFIX+File.separator+seedPath+File.separator+tempFile.getName();
String seedDir = AFL_VOLUME_WORK_DIR_PREFIX+File.separator+seedPath;
append(context,"上传模糊测试种子压缩包到指定工作目录:"+seedDir);
sftp.put(fis,seedDir);
sftp.disconnect();
append(context,"解压种子到指定工作目录"+seedDir);
String cmd = "unzip -o " + seedTarget + " -d " + seedDir;
append(context,cmd);
// 解压种子zip
exec = (ChannelExec)session.openChannel("exec");
exec.setCommand(cmd);
} catch (Exception e) {
append(context,"测试用例生成失败");
}finally {
if (exec!=null) {
if (exec.isConnected()) {
exec.disconnect();
}
}
if (sftp!=null) {
if (sftp.isConnected()) {
sftp.disconnect();
}
}
if (session!=null) {
if (session.isConnected()) {
session.disconnect();
}
}
}
}
private String getSourceName(String fileName){
if (fileName.contains(".zip")||fileName.contains(".tar")||fileName.contains(".tar.gz")) {
return fileName
.replace(".zip","")
.replace(".tar.gz","")
.replace(".tar","");
}
return "";
}

View File

@ -1,6 +1,9 @@
package cd.casic.ci.process.process.converter;
import cd.casic.ci.process.dto.req.resource.ResourceCreateReq;
import cd.casic.ci.process.dto.req.resource.ResourceUpdateReq;
import cd.casic.ci.process.dto.resp.resource.ResourceDetailResp;
import cd.casic.ci.process.dto.resp.resource.ResourceListResp;
import cd.casic.ci.process.process.dataObject.resource.PipResourceManager;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@ -18,4 +21,7 @@ import java.util.List;
public interface ResourceConverter {
ResourceConverter INSTANCE = Mappers.getMapper(ResourceConverter.class);
ResourceDetailResp converter(PipResourceManager manager);
PipResourceManager converter(ResourceUpdateReq req);
PipResourceManager converter(ResourceCreateReq req);
List<ResourceListResp> converter(List<PipResourceManager> manager);
}

View File

@ -41,4 +41,6 @@ public class PipResourceManager extends PipBaseElement {
* 资源类型ResourceConstant.RES_TYPE_*
* */
private String resourceType;
private String state;
}

View File

@ -13,11 +13,11 @@ import cd.casic.ci.process.process.dataObject.aflManager.AflCrashesInfo;
import cd.casic.ci.process.process.dataObject.aflManager.AflInfo;
import cd.casic.ci.process.process.service.aflManager.AflCrashesInfoService;
import cd.casic.ci.process.process.service.resource.ResourceManagerService;
import cd.casic.ci.process.util.CryptogramUtil;
import cd.casic.ci.process.util.SftpUploadUtil;
import cd.casic.framework.commons.exception.ServiceException;
import cd.casic.framework.commons.exception.enums.GlobalErrorCodeConstants;
import cd.casic.module.machine.dal.dataobject.MachineInfoDO;
import cd.casic.module.machine.utils.CryptogramUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import de.danielbechler.util.Collections;
@ -79,7 +79,7 @@ public class AflCrashesInfoServiceImpl extends ServiceImpl<AflCrashesInfoDao, Af
}
MachineInfoDO resourceMachine = resourceById.getMachineInfo();
String password = resourceMachine.getPassword();
String password = CryptogramUtil.doDecrypt(resourceMachine.getPassword());
resourceMachine.setPassword(password);
try {
@ -248,7 +248,7 @@ public class AflCrashesInfoServiceImpl extends ServiceImpl<AflCrashesInfoDao, Af
}
MachineInfoDO resourceMachine = resourceById.getMachineInfo();
String password = resourceMachine.getPassword();
String password = CryptogramUtil.doDecrypt(resourceMachine.getPassword());
resourceMachine.setPassword(password);
try {
@ -295,7 +295,7 @@ public class AflCrashesInfoServiceImpl extends ServiceImpl<AflCrashesInfoDao, Af
}
MachineInfoDO resourceMachine = resourceById.getMachineInfo();
String password = resourceMachine.getPassword();
String password = CryptogramUtil.doDecrypt(resourceMachine.getPassword());
resourceMachine.setPassword(password);
try {

View File

@ -12,11 +12,11 @@ import cd.casic.ci.process.process.dao.aflManager.AflInfoDao;
import cd.casic.ci.process.process.dataObject.aflManager.AflInfo;
import cd.casic.ci.process.process.service.aflManager.AflInfoService;
import cd.casic.ci.process.process.service.resource.ResourceManagerService;
import cd.casic.ci.process.util.CryptogramUtil;
import cd.casic.ci.process.util.SftpUploadUtil;
import cd.casic.framework.commons.exception.ServiceException;
import cd.casic.framework.commons.exception.enums.GlobalErrorCodeConstants;
import cd.casic.module.machine.dal.dataobject.MachineInfoDO;
import cd.casic.module.machine.utils.CryptogramUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import de.danielbechler.util.Collections;
@ -74,6 +74,7 @@ public class AflInfoServiceImpl extends ServiceImpl<AflInfoDao, AflInfo> impleme
}
MachineInfoDO resourceMachine = resourceById.getMachineInfo();
resourceMachine.setPassword(CryptogramUtil.doDecrypt(resourceMachine.getPassword()));
AflInfo aflInfo = SftpUploadUtil.downloadFileSftpForInputStreamAndSetAflInfo(resourceMachine.getHostIp(), resourceMachine.getSshPort(), resourceMachine.getUsername(), resourceMachine.getPassword(),null, remoteFilePath + "PIP_" + req.getPipelineId() + "/ai_afl/default/fuzzer_stats");
//在本地创建一个新文件夹将远程文件复制一份过去
List<String> sourceFilePaths = new ArrayList<>();
@ -132,7 +133,7 @@ public class AflInfoServiceImpl extends ServiceImpl<AflInfoDao, AflInfo> impleme
}
MachineInfoDO resourceMachine = resourceById.getMachineInfo();
String password = resourceMachine.getPassword();
String password = CryptogramUtil.doDecrypt(resourceMachine.getPassword());
resourceMachine.setPassword(password);
AflInfo aflInfo = SftpUploadUtil.downloadFileSftpForInputStreamAndSetAflInfo(resourceMachine.getHostIp(), resourceMachine.getSshPort(), resourceMachine.getUsername(), resourceMachine.getPassword(),null, remoteFilePath + "PIP_" + req.getPipelineId() + "/ai_afl/default/fuzzer_stats");
@ -216,7 +217,7 @@ public class AflInfoServiceImpl extends ServiceImpl<AflInfoDao, AflInfo> impleme
MachineInfoDO resourceMachine = resourceById.getMachineInfo();
//找出seed文件夹下的所有测试样例文件计算数量
List<String> files = SftpUploadUtil.listFilesInRemoteDirectory(
resourceMachine.getHostIp(), resourceMachine.getSshPort(), resourceMachine.getUsername(), resourceMachine.getPassword(), null, remoteFilePath + "PIP_" + req.getPipelineId() + "/SEED/");
resourceMachine.getHostIp(), resourceMachine.getSshPort(), resourceMachine.getUsername(), CryptogramUtil.doDecrypt(resourceMachine.getPassword()), null, remoteFilePath + "PIP_" + req.getPipelineId() + "/SEED/");
if (!CollectionUtils.isEmpty(files)){
resp.setTestCaseCount(files.size());

View File

@ -15,6 +15,7 @@ import cd.casic.ci.process.util.SftpUploadUtil;
import cd.casic.framework.commons.exception.ServiceException;
import cd.casic.framework.commons.exception.enums.GlobalErrorCodeConstants;
import cd.casic.module.machine.dal.dataobject.MachineInfoDO;
import cd.casic.module.machine.utils.CryptogramUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import de.danielbechler.util.Collections;
@ -69,6 +70,7 @@ public class AflPlotInfoServiceImpl extends ServiceImpl<AflPlotInfoDao, AflPlotI
}
MachineInfoDO resourceMachine = resourceById.getMachineInfo();
resourceMachine.setPassword(CryptogramUtil.doDecrypt(resourceMachine.getPassword()));
AflPlotInfo aflPlotInfo = SftpUploadUtil.downloadFileSftpForLastLineAndSetAflPlotInfo(resourceMachine.getHostIp(), resourceMachine.getSshPort(), resourceMachine.getUsername(), resourceMachine.getPassword(),null, remoteFilePath + "PIP_" + req.getPipelineId() + "/ai_afl/default/plot_data");
//在本地创建一个新文件夹将远程文件复制一份过去
List<String> sourceFilePaths = new ArrayList<>();

View File

@ -10,11 +10,11 @@ import cd.casic.ci.process.process.dao.aflManager.AflSeedInfoDao;
import cd.casic.ci.process.process.dataObject.aflManager.AflSeedInfo;
import cd.casic.ci.process.process.service.aflManager.AflSeedInfoService;
import cd.casic.ci.process.process.service.resource.ResourceManagerService;
import cd.casic.ci.process.util.CryptogramUtil;
import cd.casic.ci.process.util.SftpUploadUtil;
import cd.casic.framework.commons.exception.ServiceException;
import cd.casic.framework.commons.exception.enums.GlobalErrorCodeConstants;
import cd.casic.module.machine.dal.dataobject.MachineInfoDO;
import cd.casic.module.machine.utils.CryptogramUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import de.danielbechler.util.Collections;
@ -194,7 +194,7 @@ public class AflSeedInfoServiceImpl extends ServiceImpl<AflSeedInfoDao, AflSeedI
}
MachineInfoDO resourceMachine = resourceById.getMachineInfo();
String password = resourceMachine.getPassword();
String password = CryptogramUtil.doDecrypt(resourceMachine.getPassword());
resourceMachine.setPassword(password);
try {
// 步骤1列出源目录下的所有文件

View File

@ -1,12 +1,17 @@
package cd.casic.ci.process.process.service.resource;
import cd.casic.ci.process.dto.req.resource.ResourceCreateReq;
import cd.casic.ci.process.dto.req.resource.ResourceListReq;
import cd.casic.ci.process.dto.req.resource.ResourcePageReq;
import cd.casic.ci.process.dto.req.resource.ResourceUpdateReq;
import cd.casic.ci.process.dto.resp.resource.ResourceDetailResp;
import cd.casic.ci.process.dto.resp.resource.ResourceListResp;
import cd.casic.ci.process.process.dataObject.resource.PipResourceManager;
import cd.casic.framework.commons.pojo.PageResult;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
@ -20,8 +25,11 @@ public interface ResourceManagerService extends IService<PipResourceManager> {
/**
* 创建||申请 资源
* */
void createResource(ResourceCreateReq req);
void updateResource(ResourceUpdateReq req);
String createResource(ResourceCreateReq req);
String updateResource(ResourceUpdateReq req);
ResourceDetailResp findResourceDetailById(String resourceId);
void deleteResource(String resourceId);
PageResult<ResourceListResp> page(ResourcePageReq req);
List<ResourceListResp> list(ResourceListReq req);
}

View File

@ -2,24 +2,32 @@ package cd.casic.ci.process.process.service.resource.impl;
import cd.casic.ci.process.constant.ResourceConstant;
import cd.casic.ci.process.dto.req.resource.ResourceCreateReq;
import cd.casic.ci.process.dto.req.resource.ResourceListReq;
import cd.casic.ci.process.dto.req.resource.ResourcePageReq;
import cd.casic.ci.process.dto.req.resource.ResourceUpdateReq;
import cd.casic.ci.process.dto.resp.resource.ResourceDetailResp;
import cd.casic.ci.process.dto.resp.resource.ResourceListResp;
import cd.casic.ci.process.process.converter.ResourceConverter;
import cd.casic.ci.process.process.dao.pipeline.PipResourceManagerDao;
import cd.casic.ci.process.process.dataObject.resource.PipResourceManager;
import cd.casic.ci.process.process.service.resource.ResourceManagerService;
import cd.casic.framework.commons.pojo.PageResult;
import cd.casic.module.execute.docker.dao.DockerEndpointDao;
import cd.casic.module.execute.docker.dataobject.dto.DockerEndpointDo;
import cd.casic.module.execute.docker.dataobject.model.DockerEndpoint;
import cd.casic.module.machine.dal.dataobject.MachineInfoDO;
import cd.casic.module.machine.service.MachineInfoService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.cxf.resource.ResourceManager;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Objects;
/**
@ -42,7 +50,7 @@ public class ResourceManagerServiceImpl extends ServiceImpl<PipResourceManagerDa
private ResourceConverter converter;
@Override
public void createResource(ResourceCreateReq req) {
public String createResource(ResourceCreateReq req) {
String resourceType = req.getResourceType();
PipResourceManager manager = new PipResourceManager();
manager.setResourceName(req.getResourceName());
@ -61,16 +69,20 @@ public class ResourceManagerServiceImpl extends ServiceImpl<PipResourceManagerDa
dockerEndpointDao.insert(dockerEndpoint);
manager.setDockerId(dockerEndpoint.getId());
}
pipResourceManagerDao.insert(manager);
} else if(ResourceConstant.RES_TYPE_CLOUD.equals(resourceType)){
// 入库申请资源等操作
}
return manager.getId();
}
@Override
public void updateResource(ResourceUpdateReq req) {
public String updateResource(ResourceUpdateReq req) {
String resourceType = req.getResourceType();
String id = req.getId();
PipResourceManager manager = pipResourceManagerDao.selectById(id);
manager.setResourceName(req.getResourceName());
manager.setResourceType(req.getResourceType());
// 同类型资源修改
if (manager.getResourceType().equals(resourceType)) {
if (ResourceConstant.RES_TYPE_CUSTOM.equals(resourceType)) {
@ -83,18 +95,23 @@ public class ResourceManagerServiceImpl extends ServiceImpl<PipResourceManagerDa
// 2.维护docker信息之后需要修改
// 3.之前维护了docker信息之后不想维护了
DockerEndpointDo dockerEndpoint = new DockerEndpointDo();
dockerEndpoint.setName(machineInfoDO.getName());
dockerEndpoint.setPort(req.getDockerPort());
dockerEndpoint.setHost(machineInfoDO.getHostIp());
dockerEndpoint.setType(DockerEndpoint.DockerEndpointTypeEnum.REMOTE);
if (StringUtils.isEmpty(manager.getDockerId()) &&Objects.nonNull(req.getDockerPort())) {
String dockerId = manager.getDockerId();
if (StringUtils.isNotEmpty(dockerId)) {
dockerEndpoint = dockerEndpointDao.selectById(dockerId);
}
if (dockerEndpoint!=null) {
dockerEndpoint.setName(machineInfoDO.getName());
dockerEndpoint.setPort(req.getDockerPort());
dockerEndpoint.setHost(machineInfoDO.getHostIp());
dockerEndpoint.setType(DockerEndpoint.DockerEndpointTypeEnum.REMOTE);
}
if (StringUtils.isEmpty(dockerId) &&Objects.nonNull(req.getDockerPort())) {
dockerEndpointDao.insert(dockerEndpoint);
manager.setDockerId(dockerEndpoint.getId());
} else if (!StringUtils.isEmpty(manager.getDockerId()) &&Objects.nonNull(req.getDockerPort())) {
} else if (!StringUtils.isEmpty(dockerId) &&Objects.nonNull(req.getDockerPort())) {
dockerEndpointDao.updateById(dockerEndpoint);
manager.setDockerId(dockerEndpoint.getId());
} else if (!StringUtils.isEmpty(manager.getDockerId()) &&!Objects.nonNull(req.getDockerPort())) {
String dockerId = manager.getDockerId();
} else if (!StringUtils.isEmpty(dockerId) &&!Objects.nonNull(req.getDockerPort())) {
dockerEndpointDao.deleteById(dockerId);
manager.setDockerId(null);
}
@ -105,6 +122,7 @@ public class ResourceManagerServiceImpl extends ServiceImpl<PipResourceManagerDa
//天河国云资源转机器资源是否需要销毁原本资源还是说可以自由切换预留入口
}
pipResourceManagerDao.updateById(manager);
return req.getId();
}
@Override
@ -127,4 +145,20 @@ public class ResourceManagerServiceImpl extends ServiceImpl<PipResourceManagerDa
}
pipResourceManagerDao.deleteById(resourceId);
}
@Override
public PageResult<ResourceListResp> page(ResourcePageReq req) {
LambdaQueryWrapper<PipResourceManager> wrapper = new LambdaQueryWrapper<>();
Page<PipResourceManager> page = pipResourceManagerDao.selectPage(new Page<>(req.getPageNo(), req.getPageSize()), wrapper);
List<ResourceListResp> list = converter.converter(page.getRecords());
return new PageResult<>(list, page.getTotal(), page.getCurrent(), page.getSize());
}
@Override
public List<ResourceListResp> list(ResourceListReq req) {
LambdaQueryWrapper<PipResourceManager> wrapper = new LambdaQueryWrapper<>();
List<PipResourceManager> list = pipResourceManagerDao.selectList(wrapper);
return converter.converter(list);
}
}

View File

@ -0,0 +1,22 @@
package cd.casic.ci.process.process.service.testCase;
import cd.casic.ci.process.dto.req.testCase.TestCaseAITargetUploadReq;
import cd.casic.ci.process.dto.req.testCase.TestCaseAITaskCreateReq;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public interface TestCaseAIGeneratorService {
/**
* 目标文件上传
* */
public String targetUpload(String binaryPath, InputStream inputStream) throws IOException;
/**
* 创建测试用例生成任务
* */
public String taskCreate(TestCaseAITaskCreateReq req);
public String getTaskStatus(String taskId);
public String getTaskLog(String taskId);
public void downloadTestCase(String taskId, OutputStream outputStream) throws IOException;
}

View File

@ -0,0 +1,108 @@
package cd.casic.ci.process.process.service.testCase.impl;
import cd.casic.ci.process.constant.TestCaseAIGeneratorConstant;
import cd.casic.ci.process.dto.req.testCase.TestCaseAITargetUploadReq;
import cd.casic.ci.process.dto.req.testCase.TestCaseAITaskCreateReq;
import cd.casic.ci.process.process.service.testCase.TestCaseAIGeneratorService;
import cd.casic.ci.process.properties.TestCaseAIProperties;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.amazonaws.util.IOUtils;
import jakarta.annotation.Resource;
import net.schmizz.sshj.transport.kex.ECDHNistP;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.util.HashMap;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
@Service
public class TestCaseAIGeneratorServiceImpl implements TestCaseAIGeneratorService {
@Resource
private TestCaseAIProperties properties;
@Resource
private RestTemplate restTemplate;
@Override
public String targetUpload(String binaryPath, InputStream inputStream) throws IOException {
File tempFile = File.createTempFile("target", ".zip");
tempFile.deleteOnExit();
FileOutputStream fos = new FileOutputStream(tempFile);
ZipOutputStream zos = new ZipOutputStream(fos);
ZipEntry entry = new ZipEntry(tempFile.getName());
zos.putNextEntry(entry);
IOUtils.copy(inputStream,zos);
zos.closeEntry();
zos.close();
inputStream.close();
FileSystemResource fsr = new FileSystemResource(tempFile);
String url = properties.getBaseUrl()+ TestCaseAIGeneratorConstant.targetUpload;
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String,Object> body = new LinkedMultiValueMap<>();
body.add("file",fsr);
body.add("binary_path",binaryPath);
HttpEntity<MultiValueMap<String,Object>> entity = new HttpEntity<>(body,headers);
ResponseEntity<String> exchange = restTemplate.exchange(url, HttpMethod.POST, entity, String.class, new HashMap<>());
return exchange.getBody();
}
@Override
public String taskCreate(TestCaseAITaskCreateReq req) {
if (StringUtils.hasLength(req.getBinaryId()) &&StringUtils.hasLength(req.getCaseFormat())) {
return "";
}
JSONObject jsonObject = new JSONObject();
jsonObject.put("binary_id",req.getBinaryId());
jsonObject.put("count",req.getCount());
jsonObject.put("custom_prompt",req.getCustomPrompt());
jsonObject.put("case_format",req.getCaseFormat());
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<>(JSON.toJSONString(jsonObject),headers);
String url = properties.getBaseUrl() + TestCaseAIGeneratorConstant.taskCreate;
ResponseEntity<String> exchange = restTemplate.exchange(url, HttpMethod.POST, entity, String.class, new HashMap<>());
return exchange.getBody();
}
@Override
public String getTaskStatus(String taskId) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<>("{}",headers);
String url = properties.getBaseUrl() + TestCaseAIGeneratorConstant.getTaskStatus+taskId;
ResponseEntity<String> exchange = restTemplate.exchange(url, HttpMethod.GET, entity, String.class, new HashMap<>());
return exchange.getBody();
}
@Override
public String getTaskLog(String taskId) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<>("{}",headers);
String url = properties.getBaseUrl() + TestCaseAIGeneratorConstant.getTaskLog+taskId;
ResponseEntity<String> exchange = restTemplate.exchange(url, HttpMethod.GET, entity, String.class, new HashMap<>());
return exchange.getBody();
}
@Override
public void downloadTestCase(String taskId, OutputStream outputStream) throws IOException {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<>("{}",headers);
String url = properties.getBaseUrl() + TestCaseAIGeneratorConstant.downloadTestCase+taskId;
ResponseEntity<byte[]> exchange = restTemplate.exchange(url, HttpMethod.GET, entity, byte[].class, new HashMap<>());
outputStream.write(exchange.getBody());
}
}

View File

@ -0,0 +1,12 @@
package cd.casic.ci.process.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@ConfigurationProperties(prefix = "test-case.ai")
@Component
@Data
public class TestCaseAIProperties {
private String baseUrl;
}

View File

@ -4,6 +4,7 @@ package cd.casic.ci.process.ssh;
import cd.casic.ci.process.constant.CommandConstant;
import cd.casic.ci.process.util.ChannelShellUtil;
import cd.casic.module.machine.dal.dataobject.MachineInfoDO;
import cd.casic.module.machine.utils.CryptogramUtil;
import cn.hutool.extra.ssh.JschUtil;
import com.jcraft.jsch.ChannelShell;
import com.jcraft.jsch.JSchException;
@ -58,7 +59,7 @@ public class SshCommand implements SshClient {
*/
public SshCommand(MachineInfoDO machine) throws JSchException {
// 根据用户名主机ip端口获取一个Session对象
String decrypt = machine.getPassword();
String decrypt = CryptogramUtil.doDecrypt(machine.getPassword());
this.session = JschUtil.createSession(machine.getHostIp(), machine.getSshPort(), machine.getUsername(), decrypt);
this.session.setConfig("PreferredAuthentications", "password");
this.session.setConfig("StrictHostKeyChecking", "no");

View File

@ -1,7 +1,7 @@
package cd.casic.ci.process.ssh;
import cd.casic.ci.process.util.CryptogramUtil;
import cd.casic.module.machine.dal.dataobject.MachineInfoDO;
import cd.casic.module.machine.utils.CryptogramUtil;
import io.cloudsoft.winrm4j.client.WinRmClientContext;
import io.cloudsoft.winrm4j.winrm.WinRmTool;
import io.cloudsoft.winrm4j.winrm.WinRmToolResponse;
@ -35,7 +35,7 @@ public class WinRMHelper {
public WinRMHelper(MachineInfoDO machineInfo) {
this.ip = machineInfo.getHostIp();
this.username = machineInfo.getUsername();
this.password = machineInfo.getPassword();
this.password = CryptogramUtil.doDecrypt(machineInfo.getPassword());
}
public int execute(final String command, ExecCallback execCallback) {

View File

@ -1,175 +0,0 @@
package cd.casic.ci.process.util;
// ... 省略 package import ...
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.engines.SM4Engine;
import org.bouncycastle.crypto.generators.SM2KeyPairGenerator;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.*;
import org.bouncycastle.crypto.signers.SM2Signer;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Hex;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.ECGenParameterSpec;
public class CryptogramUtil {
static {
Security.addProvider(new BouncyCastleProvider());
}
/**
* SM2 公钥加密
*/
public static String doSm2Encrypt(String str) {
try {
byte[] data = str.getBytes(StandardCharsets.UTF_8);
ECPublicKeyParameters pubKey = getSm2PublicKey(Keypair.PUBLIC_KEY);
SM2Engine engine = new SM2Engine();
engine.init(true, pubKey);
byte[] enc = engine.processBlock(data, 0, data.length);
return Hex.toHexString(enc);
} catch (Exception e) {
throw new RuntimeException("SM2加密失败", e);
}
}
/**
* SM2 私钥解密
*/
public static String doSm2Decrypt(String str) {
try {
byte[] enc = Hex.decode(str);
ECPrivateKeyParameters priKey = getSm2PrivateKey(Keypair.PRIVATE_KEY);
SM2Engine engine = new SM2Engine();
engine.init(false, priKey);
byte[] dec = engine.processBlock(enc, 0, enc.length);
return new String(dec, StandardCharsets.UTF_8);
} catch (Exception e) {
// 解密失败返回原文
return str;
}
}
/**
* SM4 CBC 加密
*/
public static String doEncrypt(String str) {
try {
byte[] key = Hex.decode(Keypair.KEY);
byte[] iv = Hex.decode(Keypair.IV);
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new SM4Engine()));
cipher.init(true, new ParametersWithIV(new KeyParameter(key), iv));
byte[] input = str.getBytes(StandardCharsets.UTF_8);
byte[] output = new byte[cipher.getOutputSize(input.length)];
int len = cipher.processBytes(input, 0, input.length, output, 0);
len += cipher.doFinal(output, len);
return Hex.toHexString(output, 0, len);
} catch (Exception e) {
throw new RuntimeException("SM4加密失败", e);
}
}
/**
* SM4 CBC 解密
*/
public static String doDecrypt(String str) {
try {
byte[] key = Hex.decode(Keypair.KEY);
byte[] iv = Hex.decode(Keypair.IV);
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new SM4Engine()));
cipher.init(false, new ParametersWithIV(new KeyParameter(key), iv));
byte[] input = Hex.decode(str);
byte[] output = new byte[cipher.getOutputSize(input.length)];
int len = cipher.processBytes(input, 0, input.length, output, 0);
len += cipher.doFinal(output, len);
return new String(output, 0, len, StandardCharsets.UTF_8);
} catch (Exception e) {
// 解密失败返回原文
return str;
}
}
/**
* SM2 签名
*/
public static String doSignature(String str) {
try {
ECPrivateKeyParameters priKey = getSm2PrivateKey(Keypair.PRIVATE_KEY);
SM2Signer signer = new SM2Signer();
signer.init(true, priKey);
byte[] msg = str.getBytes(StandardCharsets.UTF_8);
signer.update(msg, 0, msg.length);
byte[] sig = signer.generateSignature();
return Hex.toHexString(sig);
} catch (Exception e) {
throw new RuntimeException("SM2签名失败", e);
}
}
/**
* SM2 验签
*/
public static boolean doVerifySignature(String originalStr, String str) {
try {
ECPublicKeyParameters pubKey = getSm2PublicKey(Keypair.PUBLIC_KEY);
SM2Signer signer = new SM2Signer();
signer.init(false, pubKey);
byte[] msg = originalStr.getBytes(StandardCharsets.UTF_8);
signer.update(msg, 0, msg.length);
byte[] sig = Hex.decode(str);
return signer.verifySignature(sig);
} catch (Exception e) {
return false;
}
}
/**
* SM3 哈希
*/
public static String doHashValue(String str) {
try {
SM3Digest digest = new SM3Digest();
byte[] msg = str.getBytes(StandardCharsets.UTF_8);
digest.update(msg, 0, msg.length);
byte[] hash = new byte[digest.getDigestSize()];
digest.doFinal(hash, 0);
return Hex.toHexString(hash);
} catch (Exception e) {
throw new RuntimeException("SM3哈希失败", e);
}
}
// ====== 工具方法 ======
// 获取SM2公钥参数
private static ECPublicKeyParameters getSm2PublicKey(String hex) {
org.bouncycastle.jce.spec.ECParameterSpec ecSpec = org.bouncycastle.jce.ECNamedCurveTable.getParameterSpec("sm2p256v1");
org.bouncycastle.math.ec.ECPoint q = ecSpec.getCurve().decodePoint(Hex.decode(hex));
return new ECPublicKeyParameters(q, new ECDomainParameters(ecSpec.getCurve(), ecSpec.getG(), ecSpec.getN()));
}
// 获取SM2私钥参数
private static ECPrivateKeyParameters getSm2PrivateKey(String hex) {
org.bouncycastle.jce.spec.ECParameterSpec ecSpec = org.bouncycastle.jce.ECNamedCurveTable.getParameterSpec("sm2p256v1");
return new ECPrivateKeyParameters(new java.math.BigInteger(hex, 16), new ECDomainParameters(ecSpec.getCurve(), ecSpec.getG(), ecSpec.getN()));
}
private static class Keypair {
// 公钥未压缩点hex字符串前缀04
public static final String PUBLIC_KEY = "04298364ec840088475eae92a591e01284d1abefcda348b47eb324bb521bb03b0b2a5bc393f6b71dabb8f15c99a0050818b56b23f31743b93df9cf8948f15ddb54";
// 私钥hex字符串
public static final String PRIVATE_KEY = "3037723d47292171677ec8bd7dc9af696c7472bc5f251b2cec07e65fdef22e25";
// SM4密钥16字节128位hex字符串
public static final String KEY = "0123456789abcdeffedcba9876543210";
// SM4 IV16字节hex字符串
public static final String IV = "fedcba98765432100123456789abcdef";
}
}

View File

@ -181,4 +181,6 @@ shuimu:
username: admin
grant-type: password
client-id: client
test-case:
ai:
base-url: http://175.6.27.252:8000/api/v1

View File

@ -1,5 +1,5 @@
package cd.casic.server;
import cd.casic.ci.process.util.CryptogramUtil;
import cd.casic.module.machine.utils.CryptogramUtil;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.CreateContainerResponse;
import com.github.dockerjava.api.command.ExecCreateCmdResponse;

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,66 @@
package cd.casic.server;
import cd.casic.ci.process.constant.TestCaseAIGeneratorConstant;
import cd.casic.ci.process.dto.req.testCase.TestCaseAITaskCreateReq;
import cd.casic.ci.process.process.service.testCase.TestCaseAIGeneratorService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.io.ClassPathResource;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.web.WebAppConfiguration;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@SpringBootTest(classes = {OpsServerApplication.class})
@ActiveProfiles("local")
@Slf4j
@WebAppConfiguration
public class TestCaseAIGeneratorTest {
@Resource
private TestCaseAIGeneratorService service;
@Test
public void targetUpload() throws IOException {
//{"success":true,"msg":"","id":"8711fd176b686eebcc4e3f49bdde1a18"}
ClassPathResource classPathResource = new ClassPathResource("static/pcre2test");
String s = service.targetUpload("./pcre2test", classPathResource.getInputStream());
System.out.println(s);
}
@Test
public void taskCreate(){
// {"success":true,"msg":"","task_id":"7c5d7df0-68d5-4935-aae7-00287976ae44"}
// {"success":true,"msg":"","task_id":"a70f92e9-9b8c-4be3-974f-8b0efa253237"}
TestCaseAITaskCreateReq req = new TestCaseAITaskCreateReq();
req.setBinaryId("8711fd176b686eebcc4e3f49bdde1a18");
req.setCustomPrompt("你是一个模糊测试专家,当前程序输入为文本例如 aa aaa 这种");
req.setCount(10);
String s = service.taskCreate(req);
System.out.println(s);
}
@Test
public void getTaskStatus(){
// {"success":true,"msg":"","task_id":"7c5d7df0-68d5-4935-aae7-00287976ae44","status":"success"}
String taskStatus = service.getTaskStatus("1e6e9694-5ae2-425e-ad80-9af266d33bea");
System.out.println(taskStatus);
}
@Test
public void getTaskLog(){
// {"success":true,"msg":"","log":"智能体初始化中...\n"}
String taskLog = service.getTaskLog("1e6e9694-5ae2-425e-ad80-9af266d33bea");
System.out.println(taskLog);
}
@Test
public void downloadSeed() throws IOException {
File tempFile = File.createTempFile("seed", ".zip");
FileOutputStream fos = new FileOutputStream(tempFile);
service.downloadTestCase("1e6e9694-5ae2-425e-ad80-9af266d33bea",fos);
tempFile.deleteOnExit();
fos.close();
System.out.println();
}
}

View File

@ -1,7 +1,6 @@
package cd.casic.server;
import cd.casic.ci.process.properties.TargetFileUploadProperties;
import cd.casic.ci.process.util.CryptogramUtil;
import cd.casic.ci.process.util.SftpUploadUtil;
import com.jcraft.jsch.*;
import jakarta.annotation.Resource;