diff --git a/cve-vulner-manager/Dockerfile b/cve-vulner-manager/Dockerfile index 386d3d3d430246c4bef5352c6c953f33ed6f4904..e58bc355d0fcfe341c745537e740cb583236e0f5 100644 --- a/cve-vulner-manager/Dockerfile +++ b/cve-vulner-manager/Dockerfile @@ -8,7 +8,7 @@ COPY . /go/src/gitee.com/openeuler/cve-manager RUN cd /go/src/gitee.com/openeuler/cve-manager && CGO_ENABLED=1 go build -v -o ./cve-manager main.go # copy binary config and utils -FROM openeuler/openeuler:22.03 +FROM openeuler/openeuler:24.03-lts-sp1 RUN dnf -y update && \ dnf in -y shadow && \ groupadd -g 1000 manager && \ diff --git a/cve-vulner-manager/common/common.go b/cve-vulner-manager/common/common.go index 910e636e893a7b1d53dafcafb00a7654dca18f24..27b74f33892c1d6972da44b4b253aab61c6f38aa 100644 --- a/cve-vulner-manager/common/common.go +++ b/cve-vulner-manager/common/common.go @@ -12,8 +12,11 @@ import ( "github.com/astaxie/beego/config" "github.com/astaxie/beego/logs" "github.com/astaxie/beego/orm" + "github.com/opensourceways/robot-gitee-lib/client" ) +var openEulerGiteeClient client.Client + const ( DATE_FORMAT = "2006-01-02 15:04:05" DATE_T_FORMAT = "2006-01-02T15:04:05" @@ -23,6 +26,18 @@ const ( Huntr = "huntr" ) +func init() { + token := beego.AppConfig.String("gitee::git_token") + openEulerGiteeClient = client.NewClient(func() []byte { + return []byte(token) + }) +} + +// GetOpenEulerGiteeClient get openeuler gitee client +func GetOpenEulerGiteeClient() client.Client { + return openEulerGiteeClient +} + func DesString(dbpwd string) (strs string) { defer Catchs() if "" != dbpwd || len(dbpwd) > 0 { diff --git a/cve-vulner-manager/conf/product_app.conf b/cve-vulner-manager/conf/product_app.conf index 2511e86e0920f0e81ac0a88bed119c7a781aa478..ed307468a9aaa8dfa2aafc5a772fa9587e1b1ffa 100644 --- a/cve-vulner-manager/conf/product_app.conf +++ b/cve-vulner-manager/conf/product_app.conf @@ -130,8 +130,10 @@ syncissuedateflag = 1 syncissuedate = 0 0 7,13 * * * releaseUnaffectedCveflag = 1 -releaseUnaffectedCve = 0 0 11 * * * +releaseUnaffectedCve = 0 0 11 * * 1-6 +releaseUnaffectedCveflagAll = 1 +releaseUnaffectedCveAll = 0 0 11 * * 0 [gitee] owner = src-openeuler diff --git a/cve-vulner-manager/controllers/hook.go b/cve-vulner-manager/controllers/hook.go index ab5df36df40309d18225dd17521ab53c547e603e..47c266e1ba38c120c507136f5767a5d5cdeca100 100644 --- a/cve-vulner-manager/controllers/hook.go +++ b/cve-vulner-manager/controllers/hook.go @@ -92,6 +92,10 @@ const ( CommentRepeatIssue = `%v 请检查当前: %v,是否重复创建, issue编号: %v, 重复创建的issue,将不会被再次识别.` webhookCommentLogTag = "webhook-comment" + + cmdCheckIssue = "/check-issue" + reasonCommand = "/reason" + reasonX = "xxxxxx" ) var comLock sync.Mutex @@ -443,7 +447,7 @@ func closeIssueProc(issueHook *models.IssuePayload, issueTmp *models.IssueTempla sigReviewSend(issueHook, issueTmp, token, owner, fixed, unFix, assignee, cveCenter) } if openScoreFlag { - if msg, tb, ok := taskhandler.CheckIssueAnalysisComplete(issueTmp, cveCenter.OrganizationID); !ok { + if msg, tb, ok := taskhandler.CheckIssueAnalysisComplete(issueTmp); !ok { //send comment to issue issueTmp.IssueStatus = 1 issueTmp.IssueLabel = unFix @@ -534,7 +538,8 @@ func handleIssueStateChange(issueHook *models.IssuePayload) error { logs.Error("The current issue has been rejected and will not be processed, issueHook: ", issueHook) issueTmp.Status = 4 issueTmp.StatusName = "rejected" - models.UpdateIssueTemplate(&issueTmp, "Status", "StatusName") + issueTmp.RejectReason = getRejectReason(issueTmp.Owner, issueTmp.Repo, issueTmp.IssueNum) + models.UpdateIssueTemplate(&issueTmp, "Status", "StatusName", "reject_reason") return errors.New("The current issue has been rejected and will not be processed") } owner, token := common.GetOwnerAndToken(cveCenter.CveNum, cveCenter.OrganizationID) @@ -547,18 +552,11 @@ func handleIssueStateChange(issueHook *models.IssuePayload) error { } } - var checkFunc func(template *models.IssueTemplate, organizationID int8) (string, string, bool) - switch cveCenter.OrganizationID { - case util.Openeuler: - checkFunc = taskhandler.CheckIssueAnalysisComplete - default: - checkFunc = taskhandler.CheckOtherIssueAnalysisComplete - } switch issueHook.State { case IssueOpenState: issueTmp.Status = 1 cveCenter.IsExport = 0 - _, _, ok := checkFunc(&issueTmp, cveCenter.OrganizationID) + _, _, ok := taskhandler.CheckIssueAnalysisComplete(&issueTmp) if ok { issueTmp.IssueStatus = 3 } else { @@ -569,7 +567,7 @@ func handleIssueStateChange(issueHook *models.IssuePayload) error { case IssueProgressState: issueTmp.Status = 2 cveCenter.IsExport = 0 - _, _, ok := checkFunc(&issueTmp, cveCenter.OrganizationID) + _, _, ok := taskhandler.CheckIssueAnalysisComplete(&issueTmp) if ok { issueTmp.IssueStatus = 3 } else { @@ -600,6 +598,32 @@ func handleIssueStateChange(issueHook *models.IssuePayload) error { return nil } +func getRejectReason(owner, repo, issueNum string) string { + comments, err := common.GetOpenEulerGiteeClient().ListIssueComments(owner, repo, issueNum) + if err != nil { + logs.Error("get issue comments failed:", err.Error()) + return "" + } + + var reason string + for i := len(comments) - 1; i >= 0; i-- { + body := comments[i].Body + index := strings.Index(body, reasonCommand) + if index == -1 { + continue + } + + reason = strings.TrimSpace(body[index+len(reasonCommand):]) + if reason == reasonX { + continue + } + + break + } + + return util.TrimStringNR(reason) +} + // When the issue status is complete, verify whether the pr is associated func VerifyIssueAsPr(issueTmp *models.IssueTemplate, cveCenter models.VulnCenter, effectFlag bool, assignee, prSend string) bool { @@ -1327,7 +1351,7 @@ func otherMaintainerApprove( func maintainerApprove(issueTmp *models.IssueTemplate, cuAccount, owner, token, fixed, unfixed string, organizationID int8, payload *models.CommentPayload) { - if msg, _, ok := taskhandler.CheckIssueAnalysisComplete(issueTmp, organizationID); !ok { + if msg, _, ok := taskhandler.CheckIssueAnalysisComplete(issueTmp); !ok { //send comment to issue na := "\n**请确认分析内容的准确性,待分析内容请填写完整,否则将无法关闭当前issue.**" cc := fmt.Sprintf(CommentAnalysisCplTpl, cuAccount, msg) + na @@ -1362,7 +1386,7 @@ func maintainerApprove(issueTmp *models.IssueTemplate, cuAccount, owner, token, func securityApprove(issueTmp *models.IssueTemplate, cuAccount, owner, token, fixed, unfixed string, organizationID int8, payload *models.CommentPayload) { - if msg, _, ok := taskhandler.CheckIssueAnalysisComplete(issueTmp, organizationID); !ok { + if msg, _, ok := taskhandler.CheckIssueAnalysisComplete(issueTmp); !ok { //send comment to issue na := "\n**请确认分析内容的准确性,待分析内容请填写完整,否则将无法关闭当前issue.**" cc := fmt.Sprintf(CommentAnalysisCplTpl, cuAccount, msg) + na @@ -1573,6 +1597,11 @@ func handleIssueComment(payload models.CommentPayload) { if vc.OrganizationID == 1 { VerifyCve(issueTmp) } + + } else if strings.HasPrefix(cBody, cmdCheckIssue) { + comLock.Lock() + checkAndUpdateIssue(&payload, issueTmp, owner, accessToken, path, cuAccount) + comLock.Unlock() } else { logs.Error(webhookCommentLogTag, "analysis comment, number: ", payload.Issue.Number) if payload.Issue.State == "closed" || payload.Issue.State == "rejected" || @@ -1684,7 +1713,12 @@ func analysisComment(owner, accessToken, path string, cuAccount string, cBody st canVerfy := false issueTmp.MtAuditFlag = 1 //is Analyst comment and content start with '/analysis' - vMap := util.ExtractCommentAnalysisAllValue(cBody, v.OrganizationID) + vMap, err := util.ExtractCommentAnalysisAllValue(cBody, v.OrganizationID) + if err != nil { + taskhandler.AddCommentToIssue(err.Error(), issueTmp.IssueNum, owner, path, accessToken) + return + } + logs.Error(webhookCommentLogTag, "vMap of ", issueTmp.IssueNum, vMap) if len(vMap) > 0 { canVerfy = true @@ -1773,121 +1807,101 @@ func analysisComment(owner, accessToken, path string, cuAccount string, cBody st // update gitee issue commentUpdateIssue(issueTmp, owner, accessToken, path) } - if _, ok := vMap["issue_package"]; ok { - // handle comment package - err := handleCommentPackage(vMap["issue_package"], issueTmp.CveId) - if err != nil { - logs.Error("handleCommentPackage, err: ", err) - } - } } logs.Error(webhookCommentLogTag, "canVerfy of ", issueTmp.IssueNum, canVerfy) if canVerfy { - //Check whether the data is legal - var checkFunc func(template *models.IssueTemplate, organizationID int8) (string, string, bool) - switch v.OrganizationID { - case util.Openeuler: - checkFunc = taskhandler.CheckIssueAnalysisComplete - default: - checkFunc = taskhandler.CheckOtherIssueAnalysisComplete + checkAndUpdateIssue(payload, issueTmp, owner, accessToken, path, cuAccount) + } +} + +func checkAndUpdateIssue(payload *models.CommentPayload, issueTmp models.IssueTemplate, + owner, accessToken, path, cuAccount string) { + if msg, tb, ok := taskhandler.CheckIssueAnalysisComplete(&issueTmp); !ok { + //send comment to issue + issueTmp.IssueStatus = 1 + err := models.UpdateIssueTemplate(&issueTmp, "issue_status") + if err != nil { + logs.Error(webhookCommentLogTag, "UpdateIssueTemplate, upErr: ", err, ",issueTmp: ", issueTmp.IssueNum) } - if msg, tb, ok := checkFunc(&issueTmp, v.OrganizationID); !ok { - //send comment to issue - issueTmp.IssueStatus = 1 - err := models.UpdateIssueTemplate(&issueTmp, "issue_status") - if err != nil { - logs.Error(webhookCommentLogTag, "UpdateIssueTemplate, upErr: ", err, ",issueTmp: ", issueTmp.IssueNum) - } - assignee := "" - if cuAccount != "" && len(cuAccount) > 1 { - assignee = cuAccount - } else { - assignee = issueTmp.Assignee - } - msg = fmt.Sprintf(CommentAnalysisCplTpl, assignee, msg) - taskhandler.AddCommentToIssue(msg, issueTmp.IssueNum, owner, path, accessToken) + assignee := "" + if cuAccount != "" { + assignee = cuAccount } else { - if v.OrganizationID == 1 { - //1. change issue status - issueTmp.IssueStatus = 3 - //2. Are the cvsScore and openEuler score equal .If not equal, notify the auditor to review . - var na string + assignee = issueTmp.Assignee + } + msg = fmt.Sprintf(CommentAnalysisCplTpl, assignee, msg) + taskhandler.AddCommentToIssue(msg, issueTmp.IssueNum, owner, path, accessToken) + } else { + //1. change issue status + issueTmp.IssueStatus = 3 + //2. Are the cvsScore and openEuler score equal .If not equal, notify the auditor to review . + var na string - var isScoreTypeV3 = false - score, err := models.QueryIssueScore(issueTmp.CveId) - if err != nil { - logs.Error(webhookCommentLogTag, "query score type to check failed", issueTmp.CveId, err) - } else { - if score.ScoreType == "v3" { - isScoreTypeV3 = true - } - } + var isScoreTypeV3 = false + score, err := models.QueryIssueScore(issueTmp.CveId) + if err != nil { + logs.Error(webhookCommentLogTag, "query score type to check failed", issueTmp.CveId, err) + } else { + if score.ScoreType == "v3" { + isScoreTypeV3 = true + } + } - if isScoreTypeV3 { - if util.CalculateCVSSV3BaseScore(issueTmp.OpenEulerVector) != issueTmp.OpenEulerScore { - cc := fmt.Sprintf("@%v CVSS评分和矢量值不一致,请修改至矢量值和CVSS评分一致!", issueTmp.Assignee) - taskhandler.AddCommentToIssue(cc, issueTmp.IssueNum, owner, path, accessToken) - return + if isScoreTypeV3 { + if util.CalculateCVSSV3BaseScore(issueTmp.OpenEulerVector) != issueTmp.OpenEulerScore { + cc := fmt.Sprintf("@%v CVSS评分和矢量值不一致,请修改至矢量值和CVSS评分一致!", issueTmp.Assignee) + taskhandler.AddCommentToIssue(cc, issueTmp.IssueNum, owner, path, accessToken) + return + } + } + + if issueTmp.OpenEulerScore != issueTmp.NVDScore && issueTmp.OpenEulerScore > 0 && + issueTmp.NVDScore > 0 && issueTmp.OpAuditFlag == 0 { + na = "\n**因OpenEulerScore与NvdScore不一致,分析内容需审核,请等待安全组审核!**" + //Notify the responsible person for review + notifyAuditorReview(payload, issueTmp) + } else { + if issueTmp.MtAuditFlag == 0 { + maintainerList, mainOk := models.QueryRepoAllMaintainer(issueTmp.Repo) + assList := []string{} + if mainOk && len(maintainerList) > 0 { + for _, v := range maintainerList { + assList = append(assList, "@"+v.MemberName+" ") + content := fmt.Sprintf("%v 仓库的CVE和安全问题的ISSUE,CVE编号: %v, "+ + "已经完成了模板填写,需要您对填写的内容进行审核,审核通过才能进行后续操作.", issueTmp.Repo, issueTmp.CveNum) + taskhandler.SendPrivateLetters(accessToken, content, v.MemberName) } } - - if issueTmp.OpenEulerScore != issueTmp.NVDScore && issueTmp.OpenEulerScore > 0 && - issueTmp.NVDScore > 0 && issueTmp.OpAuditFlag == 0 { - na = "\n**因OpenEulerScore与NvdScore不一致,分析内容需审核,请等待安全组审核!**" - //Notify the responsible person for review - notifyAuditorReview(payload, issueTmp) + assignee := "" + if len(assList) > 0 { + assignee = strings.Join(assList, ",") } else { - if issueTmp.MtAuditFlag == 0 { - maintainerList, mainOk := models.QueryRepoAllMaintainer(issueTmp.Repo) - assList := []string{} - if mainOk && len(maintainerList) > 0 { - for _, v := range maintainerList { - assList = append(assList, "@"+v.MemberName+" ") - content := fmt.Sprintf("%v 仓库的CVE和安全问题的ISSUE,CVE编号: %v, "+ - "已经完成了模板填写,需要您对填写的内容进行审核,审核通过才能进行后续操作.", issueTmp.Repo, issueTmp.CveNum) - taskhandler.SendPrivateLetters(accessToken, content, v.MemberName) - } - } - assignee := "" - if len(assList) > 0 { - assignee = strings.Join(assList, ",") - } else { - assignee = "@" + issueTmp.Assignee - } - na = "\n**请确认模板分析内容的准确性与完整性, 确认无误后,请在评论区输入: /approve, 否则无法关闭当前issue.**" - cc := fmt.Sprintf(ContentReview, assignee) + tb + na - taskhandler.AddCommentToIssue(cc, issueTmp.IssueNum, owner, path, accessToken) - } else { - na = "\n**请确认分析内容的准确性, 确认无误后, 您可以进行后续步骤, 否则您可以继续分析.**" - cc := fmt.Sprintf(AnalysisComplete, issueTmp.Assignee) + tb + na - taskhandler.AddCommentToIssue(cc, issueTmp.IssueNum, owner, path, accessToken) - } - // change score status - err := changeOpenEulerScoreStatus(issueTmp.CveId, 3) - if err != nil { - logs.Error(webhookCommentLogTag, "changeOpenEulerScoreStatus, err: ", err, ",issueTmp: ", issueTmp.IssueNum) - } - - if err = SetIssueStateByReason(&issueTmp, payload.Issue.StateName); err != nil { - logs.Error(webhookCommentLogTag, "SetIssueStateByReason, err: ", err, ",issueTmp: ", issueTmp.IssueNum) - } + assignee = "@" + issueTmp.Assignee } + na = "\n**请确认模板分析内容的准确性与完整性, 确认无误后,请在评论区输入: /approve, 否则无法关闭当前issue.**" + cc := fmt.Sprintf(ContentReview, assignee) + tb + na + taskhandler.AddCommentToIssue(cc, issueTmp.IssueNum, owner, path, accessToken) } else { - na := "\n**请确认分析内容的准确性, 确认无误后, 您可以进行后续步骤, 否则您可以继续分析.**" + na = "\n**请确认分析内容的准确性, 确认无误后, 您可以进行后续步骤, 否则您可以继续分析.**" cc := fmt.Sprintf(AnalysisComplete, issueTmp.Assignee) + tb + na taskhandler.AddCommentToIssue(cc, issueTmp.IssueNum, owner, path, accessToken) - // change score status - err := changeOpenEulerScoreStatus(issueTmp.CveId, 3) - if err != nil { - logs.Error(webhookCommentLogTag, "changeOpenEulerScoreStatus, err: ", err, ",issueTmp: ", issueTmp.IssueNum) - } + } + // change score status + err = changeOpenEulerScoreStatus(issueTmp.CveId, 3) + if err != nil { + logs.Error(webhookCommentLogTag, "changeOpenEulerScoreStatus, err: ", err, ",issueTmp: ", issueTmp.IssueNum) + } + + if err = SetIssueStateByReason(&issueTmp, payload.Issue.StateName); err != nil { + logs.Error(webhookCommentLogTag, "SetIssueStateByReason, err: ", err, ",issueTmp: ", issueTmp.IssueNum) } } - err := models.UpdateIssueTemplate(&issueTmp, "issue_status", "mt_audit_flag") - if err != nil { - logs.Error(webhookCommentLogTag, "UpdateIssueTemplate, updErr: ", err, ",issueTmp: ", issueTmp.IssueNum) - } + } + + err := models.UpdateIssueTemplate(&issueTmp, "issue_status", "mt_audit_flag") + if err != nil { + logs.Error(webhookCommentLogTag, "UpdateIssueTemplate, updErr: ", err, ",issueTmp: ", issueTmp.IssueNum) } } diff --git a/cve-vulner-manager/cve-ddd/app/bulletin.go b/cve-vulner-manager/cve-ddd/app/bulletin.go index 11c1f0000c59b503d6d804373a7d49100e6d408e..04ecabcde50f6344e4ada827ff3dc8db7df9ddb6 100644 --- a/cve-vulner-manager/cve-ddd/app/bulletin.go +++ b/cve-vulner-manager/cve-ddd/app/bulletin.go @@ -38,7 +38,7 @@ const ( ) type BulletinService interface { - GenerateBulletins([]string, string) (string, error) + GenerateBulletins(CmdToGenerate) (string, error) Move() error } @@ -83,7 +83,7 @@ type bulletinService struct { log *logrus.Entry } -func (b *bulletinService) GenerateBulletins(cveNum []string, date string) (string, error) { +func (b *bulletinService) GenerateBulletins(cmd CmdToGenerate) (string, error) { handleBranch, err := b.maJun.GetReleasedBranch() if err != nil { return "", fmt.Errorf("get release branch err: %w", err) @@ -93,6 +93,7 @@ func (b *bulletinService) GenerateBulletins(cveNum []string, date string) (strin domain.InitMaintainVersion(handleBranch) + cveNum := cmd.GetCveNum() b.log.Infof("need to handle cve are %v", cveNum) cves, err := b.repo.FindCves(repository.Option{CveNum: cveNum}) if err != nil { @@ -107,13 +108,16 @@ func (b *bulletinService) GenerateBulletins(cveNum []string, date string) (strin b.log.Errorf("num of cveNum %d and num of cves %d does not match", len(cveNum), len(cves)) } + // 用请求参数的分支信息过滤,只处理cve指定的分支 + cves = b.filterByRequestParam(cves, cmd) + // 用关联pr并且合入的分支进行过滤 cves = b.filterByRelatedPR(cves, handleBranch) // 用已发布的分支进行过滤 cves = b.filterByPublishedBranch(cves) - b.testResult.Init(handleBranch, date) + b.testResult.Init(handleBranch, cmd.Date) // 用成功转测的数据进行过滤,只发布转测成功的cve testedCves := b.testResult.Filter(cves) @@ -158,7 +162,7 @@ func (b *bulletinService) GenerateBulletins(cveNum []string, date string) (strin updateFixedFiles = append(updateFixedFiles, v.PathAppendToIndexFile()) - service.UploadUpdateInfoFile(b.obs, b.updateinfo, b.log, &v, date, updateInfoEarlyDir) + service.UploadUpdateInfoFile(b.obs, b.updateinfo, b.log, &v, cmd.Date, updateInfoEarlyDir) } b.uploadIndexAndFixed(uploadDir, indexContent, updateFixedFiles) @@ -197,6 +201,19 @@ func (b *bulletinService) getIndexContent() (string, error) { return string(content), err } +func (b *bulletinService) filterByRequestParam(cves domain.Cves, cmd CmdToGenerate) domain.Cves { + var filteredCves domain.Cves + for _, v := range cves { + if branches, ok := cmd.CveNum[v.CveNum]; ok { + v.AffectedVersion = branches + } + + filteredCves = append(filteredCves, v) + } + + return filteredCves +} + func (b *bulletinService) filterByRelatedPR(cves domain.Cves, handleBranch []string) domain.Cves { handleBranchSet := sets.NewString(handleBranch...) diff --git a/cve-vulner-manager/cve-ddd/app/coldpatch_dto.go b/cve-vulner-manager/cve-ddd/app/dto.go similarity index 41% rename from cve-vulner-manager/cve-ddd/app/coldpatch_dto.go rename to cve-vulner-manager/cve-ddd/app/dto.go index 78c0818e34ec42f6a9f2f976c98838cbf751f12d..27a23fa44a2272114f537a2c4791723f5ba4a478 100644 --- a/cve-vulner-manager/cve-ddd/app/coldpatch_dto.go +++ b/cve-vulner-manager/cve-ddd/app/dto.go @@ -5,3 +5,17 @@ type CmdToCollectData struct { Date string `json:"date" valid:"Required"` CallbackId string `json:"callback_id" valid:"Required"` } + +type CmdToGenerate struct { + CveNum map[string][]string `json:"cve_num" valid:"Required"` + Date string `json:"date" valid:"Required"` +} + +func (c CmdToGenerate) GetCveNum() []string { + var data []string + for k := range c.CveNum { + data = append(data, k) + } + + return data +} diff --git a/cve-vulner-manager/cve-ddd/controller/cve.go b/cve-vulner-manager/cve-ddd/controller/cve.go index c3e666864562139832c56c9ea4da5f4a09fbcecd..19b6843c8f5be34129eff5b006f9a1ddb698cfe1 100644 --- a/cve-vulner-manager/cve-ddd/controller/cve.go +++ b/cve-vulner-manager/cve-ddd/controller/cve.go @@ -94,7 +94,7 @@ func (c *CveController) Generate() { return } - uploadDir, err1 := c.BulletinService.GenerateBulletins(request.CveNum, request.Date) + uploadDir, err1 := c.BulletinService.GenerateBulletins(request) if err1 != nil { c.BulletinLog.Errorf("generate security bulletins failed: %s", err1.Error()) } else { diff --git a/cve-vulner-manager/cve-ddd/controller/cve_request.go b/cve-vulner-manager/cve-ddd/controller/cve_request.go index 1bf8247c478814285a4f4e5e4f4598319d859b86..786c03acbd70a5155d7119e468b05d1a04396198 100644 --- a/cve-vulner-manager/cve-ddd/controller/cve_request.go +++ b/cve-vulner-manager/cve-ddd/controller/cve_request.go @@ -4,7 +4,4 @@ import "cvevulner/cve-ddd/app" type CollectRequest = app.CmdToCollectData -type GenerateRequest struct { - CveNum []string `json:"cve_num" valid:"Required"` - Date string `json:"date" valid:"Required"` -} +type GenerateRequest = app.CmdToGenerate diff --git a/cve-vulner-manager/cve-ddd/infrastructure/latestrpmimpl/impl.go b/cve-vulner-manager/cve-ddd/infrastructure/latestrpmimpl/impl.go index 9df44c99cd6cc2483e05ca25316d4602d8ee89b5..9d4fb358a9531155b33dafcc84948559e6cbe275 100644 --- a/cve-vulner-manager/cve-ddd/infrastructure/latestrpmimpl/impl.go +++ b/cve-vulner-manager/cve-ddd/infrastructure/latestrpmimpl/impl.go @@ -81,7 +81,11 @@ func (l *latestRpm) parseFile(content []byte) map[string]time.Time { break } - if err1 != nil || len(line) < lineLength { + if err1 != nil { + logrus.Errorf("new-cold-patch-cve-collect parse line error:%s", err1.Error()) + } + + if len(line) < lineLength { continue } diff --git a/cve-vulner-manager/models/cve.go b/cve-vulner-manager/models/cve.go index 7ec934a16f3e281aa7a52dfbba51e62c75abf424..14400da0c0ca255fdcc357b0dd9063a81f4605fc 100644 --- a/cve-vulner-manager/models/cve.go +++ b/cve-vulner-manager/models/cve.go @@ -1099,23 +1099,9 @@ is_export in (0,3) and pack_name in ('%s') and organizate_id = 1) and status < 4 } func GetUnffectIssueNumber(startTime string, cves []string) (issueTemp []IssueTemplate, err error) { - var sql string - if len(cves) == 0 { - sql = `SELECT * FROM cve_issue_template WHERE STATUS in (1,2,3,5) AND issue_status in (1,2,3,6) AND cve_id IN ( + sql := `SELECT * FROM cve_issue_template WHERE STATUS in (1,2,3,5) AND issue_status in (1,2,3,6) AND cve_id IN ( SELECT DISTINCT cve_id FROM cve_vuln_center WHERE cve_status = 2 AND is_export IN (0,3) and organizate_id = 1) AND create_time >= '%s'` - } else { - var s string - for _, v := range cves { - s += "'" + v + "'," - } - if len(s) > 1 { - s = s[:len(s)-1] - } - sql = `SELECT * FROM cve_issue_template WHERE STATUS <= 3 AND issue_status in (1,2,3,6) AND cve_id IN ( -SELECT DISTINCT cve_id FROM cve_vuln_center WHERE cve_status = 2 AND -is_export IN (0,3) and organizate_id = 1) AND create_time >= '%s' ` + ` AND cve_num in (` + s + `)` - } sql = fmt.Sprintf(sql, startTime) o := orm.NewOrm() diff --git a/cve-vulner-manager/models/modeldb.go b/cve-vulner-manager/models/modeldb.go index 63e0f6a1a21e7ec7daba2ce7e52b4757f0efafb0..b92d8690711d08c52f52c5d0e97c162cdccadd6d 100644 --- a/cve-vulner-manager/models/modeldb.go +++ b/cve-vulner-manager/models/modeldb.go @@ -209,6 +209,7 @@ type IssueTemplate struct { PlanStarted string `orm:"size(64);column(plan_started_at);null" description:"开始日期"` Deadline string `orm:"size(64);column(deadline);null" description:"截止日期"` IsIgnore int8 `orm:"default(0);column(is_ignore)" description:"majun数据统计时是否忽略, 1-忽略,0-不忽略"` + RejectReason string `orm:"type(text);column(reject_reason)" description:"拒绝原因"` CreateTime time.Time `orm:"auto_now_add;type(datetime);column(create_time)"` UpdateTime time.Time `orm:"auto_now;type(datetime);column(update_time)"` DeleteTime time.Time `orm:"auto_now;type(datetime);column(delete_time)"` diff --git a/cve-vulner-manager/task/cve.go b/cve-vulner-manager/task/cve.go index cd6696056add230b59941368fd2d8d574e2b63e7..a9f38c4120d06f81f1a8cef81d850dc313596825 100644 --- a/cve-vulner-manager/task/cve.go +++ b/cve-vulner-manager/task/cve.go @@ -84,9 +84,16 @@ func ParamsCveOriginData() error { return errx } -func ReleaseUnaffectedCve() error { - startTime := common.TimeStrSub(common.GetCurDate(), -90) +func ReleaseUnaffectedCveOneMonth() error { + startTime := common.TimeStrSub(common.GetCurDate(), -30) + return ReleaseUnaffectedCve(startTime) +} + +func ReleaseUnaffectedCveAll() error { + return ReleaseUnaffectedCve("2020-01-01") +} +func ReleaseUnaffectedCve(startTime string) error { accessToken := os.Getenv("GITEE_TOKEN") if len(accessToken) == 0 { return fmt.Errorf("triggerUnaffectedCve, issue token acquisition failed") diff --git a/cve-vulner-manager/task/inittask.go b/cve-vulner-manager/task/inittask.go index 74d0d8125a1419a194013a713d7ffaf3b6b7d6e7..f4abb7dd082ed5505e13d17df03064676c0715d4 100644 --- a/cve-vulner-manager/task/inittask.go +++ b/cve-vulner-manager/task/inittask.go @@ -172,7 +172,11 @@ func SyncIssueDateFromMaJunTask(schema string) { } func ReleaseUnaffetcdCveTask(spec string) { - toolbox.AddTask("ReleaseUnaffetcdCveTask", toolbox.NewTask("ReleaseUnaffetcdCveTask", spec, ReleaseUnaffectedCve)) + toolbox.AddTask("ReleaseUnaffetcdCveTask", toolbox.NewTask("ReleaseUnaffetcdCveTask", spec, ReleaseUnaffectedCveOneMonth)) +} + +func ReleaseUnaffetcdCveTaskAll(spec string) { + toolbox.AddTask("ReleaseUnaffetcdCveTaskAll", toolbox.NewTask("ReleaseUnaffetcdCveTaskAll", spec, ReleaseUnaffectedCveAll)) } // start task @@ -333,5 +337,10 @@ func InitTask() bool { ReleaseUnaffetcdCveTask(BConfig.String("crontab::releaseUnaffectedCve")) } + releaseUnaffectedCveAllFlag, sErr := BConfig.Int("crontab::releaseUnaffectedCveflagAll") + if releaseUnaffectedCveAllFlag == 1 && sErr == nil { + ReleaseUnaffetcdCveTaskAll(BConfig.String("crontab::releaseUnaffectedCveAll")) + } + return true } diff --git a/cve-vulner-manager/taskhandler/check.go b/cve-vulner-manager/taskhandler/check.go index 2a1c9ee70b597942139ae597b840a99ad7cfee21..b258bd712208704a6cd4bdb2fcf2eb6892c2251f 100644 --- a/cve-vulner-manager/taskhandler/check.go +++ b/cve-vulner-manager/taskhandler/check.go @@ -23,7 +23,7 @@ var tb = `| 状态 | 分析项目 | 内容 | |%v|%v|%v| ` -func CheckIssueAnalysisComplete(i *models.IssueTemplate, organizationID int8) (msg, tbStr string, ok bool) { +func CheckIssueAnalysisComplete(i *models.IssueTemplate) (msg, tbStr string, ok bool) { if i == nil { logs.Error("issue template is nil") return msg, "", false @@ -35,13 +35,8 @@ func CheckIssueAnalysisComplete(i *models.IssueTemplate, organizationID int8) (m } affectBranchsxList := make([]string, 0) - owner, accessToken := common.GetOwnerAndToken("", organizationID) - if organizationID == 1 || organizationID == 2 { - affectBranchsxList, _ = GetBranchesInfo(accessToken, owner, i.Repo, organizationID) - } else if organizationID == 3 || organizationID == 4 { - affectBranchsxList = CreateBrandAndTags(accessToken, owner, i.Repo, organizationID) - } - + owner, accessToken := common.GetOwnerAndToken("", util.Openeuler) + affectBranchsxList, _ = GetBranchesInfo(accessToken, owner, i.Repo, util.Openeuler) if len(affectBranchsxList) == 0 { msg = "获取仓库分支信息失败" return diff --git a/cve-vulner-manager/util/parsepayload.go b/cve-vulner-manager/util/parsepayload.go index 655c6d8efdd3196bc96c33217a6f1423128dedac..995c12c8a60542cc23817e729d477a6edd810613 100644 --- a/cve-vulner-manager/util/parsepayload.go +++ b/cve-vulner-manager/util/parsepayload.go @@ -1,6 +1,7 @@ package util import ( + "errors" "fmt" "regexp" "sort" @@ -442,7 +443,7 @@ func ParseCommentWithAllLabel(content string) map[string]string { } // ExtractCommentAnalysisAllValue Extract all value by issue comment -func ExtractCommentAnalysisAllValue(content string, organizationID int8) map[string]string { +func ExtractCommentAnalysisAllValue(content string, organizationID int8) (map[string]string, error) { res := make(map[string]string, 0) ca := GenerateCommentAnalysis(content, organizationID) if len(ca) > 0 { @@ -457,7 +458,10 @@ func ExtractCommentAnalysisAllValue(content string, organizationID int8) map[str } value, ext = ExtractCommentValue(ca, KwOpenEulerScore) if ext { - score, vector := ExtractCommentOpenEulerScore(value) + score, vector, err := ExtractCommentOpenEulerScore(value) + if err != nil { + return nil, err + } if score != "" { res["openeuler_score"] = score } @@ -479,7 +483,7 @@ func ExtractCommentAnalysisAllValue(content string, organizationID int8) map[str } } } - return res + return res, nil } // ExtractCommentEffectVersion Extract the affected version from the issue comment @@ -622,13 +626,17 @@ func ExtractCommentValue(ca CaSlice, keyWord string) (string, bool) { } // ExtractCommentOpenEulerScore Extract openEuler score from issue comment -func ExtractCommentOpenEulerScore(str string) (score, vector string) { +func ExtractCommentOpenEulerScore(str string) (score, vector string, err error) { + // AT,VC are specific to CVSS4 + if strings.Contains(str, "AT") && strings.Contains(str, "VC") { + err = errors.New("目前不支持CVSS4.0,请按照cvss3.x的评分格式填写") + return + } + str = TrimString(str) score = ExtractDigital(str) vector = ExtractVector(str, CvsScoreV3) - if vector == "" { - vector = ExtractVector(str, CvsScoreV2) - } + return }