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/controllers/hook.go b/cve-vulner-manager/controllers/hook.go index ab5df36df40309d18225dd17521ab53c547e603e..88eebcca434a523566920aae59434a0f9e3bdee5 100644 --- a/cve-vulner-manager/controllers/hook.go +++ b/cve-vulner-manager/controllers/hook.go @@ -1,14 +1,11 @@ package controllers import ( - "bytes" "encoding/json" "errors" "fmt" - "io/ioutil" "net/http" "os" - "regexp" "strconv" "strings" "sync" @@ -92,6 +89,10 @@ const ( CommentRepeatIssue = `%v 请检查当前: %v,是否重复创建, issue编号: %v, 重复创建的issue,将不会被再次识别.` webhookCommentLogTag = "webhook-comment" + + cmdCheckIssue = "/check-issue" + reasonCommand = "/reason" + reasonX = "xxxxxx" ) var comLock sync.Mutex @@ -360,68 +361,6 @@ func getMaintainer(path, prSender, assignee string) string { return maintainerVaule } -func otherCloseIssueProc(issueHook *models.IssuePayload, issueTmp *models.IssueTemplate, - token, owner, fixed, unFix, path string, cveCenter *models.VulnCenter) { - unFixList := taskhandler.CheckAffectVerComplete(issueTmp.AffectedVersion, issueTmp.Repo, - issueTmp.OwnedVersion, cveCenter.OrganizationID) - if len(unFixList) > 0 { - //send comment to issue - issueTmp.IssueStatus = 1 - issueTmp.IssueLabel = unFix - issueTmp.StatusName = "open" - _, issueErr := taskhandler.UpdateIssueToGit(token, owner, issueTmp.Repo, - *cveCenter, *issueTmp) - if issueErr == nil { - na := "\n**请确认分支信息是否填写完整,否则将无法关闭当前issue.**" - cc := fmt.Sprintf(CommentCheckVersion, issueHook.Sender.UserName, strings.Join(unFixList, ",")) + na - taskhandler.AddCommentToIssue(cc, issueTmp.IssueNum, owner, issueTmp.Repo, token) - content := fmt.Sprintf("%v 仓库的CVE和安全问题的ISSUE,CVE编号: %v,", issueTmp.Repo, issueTmp.CveNum) - taskhandler.SendPrivateLetters(token, content, issueHook.Sender.UserName) - } - } else { - commonFunc := taskhandler.CheckOtherIssueClosedAnalysisComplete - if _, tb, ok := commonFunc(issueTmp, cveCenter); !ok { - //send comment to issue - issueTmp.IssueStatus = 1 - issueTmp.IssueLabel = unFix - issueTmp.StatusName = "open" - _, issueErr := taskhandler.UpdateIssueToGit(token, owner, path, - *cveCenter, *issueTmp) - if issueErr == nil { - na := "\n**请确认分析内容的准确性,待分析内容请填写完整,否则将无法关闭当前issue.**" - cc := fmt.Sprintf(ContentReview, "@"+issueHook.Sender.UserName) + tb + na - taskhandler.AddCommentToIssue(cc, issueTmp.IssueNum, owner, path, token) - } - } else { - issueTmp.IssueLabel = unFix - issueTmp.StatusName = "open" - issueTmp.Status = 1 - assignee := "@" + issueTmp.Assignee - issuePrFlag := VerifyIssueAsPr(issueTmp, *cveCenter, false, - assignee, issueHook.Sender.UserName) - if issuePrFlag { - //1. change issue status - issueTmp.IssueStatus = 2 - cveCenter.IsExport = 3 - issueTmp.StatusName = issueHook.Issue.StateName - issueTmp.Status = 3 - if isNormalCloseIssue(issueTmp.CveId, issueTmp.IssueStatus) { - issueTmp.IssueStatus = 2 - cveCenter.IsExport = 3 - issueTmp.IssueLabel = fixed - } else { - issueTmp.IssueStatus = 6 - cveCenter.IsExport = 2 - issueTmp.IssueLabel = unFix - } - } else { - issueTmp.IssueStatus = 1 - cveCenter.IsExport = 0 - } - } - } -} - func closeIssueProc(issueHook *models.IssuePayload, issueTmp *models.IssueTemplate, token, owner, fixed, unFix string, cveCenter *models.VulnCenter) { closePrBool := true @@ -443,7 +382,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 +473,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 +487,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 +502,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 { @@ -584,8 +517,6 @@ func handleIssueStateChange(issueHook *models.IssuePayload) error { } if cveCenter.OrganizationID == 1 { closeIssueProc(issueHook, &issueTmp, token, owner, fixed, unFix, &cveCenter) - } else { - otherCloseIssueProc(issueHook, &issueTmp, token, owner, fixed, unFix, path, &cveCenter) } case IssueRejectState: issueTmp.Status = 4 @@ -600,211 +531,30 @@ func handleIssueStateChange(issueHook *models.IssuePayload) error { return nil } -// 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 { - sn := models.SecurityNotice{CveId: issueTmp.CveId, CveNum: issueTmp.CveNum} - secErr := sn.Read("cve_id", "cve_num") - if secErr != nil { - logs.Error("no data has been found, issueTmp: ", issueTmp) - return true - } - affectBranchsxList := make([]string, 0) - affectedBranchs := "" - path := cveCenter.PackName - if cveCenter.OrganizationID == 3 { - if strings.EqualFold(path, "mindarmour") || strings.EqualFold(path, "mindinsight") { - return true - } +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 "" } - affectProductList := make([]string, 0) - tmpAffectBranchsxList := make([]string, 0) - owner, token := common.GetOwnerAndToken(cveCenter.CveNum, cveCenter.OrganizationID) - if cveCenter.OrganizationID == 4 { - affectedBranchs = beego.AppConfig.String("openlookeng::openlookeng_version") - affectBranchsxList = taskhandler.CreateBrandAndTags(token, owner, path, cveCenter.OrganizationID) - } else if cveCenter.OrganizationID == 3 { - affectedBranchs = beego.AppConfig.String("mindspore::mindspore_version") - affectBranchsxList = taskhandler.CreateBrandAndTags(token, owner, path, cveCenter.OrganizationID) - } else if cveCenter.OrganizationID == 2 { - affectedBranchs = strings.ReplaceAll(sn.AffectProduct, "/", ",") - if len(path) < 2 { - path = beego.AppConfig.String("opengauss::gauss_issue_path") - } - affectBranchsxList, _ = taskhandler.GetBranchesInfo(token, owner, path, cveCenter.OrganizationID) - } else { - affectedBranchs = beego.AppConfig.String("cve::affected_branchs") - path = issueTmp.Repo - if affectedBranchs != "" && len(affectedBranchs) > 0 { - affectBranchsxList = strings.Split(affectedBranchs, ",") - } - } - - if sn.WillFixProduct != "" && len(sn.WillFixProduct) > 1 { - tmpAffectBranchsxList = strings.Split(sn.WillFixProduct, "/") - } - affectProductList = common.RemoveDupString(tmpAffectBranchsxList) - if len(affectProductList) > 0 { - issueTmp.SaAuditFlag = 0 - branchMaps := make(map[string]bool) - for _, brands := range affectProductList { - brands = common.BranchVersionRep(brands) - if len(affectBranchsxList) > 0 { - keyBandList := []string{} - for _, affectBranch := range affectBranchsxList { - affectBranch = common.BranchVersionRep(affectBranch) - if affectBranch == brands { - // Query the repo that needs to submit an issue - if cveCenter.OrganizationID == 3 { - mdbt := models.MindSporeBrandTags{PackageName: path, Tags: affectBranch} - mtErr := models.QueryMindSporeBrandTags(&mdbt, "PackageName", "Tags") - if mtErr == nil { - keyBandList = append(keyBandList, mdbt.Brand) - } - } else if cveCenter.OrganizationID == 4 { - keyBandList = append(keyBandList, "master") - } else { - keyBandList = append(keyBandList, affectBranch) - } - } - } - if len(keyBandList) > 0 { - prList := getRepoIssueAllPR(keyBandList, token, owner, path, *issueTmp) - for _, brh := range keyBandList { - if len(prList) == 0 { - branchMaps[brh] = false - } else { - for _, prl := range prList { - if brh == prl.Branch { - branchMaps[brh] = prl.BrFlag - break - } - } - } - if _, ok := branchMaps[brh]; !ok { - branchMaps[brh] = false - } - } - } - } - } - if len(branchMaps) == 0 { - logs.Info("sn.WillFixProduct: ", sn.WillFixProduct, ",There is no branch to follow to associate with pr") - return true - } - brandStr := "" - //logs.Info("branchMaps===> ", branchMaps) - for brand, bv := range branchMaps { - if !bv { - logs.Error("brand: ", brand, ", pr is not related to issue, issueTmp: ", issueTmp) - brandStr = brandStr + brand + "/" - } - } - if brandStr != "" && len(brandStr) > 1 { - _, issueErr := taskhandler.UpdateIssueToGit(token, owner, path, - cveCenter, *issueTmp) - if issueErr == nil { - commentBody := assignee + "\n" + - "关闭issue前,需要将受影响的分支在合并pr时关联上当前issue编号: #" + issueTmp.IssueNum + "\n" + - "受影响分支: " + brandStr[:len(brandStr)-1] + "\n" + - "具体操作参考: " + "https://gitee.com/help/articles/4142" + "\n" - taskhandler.AddCommentToIssue(commentBody, issueTmp.IssueNum, owner, path, token) - content := issueTmp.Repo + " 仓库的CVE和安全问题的ISSUE,CVE编号: " + issueTmp.CveNum + - ",关闭issue前,需要将受影响的分支在合并pr时关联上当前issue编号: #" + issueTmp.IssueNum + - ",受影响分支: " + brandStr[:len(brandStr)-1] + - ",具体操作参考: " + "https://gitee.com/help/articles/4142." - taskhandler.SendPrivateLetters(token, content, prSend) - } - return false - } - } else { - if effectFlag && issueTmp.SaAuditFlag == 0 { - unaffectedBranchList := []string{} - if issueTmp.AffectedVersion != "" && len(issueTmp.AffectedVersion) > 1 { - unaffectedBranchList = paraAffectBrands(issueTmp.AffectedVersion) - } - branchStrs := "" - if len(unaffectedBranchList) > 0 { - for _, brands := range unaffectedBranchList { - if len(affectBranchsxList) > 0 { - for _, affectBranch := range affectBranchsxList { - if affectBranch == brands { - branchStrs = branchStrs + brands + "/" - } - } - } - } - } - if branchStrs != "" && len(branchStrs) > 1 { - branchStrs = branchStrs[:len(branchStrs)-1] - list, err := models.GetSecurityReviewerList() - if err != nil { - logs.Error("err: ", err, "\n, issueTmp: ", issueTmp) - issueTmp.SaAuditFlag = 1 - return true - } - if len(list) == 0 { - logs.Error("list is null, issueTemp: ", issueTmp) - issueTmp.SaAuditFlag = 1 - return true - } - anName := []string{} - content := fmt.Sprintf(CommentPrivateReview, issueTmp.Repo, issueTmp.CveNum) - for _, v := range list { - anName = append(anName, "@"+v.NameSpace+" ") - taskhandler.SendPrivateLetters(token, content, v.NameSpace) - } - if len(anName) > 0 { - _, issueErr := taskhandler.UpdateIssueToGit(token, owner, issueTmp.Repo, - cveCenter, *issueTmp) - if issueErr == nil { - assignee := strings.Join(anName, ",") - commentBody := assignee + "\n" + - "关闭issue前,请确认分支: " + branchStrs + ": 受影响/不受影响, 如受影响,请联系maintainer: @" + - issueTmp.Assignee + ", **进行处理后, 或者按照模板格式在评论区填写内容, 最后记得在评论区回复: /approve ,才能正常关闭issue.**" - taskhandler.AddCommentToIssue(commentBody, issueTmp.IssueNum, owner, issueTmp.Repo, token) - } - return false - } else { - issueTmp.SaAuditFlag = 1 - } - } else { - issueTmp.SaAuditFlag = 1 - } + + var reason string + for i := len(comments) - 1; i >= 0; i-- { + body := comments[i].Body + index := strings.Index(body, reasonCommand) + if index == -1 { + continue } - } - return true -} -func paraAffectBrands(affectedVersion string) (unaffectedBranchList []string) { - brandsGroup := strings.Split(affectedVersion, ",") - if len(brandsGroup) > 0 { - for _, brand := range brandsGroup { - if brand == "" || len(brand) < 2 { - continue - } - brand = common.BranchVersionRep(brand) - brandList := strings.Split(brand, ":") - if len(brandList) > 1 { - prams := strings.Replace(brandList[1], " ", "", -1) - if prams != "受影响" { - unaffectedBranchList = append(unaffectedBranchList, brandList[0]) - } - } else { - brandList = strings.Split(brand, ":") - if len(brandList) > 1 { - prams := strings.Replace(brandList[1], " ", "", -1) - if prams != "受影响" { - unaffectedBranchList = append(unaffectedBranchList, brandList[0]) - } - } - } - if len(brandList) == 1 { - unaffectedBranchList = append(unaffectedBranchList, brandList[0]) - } + reason = strings.TrimSpace(body[index+len(reasonCommand):]) + if reason == reasonX { + continue } + + break } - return unaffectedBranchList + + return util.TrimStringNR(reason) } func paraAffectBrandBool(affectedVersion string) bool { @@ -862,145 +612,6 @@ func paraAnalysisBrandBool(analysisVersion string) bool { return len(unaffectedBranchList) > 0 } -func getPRRelatedBrandsAllIssue(token, owner, repo string, num int, issueNum string) bool { - issueFlag := false - url := fmt.Sprintf(`https://gitee.com/api/v5/repos/%s/%s/pulls/%v/issues`, owner, repo, num) - pageSize := 20 - pageCount := 1 - req, err := http.NewRequest(http.MethodGet, url, nil) - if err != nil { - logs.Error(err) - return false - } - q := req.URL.Query() - q.Add("access_token", token) - q.Add("per_page", strconv.Itoa(pageSize)) - for { - q.Del("page") - q.Add("page", strconv.Itoa(pageCount)) - req.URL.RawQuery = q.Encode() - resp, err := http.DefaultClient.Do(req) - if err != nil { - logs.Error(err) - break - } - if resp.StatusCode == http.StatusOK { - var il []models.HookIssue - read, err := ioutil.ReadAll(resp.Body) - resp.Body.Close() - if err != nil { - logs.Error(err) - break - } - err = json.Unmarshal(read, &il) - if err != nil { - logs.Error(err) - break - } - for _, v := range il { - d, ok := isLegallyIssue(v) - if ok { - if issueNum == d.Number { - issueFlag = true - break - } - } - } - if len(il) < pageSize { - break - } - pageCount++ - } else { - resp.Body.Close() - break - } - } - return issueFlag -} - -// Verify that the current issue meets the requirements -func isLegallyIssue(i models.HookIssue) (pri models.PullRequestIssue, ok bool) { - if i.IssueType != CIssueType || (i.State != "closed" && i.State != "已完成") { - return - } - tt := strings.Trim(i.Title, " ") - regCveNum := regexp.MustCompile(`(?mi)CVE-[\d]{1,}-([\d]{1,})$`) - sm := util.RegexpCveNumber.FindAllStringSubmatch(i.Body, -1) - if len(sm) > 0 && len(sm[0]) > 0 { - val := sm[0][1] - tt = util.GetCveNumber(util.TrimString(val)) - if tt != "" && regCveNum.Match([]byte(tt)) { - ok = true - } - } - if ok { - pri.Id = i.Id - pri.Number = i.Number - pri.CveNumber = tt - pri.Repo = i.Repository.Path - } - return -} - -// Get the pr associated with a single repo -func getRepoIssueAllPR(affectBranch []string, token, owner, repo string, isTemp models.IssueTemplate) (prList []models.PullRequestIssue) { - url := fmt.Sprintf("https://gitee.com/api/v5/repos/%v/issues/%v/pull_requests", owner, isTemp.IssueNum) - req, err := http.NewRequest(http.MethodGet, url, nil) - if err != nil { - logs.Error("NewRequest, url: ", url, ",err: ", err) - return - } - q := req.URL.Query() - q.Add("access_token", token) - q.Add("repo", repo) - req.URL.RawQuery = q.Encode() - resp, err := http.DefaultClient.Do(req) - if err != nil { - logs.Error("DefaultClient, url: ", url, ",err: ", err) - return - } - if resp.StatusCode == http.StatusOK { - issuePr := make([]map[string]interface{}, 0) - read, err := ioutil.ReadAll(resp.Body) - if err != nil { - logs.Error("ReadAll, url: ", url, ",err: ", err) - return - } - resp.Body.Close() - //logs.Info("getRepoIssueAllPR, body ===> ", read) - err = json.Unmarshal(read, &issuePr) - if err != nil { - logs.Error("Unmarshal, url: ", url, ",err: ", err) - return - } - logs.Info("issuePr: ", issuePr) - for _, brh := range affectBranch { - pr := models.PullRequestIssue{} - pr.Branch = brh - pr.BrFlag = false - for _, v := range issuePr { - if _, ok := v["id"]; !ok { - continue - } - if v["state"].(string) == "merged" && v["mergeable"].(bool) { - if v["base"].(map[string]interface{})["label"].(string) == brh { - pr.Id = int64(v["id"].(float64)) - pr.Number = isTemp.IssueNum - pr.CveNumber = isTemp.CveNum - pr.Repo = repo - pr.BrFlag = true - break - } - } - } - prList = append(prList, pr) - } - } else { - resp.Body.Close() - } - return -} - func isNormalCloseIssue(cveID int64, issueState int8) bool { if issueState == 1 { return false @@ -1246,88 +857,9 @@ func openEulerScoreReview(issueTmp *models.IssueTemplate, cuAccount, owner, toke return approveFlag } -func otherMaintainerApprove( - issueTmp *models.IssueTemplate, cuAccount, owner, token, fixed, unfixed, path string, cveCenter models.VulnCenter, -) { - unFixList := taskhandler.CheckAffectVerComplete(issueTmp.AffectedVersion, issueTmp.Repo, - issueTmp.OwnedVersion, cveCenter.OrganizationID) - if len(unFixList) > 0 { - na := "\n**请确认分支信息是否填写完整,否则将无法关闭当前issue.**" - cc := fmt.Sprintf(CommentCheckVersion, cuAccount, strings.Join(unFixList, ",")) + na - taskhandler.AddCommentToIssue(cc, issueTmp.IssueNum, owner, path, token) - return - } - - var ( - check = taskhandler.CheckOtherIssueClosedAnalysisComplete - review func(string2 string) bool - ) - switch cveCenter.OrganizationID { - case util.OpenGauss: - review = isGaussReviewer - case util.MindSpore: - review = isMindSporeReviewer - case util.OpenLookeng: - review = isLooKengReviewer - } - - if check == nil || review == nil { - return - } - - if _, tb, ok := check(issueTmp, &cveCenter); !ok { - //send comment to issue - na := "\n**请确认分析内容的准确性,待分析内容请填写完整,否则将无法关闭当前issue.**" - cc := fmt.Sprintf(AnalysisComplete, cuAccount) + tb + na - taskhandler.AddCommentToIssue(cc, issueTmp.IssueNum, owner, path, token) - return - } else { - if !review(cuAccount) && issueTmp.Assignee != cuAccount { - logs.Error("Invalid user review, cuAccount: ", cuAccount) - taskhandler.AddCommentToIssue(fmt.Sprintf(`@%v maintainer具有通过(/approve或者/close)关闭issue, 否则请通过issue页面按钮关闭issue!`, - cuAccount), issueTmp.IssueNum, owner, path, token) - return - } - - issueTmp.IssueLabel = unfixed - issueTmp.StatusName = "open" - issueTmp.Status = 1 - assignee := "@" + issueTmp.Assignee - - issuePrFlag := VerifyIssueAsPr(issueTmp, cveCenter, false, assignee, cuAccount) - if issuePrFlag { - issueTmp.IssueLabel = fixed - issueTmp.StatusName = "closed" - taskhandler.AddCommentToIssue(fmt.Sprintf(`@%v 你已审核模板内容, cve-manager 将关闭issue!`, - cuAccount), issueTmp.IssueNum, owner, path, token) - _, issueErr := taskhandler.UpdateIssueToGit(token, owner, issueTmp.Repo, - cveCenter, *issueTmp) - if issueErr == nil { - logs.Info("Initiate an issue to close,issuetmp: ", issueTmp) - } else { - logs.Error("Issue closing operation failed, issuetmp: ", issueTmp, ",issueErr: ", issueErr) - return - } - //issueTmp.SaAuditFlag = 1 - issueTmp.Status = 3 - if isNormalCloseIssue(issueTmp.CveId, issueTmp.IssueStatus) { - issueTmp.IssueStatus = 2 - cveCenter.IsExport = 3 - } else { - issueTmp.IssueStatus = 6 - cveCenter.IsExport = 2 - } - updateBool := updateTempAndCenter(*issueTmp, cveCenter, token, owner) - if !updateBool { - return - } - } - } -} - 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 +894,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 @@ -1509,11 +1041,7 @@ func handleIssueComment(payload models.CommentPayload) { logs.Error("The issue has been closed and cannot be operated again,issuetmp: ", issueTmp) return } - if vc.OrganizationID != 1 { - comLock.Lock() - otherMaintainerApprove(&issueTmp, cuAccount, owner, accessToken, fixed, unfixed, path, vc) - comLock.Unlock() - } else { + if vc.OrganizationID == 1 { approveFlag := true if issueTmp.OpenEulerScore != issueTmp.NVDScore && issueTmp.NVDScore > 0 && issueTmp.OpAuditFlag != 1 && issueTmp.OpenEulerScore > 0 { @@ -1573,6 +1101,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" || @@ -1659,21 +1192,6 @@ func isReviewer(path string) bool { return sr.Read("name_space", "organizate_id") } -func isGaussReviewer(path string) bool { - sr := models.Reviewer{NameSpace: path, OrganizationID: 2} - return sr.Read("name_space", "organizate_id") -} - -func isMindSporeReviewer(path string) bool { - sr := models.Reviewer{NameSpace: path, OrganizationID: 3} - return sr.Read("name_space", "organizate_id") -} - -func isLooKengReviewer(path string) bool { - sr := models.Reviewer{NameSpace: path, OrganizationID: 4} - return sr.Read("name_space", "organizate_id") -} - func analysisComment(owner, accessToken, path string, cuAccount string, cBody string, payload *models.CommentPayload, issueTmp models.IssueTemplate, v models.VulnCenter) { if issueTmp.Status == 3 { @@ -1684,7 +1202,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 +1296,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 != "" { + assignee = cuAccount + } else { + 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 } - assignee := "" - if cuAccount != "" && len(cuAccount) > 1 { - assignee = cuAccount - } else { - assignee = issueTmp.Assignee + } + + 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 } - msg = fmt.Sprintf(CommentAnalysisCplTpl, assignee, msg) - taskhandler.AddCommentToIssue(msg, issueTmp.IssueNum, owner, path, accessToken) - } 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 - - 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 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) } } @@ -2048,54 +1551,6 @@ func saveVectorData(vct string, cveID int64) error { return nil } -func handleCommentPackage(packageStr string, cveID int64) error { - packageStr = util.TrimString(packageStr) - err := models.UpdatePackageByCveId(packageStr, cveID) - if err != nil { - return err - } - return nil -} - -// CloseIssue close gitee issue -func CloseIssue(token, repo, issueNum, owner string) bool { - url := fmt.Sprintf("https://gitee.com/api/v5/repos/%s/issues/%s", owner, issueNum) - param := struct { - AccessToken string `json:"access_token"` - Repo string `json:"repo"` - State string `json:"state"` - }{token, repo, "closed"} - pj, err := json.Marshal(¶m) - if err != nil { - logs.Error("json.Marshal, err:", err, ",issueNum: ", issueNum) - return false - } - return UpdateGiteIssue(url, pj) -} - -// UpdateGiteIssue update gitee issue -func UpdateGiteIssue(url string, param []byte) bool { - read := bytes.NewReader(param) - req, err := http.NewRequest(http.MethodPatch, url, read) - if err != nil { - logs.Error("NewRequest, err:", err) - return false - } - defer req.Body.Close() - req.Header.Set("Content-Type", "application/json;charset=UTF-8") - client := http.Client{} - resp, err := client.Do(req) - if err != nil { - logs.Error("client.Do, err:", err) - return false - } - defer resp.Body.Close() - if resp.StatusCode == 200 { - return true - } - return false -} - func AddGitIssue(issueHook *models.IssuePayload, desc, product string) error { issueTitle := util.TrimString(issueHook.Title) issueType := util.TrimString(issueHook.Issue.TypeName) 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/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/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 }