Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
ddec4a6671
@ -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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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/";
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package cd.casic.ci.process.dto.req.resource;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ResourceListReq {
|
||||
|
||||
}
|
@ -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 {
|
||||
}
|
@ -22,4 +22,6 @@ public class ResourceUpdateReq {
|
||||
* docker连接端口(选填)
|
||||
* */
|
||||
private Integer dockerPort;
|
||||
|
||||
private String cloudId;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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,
|
||||
|
@ -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");
|
||||
|
@ -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 "";
|
||||
}
|
||||
|
@ -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 "";
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -41,4 +41,6 @@ public class PipResourceManager extends PipBaseElement {
|
||||
* 资源类型ResourceConstant.RES_TYPE_*
|
||||
* */
|
||||
private String resourceType;
|
||||
|
||||
private String state;
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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());
|
||||
|
@ -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<>();
|
||||
|
@ -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:列出源目录下的所有文件
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
@ -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");
|
||||
|
@ -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) {
|
||||
|
@ -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 IV(16字节,hex字符串)
|
||||
public static final String IV = "fedcba98765432100123456789abcdef";
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user