diff --git a/cve-vulner-manager/controllers/hook.go b/cve-vulner-manager/controllers/hook.go index 2b7d1ca98cd8b1bab99518058784e7405040b786..c5f131fabdca35611b365e9faadd729a8d89503c 100644 --- a/cve-vulner-manager/controllers/hook.go +++ b/cve-vulner-manager/controllers/hook.go @@ -175,7 +175,7 @@ func (c *HookEventControllers) handlePushTag() { } func (c *HookEventControllers) handleIssue() { - logs.Info(string(c.Ctx.Input.RequestBody)) + logs.Error("issue event payload: ", string(c.Ctx.Input.RequestBody)) issueHook := models.IssuePayload{} err := json.Unmarshal(c.Ctx.Input.RequestBody, &issueHook) if err != nil { @@ -1864,10 +1864,22 @@ func analysisComment(owner, accessToken, path string, cuAccount string, cBody st //2. Are the cvsScore and openEuler score equal .If not equal, notify the auditor to review . var na string - if util.CalculateCVSSV3BaseScore(issueTmp.OpenEulerVector) != issueTmp.OpenEulerScore { - cc := fmt.Sprintf("@%v CVSS评分和矢量值不一致,请修改至矢量值和CVSS评分一致!", issueTmp.Assignee) - taskhandler.AddCommentToIssue(cc, issueTmp.IssueNum, owner, path, accessToken) - return + 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 && diff --git a/cve-vulner-manager/cve-ddd/adapter/hotpatch.go b/cve-vulner-manager/cve-ddd/adapter/hotpatch.go deleted file mode 100644 index 20b780591a6663895d64a47d41a5bf2922e50b5b..0000000000000000000000000000000000000000 --- a/cve-vulner-manager/cve-ddd/adapter/hotpatch.go +++ /dev/null @@ -1,165 +0,0 @@ -package adapter - -import ( - "encoding/json" - "errors" - "fmt" - "net/http" - "regexp" - "strings" - "time" - - "github.com/astaxie/beego" - "github.com/astaxie/beego/logs" - "github.com/opensourceways/server-common-lib/utils" - - "cvevulner/cve-ddd/app" - "cvevulner/cve-ddd/infrastructure/bulletinimpl" - "cvevulner/cve-ddd/infrastructure/obsimpl" - "cvevulner/cve-ddd/infrastructure/repositoryimpl" - "cvevulner/cve-ddd/infrastructure/updateinfoimpl" - "cvevulner/util" -) - -const hotPatchIssue = "https://gitee.com/api/v5/repos/openeuler/hotpatch_meta/issues?" + - "access_token=%s&state=closed&labels=%s&sort=created&direction=desc&page=%d&per_page=20&created_at=%s" - -var ( - RegexpCve = regexp.MustCompile(`(?s:(.*?))`) - RegexpRPM = regexp.MustCompile(`热补丁路径[::](?s:(.*?))热补丁信息[::]`) - RegexpMeta = regexp.MustCompile(`热补丁元数据[::](?s:(.*?))热补丁路径[::]`) - RegexpType = regexp.MustCompile(`问题类别[::](?s:(.*?))热补丁元数据[::]`) - RegexpInfo = regexp.MustCompile(`热补丁信息[::](?s:(.*?))$`) -) - -func NewHotPatchAdapter() *hotPatch { - return &hotPatch{ - service: app.NewHotPatchService( - repositoryimpl.NewRepositoryImpl(), - bulletinimpl.NewBulletinImpl(), - obsimpl.Instance(), - updateinfoimpl.NewUpdateInfoImpl(), - ), - } -} - -type hotPatch struct { - service app.HotPatchService -} - -type patchIssue = app.CmdToGenerateBulletins - -type Issue struct { - Number string `json:"number"` - Body string `json:"body"` -} - -func (h *hotPatch) Process() { - issues, err := h.getIssues() - if err != nil { - logs.Error("get hot patch issue error: %s", err.Error()) - - return - } - - var patches []patchIssue - for _, v := range issues { - pat, err := h.toPatchIssue(v.Body) - if err != nil { - logs.Error("issue number %s toPatchIssue error: %s", v.Number, err.Error()) - continue - } - pat.HotIssueNum = v.Number - - patches = append(patches, pat) - } - - if err := h.service.GenerateBulletins(patches); err != nil { - logs.Error("generate bulletins error %s", err.Error()) - } - -} - -func (h *hotPatch) getIssues() ([]Issue, error) { - var page = 1 - var issues []Issue - token := beego.AppConfig.String("gitee::git_token") - cli := utils.NewHttpClient(3) - // query the data of the last 15 days - filterCreatedTime := time.Now().AddDate(0, 0, -15).Format("20060102T1504015-") - - for { - url := fmt.Sprintf(hotPatchIssue, token, "hotpatch", page, filterCreatedTime) - req, err := http.NewRequest( - http.MethodGet, url, nil, - ) - if err != nil { - return nil, err - } - - res, _, err := cli.Download(req) - if err != nil { - return nil, err - } - - var t []Issue - if err := json.Unmarshal(res, &t); err != nil { - return nil, err - } - - if len(t) == 0 { - break - } - - issues = append(issues, t...) - - page++ - } - - return issues, nil -} - -func (h *hotPatch) toPatchIssue(body string) (v patchIssue, err error) { - t := RegexpType.FindAllStringSubmatch(body, -1) - if len(t) == 0 { - return v, errors.New("parse type failed") - } - v.Type = strings.TrimSpace(t[0][1]) - - meta := RegexpMeta.FindAllStringSubmatch(body, -1) - if len(meta) == 0 { - return v, errors.New("parse metadata failed") - } - split := strings.Split(meta[0][1], "/") - v.Branch = split[len(split)-4] - v.Component = split[len(split)-3] - - p := RegexpRPM.FindAllStringSubmatch(body, -1) - if len(p) == 0 { - return v, errors.New("parse rpm failed") - } - v.PatchUrl = strings.Split(strings.TrimSpace(p[0][1]), "\n") - - info := RegexpInfo.FindAllStringSubmatch(body, -1) - if len(info) == 0 { - return v, errors.New("parse info failed") - } - var bys []byte - for _, s := range strings.Split(strings.TrimSpace(info[0][1]), "\n") { - bys, err = util.HTTPGetCom(strings.TrimSpace(s)) - if err != nil { - continue - } - - if cve := RegexpCve.FindAllStringSubmatch(string(bys), -1); len(cve) > 0 { - v.CveNum = strings.Split(cve[0][1], ",") - break - } - } - - if len(v.CveNum) == 0 { - return v, errors.New("parse cve num failed") - } - - return -} diff --git a/cve-vulner-manager/cve-ddd/app/hotpatch.go b/cve-vulner-manager/cve-ddd/app/hotpatch.go deleted file mode 100644 index ec1815f9f95e14f3aa3ded6ea09755a3bfdc29a5..0000000000000000000000000000000000000000 --- a/cve-vulner-manager/cve-ddd/app/hotpatch.go +++ /dev/null @@ -1,205 +0,0 @@ -package app - -import ( - "fmt" - "strconv" - "strings" - "time" - - "github.com/astaxie/beego/logs" - - "cvevulner/cve-ddd/domain" - "cvevulner/cve-ddd/domain/bulletin" - "cvevulner/cve-ddd/domain/obs" - "cvevulner/cve-ddd/domain/repository" - "cvevulner/cve-ddd/domain/updateinfo" - "cvevulner/models" - "cvevulner/util" -) - -const ( - indexFileName = "index.txt" - updateFixedFileName = "update_fixed.txt" -) - -type HotPatchService interface { - GenerateBulletins([]CmdToGenerateBulletins) error -} - -func NewHotPatchService( - r repository.CveRepository, - b bulletin.Bulletin, - o obs.OBS, - u updateinfo.UpdateInfo, -) *hotPatchService { - return &hotPatchService{ - repository: r, - bulletin: b, - obs: o, - updateInfo: u, - } -} - -type hotPatchService struct { - repository repository.CveRepository - bulletin bulletin.Bulletin - obs obs.OBS - updateInfo updateinfo.UpdateInfo -} - -func (h *hotPatchService) GenerateBulletins(cmds []CmdToGenerateBulletins) error { - handleBranch := []string{ - "openEuler-20.03-LTS-SP4", - "openEuler-22.03-LTS-SP1", - "openEuler-22.03-LTS-SP3", - "openEuler-24.03-LTS", - } - - domain.InitMaintainVersion(handleBranch) - - var cvesForUpdateInfo domain.Cves - var uploadFileName []string - id, err := h.generateBulletinId() - if err != nil { - return err - } - - for _, cmd := range cmds { - if exist := h.repository.IssueNumExist(cmd.HotIssueNum); exist { - continue - } - - cves, err := h.repository.FindCves( - repository.Option{ - CveNum: cmd.CveNum, - Component: cmd.Component, - }) - if err != nil { - logs.Error("find cve %s, error %s", cmd.CveNum, err.Error()) - return err - } - if len(cves) == 0 { - logs.Error("find cve %s nil", cmd.CveNum) - continue - } - // all cves have the same hot issue number - for k := range cves { - cves[k].HotIssueNum = cmd.HotIssueNum - cves[k].AffectedVersion = []string{cmd.Branch} - cves[k].Component = cmd.Component - } - - bulletins := cves.GenerateBulletins() - for _, b := range bulletins { - b.PatchUrl = cmd.PatchUrl - - id++ - b.Identification = fmt.Sprintf("openEuler-HotPatchSA-%d-%d", util.Year(), id) - - xmlData, err := h.bulletin.GenerateHotPatch(&b) - if err != nil { - logs.Error("component: %s, to xml error: %s", b.Component, err.Error()) - - continue - } - - fileName := fmt.Sprintf("cvrf-%s.xml", b.Identification) - if err := h.obs.UploadToDynamicDir(fileName, xmlData); err != nil { - logs.Error("component: %s, upload to obs error: %s", b.Component, err.Error()) - - continue - } - - uploadFileName = append(uploadFileName, fileName) - - cvesForUpdateInfo = append(cvesForUpdateInfo, b.Cves...) - } - - if err := h.repository.SaveIssueNum(cmd.HotIssueNum); err != nil { - logs.Error("save issue num %s error %s", cmd.HotIssueNum, err.Error()) - } - } - - h.appendHotPatchToFiles(uploadFileName) - - return h.uploadUpdateInfo(cvesForUpdateInfo) -} - -func (h *hotPatchService) generateBulletinId() (int, error) { - maxID, err := h.repository.MaxBulletinID() - if err != nil { - return 0, err - } - - maxID = strings.TrimSpace(maxID) - if maxID == "" { - return 1000, nil - } - - thisYear := util.Year() - split := strings.Split(strings.Trim(maxID, ".xml"), "-") - if split[3] != strconv.Itoa(thisYear) { - return 1000, nil - } - - return strconv.Atoi(split[4]) -} - -func (h *hotPatchService) uploadUpdateInfo(cves domain.Cves) error { - if len(cves) == 0 { - return nil - } - - for version, v := range cves.GroupByVersion() { - bytes, err := h.updateInfo.Generate(v) - if err != nil { - logs.Error("generate updateinfo of %s error %s", version, err.Error()) - continue - } - - fileName := fmt.Sprintf("%s_updateinfo.xlsx", version) - if err := h.obs.UploadUpdateInfo(fileName, bytes); err != nil { - logs.Error("version: %s, upload to obs error: %s", version, err.Error()) - - continue - } - } - - return nil -} - -func (h *hotPatchService) appendHotPatchToFiles(files []string) { - if len(files) == 0 { - return - } - - var appendContent string - for _, v := range files { - appendContent += fmt.Sprintf("\n%d/%s", time.Now().Year(), v) - } - - h.updateFileByContent(updateFixedFileName, appendContent) - - var oldContent string - oldRecords := models.GetCvrfAllFile(models.SaFileRecordHotPatch) - for _, v := range oldRecords { - oldContent += fmt.Sprintf("\n%d/%s", time.Now().Year(), v.FileName) - } - - h.updateFileByContent(indexFileName, oldContent+appendContent) -} - -func (h *hotPatchService) updateFileByContent(file, newContent string) { - oldContent, err := h.obs.DownloadFromDynamicDir(file) - if err != nil { - logs.Error("download %s error: %s", file, err.Error()) - - return - } - - oldContent = append(oldContent, newContent...) - - if err = h.obs.UploadToDynamicDir(file, oldContent); err != nil { - logs.Error("upload %s error: %s", file, err.Error()) - } -} diff --git a/cve-vulner-manager/cve-ddd/app/hotpatch_dto.go b/cve-vulner-manager/cve-ddd/app/hotpatch_dto.go deleted file mode 100644 index 209c1d22628608a32b651705cb6475590de2131f..0000000000000000000000000000000000000000 --- a/cve-vulner-manager/cve-ddd/app/hotpatch_dto.go +++ /dev/null @@ -1,10 +0,0 @@ -package app - -type CmdToGenerateBulletins struct { - Type string - Branch string - Component string - CveNum []string - PatchUrl []string - HotIssueNum string -} diff --git a/cve-vulner-manager/cve-ddd/infrastructure/testresultimpl/impl.go b/cve-vulner-manager/cve-ddd/infrastructure/testresultimpl/impl.go index b8fc242d019e7e2c0f4164341ec7e37f2ffa188c..e40df8548ba4f03b536c48591078e65460638850 100644 --- a/cve-vulner-manager/cve-ddd/infrastructure/testresultimpl/impl.go +++ b/cve-vulner-manager/cve-ddd/infrastructure/testresultimpl/impl.go @@ -15,7 +15,7 @@ import ( ) const ( - testRepoBaseUrl = "http://121.36.84.172" + testRepoBaseUrl = "https://dailybuild.openeuler.openatom.cn" ) func NewTestResultImpl(log *logrus.Entry) *testResultImpl { diff --git a/cve-vulner-manager/models/issue.go b/cve-vulner-manager/models/issue.go index 802acff5ec4ab7802c697bb3e2f97598dea8c009..d023b42eecb1e8e5c12ce4b0464c5b0170638b7d 100644 --- a/cve-vulner-manager/models/issue.go +++ b/cve-vulner-manager/models/issue.go @@ -15,7 +15,7 @@ import ( var mutex sync.Mutex -//QueryIssueCveByNum query issue by cve num +// QueryIssueCveByNum query issue by cve num func QueryIssueCveByNum(cvenum, repoPath string, organizationID int8) (GiteOriginIssue, bool) { o := orm.NewOrm() var cve GiteOriginIssue @@ -31,7 +31,7 @@ func QueryIssueCveByNum(cvenum, repoPath string, organizationID int8) (GiteOrigi } } -//QueryIssue query issuewhitelist +// QueryIssue query issuewhitelist func QueryIssueWhitelist(status int8) ([]IssueRepoWhitelist, error) { o := orm.NewOrm() var irw []IssueRepoWhitelist @@ -60,7 +60,7 @@ func QueryIssueWhitelist(status int8) ([]IssueRepoWhitelist, error) { } } -//QueryIssue query center +// QueryIssue query center func QueryIssueByPackName(packName, days string, prcnum int) ([]VulnCenter, error) { o := orm.NewOrm() var vc []VulnCenter @@ -76,7 +76,7 @@ func QueryIssueByPackName(packName, days string, prcnum int) ([]VulnCenter, erro return vc, err } -//QueryIssue query center +// QueryIssue query center func QueryIssue(days string, prcnum int, list []string) ([]VulnCenter, error) { o := orm.NewOrm() var vc []VulnCenter @@ -118,7 +118,7 @@ func GetVulnCenterByCVEID(vc *VulnCenter, cveId int64, fields ...string) error { return err } -//QueryIssueSecurity 查找安全公告 +// QueryIssueSecurity 查找安全公告 func QueryIssueSecurity(cveId int64, cveNum string) (SecurityNotice, error) { o := orm.NewOrm() var sn SecurityNotice @@ -541,7 +541,7 @@ func UpdateIssueCommentId(issueNum, cveNum string, commentId int64) (id int64) { return } -//IssueExistByNumber Determine whether the issue exists +// IssueExistByNumber Determine whether the issue exists func IssueExistByNumber(number string, id int64) bool { if number == "" { return false @@ -588,7 +588,7 @@ func CreateIssueRecord(icr *IssueCreateRecord) (issueRecordId int64, err error) } } -//QueryIssue query center +// QueryIssue query center func QueryIssueTemplateByTime(beforeTime string, prcnum int, templateId int64, status int8) ([]IssueTemplate, error) { o := orm.NewOrm() @@ -676,7 +676,7 @@ func QueryGiteOriginIssue(cveNum, path string, organizationID int8) (gi []GiteOr func QueryEulerOriginBRepo(packName, branch string) (ori []OpenEulerRepoOrigin) { o := orm.NewOrm() brandStr := "%" + branch + "%" - sql := fmt.Sprintf(`select * from cve_open_euler_repo_origin where package_name='%s' and branch like '%s'`, packName, brandStr) + sql := fmt.Sprintf(`select * from cve_open_euler_repo_origin where package_name='%s' and branch like '%s' order by update_time desc`, packName, brandStr) logs.Info("sql===> ", sql) num, err := o.Raw(sql).QueryRows(&ori) if err == nil && num > 0 { diff --git a/cve-vulner-manager/taskhandler/check.go b/cve-vulner-manager/taskhandler/check.go index 4c664d75a5275bcdfc88b2a9eac7db618db33a16..2d869fc178b53fd67912e925eb112b3b4fee6265 100644 --- a/cve-vulner-manager/taskhandler/check.go +++ b/cve-vulner-manager/taskhandler/check.go @@ -89,7 +89,7 @@ func CheckIssueAnalysisComplete(i *models.IssueTemplate, v *models.VulnCenter) ( tbContent[7] = "3.openEulerVector" tbContent[8] = util.TrimStringNR(i.OpenEulerVector) } else { - if i.OpenEulerScore == 0.0 { + if i.OpenEulerScore == 0.0 && i.OpenEulerVector != util.VectorNone { msg = fmt.Sprintf("2.openEulerScore=> 没有填写或正确填写(0-10)") ok = false return @@ -335,7 +335,7 @@ func CheckIssueClosedAnalysisComplete(i *models.IssueTemplate) (msg, tbStr strin tbContent[7] = "3.openEulerVector" tbContent[8] = util.TrimStringNR(i.OpenEulerVector) } else { - if i.OpenEulerScore == 0.0 { + if i.OpenEulerScore == 0.0 && i.OpenEulerVector != util.VectorNone { tbContent[3] = "待分析" tbContent[4] = "2.openEulerScore" tbContent[5] = fmt.Sprintf("2.openEulerScore=> 没有填写或正确填写(0-10)") diff --git a/cve-vulner-manager/taskhandler/common.go b/cve-vulner-manager/taskhandler/common.go index 9351c6f82c114742e3380eb4691678aa5ef92cc7..196b7289efd3facecc678e1029800c1cf9a5d825 100644 --- a/cve-vulner-manager/taskhandler/common.go +++ b/cve-vulner-manager/taskhandler/common.go @@ -906,6 +906,12 @@ func CreateIssueBody(accessToken, owner, path, assignee string, if err != nil { floatOpenEulerScore = 0.0 } + + nvdScore, err := strconv.ParseFloat(score, 64) + if err != nil { + nvdScore = 0.0 + } + cveAnalysis := "" if its.CveAnalysis != "" && len(its.CveAnalysis) > 1 { cveAnalysis = strings.Replace(its.CveAnalysis, "\n", "", -1) @@ -981,7 +987,7 @@ func CreateIssueBody(accessToken, owner, path, assignee string, cvePkg := fmt.Sprintf("[%s](https://gitee.com/%s/%s)", cve.PackName, owner, path) cveRepo := fmt.Sprintf("[%s](https://gitee.com/%s/%s)", cve.RepoName, owner, path) cve.CveDetailUrl = "https://nvd.nist.gov/vuln/detail/" + cve.CveNum - cve.CveLevel = models.OpenEulerScoreProc(its.OpenEulerScore) + cve.CveLevel = models.OpenEulerScoreProc(nvdScore) if len(cve.CveVersion) > 0 && cve.CveVersion[0] == ',' { cve.CveVersion = cve.CveVersion[1:] } diff --git a/cve-vulner-manager/util/calculator.go b/cve-vulner-manager/util/calculator.go index 8a92e8a71256d33f14c7f2c9fbd8ea6b0e184a2f..60562ebf3884342dc62a0597cf13feef68dcb36b 100644 --- a/cve-vulner-manager/util/calculator.go +++ b/cve-vulner-manager/util/calculator.go @@ -23,10 +23,16 @@ const ( changeImpactFactor5 = 15 iscFactor = 1 exFactor = 8.22 + + VectorNone = "None" ) // Calculate CVSS v3 basescore based on vector func CalculateCVSSV3BaseScore(vector string) float64 { + if vector == VectorNone { + return 0 + } + vectors := strings.Split(vector, "/") if len(vectors) != vectorLength { return defaultBaseScore diff --git a/cve-vulner-manager/util/parsepayload.go b/cve-vulner-manager/util/parsepayload.go index 61a9069479fe28a2be32798d3c221ec776b1aee1..02d27591dba2cb3af166f17a1467aeb9f88a6a05 100644 --- a/cve-vulner-manager/util/parsepayload.go +++ b/cve-vulner-manager/util/parsepayload.go @@ -544,6 +544,11 @@ func ExtractCommentOpenEulerScore(str string) (score, vector string) { if vector == "" { vector = ExtractVector(str, CvsScoreV2) } + + if vector == "" { + vector = VectorNone + } + return }