diff --git a/.gitignore b/.gitignore index 1879e48a370ea47b43ed19755df4abb2d297fbe5..87abaa955ba77d9ce91d876c29807d985f50fd14 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,5 @@ go.sum logs/ lastupdate.tmp commentsRouter_controllers.go -commentsRouter___________________goWork_src_cvevulner_controllers.go \ No newline at end of file +commentsRouter___________________goWork_src_cvevulner_controllers.go +*.xlsx \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..a10985f0870b66a8385e18df5fe94ec35ff5919a --- /dev/null +++ b/LICENSE @@ -0,0 +1,122 @@ +木兰宽松许可证, 第1版 + +2019年8月 http://license.coscl.org.cn/MulanPSL + +您对“软件”的复制、使用、修改及分发受木兰宽松许可证,第1版(“本许可证”)的如下条款的约束: + +0. 定义 + +“软件”是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。 + +“贡献者”是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。 + +“法人实体”是指提交贡献的机构及其“关联实体”。 + +“关联实体”是指,对“本许可证”下的一方而言,控制、受控制或与其共同受控制的机构,此处的控制是指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。 + +“贡献”是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。 + +1. 授予版权许可 + +每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可以复制、使用、修改、分发其“贡献”,不论修改与否。 + +2. 授予专利许可 + +每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软件”结合而将必然会侵犯的专利权利要求,不包括仅因您或他人修改“贡献”或其他结合而将必然会侵犯到的专利权利要求。如您或您的“关联实体”直接或间接地(包括通过代理、专利被许可人或受让人),就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权行动之日终止。 + +3. 无商标许可 + +“本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可,但您为满足第4条规定的声明义务而必须使用除外。 + +4. 分发限制 + +您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。 + +5. 免责声明与责任限制 + +“软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。 + +条款结束 + +如何将木兰宽松许可证,第1版,应用到您的软件 + +如果您希望将木兰宽松许可证,第1版,应用到您的新软件,为了方便接收者查阅,建议您完成如下三步: + +1, 请您补充如下声明中的空白,包括软件名、软件的首次发表年份以及您作为版权人的名字; + +2, 请您在软件包的一级目录下创建以“LICENSE”为名的文件,将整个许可证文本放入该文件中; + +3, 请将如下声明文本放入每个源文件的头部注释中。 + +Copyright (c) [2019] [name of copyright holder] +[Software Name] is licensed under the Mulan PSL v1. +You can use this software according to the terms and conditions of the Mulan PSL v1. +You may obtain a copy of Mulan PSL v1 at: + http://license.coscl.org.cn/MulanPSL +THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +PURPOSE. +See the Mulan PSL v1 for more details. + + + +Mulan Permissive Software License,Version 1 + +Mulan Permissive Software License,Version 1 (Mulan PSL v1) + +August 2019 http://license.coscl.org.cn/MulanPSL + +Your reproduction, use, modification and distribution of the Software shall be subject to Mulan PSL v1 (this License) with following terms and conditions: + +0. Definition + +Software means the program and related documents which are comprised of those Contribution and licensed under this License. + +Contributor means the Individual or Legal Entity who licenses its copyrightable work under this License. + +Legal Entity means the entity making a Contribution and all its Affiliates. + +Affiliates means entities that control, or are controlled by, or are under common control with a party to this License, ‘control’ means direct or indirect ownership of at least fifty percent (50%) of the voting power, capital or other securities of controlled or commonly controlled entity. + +Contribution means the copyrightable work licensed by a particular Contributor under this License. + +1. Grant of Copyright License + +Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable copyright license to reproduce, use, modify, or distribute its Contribution, with modification or not. + +2. Grant of Patent License + +Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (except for revocation under this Section) patent license to make, have made, use, offer for sale, sell, import or otherwise transfer its Contribution where such patent license is only limited to the patent claims owned or controlled by such Contributor now or in future which will be necessarily infringed by its Contribution alone, or by combination of the Contribution with the Software to which the Contribution was contributed, excluding of any patent claims solely be infringed by your or others’ modification or other combinations. If you or your Affiliates directly or indirectly (including through an agent, patent licensee or assignee), institute patent litigation (including a cross claim or counterclaim in a litigation) or other patent enforcement activities against any individual or entity by alleging that the Software or any Contribution in it infringes patents, then any patent license granted to you under this License for the Software shall terminate as of the date such litigation or activity is filed or taken. + +3. No Trademark License + +No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor, except as required to fulfill notice requirements in section 4. + +4. Distribution Restriction + +You may distribute the Software in any medium with or without modification, whether in source or executable forms, provided that you provide recipients with a copy of this License and retain copyright, patent, trademark and disclaimer statements in the Software. + +5. Disclaimer of Warranty and Limitation of Liability + +The Software and Contribution in it are provided without warranties of any kind, either express or implied. In no event shall any Contributor or copyright holder be liable to you for any damages, including, but not limited to any direct, or indirect, special or consequential damages arising from your use or inability to use the Software or the Contribution in it, no matter how it’s caused or based on which legal theory, even if advised of the possibility of such damages. + +End of the Terms and Conditions + +How to apply the Mulan Permissive Software License,Version 1 (Mulan PSL v1) to your software + +To apply the Mulan PSL v1 to your work, for easy identification by recipients, you are suggested to complete following three steps: + +1. Fill in the blanks in following statement, including insert your software name, the year of the first publication of your software, and your name identified as the copyright owner; +2. Create a file named “LICENSE” which contains the whole context of this License in the first directory of your software package; +3. Attach the statement to the appropriate annotated syntax at the beginning of each source file. + +Copyright (c) [2019] [name of copyright holder] +[Software Name] is licensed under the Mulan PSL v1. +You can use this software according to the terms and conditions of the Mulan PSL v1. +You may obtain a copy of Mulan PSL v1 at: + http://license.coscl.org.cn/MulanPSL +THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +PURPOSE. +See the Mulan PSL v1 for more details. + diff --git a/common/common.go b/common/common.go index 0e798ddbaab478d190a6ec367ec82c1f15c0cbee..f5f2c226b96e78ef857129045415e283841e52e2 100644 --- a/common/common.go +++ b/common/common.go @@ -1,7 +1,9 @@ package common import ( + "errors" "github.com/astaxie/beego" + "github.com/astaxie/beego/config" "github.com/astaxie/beego/logs" "strings" "time" @@ -115,6 +117,10 @@ func GetCurTime() string{ return time.Now().Format("2006-01-02 15:04:05") } +func GetCurDate() string { + return time.Now().Format("2006-01-02") +} + func GetBeforeTime(days int) string { nowTime := time.Now() getTime := nowTime.AddDate(0, 0, days) //年,月,日 获取一天前的时间 @@ -275,11 +281,11 @@ type CveOriginData struct { Ids string `json:"ids"` CveNum string `json:"cveNum"` UpdateType string `json:"updateType"` - CvePackName string `json:"cvePackName"` - PackName string `json:"packName"` + CvePackName []string `json:"cvePackName"` + PackName []string `json:"packName"` Description CveDescription `json:"description"` Title string `json:"title"` - AffectProduct string `json:"affectProduct"` + AffectProduct []string `json:"affectProduct"` Configurations CveConfigurations `json:"configurations"` CnnvdID string `json:"cnnvdID"` CnvdID string `json:"cnvdID"` @@ -297,4 +303,18 @@ type CveOriginData struct { type UploadData struct { Token string `json:"Token"` CveData []CveOriginData +} + +func GetRepoOrg() (string, error) { + BConfig, err := config.NewConfig("ini", "conf/app.conf") + if err != nil{ + logs.Error("config init error:", err) + return "", err + } + owner := BConfig.String("gitee::owner") + if owner == "" { + logs.Error("config gitee::owner error: invalid value is ", owner) + return "", errors.New("value is nil") + } + return owner, nil } \ No newline at end of file diff --git a/conf/app.conf b/conf/app.conf index 9c657e8ac59347b2d091d050aabd480d9dc76cd8..490092f6743fd602fafee2eb98ffafdb62d1a0aa 100644 --- a/conf/app.conf +++ b/conf/app.conf @@ -7,10 +7,10 @@ copyrequestbody = true EnableDocs = true sqlconn = # 登录双方约定的key -key = "${AES_KEY||***}" +key = "${AES_KEY||djS*@+8K9{J!ymk6}" initdb = 1 # 登录key -loginkey = "{${LOGIN_KEY||***}" +loginkey = "{${LOGIN_KEY||djS*@+8K9{-!yo%64}" # token 有效期,单位:天 token_expir_time=3 #分析指令 @@ -21,11 +21,13 @@ approveCmd = "/approve" [mysql] +#dbhost = 127.0.0.1 dbhost = 159.138.2.2 dbport = 3306 #dbuser = "${DB_USER||root}" dbuser = "${DB_USER||cve}" -dbpwd = "${DB_PWD||***}" +#dbpwd = "${DB_PWD||***}" +dbpwd = "+KAOKtEnEn7gRlDEIjeh59lutAMw2688YOqKVJQ2+Lo=" dbname = cvevulner dbprefix = cve_ maxidle = 30 @@ -36,20 +38,25 @@ maxconn = 3000 log_level = 7 #log_path = C:\GoPject\src\cvevulner\logs\cve.log log_path = logs/cve.log -maxlines=10000 +maxlines=200000 maxsize=1024000 [crontab] ymalflag = 2 -cveflag = 2 -oricveflag = 2 getymal = 00 00 23 * * * +cveflag = 1 getcve = 00 00 01 * * * +oricveflag = 1 oricvecheck = 00 00 02 * * * -issueflag = 2 -createissue = * */5 * * * * +getissueflag = 1 +getissue = 00 00 03 * * * +issueflag = 1 +createissue = * * 01 * * * test = 0/10 * * * * * +gittokenflag = 1 issueoath = * * */20 * * * +genexcelflag = 2 +genexcel = 00 00 04 * * * days = -30 prcnum = 100 @@ -61,7 +68,7 @@ prcnum = 100 #redirect_uri = http://119.8.126.102:80/v1/issue/oauth/callback # -------jianjun gitee 配置 -------- owner = zhangjianjun_code -path = test1 +path = jasper email = 7844966+zhangjianjun_code@user.noreply.gitee.com redirect_uri = http://159.138.2.2:80/v1/issue/oauth/callback @@ -76,12 +83,12 @@ git_token = "${GITEE_TOKEN||xxx}" [hook] hookpwd = "${HOOK_PWD||***}" -#hookurl = http://159.138.2.2:80/issue hookurl = http://159.138.2.2:80/v1/issue/hook/event +#hookurl = http://119.8.126.102:80/v1/issue/hook/event [yaml] -apiurl = https://api.openeuler.org/pkgmanagedebug +apiurl = https://api.openeuler.org/pkgmanage [cve] cveref = https://nvd.nist.gov/vuln/detail/ @@ -89,3 +96,8 @@ openeulernum = 3000 [reflink] comment_cmd = https://gitee.com/openeuler/cve-manager/blob/master/doc/md/manual.md + +[excel] +forcerewrite = false +snprefix = op-2020-10- +snsuffix = 1002 \ No newline at end of file diff --git a/controllers/file.go b/controllers/file.go new file mode 100644 index 0000000000000000000000000000000000000000..54bc1ac1307be34fa57acedfceae40f6f1968280 --- /dev/null +++ b/controllers/file.go @@ -0,0 +1,21 @@ +package controllers + +import ( + "cvevulner/models" + "github.com/astaxie/beego" +) + +type FileController struct { + beego.Controller +} + +// @router /lastExcel [get] +func (f *FileController) DownloadLastExcel() { + er :=models.ExportRecord{} + err := er.QueryLast() + if err != nil { + _ = f.Ctx.Output.Body([]byte("no file ")) + } + fp := "./"+er.FileName + f.Ctx.Output.Download(fp,er.FileName) +} diff --git a/controllers/hook.go b/controllers/hook.go index e51717af1329f8513b7d5b4e5cc098f6f23f45a7..17d84258bf8f59374cbfc4431570a5070d3a507f 100644 --- a/controllers/hook.go +++ b/controllers/hook.go @@ -21,18 +21,20 @@ var ( NoteHookType = "Note Hook" // type of comment PullReqHookType = "merge_request_hooks" // type of pull request PushTagHookType = "push_hooks/tag_push_hooks" // type of push or tag - IssueHookType = "Issue Hook" //type of issue + IssueHookType = "Issue Hook" //type of issue ) const ( - CommentAnalysisCplTpl ="@%v %v" + CommentAnalysisCplTpl = "@%v %v" ReviewPrivateLettersTpl = `%s(%s)analysis is over,CVEScore:%v;OpenEulerScore:%v。Please review!` - ReviewRejectScore = `@%v you submit issue score audit failed(reject by %v),Please re-analyze and submit!` - CommentReviewTpl = `@%v The CVE score needs to be reviewed (the review instruction /approve&/reject means agreement and rejection)。` - IssueRejectState = "rejected" - IssueCloseState = "closed" - IssueProgressState = "progressing" - IssueOpenState = "open" + ReviewRejectScore = `@%v you submit issue score audit failed(reject by %v),Please re-analyze and submit!` + ReviewApproveScore = `@%v you submit issue score audit success(approved by %v),You can proceed to the next step!` + CommentReviewTpl = `%v The CVE score needs to be reviewed (the review instruction /approve&/reject means agreement and rejection)。` + IssueRejectState = "rejected" + IssueCloseState = "closed" + IssueProgressState = "progressing" + IssueOpenState = "open" + AnalysisComplete = "@%v 经过 CVE-Manager 解析, 您分析的内容如下表所示:\n" ) type HookEventControllers struct { @@ -111,13 +113,26 @@ func (c *HookEventControllers) handlePushTag() { func (c *HookEventControllers) handleIssue() { logs.Info(string(c.Ctx.Input.RequestBody)) - issueHook := models.IssuePayload{} + issueHook := models.IssuePayload{} err := json.Unmarshal(c.Ctx.Input.RequestBody, &issueHook) - if err != nil{ + if err != nil { logs.Error(err) return } - if issueHook.Action == "state_change"{ + if issueHook.Action == "assign" { + //更新issue 模板负责人 + issueTmp := models.IssueTemplate{IssueNum: issueHook.Iid} + err := models.GetIssueTemplateByColName(&issueTmp, "issue_num") + if err != nil { + logs.Error(err) + } + issueTmp.Assignee = issueHook.Assignee.Login + err = models.UpdateIssueTemplate(&issueTmp, "issue_assignee") + if err != nil { + logs.Error(err) + } + } + if issueHook.Action == "state_change" { //handle issue state change err = handleIssueStateChange(&issueHook) if err != nil { @@ -127,39 +142,57 @@ func (c *HookEventControllers) handleIssue() { } -func handleIssueStateChange(issueHook *models.IssuePayload) error{ +func handleIssueStateChange(issueHook *models.IssuePayload) error { issueTmp := models.IssueTemplate{IssueNum: issueHook.Iid} err := models.GetIssueTemplateByColName(&issueTmp, "issue_num") if err != nil { return err } + cveCenter := models.VulnCenter{CveId: issueTmp.CveId} + err = models.GetVulnCenterByCid(&cveCenter, "cve_id") + if err != nil { + return err + } switch issueHook.State { case IssueOpenState: issueTmp.Status = 1 + cveCenter.IsExport = 0 case IssueProgressState: issueTmp.Status = 2 + cveCenter.IsExport = 0 case IssueCloseState: issueTmp.Status = 3 - if isNormalCloseIssue(issueTmp.CveId,issueTmp.IssueStatus){ + if isNormalCloseIssue(issueTmp.CveId, issueTmp.IssueStatus) { issueTmp.IssueStatus = 2 - }else { + cveCenter.IsExport = 3 + } else { issueTmp.IssueStatus = 6 + cveCenter.IsExport = 2 } case IssueRejectState: issueTmp.Status = 4 - if isNormalCloseIssue(issueTmp.CveId,issueTmp.IssueStatus){ + issueTmp.IssueStatus = 6 + cveCenter.IsExport = 2 + /*if isNormalCloseIssue(issueTmp.CveId, issueTmp.IssueStatus) { issueTmp.IssueStatus = 2 - }else { + } else { issueTmp.IssueStatus = 6 - } + }*/ } issueTmp.StatusName = issueHook.Issue.StateName err = models.UpdateIssueTemplate(&issueTmp, "status", "issue_status", "status_name") - return err + update := models.UpdateVulnCenter(&cveCenter, "is_export") + if err != nil { + return err + } + if update != true { + return errors.New("update vulnCenter fail ") + } + return nil } -func isNormalCloseIssue(cveId int64,issueState int8) bool { - if issueState == 1{ +func isNormalCloseIssue(cveId int64, issueState int8) bool { + if issueState == 1 { return false } score, err := models.QueryIssueScore(cveId) @@ -190,7 +223,7 @@ func handleIssueComment(payload models.CommentPayload) { } if strings.HasPrefix(cBody, cmdRej) { //审核拒绝 添加评论 @分析人 - if !isReviewer(cuAccount){ + if !isReviewer(cuAccount) { return } issueTmp := models.IssueTemplate{IssueNum: issueNum} @@ -205,11 +238,12 @@ func handleIssueComment(payload models.CommentPayload) { } accessToken := os.Getenv("GITEE_TOKEN") owner := beego.AppConfig.String("gitee::owner") - path := beego.AppConfig.String("gitee::path") - taskhandler.AddCommentToIssue(fmt.Sprintf(ReviewRejectScore,issueTmp.Assignee,cuAccount),issueTmp.IssueNum,owner,path,accessToken) + //path := beego.AppConfig.String("gitee::path") + path := issueTmp.Repo + taskhandler.AddCommentToIssue(fmt.Sprintf(ReviewRejectScore, issueTmp.Assignee, cuAccount), issueTmp.IssueNum, owner, path, accessToken) } else if strings.HasPrefix(cBody, cmdApe) { //审核通过 修改评分状态 - if !isReviewer(cuAccount){ + if !isReviewer(cuAccount) { return } issueTmp := models.IssueTemplate{IssueNum: issueNum} @@ -221,9 +255,17 @@ func handleIssueComment(payload models.CommentPayload) { err = changeOpenEulerScoreStatus(issueTmp.CveId, 3) if err != nil { logs.Error(err) + } else { + accessToken := os.Getenv("GITEE_TOKEN") + owner := beego.AppConfig.String("gitee::owner") + //path := beego.AppConfig.String("gitee::path") + path := issueTmp.Repo + taskhandler.AddCommentToIssue(fmt.Sprintf(ReviewApproveScore, issueTmp.Assignee, cuAccount), issueTmp.IssueNum, owner, path, accessToken) } + } else { - analysisComment(issueNum, cuAccount, cBody,&payload) + cBody = strings.ReplaceAll(cBody, ":", ":") + analysisComment(issueNum, cuAccount, cBody, &payload) } } @@ -233,19 +275,22 @@ func isReviewer(path string) bool { return sr.Read("name_space") } -func analysisComment(issueNum string, cuAccount string, cBody string,payload *models.CommentPayload) { - cmdAys := beego.AppConfig.DefaultString("analysisCmd", "/analysis") - cmdEnd := beego.AppConfig.DefaultString("endCmd", "/done") +func analysisComment(issueNum string, cuAccount string, cBody string, payload *models.CommentPayload) { + //cmdAys := beego.AppConfig.DefaultString("analysisCmd", "//不需要分析指令 + //cmdEnd := beego.AppConfig.DefaultString("endCmd", "/done") //不需要结束指令 issueTmp := models.IssueTemplate{IssueNum: issueNum} err := models.GetIssueTemplateByColName(&issueTmp, "issue_num") if err != nil { logs.Error(err) return } - if cuAccount == issueTmp.Assignee && strings.Contains(cBody, cmdAys) { + canVerfy := false + //if cuAccount == issueTmp.Assignee && strings.Contains(cBody, cmdAys) { + if cuAccount == issueTmp.Assignee { //is Analyst comment and content start with '/analysis' - vMap := util.ParseCommentWithAllLabel(cBody) + vMap := util.ExtractCommentAnalysisAllValue(cBody) if len(vMap) > 0 { + canVerfy = true cols := make([]string, 0) for k, v := range vMap { switch k { @@ -291,7 +336,7 @@ func analysisComment(issueNum string, cuAccount string, cBody string,payload *mo } else { score.OpenEulerScore = issueTmp.OpenEulerScore score.Ostatus = 1 - err := models.UpdateScore(&score, "openeuler_score","o_score_status") + err := models.UpdateScore(&score, "openeuler_score", "o_score_status") if err != nil { logs.Error(err) } @@ -306,105 +351,157 @@ func analysisComment(issueNum string, cuAccount string, cBody string,payload *mo logs.Error(err) } } + // update gitee issue + commentUpdateIssue(issueTmp) } - // update gitee issue - commentUpdateIssue(issueTmp) + } - if cuAccount == issueTmp.Assignee && strings.Contains(cBody, cmdEnd) { + //if cuAccount == issueTmp.Assignee && strings.Contains(cBody, cmdEnd) { + if cuAccount == issueTmp.Assignee && canVerfy { //Check whether the data is legal - if msg,ok :=checkIssueAnalysisComplete(&issueTmp);!ok{ - //send comment to issue - msg = fmt.Sprintf(CommentAnalysisCplTpl,issueTmp.Assignee,msg) - accessToken := os.Getenv("GITEE_TOKEN") - owner := beego.AppConfig.String("gitee::owner") - path := beego.AppConfig.String("gitee::path") - taskhandler.AddCommentToIssue(msg,issueTmp.IssueNum,owner,path,accessToken) - }else { + accessToken := os.Getenv("GITEE_TOKEN") + owner := beego.AppConfig.String("gitee::owner") + //path := beego.AppConfig.String("gitee::path") + path := issueTmp.Repo + if msg, tb, ok := checkIssueAnalysisComplete(&issueTmp); !ok { + //send comment to issue + issueTmp.IssueStatus = 1 + err := models.UpdateIssueTemplate(&issueTmp, "issue_status") + if err != nil { + logs.Error(err) + } + msg = fmt.Sprintf(CommentAnalysisCplTpl, issueTmp.Assignee, msg) + taskhandler.AddCommentToIssue(msg, issueTmp.IssueNum, owner, path, accessToken) + } else { //1. change issue status issueTmp.IssueStatus = 3 err := models.UpdateIssueTemplate(&issueTmp, "issue_status") - if err != nil{ + if err != nil { logs.Error(err) } //2. Are the cvsScore and openEuler score equal .If not equal, notify the auditor to review . - if issueTmp.OpenEulerScore != issueTmp.NVDScore { - //Notify the responsible person for review - notifyAuditorReview(payload,issueTmp) - }else { + var na string + if issueTmp.OpenEulerScore != issueTmp.NVDScore { + na = "\n**因OpenEulerScore与NvdScore不一致,分析内容需审核,请等待审核!**" + //Notify the responsible person for review + notifyAuditorReview(payload, issueTmp) + } else { + na = "\n**请确认分析内容的准确性,确认无误后,您可以进行后续步骤,否则您可以继续分析。**" // change score status err := changeOpenEulerScoreStatus(issueTmp.CveId, 3) if err != nil { logs.Error(err) } } + cc := fmt.Sprintf(AnalysisComplete, issueTmp.Assignee) + tb + na + taskhandler.AddCommentToIssue(cc, issueTmp.IssueNum, owner, path, accessToken) } } } -func notifyAuditorReview(payload *models.CommentPayload,issueTmp models.IssueTemplate){ +func notifyAuditorReview(payload *models.CommentPayload, issueTmp models.IssueTemplate) { //Notify the responsible person for review list, err := models.GetSecurityReviewerList() - if err != nil{ + if err != nil { logs.Error(err) return } + if len(list) == 0 { + return + } accessToken := os.Getenv("GITEE_TOKEN") content := fmt.Sprintf(ReviewPrivateLettersTpl, - payload.Issue.Title,payload.Issue.HtmlUrl,issueTmp.NVDScore,issueTmp.OpenEulerScore) + payload.Issue.Title, payload.Issue.HtmlUrl, issueTmp.NVDScore, issueTmp.OpenEulerScore) owner := beego.AppConfig.String("gitee::owner") - path := beego.AppConfig.String("gitee::path") - for _,v := range list{ - taskhandler.SendPrivateLetters(accessToken,content,v.NameSpace) + //path := beego.AppConfig.String("gitee::path") + path := issueTmp.Repo + ns := make([]string, len(list)) + for k, v := range list { + ns[k] = "@" + v.NameSpace+" " + taskhandler.SendPrivateLetters(accessToken, content, v.NameSpace) //add @comment - msg := fmt.Sprintf(CommentReviewTpl,v.NameSpace) - taskhandler.AddCommentToIssue(msg,issueTmp.IssueNum,owner,path,accessToken) } - + msg := fmt.Sprintf(CommentReviewTpl, strings.Join(ns, ",")) + taskhandler.AddCommentToIssue(msg, issueTmp.IssueNum, owner, path, accessToken) } -func changeOpenEulerScoreStatus(cveId int64,status int8) error{ +func changeOpenEulerScoreStatus(cveId int64, status int8) error { score, err := models.QueryIssueScore(cveId) if err != nil { return err } score.Ostatus = status err = models.UpdateScore(&score, "o_score_status") - return err + return err } -func checkIssueAnalysisComplete(i *models.IssueTemplate) (msg string,ok bool) { +func checkIssueAnalysisComplete(i *models.IssueTemplate) (msg, tbStr string, ok bool) { + tb := + `| 状态 | 需分析 | 内容 | +|-----|-----------------|---------| +|%v|%v|%v| +|%v|%v|%v| +|%v|%v|%v| +|%v|%v|%v| +` + if i == nil { logs.Error("issue template is nil") - return msg,false + return msg, "", false } ok = true + tbContent := make([]interface{}, 12) if i.OpenEulerScore == 0.0 { - msg = fmt.Sprintf("openEulerScore:%v",i.OpenEulerScore) + msg = fmt.Sprintf("openEulerScore没有填写:%v", i.OpenEulerScore) ok = false return + } else { + tbContent[0] = "已分析" + tbContent[1] = "openEulerScore" + tbContent[2] = i.OpenEulerScore } if i.CveAnalysis == "" { - msg = fmt.Sprintf("影响性分析说明:%v",i.CveAnalysis) + msg = fmt.Sprintf("影响性分析说明没有填写:%v", i.CveAnalysis) ok = false return + } else { + tbContent[3] = "已分析" + tbContent[4] = "影响性分析说明" + tbContent[5] = util.TrimStringNR(i.CveAnalysis) } - if i.PrincipleAnalysis == "" { + //新模板没有该值 + /*if i.PrincipleAnalysis == "" { msg = fmt.Sprintf("原理分析:%v",i.PrincipleAnalysis) ok = false return - } + }*/ if i.OpenEulerVector == "" { - msg = fmt.Sprintf("OpenEulerVector:%v",i.OpenEulerVector) + msg = fmt.Sprintf("OpenEulerVector没有填写:%v", i.OpenEulerVector) ok = false return + } else { + tbContent[6] = "已分析" + tbContent[7] = "openEulerVector" + tbContent[8] = util.TrimStringNR(i.OpenEulerVector) + } + if i.AffectedVersion != "" { + tbContent[9] = "已分析" + tbContent[10] = "受影响版本排查" + tbContent[11] = util.TrimStringNR(i.AffectedVersion) + } else { + tbContent[9] = "待分析" + tbContent[10] = "受影响版本排查" + tbContent[11] = "" } - if i.AffectedVersion == "" { + //非必填字段 + /*if i.AffectedVersion == "" { msg = fmt.Sprintf("受影响的包:%v",i.OpenEulerVector) ok = false return - } - if i.Solution == ""{ + }*/ + //新模板没有该值 + /*if i.Solution == ""{ msg = fmt.Sprintf("规避方案或消减措施:%v",i.OpenEulerVector) ok = false return @@ -415,14 +512,16 @@ func checkIssueAnalysisComplete(i *models.IssueTemplate) (msg string,ok bool) { } if len(pkg) == 0 { return "受影响的包",false - } + }*/ + tbStr = fmt.Sprintf(tb, tbContent...) return } func commentUpdateIssue(issueTmp models.IssueTemplate) { accessToken := os.Getenv("GITEE_TOKEN") owner := beego.AppConfig.String("gitee::owner") - path := beego.AppConfig.String("gitee::path") + //path := beego.AppConfig.String("gitee::path") + path := issueTmp.Repo if accessToken != "" && owner != "" && path != "" { cvlnCenter := models.VulnCenter{} err := models.GetVulnCenterByCVEID(&cvlnCenter, issueTmp.CveId) @@ -445,52 +544,87 @@ func saveVectorData(vct string, cveId int64) error { if vct == "" { return errors.New("vct value is empty") } + upFields := make([]string, 0) + score.OvectorVule = vct + upFields = append(upFields, "o_vector_value") vMap, ok := util.VctToMap(vct) if !ok { return errors.New("vector value illegal") } - upFields := make([]string, 0) - score.OvectorVule = vct - upFields = append(upFields, "o_vector_value") - avv := util.ReadVmValue(vMap["AV"]) - if avv != "" { - score.OattackVector = avv - upFields = append(upFields, "o_attack_vector") - } - acv := util.ReadVmValue(vMap["AC"]) - if acv != "" { - score.OattackComplexity = acv - upFields = append(upFields, "o_attack_complexity") - } - prv := util.ReadVmValue(vMap["PR"]) - if prv != "" { - score.OprivilegeRequired = prv - upFields = append(upFields, "o_privilege_required") - } - uiv := util.ReadVmValue(vMap["UI"]) - if uiv != "" { - score.OuserInteraction = uiv - upFields = append(upFields, "o_user_interaction") - } - sv := util.ReadVmValue(vMap["S"]) - if sv != "" { - score.Oscope = sv - upFields = append(upFields, "o_scope") - } - cv := util.ReadVmValue(vMap["C"]) - if cv != "" { - score.Oconfidentiality = cv - upFields = append(upFields, "o_confidentiality") - } - iv := util.ReadVmValue(vMap["I"]) - if iv != "" { - score.Ointegrity = iv - upFields = append(upFields, "o_integrity") - } - av := util.ReadVmValue(vMap["A"]) - if av != "" { - score.Oavailability = av - upFields = append(upFields, "o_availability") + if util.RegexpVectorV2.Match([]byte(vct)) { + //update v2 vector + avv := util.ReadVmValueV2(vMap["AV"]) + if avv != "" { + score.OaccessVector = avv + upFields = append(upFields, "o_access_vector") + } + acv := util.ReadVmValueV2(vMap["AC"]) + if acv != "" { + score.OaccessComplexity = acv + upFields = append(upFields, "o_access_complexity") + } + au := util.ReadVmValueV2(vMap["Au"]) + if au != "" { + score.Oauthentication = au + upFields = append(upFields, "o_authentication") + } + cv := util.ReadVmValueV2(vMap["C"]) + if cv != "" { + score.Oconfidentiality = cv + upFields = append(upFields, "o_confidentiality") + } + iv := util.ReadVmValueV2(vMap["I"]) + if iv != "" { + score.Ointegrity = iv + upFields = append(upFields, "o_integrity") + } + av := util.ReadVmValueV2(vMap["A"]) + if av != "" { + score.Oavailability = av + upFields = append(upFields, "o_availability") + } + } else { + //update v3 vector + avv := util.ReadVmValue(vMap["AV"]) + if avv != "" { + score.OattackVector = avv + upFields = append(upFields, "o_attack_vector") + } + acv := util.ReadVmValue(vMap["AC"]) + if acv != "" { + score.OattackComplexity = acv + upFields = append(upFields, "o_attack_complexity") + } + prv := util.ReadVmValue(vMap["PR"]) + if prv != "" { + score.OprivilegeRequired = prv + upFields = append(upFields, "o_privilege_required") + } + uiv := util.ReadVmValue(vMap["UI"]) + if uiv != "" { + score.OuserInteraction = uiv + upFields = append(upFields, "o_user_interaction") + } + sv := util.ReadVmValue(vMap["S"]) + if sv != "" { + score.Oscope = sv + upFields = append(upFields, "o_scope") + } + cv := util.ReadVmValue(vMap["C"]) + if cv != "" { + score.Oconfidentiality = cv + upFields = append(upFields, "o_confidentiality") + } + iv := util.ReadVmValue(vMap["I"]) + if iv != "" { + score.Ointegrity = iv + upFields = append(upFields, "o_integrity") + } + av := util.ReadVmValue(vMap["A"]) + if av != "" { + score.Oavailability = av + upFields = append(upFields, "o_availability") + } } if len(upFields) > 0 { //执行更新 diff --git a/controllers/login.go b/controllers/login.go index 3282f2a14d7f7fa0ca1a3423f016bafcf1f6b604..240c47092b0d84d9ea95d32b28a39ba66b053803 100644 --- a/controllers/login.go +++ b/controllers/login.go @@ -41,14 +41,14 @@ func (u *UserLoginController) Post() { json.Unmarshal(u.Ctx.Input.RequestBody,&req) logs.Info("登录请求参数:", &req) //判断是否合法 - if req["UserName"] == nil || req["PassWord"] ==nil{ + if req["userName"] == nil || req["passWord"] == nil{ resp["errno"]=errcode.RECODE_DATAERR resp["errmsg"]=errcode.RecodeText(errcode.RECODE_DATAERR) resp["body"] = Result{} logs.Error("数据错误") return } - password := fmt.Sprintf("%s", req["PassWord"]) + password := fmt.Sprintf("%s", req["passWord"]) // 加密先注释 //password = common.DesString(password) if password == "" || len(password) == 0{ @@ -59,7 +59,7 @@ func (u *UserLoginController) Post() { return } var strc Result - username := fmt.Sprintf("%s", req["UserName"]) + username := fmt.Sprintf("%s", req["userName"]) resp_model, err := models.GetCveUserByUser(username, password) logs.Info(resp_model) if resp_model!= nil && err == nil { diff --git a/controllers/upload.go b/controllers/upload.go index 12045cb90e0c07fd9d5fbb6cb9cbf6884ecff300..f3ebf792a9af9955cb7b2e2c285a97cddf9c9164 100644 --- a/controllers/upload.go +++ b/controllers/upload.go @@ -33,6 +33,9 @@ func (c *UserUploadController) RetData(resp map[string]interface{}) { func (u *UserUploadController) Post() { var uploaddata common.UploadData var ResDataList []ResultData + req := u.Ctx.Request + addr := req.RemoteAddr + logs.Info("Method: ",req.Method, "客户端请求的:addr: ", addr, "Header: ", req.Header) resp := make(map[string]interface{}) resp["errno"]=errcode.RECODE_UNKNOWERR resp["errmsg"]=errcode.RecodeText(errcode.RECODE_UNKNOWERR) @@ -40,6 +43,20 @@ func (u *UserUploadController) Post() { defer u.RetData(resp) json.Unmarshal(u.Ctx.Input.RequestBody,&uploaddata) logs.Info("Cve上传请求参数:", &uploaddata) + var iw models.IpWhite + if addr != "" { + addrIp := strings.Split(addr, ":") + err := models.GetIpWhite(addrIp[0], &iw) + if err != nil { + resp["errno"]=errcode.RECODE_IPERR + resp["errmsg"]=errcode.RecodeText(errcode.RECODE_IPERR) + return + } + } else { + resp["errno"]=errcode.RECODE_IPERR + resp["errmsg"]=errcode.RecodeText(errcode.RECODE_IPERR) + return + } //判断是否合法 if uploaddata.Token == "" { resp["errno"]=errcode.RECODE_SESSIONERR @@ -83,10 +100,21 @@ func (u *UserUploadController) Post() { logs.Error("cveNum 为空, ids: ", ids) } updateType := CveDataDict.UpdateType - cvePackName := CveDataDict.CvePackName - packName := CveDataDict.PackName + cvePackName := "" + if len(CveDataDict.CvePackName) > 0 { + cvePackName = strings.Join(CveDataDict.CvePackName, ",") + } + packName := "" + if len(CveDataDict.PackName) > 0 { + packName = strings.Join(CveDataDict.PackName, ",") + } title := CveDataDict.Title - affectProduct := CveDataDict.AffectProduct + affectProduct := "" + if len(CveDataDict.AffectProduct) > 1 { + affectProduct = strings.Join(CveDataDict.AffectProduct, ",") + } else { + affectProduct = packName + } cnnvdID := CveDataDict.CnnvdID cnvdID := CveDataDict.CnvdID publishedDate := CveDataDict.PublishedDate @@ -95,6 +123,9 @@ func (u *UserUploadController) Post() { logs.Error("Version 为空, ids: ", ids) } version := CveDataDict.Version + if version == "" { + version = packName + } var orCve models.OriginUpstream if ids != "" { ids = common.DeletePreAndSufSpace(ids) @@ -117,13 +148,24 @@ func (u *UserUploadController) Post() { } orCve.CnnvdID = cnnvdID orCve.CnvdID = cnvdID + orCve.IsExit = 0 orCve.PublishedDate = publishedDate - gits, ok := models.QueryCveOpeneulerdata(packName, version) - if !ok { - orCve.IsExit = 0 - } else { - orCve.IsExit = 1 - logs.Info("对应src-openEuler的数据为: ", gits) + packNameList := []string{} + if packName != "" && len(packName) > 0 { + packNameList = strings.Split(packName, ",") + } + if len(packNameList) > 0 { + for _, pk := range packNameList { + pkList := strings.Split(pk, "==") + if len(pkList) == 2 { + gits, ok := models.QueryCveOpeneulerdata(pkList[0], pkList[1]) + if ok { + orCve.IsExit = 1 + logs.Info("对应src-openEuler的数据为: ", gits) + break + } + } + } } orCve.VulStatus = vulStatus if strings.ToLower(updateType) == "delete" { diff --git a/doc/image/Framework.png b/doc/image/Framework.png index 4e60704a70b3c61b1d0f81751acd0acd9b68ab2f..28a39c7d5d7ee691e8b442b8a0ffeb8e55b5729f 100644 Binary files a/doc/image/Framework.png and b/doc/image/Framework.png differ diff --git "a/doc/image/\350\247\246\345\217\221issue\346\265\201\347\250\213\345\233\276.png" "b/doc/image/\350\247\246\345\217\221issue\346\265\201\347\250\213\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..beb34a870166556336f353cd638c3d5435249967 Binary files /dev/null and "b/doc/image/\350\247\246\345\217\221issue\346\265\201\347\250\213\345\233\276.png" differ diff --git a/doc/md/manual.md b/doc/md/manual.md index 5aecbc60c53effb659af6e307836d3eac240fe44..34d49676419147dc2466936ed25022b36d82e773 100644 --- a/doc/md/manual.md +++ b/doc/md/manual.md @@ -1,34 +1,74 @@ -##### issue 分析评论规则 -issue分析员注意事项 -1. 分析以/analysis标识开始 -2. 分析完结以 /end 结束 -3. 分析issue后需要在评论中修改issue中的模板字段值必须用对应评论标签包裹 +## issue分析说明 - | 模板字段中文名 | 模板字段英文名 | 评论标签 | - | ------------- | ------------- | ------------- | - | 漏洞编号 | Loophole number| [LN][/LN] | - | 漏洞组件 | loophole ascription component | [LAC][/LAC] | - | 漏洞版本 | loophole ascription version | [LAV][/LAV] | - | CVSS v3.0分值 | cvss v3.0 score | [CVS][/CVS] | - | CVSS 向量 | cvss V3.1 vector | [CVV][/CVV] | - | 漏洞 描述 | loophole description | [LD][/LD] | - | 影响分析说明 | impact analysis description | [IAD][/IAD] | - | 原理分析 | principle analysis | [PA][/PA] | - | openEuler评分 | openEuler score | [OES][/OES] | - | openEuler向量 | openEuler Vector | [OEV][/OEV] | - | 影响的版本 | impact version | [IV][/IV] | - | 规避方案和措施 | Circumvention plan or mitigation measures | [CPMM][/CPMM] | - | 影响的包 | impact wrap| [IW][/IW] -- 分析issue填写模板(ps 每一次分析评论必须用/analysis指令 填写项可以一次填完也可不填写完 填写完成加上/done指令 - /analysis - 影响分析说明:[IAD]此处为填写影响分析说明的内容[/IAD] - 原理分析:[PA]此处为填写原理分析的内容[/PA] - openEuler评分:[OES]此处为填写openEuler评分的内容[/OES] - openEuler向量:[OEV]此处为填写openEuler向量的内容[/OEV] - 影响的版本:[IV]此处为填写影响版本的内容[/IV] - 规避方案和措施:[IV]此处为填写规避方案和措施的内容[/IV] - 影响的包:[IW]此处为填写影响的包的内容(内容以英文逗号分隔)[/IW] - /done +### issue分析触发流程图 + + +#### issue 分析评论流程 + +issue分析注意事项 +- 只有issue的Maintainer的评论分析才是有效分析 +- 分析issue模板并拷贝以下内容在**评论区回复**: + ```batch + 影响性分析说明: + openEuler评分: + 受影响版本排查(受影响/不受影响): + 1.openEuler-20.03-LTS: + 2.openEuler-20.09: + ``` +- 受影响版本排查(受影响/不受影响)填写说明: + ```batch + 1>issue模板或第一条评论中不包含 如:1.openEuler-20.03-LTS:之类的填写项则不需要填写, + 如Maintainer发现有对应的版本需要填写则参考下方说明格式填写 + 2>填写方式: + 1.openEuler-20.03-LTS:受影响 + 2.openEuler-20.09:不受影响 + ``` + - 分析内容可一次性填写完整也可分条填写 + - 重复分析内容可覆盖上一次分析的内容(只要包含键值的评论不管内容是否为空都会覆盖) + - cve-manage 在每次分析评论提交后根据内容进行解析并根据解析后的内容进行回复,Maintainer在评论后没得到回复可主动刷新页面或有延迟 + - 当内容填写完整会触发两种回复中的一种: - #### security-committee #### - * 整理中 \ No newline at end of file + 1.评分不一致需要审核 + + | 状态 | 需分析 | 内容 | + |-----|----------------|------------------------| + | 已分析 | openEulerScore | 6.0 | + | 已分析 | 影响性分析说明 | 您分析的内容 | + | 已分析 | OpenEulerVector | AV:A/AC:C... | + | 已分析 | 受影响的版本 | openEuler-20.03-LTS:受影响 | + **因OpenEulerScore与NvdScore不一致,分析内容需审核,请等待审核** + + 2.评分一致 + + | 状态 | 需分析 | 内容 | + |-----|----------------|------------------------| + | 已分析 | openEulerScore | 6.0 | + | 已分析 | 影响性分析说明 | 您分析的内容 | + | 已分析 | OpenEulerVector | AV:A/AC:C... | + | 已分析 | 受影响的版本 | openEuler-20.03-LTS:受影响 | + **请确认分析内容的准确性,确认无误后,您可以进行后续步骤或您可以继续分析。** + - 评分不一致则需等待审核员审核后进行下一步 **否则将视为无效分析将不可导出** + - issue 已完成(关闭)且已分析完结、评分不一致需审核通过后的issue才具备发布安全公告到官网 + + ### 审核员操作说明 + - 审核员对Maintainer填写的评分在当前issue的评论区回复如下指令 + - 使用指令说明 + + | 指令 | 指令说明 | 使用权限 | + | ------ | ------- | ------- | + | /approve | 审核通过 | security-committee-sig组成员 | + | /reject | 审核拒绝 | security-committee-sig组成员 | + + - 注意事项 + ```batch + 1.指令独占一行 + 2.以最后一位审核员评论审核的指令为最终指令 + 3.审核评论成功 cve-manage 会新增一条@责任人的评论 + (若没有新增评论,可主动刷新页面,多次刷新后没有回复则没有审核评论成功) +``` + +### 分析导出 +- 每天凌晨2:00 cve-manage 会通过定时任务生成excel文件 +- 通过 http://159.138.2.2:80/v1/download/excel 下载最新的excel文件 +- 未发布到官网的CVE 都会在最新的excel文档中 如果之前下载的未能及时同步到官网可下载最新文档再同步即可。 + diff --git a/doc/md/template.md b/doc/md/template.md new file mode 100644 index 0000000000000000000000000000000000000000..6a63812447cd1223a8ba18e3dcd0808441ac109e --- /dev/null +++ b/doc/md/template.md @@ -0,0 +1,78 @@ +#### issue 分析评论规则 #### +issue分析员注意事项 +1. 分析以/analysis标识开始 +2. 分析完结以 /end 结束 +3. 分析issue后需要在评论中修改issue中的模板字段值必须用对应评论标签包裹 + + | 模板字段中文名 | 模板字段英文名 | 评论标签 | + | ------------- | ------------- | ------------- | + | 漏洞编号 | Loophole number| [LN][/LN] | + | 漏洞组件 | loophole ascription component | [LAC][/LAC] | + | 漏洞版本 | loophole ascription version | [LAV][/LAV] | + | CVSS v3.0分值 | cvss v3.0 score | [CVS][/CVS] | + | CVSS 向量 | cvss V3.1 vector | [CVV][/CVV] | + | 漏洞简述 | loophole description | [LD][/LD] | + | 影响性分析说明 | impact analysis description | [IAD][/IAD] | + | openEuler评分 | openEuler score | [OES][/OES] | + | 影响的版本 | impact version | [IV][/IV] | +- 分析issue填写模板(ps 每一次分析评论必须用/analysis指令 填写项可以一次填完也可不填写完 填写完成加上/done指令 拷贝以下内容: + /analysis + 影响性分析说明: + [IAD]此处为填写影响分析说明的内容[/IAD] + openEuler评分: + [OES]此处为填写openEuler评分的内容[/OES] + 影响的版本: + [IV]此处为填写影响版本的内容[/IV] + /done + +#### 以下内容为本仓库维护组填写 #### +- [Y]表示不需要填写,或者可以修改 | [N]需要填写且必填 | [?] 无法判断是否已填写 + + |是否填写 | 模板名称 | 模板内容 | 模板标签 | + |------- | ------------- | ------------- | ------------- | + | [N] | 影响性分析说明 | [IAD]此处为填写影响分析说明的内容[/IAD] | [IAD][/IAD] | + | [N] | 原理分析 | [PA]此处为填写原理分析的内容[/PA] | [PA][/PA] | + | [N] | openEuler评分 | [OES]此处为填写openEuler评分的内容[/OES] | [OES][/OES] | + | [N] | openEuler向量 | [OEV]此处为填写openEuler向量的内容[/OEV] | [OEV][/OEV] | + | [N] | 影响的版本 | [IV]此处为填写影响版本的内容[/IV] | [IV][/IV] | + | [N] | 规避方案和措施 | [CPMM]此处为填写规避方案和措施的内容[/CPMM] | [CPMM][/CPMM] | + | [N] | 影响的包 | [IW]此处为填写影响的包的内容(内容以英文逗号分隔)[/IW]| [IW][/IW] + + #### 具体示例如下: #### +- 分析issue填写模板(ps 每一次分析评论必须用/analysis指令 填写项可以一次填完也可不填写完 填写完成加上/done指令 请拷贝以下内容: + /analysis + 影响性分析说明: + [IAD]此处为填写影响分析说明的内容[/IAD] + 原理分析: + [PA]此处为填写原理分析的内容[/PA] + openEuler评分: + [OES]此处为填写openEuler评分的内容[/OES] + openEuler向量: + [OEV]此处为填写openEuler向量的内容[/OEV] + 影响的版本: + [IV]此处为填写影响版本的内容[/IV] + 规避方案和措施: + [CPMM]此处为填写规避方案和措施的内容[/CPMM] + 影响的包: + [IW]此处为填写影响的包的内容(内容以英文逗号分隔)[/IW] + /done + + #### 新模板内容 #### + - [Y]表示不需要填写,或者可以修改 | [N]需要填写且必填 | [?] 无法判断是否已填写 + + |是否填写 | 模板名称 | 模板内容 | 模板标签 | + |------- | ------------- | ------------- | ------------- | + | [N] | 影响性分析说明 | [IAD]此处为填写影响分析说明的内容[/IAD] | [IAD][/IAD] | + | [N] | openEuler评分 | [OES]此处为填写openEuler评分的内容[/OES] | [OES][/OES] | + | [N] | 影响的版本 | [IV]此处为填写影响版本的内容[/IV] | [IV][/IV] | + + #### 具体示例如下: #### + - 分析issue填写模板(ps 每一次分析评论必须用/analysis指令 填写项可以一次填完也可不填写完 填写完成加上/done指令 请拷贝以下内容: + /analysis + 影响性分析说明: + [IAD]此处为填写影响分析说明的内容[/IAD] + openEuler评分: + [OES]此处为填写openEuler评分的内容[/OES] + 影响的版本: + [IV]此处为填写影响版本的内容[/IV] + /done \ No newline at end of file diff --git a/doc/sql/db_struct.sql b/doc/sql/db_struct.sql index 1c3f2ca7b33f5df1b18efd037df40fa6b74f88cb..dae840031beecaa0e1460f06b31f608e3e9721aa 100644 --- a/doc/sql/db_struct.sql +++ b/doc/sql/db_struct.sql @@ -28,6 +28,18 @@ CREATE TABLE `cve_admin_user` ( PRIMARY KEY (`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*Table structure for table `cve_export_record` */ + +DROP TABLE IF EXISTS `cve_export_record`; + +CREATE TABLE `cve_export_record` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `file_name` varchar(255) NOT NULL DEFAULT '', + `create_time` datetime NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `file_name` (`file_name`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; + /*Table structure for table `cve_git_open_euler` */ DROP TABLE IF EXISTS `cve_git_open_euler`; @@ -59,7 +71,21 @@ CREATE TABLE `cve_git_open_euler` ( KEY `cve_git_open_euler_package_id` (`package_id`), KEY `cve_git_open_euler_version` (`version`), KEY `cve_git_open_euler_table_id` (`table_id`) -) ENGINE=InnoDB AUTO_INCREMENT=9860 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=8159 DEFAULT CHARSET=utf8; + +/*Table structure for table `cve_git_open_euler_table_relate` */ + +DROP TABLE IF EXISTS `cve_git_open_euler_table_relate`; + +CREATE TABLE `cve_git_open_euler_table_relate` ( + `relate_id` bigint NOT NULL AUTO_INCREMENT, + `git_id` bigint NOT NULL DEFAULT '0', + `brands` varchar(256) NOT NULL DEFAULT '', + `table_name` varchar(256) NOT NULL DEFAULT '', + PRIMARY KEY (`relate_id`), + UNIQUE KEY `cve_git_open_euler_table_gitid_tab_un` (`git_id`,`table_name`), + KEY `cve_git_open_euler_table_relate_git_id` (`git_id`) +) ENGINE=InnoDB AUTO_INCREMENT=4570 DEFAULT CHARSET=utf8; /*Table structure for table `cve_git_package_info` */ @@ -90,7 +116,7 @@ CREATE TABLE `cve_git_package_info` ( KEY `cve_git_package_info_git_id` (`git_id`), KEY `cve_git_package_info_git_ids` (`git_ids`), KEY `cve_git_package_info_version` (`version`) -) ENGINE=InnoDB AUTO_INCREMENT=4794 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=979 DEFAULT CHARSET=utf8; /*Table structure for table `cve_git_package_table` */ @@ -99,8 +125,20 @@ DROP TABLE IF EXISTS `cve_git_package_table`; CREATE TABLE `cve_git_package_table` ( `table_id` bigint NOT NULL AUTO_INCREMENT, `table_name` varchar(128) NOT NULL DEFAULT '', + `brands` varchar(256) NOT NULL DEFAULT '', PRIMARY KEY (`table_id`) -) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8; + +/*Table structure for table `cve_git_repo_groups` */ + +DROP TABLE IF EXISTS `cve_git_repo_groups`; + +CREATE TABLE `cve_git_repo_groups` ( + `group_id` bigint NOT NULL AUTO_INCREMENT, + `group_name` varchar(255) NOT NULL DEFAULT '', + PRIMARY KEY (`group_id`), + KEY `cve_git_repo_groups_group_name` (`group_name`) +) ENGINE=InnoDB AUTO_INCREMENT=72 DEFAULT CHARSET=utf8; /*Table structure for table `cve_git_sub_pack` */ @@ -114,7 +152,7 @@ CREATE TABLE `cve_git_sub_pack` ( PRIMARY KEY (`sub_id`), KEY `cve_git_sub_pack_detail_id` (`detail_id`), KEY `cve_git_sub_pack_ids` (`ids`) -) ENGINE=InnoDB AUTO_INCREMENT=16942 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=2438 DEFAULT CHARSET=utf8; /*Table structure for table `cve_git_sub_pack_provides` */ @@ -129,7 +167,7 @@ CREATE TABLE `cve_git_sub_pack_provides` ( PRIMARY KEY (`provide_id`), KEY `cve_git_sub_pack_provides_sub_id` (`sub_id`), KEY `cve_git_sub_pack_provides_ids` (`ids`) -) ENGINE=InnoDB AUTO_INCREMENT=87847 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=10556 DEFAULT CHARSET=utf8; /*Table structure for table `cve_git_sub_pack_require` */ @@ -144,7 +182,7 @@ CREATE TABLE `cve_git_sub_pack_require` ( PRIMARY KEY (`require_id`), KEY `cve_git_sub_pack_require_sub_id` (`sub_id`), KEY `cve_git_sub_pack_require_ids` (`ids`) -) ENGINE=InnoDB AUTO_INCREMENT=110712 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=13525 DEFAULT CHARSET=utf8; /*Table structure for table `cve_git_sub_pack_requiredby` */ @@ -156,7 +194,91 @@ CREATE TABLE `cve_git_sub_pack_requiredby` ( `requiredb` varchar(256) NOT NULL DEFAULT '', PRIMARY KEY (`id`), KEY `cve_git_sub_pack_requiredby_provide_id` (`provide_id`) -) ENGINE=InnoDB AUTO_INCREMENT=127479 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=2214 DEFAULT CHARSET=utf8; + +/*Table structure for table `cve_gite_origin_issue` */ + +DROP TABLE IF EXISTS `cve_gite_origin_issue`; + +CREATE TABLE `cve_gite_origin_issue` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `issue_id` bigint NOT NULL DEFAULT '0', + `url` varchar(255) NOT NULL DEFAULT '', + `number` varchar(50) NOT NULL DEFAULT '', + `state` varchar(50) NOT NULL DEFAULT '', + `title` varchar(255) DEFAULT NULL, + `cve_number` varchar(255) NOT NULL DEFAULT '', + `body` longtext, + `issue_create` varchar(255) NOT NULL DEFAULT '', + `issue_assignee` varchar(255) DEFAULT NULL, + `repo_path` varchar(255) NOT NULL DEFAULT '', + `repo_url` varchar(255) NOT NULL DEFAULT '', + `issue_type` varchar(255) NOT NULL DEFAULT '', + `issue_exist_tpl` tinyint(1) NOT NULL DEFAULT '0', + `security_hole` tinyint(1) NOT NULL DEFAULT '0', + `issue_create_at` datetime DEFAULT NULL, + `issue_update_at` datetime DEFAULT NULL, + `issue_finish_at` datetime DEFAULT NULL, + `grab_time` datetime NOT NULL, + `proc_status` tinyint NOT NULL DEFAULT '0', + `inf_product` varchar(255) DEFAULT NULL, + `repo_desc` varchar(2048) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `issue_id` (`issue_id`), + UNIQUE KEY `number` (`number`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +/*Table structure for table `cve_gite_repo` */ + +DROP TABLE IF EXISTS `cve_gite_repo`; + +CREATE TABLE `cve_gite_repo` ( + `repo_id` bigint NOT NULL AUTO_INCREMENT, + `group_id` bigint NOT NULL DEFAULT '0', + `org_id` bigint NOT NULL DEFAULT '0', + `org_path` varchar(128) DEFAULT NULL, + `path` varchar(512) DEFAULT NULL, + `status` tinyint DEFAULT '0', + `public` tinyint(1) NOT NULL DEFAULT '0', + `private` tinyint(1) NOT NULL DEFAULT '0', + `fork` tinyint(1) NOT NULL DEFAULT '0', + `create_time` varchar(255) DEFAULT NULL, + `update_time` varchar(255) DEFAULT NULL, + `delete_time` varchar(255) DEFAULT NULL, + PRIMARY KEY (`repo_id`), + KEY `cve_gite_repo_group_id` (`group_id`) +) ENGINE=InnoDB AUTO_INCREMENT=7072 DEFAULT CHARSET=utf8; + +/*Table structure for table `cve_gite_repo_branch` */ + +DROP TABLE IF EXISTS `cve_gite_repo_branch`; + +CREATE TABLE `cve_gite_repo_branch` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `repo_id` bigint NOT NULL DEFAULT '0', + `protection_url` varchar(255) NOT NULL DEFAULT '', + `name` varchar(255) NOT NULL DEFAULT '', + `protected` varchar(255) NOT NULL DEFAULT '', + PRIMARY KEY (`id`), + KEY `cve_gite_repo_branch_repo_id` (`repo_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +/*Table structure for table `cve_gite_repo_member` */ + +DROP TABLE IF EXISTS `cve_gite_repo_member`; + +CREATE TABLE `cve_gite_repo_member` ( + `repo_id` bigint NOT NULL AUTO_INCREMENT, + `group_id` bigint NOT NULL DEFAULT '0', + `member_name` varchar(512) DEFAULT NULL, + `member_type` varchar(128) DEFAULT NULL, + `create_time` varchar(255) DEFAULT NULL, + `update_time` varchar(255) DEFAULT NULL, + `delete_time` varchar(255) DEFAULT NULL, + PRIMARY KEY (`repo_id`), + KEY `cve_gite_repo_member_group_id` (`group_id`), + CONSTRAINT `member_groups_group_id` FOREIGN KEY (`group_id`) REFERENCES `cve_git_repo_groups` (`group_id`) +) ENGINE=InnoDB AUTO_INCREMENT=437 DEFAULT CHARSET=utf8; /*Table structure for table `cve_ip_white` */ @@ -169,7 +291,7 @@ CREATE TABLE `cve_ip_white` ( `access_count` bigint NOT NULL DEFAULT '0', PRIMARY KEY (`ip_id`), KEY `cve_ip_white_machine_ip` (`machine_ip`) -) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; /*Table structure for table `cve_issue_hooks` */ @@ -189,10 +311,15 @@ CREATE TABLE `cve_issue_hooks` ( `issues_events` tinyint NOT NULL DEFAULT '1', `note_events` tinyint NOT NULL DEFAULT '1', `merge_requests_events` tinyint NOT NULL DEFAULT '1', + `status` tinyint NOT NULL DEFAULT '1', + `create_time` varchar(32) NOT NULL DEFAULT '', + `update_time` varchar(32) DEFAULT NULL, + `delete_time` varchar(32) DEFAULT NULL, PRIMARY KEY (`id`), - KEY `cve_issue_hooks_issue_num` (`issue_num`), - KEY `cve_issue_hooks_Cve_id` (`cve_id`) -) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8; + UNIQUE KEY `cve_issue_hooks_owner_repo_status_un` (`owner`,`repo`,`hook_url`,`status`), + KEY `cve_issue_hooks_Cve_id` (`cve_id`), + KEY `cve_issue_hooks_issue_num` (`issue_num`) +) ENGINE=InnoDB AUTO_INCREMENT=33 DEFAULT CHARSET=utf8; /*Table structure for table `cve_issue_template` */ @@ -234,9 +361,10 @@ CREATE TABLE `cve_issue_template` ( `update_time` datetime NOT NULL, `delete_time` datetime NOT NULL, PRIMARY KEY (`template_id`), + UNIQUE KEY `cve_issue_template_cvn_issnu` (`cve_num`,`issue_num`), KEY `cve_issue_template_cve_id` (`cve_id`), KEY `cve_issue_template_issue_num` (`issue_num`) -) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8; /*Table structure for table `cve_open_euler_s_a` */ @@ -250,7 +378,42 @@ CREATE TABLE `cve_open_euler_s_a` ( PRIMARY KEY (`openeuler_id`), UNIQUE KEY `openeuler_sa_num` (`openeuler_sa_num`), KEY `cve_open_euler_s_a_cve_id` (`cve_id`) -) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=utf8; + +/*Table structure for table `cve_origin_excel` */ + +DROP TABLE IF EXISTS `cve_origin_excel`; + +CREATE TABLE `cve_origin_excel` ( + `cve_id` bigint NOT NULL AUTO_INCREMENT, + `cve_num` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, + `cve_url` varchar(2048) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, + `cve_version` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, + `pack_name` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, + `score_type` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, + `nvd_score` decimal(10,1) DEFAULT NULL, + `cve_level` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, + `cve_desc` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci, + `repair_time` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, + `vector_value` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, + `attack_vector` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, + `access_vector` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, + `attack_complexity` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, + `access_complexity` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, + `privilege_required` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, + `user_interaction` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, + `scope` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, + `confidentiality` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, + `integrity` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, + `availability` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, + `authentication` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, + `cve_status` tinyint DEFAULT NULL, + `create_time` datetime DEFAULT NULL, + `update_time` datetime DEFAULT NULL, + `delete_time` datetime DEFAULT NULL, + PRIMARY KEY (`cve_id`) USING BTREE, + UNIQUE KEY `cve_origin_excel_num_un` (`cve_num`) +) ENGINE=InnoDB AUTO_INCREMENT=149 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC; /*Table structure for table `cve_origin_upstream` */ @@ -283,7 +446,7 @@ CREATE TABLE `cve_origin_upstream` ( KEY `cve_origin_upstream_cve_packname` (`cve_packname`), KEY `cve_origin_upstream_git_packname` (`git_packname`), KEY `cve_origin_upstream_version` (`version`) -) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=25 DEFAULT CHARSET=utf8; /*Table structure for table `cve_origin_upstream_config` */ @@ -295,7 +458,7 @@ CREATE TABLE `cve_origin_upstream_config` ( `nodes` varchar(32) DEFAULT NULL, PRIMARY KEY (`conf_id`), KEY `cve_origin_upstream_config_cve_id` (`cve_id`) -) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=49 DEFAULT CHARSET=utf8; /*Table structure for table `cve_origin_upstream_config_node` */ @@ -307,7 +470,7 @@ CREATE TABLE `cve_origin_upstream_config_node` ( `operator` varchar(256) DEFAULT NULL, PRIMARY KEY (`node_id`), KEY `cve_origin_upstream_config_node_conf_id` (`conf_id`) -) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=69 DEFAULT CHARSET=utf8; /*Table structure for table `cve_origin_upstream_config_node_cpe` */ @@ -321,7 +484,7 @@ CREATE TABLE `cve_origin_upstream_config_node_cpe` ( `vulner_able` varchar(64) DEFAULT NULL, PRIMARY KEY (`cpe_id`), KEY `cve_origin_upstream_config_node_cpe_node_id` (`node_id`) -) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=2601 DEFAULT CHARSET=utf8; /*Table structure for table `cve_origin_upstream_desc` */ @@ -334,7 +497,7 @@ CREATE TABLE `cve_origin_upstream_desc` ( `zh_desc` text CHARACTER SET utf8 COLLATE utf8_general_ci, PRIMARY KEY (`desc_id`), KEY `cve_origin_upstream_desc_cve_id` (`cve_id`) -) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=49 DEFAULT CHARSET=utf8; /*Table structure for table `cve_origin_upstream_event` */ @@ -349,7 +512,7 @@ CREATE TABLE `cve_origin_upstream_event` ( `description` text CHARACTER SET utf8 COLLATE utf8_general_ci, PRIMARY KEY (`event_id`), KEY `cve_origin_upstream_event_cve_id` (`cve_id`) -) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=49 DEFAULT CHARSET=utf8; /*Table structure for table `cve_origin_upstream_fix_suggest` */ @@ -361,7 +524,7 @@ CREATE TABLE `cve_origin_upstream_fix_suggest` ( `detail` varchar(1024) DEFAULT NULL, PRIMARY KEY (`fix_id`), KEY `cve_origin_upstream_fix_suggest_cve_id` (`cve_id`) -) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=49 DEFAULT CHARSET=utf8; /*Table structure for table `cve_origin_upstream_fix_suggest_ref` */ @@ -375,7 +538,7 @@ CREATE TABLE `cve_origin_upstream_fix_suggest_ref` ( `name` varchar(1024) DEFAULT NULL, PRIMARY KEY (`fix_ref_id`), KEY `cve_origin_upstream_fix_suggest_ref_fix_id` (`fix_id`) -) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8; /*Table structure for table `cve_origin_upstream_fix_suggest_ref_tag` */ @@ -387,7 +550,7 @@ CREATE TABLE `cve_origin_upstream_fix_suggest_ref_tag` ( `name` varchar(512) DEFAULT NULL, PRIMARY KEY (`tag_id`), KEY `cve_origin_upstream_fix_suggest_ref_tag_fix_ref_id` (`fix_ref_id`) -) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=34 DEFAULT CHARSET=utf8; /*Table structure for table `cve_origin_upstream_impact` */ @@ -399,7 +562,7 @@ CREATE TABLE `cve_origin_upstream_impact` ( `impact` varchar(32) DEFAULT NULL, PRIMARY KEY (`impact_id`), KEY `cve_origin_upstream_impact_cve_id` (`cve_id`) -) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=49 DEFAULT CHARSET=utf8; /*Table structure for table `cve_origin_upstream_impact_score` */ @@ -415,7 +578,7 @@ CREATE TABLE `cve_origin_upstream_impact_score` ( `score_status` tinyint DEFAULT '1', PRIMARY KEY (`score_id`), KEY `cve_origin_upstream_impact_score_impact_id` (`impact_id`) -) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=97 DEFAULT CHARSET=utf8; /*Table structure for table `cve_origin_upstream_impact_score_v2` */ @@ -444,7 +607,7 @@ CREATE TABLE `cve_origin_upstream_impact_score_v2` ( `cve_level` varchar(32) DEFAULT NULL, PRIMARY KEY (`v2_id`), KEY `cve_origin_upstream_impact_score_v2_score_id` (`score_id`) -) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=49 DEFAULT CHARSET=utf8; /*Table structure for table `cve_origin_upstream_impact_score_v3` */ @@ -470,7 +633,7 @@ CREATE TABLE `cve_origin_upstream_impact_score_v3` ( `cve_level` varchar(32) DEFAULT NULL, PRIMARY KEY (`v3_id`), KEY `cve_origin_upstream_impact_score_v3_score_id` (`score_id`) -) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=49 DEFAULT CHARSET=utf8; /*Table structure for table `cve_origin_upstream_poc` */ @@ -487,7 +650,7 @@ CREATE TABLE `cve_origin_upstream_poc` ( `desc` text CHARACTER SET utf8 COLLATE utf8_general_ci, PRIMARY KEY (`poc_id`), KEY `cve_origin_upstream_poc_cve_id` (`cve_id`) -) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=49 DEFAULT CHARSET=utf8; /*Table structure for table `cve_origin_upstream_reference` */ @@ -502,7 +665,7 @@ CREATE TABLE `cve_origin_upstream_reference` ( `tags` text CHARACTER SET utf8 COLLATE utf8_general_ci, PRIMARY KEY (`ref_id`), KEY `cve_origin_upstream_reference_cve_id` (`cve_id`) -) ENGINE=InnoDB AUTO_INCREMENT=37 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=1089 DEFAULT CHARSET=utf8; /*Table structure for table `cve_origin_upstream_vul_type` */ @@ -516,7 +679,7 @@ CREATE TABLE `cve_origin_upstream_vul_type` ( `zh_desc` text CHARACTER SET utf8 COLLATE utf8_general_ci, PRIMARY KEY (`vul_id`), KEY `cve_origin_upstream_vul_type_cve_id` (`cve_id`) -) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=49 DEFAULT CHARSET=utf8; /*Table structure for table `cve_other_user` */ @@ -582,10 +745,16 @@ CREATE TABLE `cve_score` ( `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `delete_time` datetime NOT NULL, + `n_access_vector` varchar(256) DEFAULT NULL, + `o_access_vector` varchar(256) DEFAULT NULL, + `n_access_complexity` varchar(64) DEFAULT NULL, + `o_access_complexity` varchar(64) DEFAULT NULL, + `n_authentication` varchar(64) DEFAULT NULL, + `o_authentication` varchar(64) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `openeuler_id` (`openeuler_id`), KEY `cve_score_cve_id` (`cve_id`) -) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=utf8; /*Table structure for table `cve_score_record` */ @@ -600,7 +769,7 @@ CREATE TABLE `cve_score_record` ( `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `cve_score_record_cve_id` (`cve_id`) -) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=utf8; /*Table structure for table `cve_security_notice` */ @@ -626,7 +795,7 @@ CREATE TABLE `cve_security_notice` ( PRIMARY KEY (`sec_id`), UNIQUE KEY `openeuler_id` (`openeuler_id`), KEY `cve_security_notice_cve_id` (`cve_id`) -) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=utf8; /*Table structure for table `cve_security_reviewer` */ @@ -637,7 +806,7 @@ CREATE TABLE `cve_security_reviewer` ( `name_space` varchar(255) NOT NULL DEFAULT '', PRIMARY KEY (`id`), UNIQUE KEY `name_space` (`name_space`) -) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; +) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8; /*Table structure for table `cve_vuln_center` */ @@ -651,14 +820,16 @@ CREATE TABLE `cve_vuln_center` ( `cve_status` tinyint NOT NULL DEFAULT '0', `cve_version` varchar(128) NOT NULL DEFAULT '', `repair_time` varchar(32) NOT NULL DEFAULT '', - `pack_name` varchar(1024) NOT NULL DEFAULT '', + `pack_name` varchar(512) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', `cve_url` varchar(2048) NOT NULL DEFAULT '', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `delete_time` datetime NOT NULL, + `is_export` tinyint NOT NULL DEFAULT '0', PRIMARY KEY (`cve_id`), - UNIQUE KEY `cve_num` (`cve_num`) -) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8; + UNIQUE KEY `cve_vuln_c_n_pk_v_un` (`cve_num`,`cve_version`,`pack_name`), + KEY `cve_vuln_center_cve_num` (`cve_num`) +) ENGINE=InnoDB AUTO_INCREMENT=46 DEFAULT CHARSET=utf8; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; diff --git a/git b/git new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/go.mod b/go.mod index 68466c20f9addecb88c8fd070f3ee523393ed9cc..157bff73de86da6a7eb20796076b5d96bdc766a2 100644 --- a/go.mod +++ b/go.mod @@ -13,4 +13,5 @@ require ( golang.org/x/sys v0.0.0-20200819091447-39769834ee22 // indirect golang.org/x/text v0.3.2 // indirect gopkg.in/yaml.v2 v2.3.0 // indirect + github.com/360EntSecGroup-Skylar/excelize/v2 v2.3.0 ) diff --git a/main.go b/main.go index d80e0ea7d6a82e98f2833989eece809cd5e45f06..2991512144dd3cc9889b80b72f6bcac00f252eab 100644 --- a/main.go +++ b/main.go @@ -17,6 +17,9 @@ func init() { models.Initdb() // 初始化定时任务 task.InitTask() + // test 后续删除 + //test.Init() + } func main() { diff --git a/models/cve.go b/models/cve.go index 2d45af1ab5226846d725327c73388ed53328cd6e..c05f15271c9a632b5d779f7152071b35f5c88e9a 100644 --- a/models/cve.go +++ b/models/cve.go @@ -2,146 +2,213 @@ package models import ( "cvevulner/common" + "fmt" "github.com/astaxie/beego/logs" "github.com/astaxie/beego/orm" ) +func QueryOriginCveExcel(days string, prcnum int) ([]OriginExcel, int64, error) { + o := orm.NewOrm() + var coe []OriginExcel + num, err := o.Raw("select cve_id,cve_num,cve_url, cve_version, pack_name,"+ + "score_type,nvd_score,cve_level,cve_desc,repair_time,vector_value,attack_vector,access_vector,attack_complexity,"+ + "access_complexity,privilege_required,user_interaction,scope,confidentiality,integrity,availability,authentication,"+ + "cve_status,create_time from cve_origin_excel where update_time >= ? and cve_status in (?, ?)"+ + "order by cve_id asc limit ?", days, 0, 1, prcnum).QueryRows(&coe) + if err == nil && num > 0 { + logs.Info("cve_origin_excel 查询结果: ", num) + } else { + logs.Info("当前无新增或者更新的cve, cur_time:", common.GetCurTime(), "err: ", err) + } + return coe, num, err +} + +func UpdateCveIssueStatusById(status int, issueId int64) (id int64) { + o := orm.NewOrm() + _ = o.Raw("UPDATE cve_gite_origin_issue SET proc_status = ?, issue_update_at = ?"+ + " WHERE id = ?", status, common.GetCurTime(), issueId).QueryRow() + return +} + +func QueryOriginCveIssue(prcnum int) ([]GiteOriginIssue, int64, error) { + o := orm.NewOrm() + var gs []GiteOriginIssue + num, err := o.Raw("select *"+ + " from cve_gite_origin_issue where proc_status = ? "+ + "order by id asc limit ?", 0, prcnum).QueryRows(&gs) + if err == nil && num > 0 { + logs.Info("cve_gite_origin_issue 查询结果: ", num) + } else { + logs.Info("当前无新增或者更新的cveissue, cve_gite_origin_issue, cur_time:", common.GetCurTime(), "err: ", err) + } + return gs, num, err +} + func QueryOriginCve(days string, prcnum int) ([]OriginUpstream, int64, error) { o := orm.NewOrm() - var os []OriginUpstream - num, err := o.Raw("select cve_id,cve_un_ids,cve_num, update_type,cve_packname," + + var gs []OriginUpstream + num, err := o.Raw("select cve_id,cve_un_ids,cve_num, update_type,cve_packname,"+ "git_packname,cve_title,affect_porduct,cnnvd_id,cnvd_id,published_date,vul_status,cve_status,version"+ " from cve_origin_upstream where update_time >= ? and cve_status in (?, ?) and is_exit = ? "+ - "order by cve_id asc limit ?", days, 0, 1, 1, prcnum).QueryRows(&os) + "order by cve_id asc limit ?", days, 0, 1, 1, prcnum).QueryRows(&gs) if err == nil && num > 0 { logs.Info("cve_origin_upstream 查询结果: ", num) } else { logs.Info("当前无新增或者更新的cve, cur_time:", common.GetCurTime(), "err: ", err) } - return os, num, err + return gs, num, err } - -func QueryCveDesc(cveId int64) (OriginUpstreamDesc, bool){ +func QueryCveDesc(cveId int64) (OriginUpstreamDesc, bool) { o := orm.NewOrm() var cveDesc OriginUpstreamDesc err := o.Raw("select * from cve_origin_upstream_desc where cve_id = ?", cveId).QueryRow(&cveDesc) if err != nil { logs.Error(cveId, "cve_origin_upstream_desc cve描述查询不到") - return cveDesc,false + return cveDesc, false } else { - return cveDesc,true + return cveDesc, true } } -func QueryCveImpact(cveId int64) (OriginUpstreamImpact, bool){ +func QueryCveImpact(cveId int64) (OriginUpstreamImpact, bool) { o := orm.NewOrm() var cveImpact OriginUpstreamImpact err := o.Raw("select * from cve_origin_upstream_impact where cve_id = ?", cveId).QueryRow(&cveImpact) if err != nil { logs.Error(cveId, "cve_origin_upstream_impact cve impact查询不到") - return cveImpact,false + return cveImpact, false } else { - return cveImpact,true + return cveImpact, true } } -func QueryCveScore(impactId int64, typex string) (OriginUpstreamImpactScore, bool){ +func QueryCveScore(impactId int64, typex string) (OriginUpstreamImpactScore, bool) { o := orm.NewOrm() var cveScore OriginUpstreamImpactScore if typex == "v3" { - err := o.Raw("select * from cve_origin_upstream_impact_score where " + + err := o.Raw("select * from cve_origin_upstream_impact_score where "+ "impact_id = ? and base_met_v3=? and cvss_v3=?", impactId, 1, 1).QueryRow(&cveScore) if err != nil { logs.Error(impactId, "cve_origin_upstream_impact_score cve score查询不到") - return cveScore,false + return cveScore, false } else { - return cveScore,true + return cveScore, true } } else { - err := o.Raw("select * from cve_origin_upstream_impact_score where " + + err := o.Raw("select * from cve_origin_upstream_impact_score where "+ "impact_id = ? and base_met_v2=? and cvss_v2=?", impactId, 1, 1).QueryRow(&cveScore) if err != nil { logs.Error(impactId, "cve_origin_upstream_impact_score cve score查询不到") - return cveScore,false + return cveScore, false } else { - return cveScore,true + return cveScore, true } } } -func QueryCveCvssV3(scoreId int64) (OriginUpstreamImpactScoreV3, bool){ +func QueryCveCvssV3(scoreId int64) (OriginUpstreamImpactScoreV3, bool) { o := orm.NewOrm() var cveScoreV3 OriginUpstreamImpactScoreV3 err := o.Raw("select * from cve_origin_upstream_impact_score_v3 where score_id = ?", scoreId).QueryRow(&cveScoreV3) if err != nil { logs.Error(scoreId, "cve_origin_upstream_impact_score_v3 cve cvssv3 查询不到") - return cveScoreV3,false + return cveScoreV3, false } else { - return cveScoreV3,true + return cveScoreV3, true } } -func QueryCveByNum(cvenum string) (VulnCenter, bool){ +func QueryCveCvssV2(scoreId int64) (OriginUpstreamImpactScoreV2, bool) { + o := orm.NewOrm() + var cveScoreV2 OriginUpstreamImpactScoreV2 + err := o.Raw("select * from cve_origin_upstream_impact_score_v2 where score_id = ?", scoreId).QueryRow(&cveScoreV2) + if err != nil { + logs.Error(scoreId, "cve_origin_upstream_impact_score_v2 cve cvssv2 查询不到") + return cveScoreV2, false + } else { + return cveScoreV2, true + } +} + +func QueryCveByNum(cveNum, packName, version string) (VulnCenter, bool) { o := orm.NewOrm() var cve VulnCenter - err := o.Raw("select * from cve_vuln_center where cve_num = ?", cvenum).QueryRow(&cve) + err := o.Raw("select * from cve_vuln_center where cve_num = ? and pack_name = ? and cve_version = ?", + cveNum, packName, version).QueryRow(&cve) if err != nil { - logs.Error(cvenum, "cve_vuln_center 查询不到") - return cve,false + logs.Error(cveNum, packName, version, "cve_vuln_center 查询不到, err: ", err) + return cve, false } else { - return cve,true + return cve, true + } +} + +func UpdateCveStatusExportByNum(updatetime, cveNum string, status, isExport int, repoPath string) bool { + o := orm.NewOrm() + res, err := o.Raw("UPDATE cve_vuln_center SET "+ + "is_export = ?, cve_status = ?, update_time = ? where cve_num = ? and pack_name = ?", isExport, status, updatetime, cveNum, repoPath).Exec() + if err == nil { + num, _ := res.RowsAffected() + if num > 0 { + logs.Info("cve_vuln_center row affected nums: ", num, ",cveNum: ", cveNum, ",", updatetime) + return true + } + return false + } else { + logs.Error("更新失败, cve_vuln_center, ", ",cveNum: ", cveNum, ",", updatetime, ", err: ", err) + return false } } -func QueryScoreByCveId(CveId int64) (Score, bool){ +func QueryScoreByCveId(CveId int64) (Score, bool) { o := orm.NewOrm() var score Score err := o.Raw("select * from cve_score where cve_id = ?", CveId).QueryRow(&score) if err != nil { logs.Error(CveId, "cve_score 查询不到") - return score,false + return score, false } else { - return score,true + return score, true } } -func QueryOpenEulerSAByCveId(CveId int64) (OpenEulerSA, bool){ +func QueryOpenEulerSAByCveId(CveId int64) (OpenEulerSA, bool) { o := orm.NewOrm() op := OpenEulerSA{CveId: CveId} err := o.Read(&op, "CveId") if err == orm.ErrNoRows { logs.Error(CveId, "cve_open_euler_s_a 查询不到") - return op,false + return op, false } else if err == orm.ErrMissPK { logs.Error(CveId, "cve_open_euler_s_a pk 查询不到") - return op,false + return op, false } else { - return op,true + return op, true } } -func QuerySecNoticeByCveId(CveId int64) (SecurityNotice, bool){ +func QuerySecNoticeByCveId(CveId int64) (SecurityNotice, bool) { o := orm.NewOrm() var secNotice SecurityNotice err := o.Raw("select * from cve_security_notice where cve_id = ?", CveId).QueryRow(&secNotice) if err != nil { logs.Error(CveId, "cve_security_notice 查询不到") - return secNotice,false + return secNotice, false } else { - return secNotice,true + return secNotice, true } } -func CreateSecurityNotice(sec *SecurityNotice) (SecId int64, err error){ +func CreateSecurityNotice(sec *SecurityNotice) (SecId int64, err error) { o := orm.NewOrm() errs := o.Begin() if errs == nil { var num int64 if num, err = o.Insert(sec); err == nil { logs.Info("insert cve_security_notice success, num:, cveNum", num, sec.CveNum) - }else { + } else { logs.Error("insert cve_security_notice failed, cveNum:", sec.CveNum) o.Rollback() return 0, err @@ -155,7 +222,7 @@ func CreateSecurityNotice(sec *SecurityNotice) (SecId int64, err error){ return SecId, nil } -func CreateScore(score *Score) (Id int64, err error){ +func CreateScore(score *Score) (Id int64, err error) { o := orm.NewOrm() errs := o.Begin() if errs == nil { @@ -176,7 +243,7 @@ func CreateScore(score *Score) (Id int64, err error){ return Id, nil } -func CreateOpenEulerSA(op *OpenEulerSA) (OpenId int64, err error){ +func CreateOpenEulerSA(op *OpenEulerSA) (OpenId int64, err error) { o := orm.NewOrm() errs := o.Begin() if errs == nil { @@ -197,7 +264,7 @@ func CreateOpenEulerSA(op *OpenEulerSA) (OpenId int64, err error){ return OpenId, nil } -func CreateScoreRecord(sc *ScoreRecord) (scoreId int64, err error){ +func CreateScoreRecord(sc *ScoreRecord) (scoreId int64, err error) { o := orm.NewOrm() errs := o.Begin() if errs == nil { @@ -218,15 +285,32 @@ func CreateScoreRecord(sc *ScoreRecord) (scoreId int64, err error){ return scoreId, nil } -func CreateCveRelat(cve *VulnCenter, sec *SecurityNotice, score * Score, op *OpenEulerSA, sc *ScoreRecord) (cveid int64, err error) { +func InsertScoreRecord(sc *ScoreRecord) (int64, error) { + o := orm.NewOrm() + errs := o.Begin() + if errs == nil { + if num, err := o.Insert(sc); err == nil { + logs.Info("insert cve_score_record, num:, CveId:", num, sc.CveId) + } else { + logs.Error("insert cve_score_record failed, CveId:", sc.CveId, ",err: ", err) + o.Rollback() + return 0, err + } + o.Commit() + } + return 0, nil +} + +func CreateCveRelat(cve *VulnCenter, sec *SecurityNotice, score *Score, op *OpenEulerSA, sc *ScoreRecord) (cveid int64, err error) { o := orm.NewOrm() errs := o.Begin() if errs == nil { var num int64 + var err error if num, err = o.Insert(cve); err == nil { logs.Info("insert cve_vuln_center success, num:, cveNum:", num, cve.CveNum) } else { - logs.Error("insert cve_vuln_center failed, CveNum:", cve.CveNum) + logs.Error("insert cve_vuln_center failed, CveNum:", cve.CveNum, ",err: ", err) o.Rollback() return 0, err } @@ -236,7 +320,7 @@ func CreateCveRelat(cve *VulnCenter, sec *SecurityNotice, score * Score, op *Ope if num, err = o.Insert(op); err == nil { logs.Info("insert cve_open_euler_s_a success, num:, cveNum:", num, cve.CveNum) } else { - logs.Error("insert cve_open_euler_s_a failed, CveNum:", cve.CveNum) + logs.Error("insert cve_open_euler_s_a failed, CveNum:", cve.CveNum, ",err: ", err) o.Rollback() return 0, err } @@ -244,8 +328,8 @@ func CreateCveRelat(cve *VulnCenter, sec *SecurityNotice, score * Score, op *Ope score.OpenId = num if num, err = o.Insert(sec); err == nil { logs.Info("insert cve_security_notice success, num:, cveNum", num, cve.CveNum) - }else { - logs.Error("insert cve_security_notice failed, cveNum:", cve.CveNum) + } else { + logs.Error("insert cve_security_notice failed, cveNum:", cve.CveNum, ",err: ", err) o.Rollback() return 0, err } @@ -253,7 +337,7 @@ func CreateCveRelat(cve *VulnCenter, sec *SecurityNotice, score * Score, op *Ope if num, err = o.Insert(score); err == nil { logs.Info("insert cve_score success, num:, cveNum:", num, cve.CveNum) } else { - logs.Error("insert cve_score failed, CveNum:", cve.CveNum) + logs.Error("insert cve_score failed, CveNum:", cve.CveNum, ",err: ", err) o.Rollback() return 0, err } @@ -261,74 +345,97 @@ func CreateCveRelat(cve *VulnCenter, sec *SecurityNotice, score * Score, op *Ope if num, err = o.Insert(sc); err == nil { logs.Info("insert cve_score_record, num:, CveId:", num, cve.CveId) } else { - logs.Error("insert cve_score_record failed, CveId:", cve.CveId) + logs.Error("insert cve_score_record failed, CveId:", cve.CveId, ",err: ", err) o.Rollback() return 0, err } o.Commit() } else { - logs.Error("事务创建失败,CveId:", cve.CveId) + logs.Error("事务创建失败,CveId:", cve.CveId, ",err: ", errs) return 0, errs } return cveid, nil } -func UpdateCveRelat(cve *VulnCenter, sec *SecurityNotice, score * Score) (err error) { +func UpdateCveRelat(cve *VulnCenter, sec *SecurityNotice, score *Score) error { o := orm.NewOrm() errs := o.Begin() if errs == nil { var cv VulnCenter - err := o.Raw("select cve_id from cve_vuln_center where cve_id = ?", cve.CveId).QueryRow(&cv) - if err == nil { + cvError := o.Raw("select cve_id from cve_vuln_center where cve_id = ?", cve.CveId).QueryRow(&cv) + if cvError == nil { var num int64 + var err error cve.CveId = cv.CveId if num, err = o.Update(cve); err == nil { logs.Info("update cve_vuln_center success, num:, cveNum", num, cve.CveNum) - }else { - logs.Error("update cve_vuln_center failed, CveId:", cve.CveId) + } else { + logs.Error("update cve_vuln_center failed, CveId:", cve.CveId, ",err: ", err) o.Rollback() return err } } else { - logs.Error("update cve_security_notice failed, CveId:", cve.CveId) - o.Rollback() - return err + logs.Info("insert cve_vuln_center failed, CveId:", cve.CveId) + var num int64 + var err error + if num, err = o.Insert(cve); err == nil { + logs.Info("insert cve_vuln_center success, num:, cveNum:", num, cve.CveNum) + } else { + logs.Error("insert cve_vuln_center failed, CveNum:", cve.CveNum, ",err:", err) + o.Rollback() + return err + } + } var se SecurityNotice - err = o.Raw("select sec_id from cve_security_notice where cve_id = ?", cve.CveId).QueryRow(&se) - if err == nil { + seError := o.Raw("select sec_id from cve_security_notice where cve_id = ?", cve.CveId).QueryRow(&se) + if seError == nil { var num int64 sec.SecId = se.SecId + var err error if num, err = o.Update(sec); err == nil { logs.Info("update cve_security_notice success, num:, cve.CveId", num, cve.CveId) } else { - logs.Error("update cve_security_notice failed, CveId:", cve.CveId) + logs.Error("update cve_security_notice failed, CveId:", cve.CveId, ",err: ", err) + o.Rollback() + return err + } + } else { + sec.CveId = cve.CveId + var err error + var num int64 + if num, err = o.Insert(sec); err == nil { + logs.Info("insert cve_security_notice success, num:, cveNum:", num, cve.CveNum) + } else { + logs.Error("insert cve_security_notice failed, CveNum:", cve.CveNum, ",err:", err) o.Rollback() return err } - }else { - logs.Error("update cve_security_notice failed, CveId:", cve.CveId) - o.Rollback() - return err } var sc Score - err = o.Raw("select id from cve_score where cve_id = ?", cve.CveId).QueryRow(&sc) - if err == nil { + scError := o.Raw("select id from cve_score where cve_id = ?", cve.CveId).QueryRow(&sc) + if scError == nil { var num int64 score.Id = sc.Id + var err error if num, err = o.Update(score); err == nil { logs.Info("update cve_score success, num:, cve.CveId:", num, cve.CveId) } else { - logs.Error("update cve_score failed, CveId:", cve.CveId) + logs.Error("update cve_score failed, CveId:", cve.CveId, ",err: ", err) + o.Rollback() + return err + } + } else { + score.CveId = cve.CveId + if num, err := o.Insert(score); err == nil { + logs.Info("insert cve_score success, num:, cveNum:", num, cve.CveNum) + } else { + logs.Error("insert cve_score failed, CveNum:", cve.CveNum, ",err: ", err) o.Rollback() return err } - }else { - logs.Error("update cve_score failed, CveId:", cve.CveId) - o.Rollback() - return err } - }else { + } else { logs.Error("事务创建失败,CveId:", cve.CveId) return errs } @@ -345,15 +452,20 @@ func UpdateCveRelat1(cve *VulnCenter, sec *SecurityNotice) (err error) { var num int64 if num, err = o.Update(cve); err == nil { logs.Info("update cve_vuln_center success, num:, cveNum", num, cve.CveNum) - }else { - logs.Error("update cve_vuln_center failed, CveId:", cve.CveId) + } else { + logs.Error("update cve_vuln_center failed, CveId:", cve.CveId, ",err: ", err) o.Rollback() return err } } else { - logs.Error("update cve_security_notice failed, CveId:", cve.CveId) - o.Rollback() - return err + var num int64 + if num, err = o.Insert(cve); err == nil { + logs.Info("insert cve_vuln_center success, num:, cveNum:", num, cve.CveNum) + } else { + logs.Error("insert cve_vuln_center failed, CveNum:", cve.CveNum, ",err:", err) + o.Rollback() + return err + } } se := SecurityNotice{CveId: cve.CveId} if err = o.Read(&se, "CveId"); err == nil { @@ -361,24 +473,29 @@ func UpdateCveRelat1(cve *VulnCenter, sec *SecurityNotice) (err error) { if num, err = o.Update(sec); err == nil { logs.Info("update cve_security_notice success, num:, cve.CveId:", num, cve.CveId) } else { - logs.Error("update cve_security_notice failed, CveId:", cve.CveId) + logs.Error("update cve_security_notice failed, CveId:", cve.CveId, ",err: ", err) + o.Rollback() + return err + } + } else { + sec.CveId = cve.CveId + if num, err := o.Insert(sec); err == nil { + logs.Info("insert cve_security_notice success, num:, cveNum:", num, cve.CveNum) + } else { + logs.Error("insert cve_security_notice failed, CveNum:", cve.CveNum, ",err:", err) o.Rollback() return err } - }else { - logs.Error("update cve_security_notice failed, CveId:", cve.CveId) - o.Rollback() - return err } - }else { - logs.Error("事务创建失败,CveId:", cve.CveId) + } else { + logs.Error("事务创建失败,CveId:", cve.CveId, ",err: ", errs) return errs } o.Commit() return nil } -func UpdateCveRelat2(cve *VulnCenter, score * Score) (err error) { +func UpdateCveRelat2(cve *VulnCenter, score *Score) (err error) { o := orm.NewOrm() errs := o.Begin() if errs == nil { @@ -387,15 +504,20 @@ func UpdateCveRelat2(cve *VulnCenter, score * Score) (err error) { var num int64 if num, err = o.Update(cve); err == nil { logs.Info("update cve_vuln_center success, num:, cveNum", num, cve.CveNum) - }else { - logs.Error("update cve_vuln_center failed, CveId:", cve.CveId) + } else { + logs.Error("update cve_vuln_center failed, CveId:", cve.CveId, ", err: ", err) o.Rollback() return err } } else { - logs.Error("update cve_security_notice failed, CveId:", cve.CveId) - o.Rollback() - return err + var num int64 + if num, err = o.Insert(cve); err == nil { + logs.Info("insert cve_vuln_center success, num:, cveNum:", num, cve.CveNum) + } else { + logs.Error("insert cve_vuln_center failed, CveNum:", cve.CveNum, ",err:", err) + o.Rollback() + return err + } } sc := Score{CveId: cve.CveId} if err = o.Read(&sc, "CveId"); err == nil { @@ -403,24 +525,29 @@ func UpdateCveRelat2(cve *VulnCenter, score * Score) (err error) { if num, err = o.Update(score); err == nil { logs.Info("update cve_score success, num:, cve.CveId", num, cve.CveId) } else { - logs.Error("update cve_score failed, CveId:", cve.CveId) + logs.Error("update cve_score failed, CveId:", cve.CveId, ",err: ", err) + o.Rollback() + return err + } + } else { + score.CveId = cve.CveId + if num, err := o.Insert(score); err == nil { + logs.Info("insert cve_score success, num:, cveNum:", num, cve.CveNum) + } else { + logs.Error("insert cve_score failed, CveNum:", cve.CveNum, ",err: ", err) o.Rollback() return err } - }else { - logs.Error("update cve_score failed, CveId:", cve.CveId) - o.Rollback() - return err } - }else { - logs.Error("事务创建失败,CveId:", cve.CveId) + } else { + logs.Error("事务创建失败,CveId:", cve.CveId, ",err: ", errs) return errs } o.Commit() return nil } -func QueryOpenSaLastId() (OpenEulerSA, error){ +func QueryOpenSaLastId() (OpenEulerSA, error) { o := orm.NewOrm() var os OpenEulerSA err := o.Raw("select openeuler_id, openeuler_sa_num from cve_open_euler_s_a order by openeuler_id desc limit 1").QueryRow(&os) @@ -430,20 +557,124 @@ func QueryOpenSaLastId() (OpenEulerSA, error){ return os, err } +func UpdateOriginStatus(updateTime, pakName, version string, cveId int64, status int) bool { + o := orm.NewOrm() + res, err := o.Raw("UPDATE cve_origin_upstream SET "+ + "cve_status = ?, update_time = ? where cve_id = ? and git_packname = ? and version = ?", status, updateTime, cveId, pakName, version).Exec() + if err == nil { + num, _ := res.RowsAffected() + if num > 0 { + logs.Info("cve_origin_upstream row affected nums: ", num, ",cveId: ", cveId, ",", updateTime, pakName, version) + return true + } + return false + } else { + logs.Error("更新失败, cve_origin_upstream, ", ",cveId: ", cveId, ",", updateTime, pakName, version, ", err: ", err) + return false + } +} -func UpdateOriginStatus(updatetime, pakName, version string, cveId int64) (bool){ +func UpdateOriginExcelStatus(updateTime string, cveId int64, status int) bool { o := orm.NewOrm() - res, err := o.Raw("UPDATE cve_origin_upstream SET " + - "cve_status = ?, update_time = ? where cve_id = ? and git_packname = ? and version = ?", 2, updatetime, cveId, pakName, version).Exec() + res, err := o.Raw("UPDATE cve_origin_excel SET "+ + "cve_status = ?, update_time = ? where cve_id = ?", status, updateTime, cveId).Exec() if err == nil { num, _ := res.RowsAffected() if num > 0 { - logs.Info("cve_origin_upstream row affected nums: ", num, ",cveId: ", cveId, ",", updatetime, pakName, version) + logs.Info("cve_origin_excel row affected nums: ", num, ",cveId: ", cveId, ",", updateTime) return true } return false } else { - logs.Error("更新失败, cve_origin_upstream, ", ",cveId: ", cveId, ",", updatetime, pakName, version, ", err: ", err) + logs.Error("更新失败, cve_origin_excel, ", ",cveId: ", cveId, ",", updateTime, ", err: ", err) return false } -} \ No newline at end of file +} + +func UpdateVulnCenter(cve *VulnCenter, field ...string) bool { + o := orm.NewOrm() + _, err := o.Update(cve, field...) + if err != nil { + logs.Error(err) + return false + } + return true +} + +func GetVulnCenterByCid(cve *VulnCenter,field ...string) error { + o := orm.NewOrm() + err := o.Read(cve, field...) + return err +} + +func GetCanExportVulnCenterData() (data []VulnCenter, err error) { + o := orm.NewOrm() + qs := o.QueryTable("cve_vuln_center") + _, err = qs.Filter("is_export", 3).All(&data) + return +} + +func GetCvePackageList(secId int64) (data []Package, err error) { + o := orm.NewOrm() + qs := o.QueryTable("cve_package") + _, err = qs.Filter("sec_id", secId).All(&data) + return +} + +func GetCanExportVulnCenterCount() (count int64) { + sql := ` SELECT COUNT(*) total FROM (SELECT COUNT(*) num,bc.cve_id,bc.cve_num + FROM (SELECT DISTINCT cve_num FROM cve_vuln_center WHERE is_export = 3) ac + JOIN cve_vuln_center bc ON ac.cve_num = bc.cve_num GROUP BY bc.cve_num) a` + res := struct { + Total int64 + }{} + o := orm.NewOrm() + err := o.Raw(sql).QueryRow(&res) + //qs := o.QueryTable("cve_vuln_center") + //cot, err := qs.Filter("is_export", 3).Count() //.Filter("cve_status", 2) + if err != nil { + logs.Error(err) + return 0 + } + return res.Total +} + +func GetCanExportCveData(page int64, pageSize int) (list []ExcelExport, err error) { + sql := `SELECT b.num,c.*,a.owned_component,a.cve_brief, +d.sec_id,d.introduction,d.summary,d.theme,d.description,d.influence_component, +d.affect_product,d.reference_link,d.affect_status,e.public_date,openeuler_sa_num +FROM cve_issue_template a +RIGHT JOIN (SELECT COUNT(*) num,bc.cve_id,bc.cve_num FROM +(SELECT DISTINCT cve_num FROM cve_vuln_center WHERE is_export = 3) ac +JOIN cve_vuln_center bc ON ac.cve_num = bc.cve_num GROUP BY bc.cve_num LIMIT ?,? ) b +ON a.cve_id = b.cve_id +LEFT JOIN cve_score c +ON b.cve_id = c.cve_id +LEFT JOIN cve_security_notice d +ON b.cve_id = d.cve_id +LEFT JOIN cve_open_euler_s_a e +ON b.cve_id = e.cve_id +` + o := orm.NewOrm() + _, err = o.Raw(sql, page, pageSize).QueryRows(&list) + return +} + +func GetCanExportCveDataSameNum(cId string) (list []ExcelExport, err error) { + sql := `SELECT a.cve_id,a.owned_component,a.cve_brief,c.*,d.sec_id,d.introduction,d.summary,d.theme,d.description,d.influence_component, +d.affect_product,d.reference_link,d.affect_status,e.public_date,e.openeuler_sa_num +FROM cve_issue_template a +LEFT JOIN cve_score c +ON c.cve_id = a.cve_id +LEFT JOIN cve_security_notice d +ON d.cve_id = a.cve_id +LEFT JOIN cve_open_euler_s_a e +ON e.cve_id = a.cve_id +WHERE a.cve_id IN (%s) +ORDER BY c.openeuler_score DESC +` + sql = fmt.Sprintf(sql,cId) + o := orm.NewOrm() + _, err = o.Raw(sql).QueryRows(&list) + return +} diff --git a/models/cve_web.go b/models/cve_web.go new file mode 100644 index 0000000000000000000000000000000000000000..b15902991e185af2d3e9bed866a2da904c7d4c69 --- /dev/null +++ b/models/cve_web.go @@ -0,0 +1,18 @@ +package models + +type RespCommon struct { + Code int + Msg string + Success bool +} + +type CveDetail struct { + Id int64 + CveId string `json:"cveId"` + AffectedProduct string `json:"affectedProduct"` +} + +type RespCveDetail struct { + RespCommon + Result *CveDetail +} diff --git a/models/excel.go b/models/excel.go new file mode 100644 index 0000000000000000000000000000000000000000..97626898ed0a55965130faeae662f2fc7d3f12b0 --- /dev/null +++ b/models/excel.go @@ -0,0 +1,33 @@ +package models + +import "github.com/astaxie/beego/orm" + +type ExcelExport struct { + Num int64 + Score + CveBrief string `json:"cve_brief"` + OwnedComponent string `json:"owned_component"` + SecId int64 `json:"sec_id"` + Introduction string `json:"introduction"` + Summary string `json:"summary"` + Theme string `json:"theme"` + Description string `json:"description"` + InfluenceComponent string `json:"influence_component" orm:"size(256);null;column(influence_component)"` + AffectProduct string `json:"affect_product"` + ReferenceLink string `json:"reference_link"` + AffectStatus string `json:"affect_status"` + PublicDate string `json:"public_date"` + OpenEulerSANum string `json:"openeuler_sa_num" orm:"size(128);column(openeuler_sa_num)"` +} + +func (er ExportRecord) Insert() error { + o := orm.NewOrm() + _, err := o.Insert(&er) + return err +} + +func (er *ExportRecord) QueryLast() error { + o := orm.NewOrm() + err := o.QueryTable(er).OrderBy("-create_time").One(er) + return err +} diff --git a/models/giteeissue.go b/models/giteeissue.go index e0acc198c037ee53731fff89969a9136289bae20..4c41073ae6d4baa99e7b775122b0b76ce0da2ea1 100644 --- a/models/giteeissue.go +++ b/models/giteeissue.go @@ -1,27 +1,283 @@ package models -import "time" - -//GiteOriginIssue 码云上已经存在的issue -type GiteOriginIssue struct { - Id int64 `orm:"pk;auto"` - IssueId int64 `json:"issue_id" orm:"unique"` - Url string ` description:"issue gitee 链接"` - Number string `orm:"size(50);unique" description:"issue 编号"` - State string `orm:"size(50)" description:"issue 状态"` - Title string `orm:"null" description:"issue 标题"` - CveNumber string `json:"cve_number" description:"CVE 编号"` - Body string `orm:"null;type(text)" description:"issue 主体"` - IssueCreate string `json:"issue_create" description:"issue 创建者"` - IssueAssignee string `json:"issue_assignee" orm:"null" description:"issue 责任人"` - RepoPath string `json:"repo_path" description:"仓库空间地址"` - RepoUrl string `json:"repo_url" description:"仓库码云地址链接"` - IssueType string `json:"issue_type" description:"issue 类型"` - IssueExistTpl bool `json:"issue_exist_tpl" description:"此 issue 是否有对应的模板"` - SecurityHole bool `json:"security_hole" description:"是否为安全漏洞"` - IssueCreateAt time.Time `json:"issue_create_at" orm:"null" description:"issue 创建的时间"` - IssueUpdateAt time.Time `json:"issue_update_at" orm:"null" description:"issue 更新的时间"` - IssueFinishAt time.Time `json:"issue_finish_at" orm:"null" description:"issue 关闭的时间"` - GrabTime time.Time `json:"grab_time" orm:"auto_now;type(datetime)" description:"记录当前issue抓取的时间"` +import ( + "cvevulner/util" + "errors" + "github.com/astaxie/beego/logs" + "github.com/astaxie/beego/orm" +) + +//Loophole issue body model +type Loophole struct { + Number string //编号 + Components string // 漏洞归属的组件 + Version string // 漏洞归属的版本 + CvsScore string //cvss 评分 + CvsVector string //cvs向量 + BriefIntroduction string //漏洞简述 + Influences string //漏洞造成的影响 + Principle string //漏洞原理 + OpScore string //openEuler 评分 + OpVector string //openEuler 向量 + InfVersion string //受影响的组件版本 + AvoidScheme string //规避方案 + InfPackage string //受影响的软件包 + InfProduct string //受影响的产品 + Repo string //漏洞所属仓库 + RepoDesc string //组件描述 + ScoreType string //评分类型 v2 v3 +} + +//VectorValue cvss V3.0 vector model +type VectorValue struct { + AttackVector string //AV + AttackComplexity string //AC + PrivilegesRequired string //PR + UserInteraction string //UI + Scope string //S + Confidentiality string //C + Integrity string //I + Availability string //A +} + +//VectorValueV2 cvss v2 vector model +type VectorValueV2 struct { + AccessVector string //AV + AccessComplexity string //AC + Authentication string //Au + Confidentiality string //C + IntegrityImpact string //I + Availability string //A +} + +func (g *GiteOriginIssue) Insert() error { + o := orm.NewOrm() + _, err := o.Insert(g) + return err +} + +func (g GiteOriginIssue) Update() error { + o := orm.NewOrm() + _, err := o.Update(g) + return err +} + +func (g *GiteOriginIssue) InsertOrUpdate() error { + if g.Number == "" { + return errors.New("issue number can not be null") + } + o := orm.NewOrm() + ex := GiteOriginIssue{Number: g.Number} + err := o.Read(&ex, "number") + if err == nil { + g.Id = ex.Id + } + _, err = o.InsertOrUpdate(g) + return err +} + +func (g *GiteOriginIssue) ParseToLoophole() (hole Loophole, err error) { + lp := Loophole{} + if g.Body == "" { + return lp, errors.New("can not parse a null body") + } + lp.InfProduct = g.InfProduct + lp.Repo = g.RepoPath + lp.RepoDesc = g.RepoDesc + scoreType, err := judgeScoreType(g.Body) + if err != nil { + logs.Error(err) + } + lp.ScoreType = scoreType + if isNewTpl(g.Body) { + parseNewTplToLoopHole(&lp, g.Body) + } else { + parseOldTplToLoopHole(&lp, g.Body) + } + return lp, nil +} + +func (v *VectorValue) VctToVectorValue(vector string) bool { + if util.TrimString(vector) == "" { + return false + } + m, ok := util.VctToMap(vector) + if !ok { + return false + } + v.AttackVector = util.ReadVmValue(m["AV"]) + v.AttackComplexity = util.ReadVmValue(m["AC"]) + v.Availability = util.ReadVmValue(m["A"]) + v.Confidentiality = util.ReadVmValue(m["C"]) + v.Integrity = util.ReadVmValue(m["I"]) + v.PrivilegesRequired = util.ReadVmValue(m["PR"]) + v.UserInteraction = util.ReadVmValue(m["UI"]) + v.Scope = util.ReadVmValue(m["S"]) + return true +} + +func (v *VectorValueV2) VctToVectorValue(vector string) bool { + if util.TrimString(vector) == "" { + return false + } + m, ok := util.VctToMap(vector) + if !ok { + return false + } + v.AccessVector = util.ReadVmValueV2(m["AV"]) + v.AccessComplexity = util.ReadVmValueV2(m["AC"]) + v.Availability = util.ReadVmValueV2(m["A"]) + v.Confidentiality = util.ReadVmValueV2(m["C"]) + v.IntegrityImpact = util.ReadVmValueV2(m["I"]) + v.Authentication = util.ReadVmValueV2(m["Au"]) + return true +} + +func judgeScoreType(body string) (st string, err error) { + if body == "" { + return "", errors.New("can not judge score type by nil body") + } + tb := []byte(body) + vs := util.RegexpScoreTypeV2.Find(tb) + if len(vs) > 0 { + return util.CvsScoreV2, nil + } + vs = util.RegexpScoreTypeV3.Find(tb) + if len(vs) > 0 { + return util.CvsScoreV3, nil + } + return "", errors.New("can not judge score type") +} + +func isNewTpl(body string) bool { + tb := []byte(body) + v1 := util.RegexpIsNewTpl.Find(tb) + v2 := util.RegexpIsNewTpl2.Find(tb) + if len(v1) > 0 || len(v2) > 0 { + return false + } else { + return true + } +} + +func parseOldTplToLoopHole(lp *Loophole, body string) { + sm := util.RegexpCveNumber.FindAllStringSubmatch(body, -1) + if len(sm) > 0 && len(sm[0]) > 0 { + val := sm[0][1] + lp.Number = util.GetCveNumber(util.TrimString(val)) + } + sm = util.RegexpCveComponents.FindAllStringSubmatch(body, -1) + if len(sm) > 0 && len(sm[0]) > 0 { + lp.Components = util.TrimString(sm[0][1]) + } + sm = util.RegexpCveVersion.FindAllStringSubmatch(body, -1) + if len(sm) > 0 && len(sm[0]) > 0 { + lp.Version = util.TrimString(sm[0][1]) + } + sm = util.RegexpCveScore.FindAllStringSubmatch(body, -1) + if len(sm) > 0 && len(sm[0]) > 0 { + vs := util.TrimString(sm[0][1]) + if cs := util.ExtractDigital(vs); cs != "" { + lp.CvsScore = cs + } + if v := util.ExtractVector(vs, lp.ScoreType); v != "" { + lp.CvsVector = v + } + } + sm = util.RegexpCveBriefDesc.FindAllStringSubmatch(body, -1) + if len(sm) > 0 && len(sm[0]) > 0 { + //lp.BriefIntroduction = util.TrimString(sm[0][1]) + lp.BriefIntroduction = sm[0][1] + } + sm = util.RegexpCveInfluencesDesc.FindAllStringSubmatch(body, -1) + if len(sm) > 0 && len(sm[0]) > 0 { + //lp.Influences = util.TrimString(sm[0][1]) + lp.Influences = sm[0][1] + } + sm = util.RegexpCvePrincipleDesc.FindAllStringSubmatch(body, -1) + if len(sm) > 0 && len(sm[0]) > 0 { + //lp.Principle = util.TrimString(sm[0][1]) + lp.Principle = sm[0][1] + } + sm = util.RegexpCveOpScore.FindAllStringSubmatch(body, -1) + if len(sm) > 0 { + vp := util.TrimString(sm[0][1]) + if cs := util.ExtractDigital(vp); cs != "" { + lp.OpScore = cs + } + if v := util.ExtractVector(vp, lp.ScoreType); v != "" { + lp.OpVector = v + } + } + sm = util.RegexpCveInfluencesVersion.FindAllStringSubmatch(body, -1) + if len(sm) > 0 && len(sm[0]) > 0 { + lp.InfVersion = util.TrimString(sm[0][1]) + } + sm = util.RegexpCvePlannedMeasures.FindAllStringSubmatch(body, -1) + if len(sm) > 0 { + if len(sm[0]) > 0 { + //lp.AvoidScheme = util.TrimString(sm[0][1]) + lp.AvoidScheme = sm[0][1] + } + + } else { + sm = util.RegexpCvePlannedMeasures1.FindAllStringSubmatch(body, -1) + if len(sm) > 0 && len(sm[0]) > 0 { + //lp.AvoidScheme = util.TrimString(sm[0][1]) + lp.AvoidScheme = sm[0][1] + } + } + sm = util.RegexpCveInfluencesPkg.FindAllStringSubmatch(body, -1) + if len(sm) > 0 { + lp.InfPackage = util.TrimString(sm[0][1]) + } +} + +func parseNewTplToLoopHole(lp *Loophole, body string) { + sm := util.RegexpCveNumber.FindAllStringSubmatch(body, -1) + if len(sm) > 0 && len(sm[0]) > 0 { + val := sm[0][1] + lp.Number = util.GetCveNumber(util.TrimString(val)) + } + if len(sm) > 0 && len(sm[0]) > 0 { + lp.Components = util.TrimString(sm[0][1]) + } + sm = util.RegexpCveVersion.FindAllStringSubmatch(body, -1) + if len(sm) > 0 && len(sm[0]) > 0 { + lp.Version = util.TrimString(sm[0][1]) + } + sm = util.RegexpCveScore.FindAllStringSubmatch(body, -1) + if len(sm) > 0 && len(sm[0]) > 0 { + vs := util.TrimString(sm[0][1]) + if cs := util.ExtractDigital(vs); cs != "" { + lp.CvsScore = cs + } + if v := util.ExtractVector(vs, lp.ScoreType); v != "" { + lp.CvsVector = v + } + } + sm = util.RegexpCveBriefDesc.FindAllStringSubmatch(body, -1) + if len(sm) > 0 && len(sm[0]) > 0 { + //lp.BriefIntroduction = util.TrimString(sm[0][1]) + lp.BriefIntroduction = sm[0][1] + } + sm = util.RegexpCveInfluencesDescNew.FindAllStringSubmatch(body, -1) + if len(sm) > 0 && len(sm[0]) > 0 { + lp.Influences = sm[0][1] + } + sm = util.RegexpCveOpScoreNew.FindAllStringSubmatch(body, -1) + if len(sm) > 0 { + vp := util.TrimString(sm[0][1]) + if cs := util.ExtractDigital(vp); cs != "" { + lp.OpScore = cs + } + if v := util.ExtractVector(vp, lp.ScoreType); v != "" { + lp.OpVector = v + } + } + sm = util.RegexpCveInfluencesVersionNew.FindAllStringSubmatch(body, -1) + if len(sm) > 0 && len(sm[0]) > 0 { + lp.InfVersion = util.TrimString(sm[0][1]) + } } diff --git a/models/hookevent.go b/models/hookevent.go index ab45f4115ee97d7ab884d1e3ede07e416cc91fcf..683cf219506426ec9a6e69204fd7de52676e01c9 100644 --- a/models/hookevent.go +++ b/models/hookevent.go @@ -24,8 +24,8 @@ type HookIssue struct { User HookUser Assignee HookUser Repository HookRepository - CreateAt time.Time `json:"create_at"` - UpdateAt time.Time `json:"update_at"` + CreateAt time.Time `json:"created_at"` + UpdateAt time.Time `json:"updated_at"` FinishedAt time.Time `json:"finished_at"` IssueType string `json:"issue_type"` SecurityHole bool `json:"security_hole"` diff --git a/models/issue.go b/models/issue.go index f9ac7ad65e4ff2a490fb2f114ba2c41e6de4ac66..df5f9d7d189c65e67f5a7d0cc6f3dbf7af10f0d8 100644 --- a/models/issue.go +++ b/models/issue.go @@ -13,6 +13,18 @@ import ( var mutex sync.Mutex +func QueryIssueCveByNum(cvenum, repoPath string) (GiteOriginIssue, bool) { + o := orm.NewOrm() + var cve GiteOriginIssue + err := o.Raw("select * from cve_gite_origin_issue where cve_number = ? and repo_path = ?", cvenum, repoPath).QueryRow(&cve) + if err != nil { + logs.Error(cvenum, "cve_gite_origin_issue 查询不到") + return cve, false + } else { + return cve, true + } +} + func QueryIssue(days string, prcnum int) ([]VulnCenter, error) { o := orm.NewOrm() var vc []VulnCenter @@ -67,6 +79,21 @@ func QueryIssueScore(cveId int64) (Score, error) { return sc, err } +func QueryCveBrands(gitId int64) ([]GitOpenEulerTableRelate, error) { + o := orm.NewOrm() + var gt []GitOpenEulerTableRelate + var num int64 + num, err := o.Raw("select *"+ + " from cve_git_open_euler_table_relate where git_id = ?", gitId).QueryRows(>) + if err == nil && num > 0 { + logs.Info("cve_git_open_euler_table_relate 查询结果:", gt) + return gt, nil + } else { + logs.Info("查询 cve_git_open_euler_table_relate err, gitId: ", gitId, "err: ", err) + } + return gt, err +} + func QueryIssueScoreRecord(cveId int64, status int8) (ScoreRecord, error) { o := orm.NewOrm() var sr ScoreRecord @@ -100,6 +127,7 @@ func GetIssueTemplateByColName(it *IssueTemplate, colName string) error { } func UpdateIssueTemplate(it *IssueTemplate, fields ...string) error { + logs.Error("===>", it, fields) o := orm.NewOrm() _, err := o.Update(it, fields...) return err @@ -207,14 +235,13 @@ func CreateIssueTemplet(it *IssueTemplate) (issTempId int64, err error) { } } -func GetIssueHook(ih *IssueHooks) (localh IssueHooks, value bool) { +func GetIssueHook(ih *IssueHooks) (localh []IssueHooks, value bool) { o := orm.NewOrm() - var localIh IssueHooks - localIh.CveId = ih.CveId - localIh.IssueNum = ih.IssueNum - err := o.Raw("select *"+ - " from cve_issue_hooks where cve_id = ? and issue_num = ?", ih.CveId, ih.IssueNum).QueryRow(&localIh) - if err == nil { + var localIh []IssueHooks + var num int64 + num, err := o.Raw("select *"+ + " from cve_issue_hooks where owner = ? and repo = ? and status = ?", ih.Owner, ih.Repo, ih.Status).QueryRows(&localIh) + if err == nil && num > 0 { logs.Info("cve_issue_hooks 查询结果:", localIh) return localIh, true } else { @@ -265,6 +292,10 @@ func UpdateSecNotice(sec *SecurityNotice) (secId int64, err error) { sec.SecId = localSec.SecId sec.OpenId = localSec.OpenId sec.InfluenceComponent = localSec.InfluenceComponent + sec.Description = localSec.Description + sec.Summary = localSec.Summary + sec.AffectStatus = localSec.AffectStatus + sec.Status = localSec.Status sec.ReferenceLink = localSec.ReferenceLink if num, err := o.Update(sec); err == nil { logs.Info("update cve_security_notice success, SecId: ", num, "CveNum: ", sec.CveNum) @@ -308,4 +339,19 @@ func UpdateIssueCommentId(issueNum, cveNum string, commentId int64) (id int64) { o := orm.NewOrm() _ = o.Raw("UPDATE cve_issue_template SET comment_id = ? WHERE issue_num = ? and cve_num = ?", commentId, issueNum, cveNum).QueryRow() return -} \ No newline at end of file +} + +func IssueExistByNumber(number string) bool { + if number == "" { + return false + } + o := orm.NewOrm() + exit := o.QueryTable("cve_issue_template").Filter("issue_num", number).Exist() + return exit +} + +func GetIssueTplByCveNum(num string) (list []IssueTemplate, err error) { + o := orm.NewOrm() + _, err = o.QueryTable("cve_issue_template").Filter("cve_num", num).All(&list) + return +} diff --git a/models/modeldb.go b/models/modeldb.go index c9d5b14ee6717719a90b8264cf823727139838a5..ba9a96c14accff107c9d4967073d3725c9b35de5 100644 --- a/models/modeldb.go +++ b/models/modeldb.go @@ -9,293 +9,312 @@ import ( ) type IpWhite struct { - IPId int `orm:"pk;auto;column(ip_id)"` // 自增的值 + IPId int `orm:"pk;auto;column(ip_id)"` // 自增的值 MachineName string `orm:"size(128);column(machine_name)" description:"机器名称"` - MachineIp string `orm:"size(128);column(machine_ip);index" description:"机器ip"` - AccessCount int64 `orm:"default(0);column(access_count)" description:"0: 不受限制; 10000:可以连续访问次数"` + MachineIp string `orm:"size(128);column(machine_ip);index" description:"机器ip"` + AccessCount int64 `orm:"default(0);column(access_count)" description:"0: 不受限制; 10000:可以连续访问次数"` } type OtherUser struct { - UerId int `orm:"pk;auto;column(user_id)"` // 自增的值 - UserName string `orm:"size(64);column(user_name)"` - PassWord string `orm:"size(256);column(pass_word)"` - AesKey string `orm:"size(512);colnum(aes_key)"` - ExpirationTime string `orm:"size(32);column(expiration_time)" description:"token的过期时间"` - CreateTime time.Time `orm:"auto_now;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)"` + UerId int `orm:"pk;auto;column(user_id)"` // 自增的值 + UserName string `orm:"size(64);column(user_name)"` + PassWord string `orm:"size(256);column(pass_word)"` + AesKey string `orm:"size(512);colnum(aes_key)"` + ExpirationTime string `orm:"size(32);column(expiration_time)" description:"token的过期时间"` + CreateTime time.Time `orm:"auto_now;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)"` } type AdminUser struct { - UerId int `orm:"pk;auto;column(user_id)"` // 自增的值 - UserName string `orm:"size(64);column(user_name)"` - PassWord string `orm:"size(256);column(pass_word)"` + UerId int `orm:"pk;auto;column(user_id)"` // 自增的值 + UserName string `orm:"size(64);column(user_name)"` + PassWord string `orm:"size(256);column(pass_word)"` CreateTime time.Time `orm:"auto_now;type(datetime);column(create_time)"` } type VulnCenter struct { - CveId int64 `orm:"pk;auto;column(cve_id)"` - CveNum string `orm:"size(256);column(cve_num);unique" description:"cve编号"` - Description string `orm:"size(8192);column(cve_desc)" description:"cve描述"` - CveLevel string `orm:"size(32);column(cve_level)" description:"致命(Critical);严重(High);中等(Medium);一般(Low);其他"` - Status int8 `orm:"default(0);column(cve_status)" description:"0:cve新增;1:数据已变化;2:已创建issue"` - CveVersion string `orm:"size(128);column(cve_version)" description:"cve归属版本"` - RepairTime string `orm:"size(32);column(repair_time)" description:"cve修复时间"` - PackName string `orm:"size(1024);column(pack_name)" description:"cve对应得包名称"` - CveUrl string `orm:"size(2048);column(cve_url)" description:"cve下载链接"` - 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)"` + CveId int64 `orm:"pk;auto;column(cve_id)"` + CveNum string `orm:"size(256);column(cve_num);index" description:"cve编号"` + Description string `orm:"size(8192);column(cve_desc)" description:"cve描述"` + CveLevel string `orm:"size(32);column(cve_level)" description:"致命(Critical);严重(High);中等(Medium);一般(Low);其他"` + Status int8 `orm:"default(0);column(cve_status)" description:"0:cve新增;1:数据已变化;2:已创建issue"` + CveVersion string `orm:"size(128);column(cve_version)" description:"cve归属版本"` + RepairTime string `orm:"size(32);column(repair_time)" description:"cve修复时间"` + PackName string `orm:"size(512);column(pack_name)" description:"cve对应得包名称"` + CveUrl string `orm:"size(2048);column(cve_url)" description:"cve下载链接"` + IsExport int8 `orm:"default(0);column(is_export)" description:"0:数据初始化;1:数据已同步到官网;2:数据不需要同步到官网;3:issue已关闭需要同步到官网"` + 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)"` } type OpenEulerSA struct { - OpenId int64 `orm:"pk;auto;column(openeuler_id)"` - CveId int64 `orm:"index;column(cve_id)"` - PublicDate string `orm:"size(16);column(public_date);null" description:"安全公告时间"` + OpenId int64 `orm:"pk;auto;column(openeuler_id)"` + CveId int64 `orm:"index;column(cve_id)"` + PublicDate string `orm:"size(16);column(public_date);null" description:"安全公告时间"` OpenEulerSANum string `orm:"size(128);column(openeuler_sa_num);unique" description:"安全公告"` } type ScoreRecord struct { - Id int64 `orm:"pk;auto"` - CveId int64 `orm:"index;column(cve_id)"` - NVDScore float64 `orm:"digits(10);decimals(1);column(nvd_score)"` - NvectorVule string `orm:"size(256);column(n_vector_value)" description:"nvd vector 原始值"` - Status int8 `orm:"default(0);column(status)" description:"0:未处理;1:已处理"` - CreateTime time.Time `orm:"auto_now_add;type(datetime);column(create_time)"` + Id int64 `orm:"pk;auto"` + CveId int64 `orm:"index;column(cve_id)"` + NVDScore float64 `orm:"digits(10);decimals(1);column(nvd_score)"` + NvectorVule string `orm:"size(256);column(n_vector_value)" description:"nvd vector 原始值"` + Status int8 `orm:"default(0);column(status)" description:"0:未处理;1:已处理"` + CreateTime time.Time `orm:"auto_now_add;type(datetime);column(create_time)"` } type Score struct { - Id int64 `orm:"pk;auto"` - CveId int64 `orm:"index;column(cve_id)"` - CveNum string `orm:"size(256);column(cve_num)" description:"cve编号"` - NVDScore float64 `orm:"digits(10);decimals(1);column(nvd_score)" description:"nvd 评分"` - OpenEulerScore float64 `orm:"digits(10);decimals(1);column(openeuler_score)" description:"openeuler评分"` - NvectorVule string `orm:"size(256);column(n_vector_value)" description:"nvd vector 原始值"` - OvectorVule string `orm:"size(256);column(o_vector_value)" description:"openeuler vector 原始值"` - NattackVector string `orm:"size(64);column(n_attack_vector)"` - OattackVector string `orm:"size(64);column(o_attack_vector)"` - NattackComplexity string `orm:"size(64);column(n_attack_complexity)"` - OattackComplexity string `orm:"size(64);column(o_attack_complexity)"` - NprivilegeRequired string `orm:"size(64);column(n_privilege_required)"` - OprivilegeRequired string `orm:"size(64);column(o_privilege_required)"` - NuserInteraction string `orm:"size(64);column(n_user_interaction)"` - OuserInteraction string `orm:"size(64);column(o_user_interaction)"` - Nscope string `orm:"size(64);column(n_scope)"` - Oscope string `orm:"size(64);column(o_scope)"` - Nconfidentiality string `orm:"size(64);column(n_confidentiality)"` - Oconfidentiality string `orm:"size(64);column(o_confidentiality)"` - Nintegrity string `orm:"size(64);column(n_integrity)"` - Ointegrity string `orm:"size(64);column(o_integrity)"` - Navailability string `orm:"size(64);column(n_availability)"` - Oavailability string `orm:"size(64);column(o_availability)"` - ScoreType string `orm:"size(16);column(score_type)"` - OpenId int64 `orm:"unique;column(openeuler_id);null"` - Nstatus int8 `orm:"default(0);column(n_score_status)" description:"0:新增评分,无改变;1:修改nvd评分;2:已提交issue;3:已处理"` - Ostatus int8 `orm:"default(0);column(o_score_status)" description:"0:新增评分,无改变;1:修改nvd评分;2:修改评分未通过;3:修改评分已通过"` - 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)"` + Id int64 `orm:"pk;auto"` + CveId int64 `orm:"index;column(cve_id)"` + CveNum string `orm:"size(256);column(cve_num)" description:"cve编号"` + NVDScore float64 `orm:"digits(10);decimals(1);column(nvd_score)" description:"nvd 评分"` + OpenEulerScore float64 `orm:"digits(10);decimals(1);column(openeuler_score)" description:"openeuler评分"` + NvectorVule string `orm:"size(256);column(n_vector_value)" description:"nvd vector 原始值"` + OvectorVule string `orm:"size(256);column(o_vector_value)" description:"openeuler vector 原始值"` + NattackVector string `orm:"size(64);column(n_attack_vector)"` + NaccessVector string `orm:"size(256);column(n_access_vector);null" description:"nvd 2.0 评分向量"` + OattackVector string `orm:"size(64);column(o_attack_vector)"` + OaccessVector string `orm:"size(256);column(o_access_vector);null" description:"nvd 2.0 评分向量"` + NattackComplexity string `orm:"size(64);column(n_attack_complexity)"` + NaccessComplexity string `orm:"size(64);column(n_access_complexity);null"` + OattackComplexity string `orm:"size(64);column(o_attack_complexity)"` + OaccessComplexity string `orm:"size(64);column(o_access_complexity);null"` + NprivilegeRequired string `orm:"size(64);column(n_privilege_required)"` + OprivilegeRequired string `orm:"size(64);column(o_privilege_required)"` + NuserInteraction string `orm:"size(64);column(n_user_interaction)"` + OuserInteraction string `orm:"size(64);column(o_user_interaction)"` + Nscope string `orm:"size(64);column(n_scope)"` + Oscope string `orm:"size(64);column(o_scope)"` + Nconfidentiality string `orm:"size(64);column(n_confidentiality)"` + Oconfidentiality string `orm:"size(64);column(o_confidentiality)"` + Nintegrity string `orm:"size(64);column(n_integrity)"` + Ointegrity string `orm:"size(64);column(o_integrity)"` + Navailability string `orm:"size(64);column(n_availability)"` + Oavailability string `orm:"size(64);column(o_availability)"` + Nauthentication string `orm:"size(64);column(n_authentication);null"` + Oauthentication string `orm:"size(64);column(o_authentication);null"` + ScoreType string `orm:"size(16);column(score_type)"` + OpenId int64 `orm:"unique;column(openeuler_id);null"` + Nstatus int8 `orm:"default(0);column(n_score_status)" description:"0:新增评分,无改变;1:修改nvd评分;2:已提交issue;3:已处理"` + Ostatus int8 `orm:"default(0);column(o_score_status)" description:"0:新增评分,无改变;1:修改nvd评分;2:修改评分未通过;3:修改评分已通过"` + 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)"` } type SecurityNotice struct { - SecId int64 `orm:"pk;auto;column(sec_id)" description:"安全公告"` - CveId int64 `orm:"index;column(cve_id)"` - CveNum string `orm:"size(256);column(cve_num)" description:"cve编号"` - OpenId int64 `orm:"unique;column(openeuler_id);null" description:"OpenEulerSA"` - Introduction string `orm:"size(256);null;column(introduction)" description:"简介"` - Summary string `orm:"size(256);null;column(summary)" description:"概要"` - Theme string `orm:"size(2048);null;column(theme)" description:"主题"` - Description string `orm:"size(8192);column(description)" description:"安全公告描述"` - InfluenceComponent string `orm:"size(256);null;column(influence_component)" description:"影响组件"` - AffectProduct string `orm:"size(256);null;column(affect_product)" description:"影响产品"` - ReferenceLink string `orm:"size(1024);null;column(reference_link)" description:"参考链接"` - Status int8 `orm:"default(0);column(sec_status)" description:"0:未发布;1:已发布"` - AffectStatus string `orm:"size(16);null;column(affect_status)" description:"Fixed:已解决;UnFixed:未解决;UnAffected:不影响"` - 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)"` + SecId int64 `orm:"pk;auto;column(sec_id)" description:"安全公告"` + CveId int64 `orm:"index;column(cve_id)"` + CveNum string `orm:"size(256);column(cve_num)" description:"cve编号"` + OpenId int64 `orm:"unique;column(openeuler_id);null" description:"OpenEulerSA"` + Introduction string `orm:"size(256);null;column(introduction)" description:"简介"` + Summary string `orm:"size(256);null;column(summary)" description:"概要"` + Theme string `orm:"size(2048);null;column(theme)" description:"主题"` + Description string `orm:"size(8192);column(description)" description:"安全公告描述"` + InfluenceComponent string `orm:"size(256);null;column(influence_component)" description:"影响组件"` + AffectProduct string `orm:"size(256);null;column(affect_product)" description:"影响产品"` + ReferenceLink string `orm:"size(1024);null;column(reference_link)" description:"参考链接"` + Status int8 `orm:"default(0);column(sec_status)" description:"0:未发布;1:已发布"` + AffectStatus string `orm:"size(16);null;column(affect_status)" description:"Fixed:已解决;UnFixed:未解决;UnAffected:不影响"` + 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)"` } type Package struct { - Id int64 `orm:"pk;auto"` - SecId int64 `orm:"index;column(sec_id)"` + Id int64 `orm:"pk;auto"` + SecId int64 `orm:"index;column(sec_id)"` PackName string `orm:"size(1024);null;column(pack_name)" description:"包名"` - PackUrl string `orm:"size(2048);null;column(pack_url)" description:"包下载链接"` + PackUrl string `orm:"size(2048);null;column(pack_url)" description:"包下载链接"` } type IssueTemplate struct { - TemplateId int64 `orm:"pk;auto;column(template_id)"` - CveId int64 `orm:"index;column(cve_id)"` - CveNum string `orm:"size(256);column(cve_num)" description:"cve编号"` - OwnedComponent string `orm:"size(256);column(owned_component)" description:"漏洞归属组件"` - OwnedVersion string `orm:"size(256);column(owned_version)" description:"漏洞归属版本"` - NVDScore float64 `orm:"digits(10);decimals(1);column(nvd_score)" description:"nvd评分"` - OpenEulerScore float64 `orm:"digits(10);decimals(1);column(openeuler_score)" description:"openeuler评分"` - NVDVector string `orm:"size(256);column(nvd_vector)" description:"nvd评分向量"` - OpenEulerVector string `orm:"size(256);column(openeuler_vector)" description:"openeuler评分向量"` - CveBrief string `orm:"size(4096);column(cve_brief)" description:"漏洞简述"` - CveAnalysis string `orm:"size(4096);column(cve_analysis)" description:"影响性分析说明"` - PrincipleAnalysis string `orm:"size(4096);column(principle_analysis)" description:"原理分析"` - AffectedVersion string `orm:"size(256);column(affected_version)" description:"受影响的版本"` - Solution string `orm:"size(1024);column(solution)" description:"规避方案或消减措施"` - IssueId int64 `orm:"column(issue_id)" description:"issue的id"` - IssueNum string `orm:"size(64);column(issue_num);index" description:"issue编号"` - Assignee string `orm:"size(128);column(issue_assignee)" description:"issue所属责任人"` - Status int8 `orm:"default(0);column(status)" description:"1:待办的;2:进行中;3:已完成;4:已拒绝"` - StatusName string `orm:"size(128);column(status_name)" description:"issue状态名称"` - IssueStatus int8 `orm:"default(0);column(issue_status)" description:"1:待分析;2:已正常关闭;3已分析,待修复;4:已修复;5:已发布;6:已异常关闭"` - IssueLabel string `orm:"size(256);column(issue_label)" description:"issue标签, cve/Undisclosed, cve/Disclosed"` - Owner string `orm:"size(128);column(owner)" description:"仓库地址"` - Repo string `orm:"size(128);column(repo)" description:"仓库路径"` - Title string `orm:"size(512);column(title)" description:"issue标题"` - IssueType string `orm:"size(64);column(issue_type)" description:"CVE和安全问题"` - Collaborators string `orm:"size(128);column(collaborators);null" description:"协助者"` - Milestone string `orm:"size(64);column(milestone);null" description:"里程碑序号"` - Program string `orm:"size(64);column(program);null" description:"项目编号"` - SecurityHole int8 `orm:"default(0);column(security_hole)" description:"是否是私有issue"` - CveLevel string `orm:"size(32);column(cve_level)" description:"致命(Critical);严重(High);中等(Medium);一般(Low);其他"` - CommentId int64 `orm:"column(comment_id), null" description:"首条评论id"` - 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)"` + TemplateId int64 `orm:"pk;auto;column(template_id)"` + CveId int64 `orm:"index;column(cve_id)"` + CveNum string `orm:"size(256);column(cve_num)" description:"cve编号"` + OwnedComponent string `orm:"size(256);column(owned_component)" description:"漏洞归属组件"` + OwnedVersion string `orm:"size(256);column(owned_version)" description:"漏洞归属版本"` + NVDScore float64 `orm:"digits(10);decimals(1);column(nvd_score)" description:"nvd评分"` + OpenEulerScore float64 `orm:"digits(10);decimals(1);column(openeuler_score)" description:"openeuler评分"` + NVDVector string `orm:"size(256);column(nvd_vector)" description:"nvd评分向量"` + OpenEulerVector string `orm:"size(256);column(openeuler_vector)" description:"openeuler评分向量"` + CveBrief string `orm:"size(4096);column(cve_brief)" description:"漏洞简述"` + CveAnalysis string `orm:"size(4096);column(cve_analysis)" description:"影响性分析说明"` + PrincipleAnalysis string `orm:"size(4096);column(principle_analysis)" description:"原理分析"` + AffectedVersion string `orm:"size(256);column(affected_version)" description:"受影响的版本"` + Solution string `orm:"size(1024);column(solution)" description:"规避方案或消减措施"` + IssueId int64 `orm:"column(issue_id)" description:"issue的id"` + IssueNum string `orm:"size(64);column(issue_num);index" description:"issue编号"` + Assignee string `orm:"size(128);column(issue_assignee)" description:"issue所属责任人"` + Status int8 `orm:"default(0);column(status)" description:"1:待办的;2:进行中;3:已完成;4:已拒绝"` + StatusName string `orm:"size(128);column(status_name)" description:"issue状态名称"` + IssueStatus int8 `orm:"default(0);column(issue_status)" description:"1:待分析;2:已正常关闭;3已分析,待修复;4:已修复;5:已发布;6:已异常关闭"` + IssueLabel string `orm:"size(256);column(issue_label)" description:"issue标签, cve/Undisclosed, cve/Disclosed"` + Owner string `orm:"size(128);column(owner)" description:"仓库地址"` + Repo string `orm:"size(128);column(repo)" description:"仓库路径"` + Title string `orm:"size(512);column(title)" description:"issue标题"` + IssueType string `orm:"size(64);column(issue_type)" description:"CVE和安全问题"` + Collaborators string `orm:"size(128);column(collaborators);null" description:"协助者"` + Milestone string `orm:"size(64);column(milestone);null" description:"里程碑序号"` + Program string `orm:"size(64);column(program);null" description:"项目编号"` + SecurityHole int8 `orm:"default(0);column(security_hole)" description:"是否是私有issue"` + CveLevel string `orm:"size(32);column(cve_level)" description:"致命(Critical);严重(High);中等(Medium);一般(Low);其他"` + CommentId int64 `orm:"column(comment_id), null" description:"首条评论id"` + 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)"` } type IssueHooks struct { - Id int64 `orm:"pk;auto"` - CveId int64 `orm:"index;column(cve_id)"` - IssueId int64 `orm:"column(issue_id)" description:"issue的id"` - IssueNum string `orm:"size(64);column(issue_num);index" description:"issue编号"` - HookId int64`orm:"column(hook_id)" decrtiption:"钩子id"` - Owner string `orm:"size(128);column(owner)" description:"仓库地址"` - Repo string `orm:"size(128);column(repo)" description:"仓库路径"` - HookUrl string `orm:"size(512);column(hook_url)" description:"回调地址"` - PushEvent int8 `orm:"column(push_event);default(1)" description:"Push代码到仓库; 默认1:已监听; 0: 未监听"` - TagPushEvent int8 `orm:"column(tag_push_events);default(1)" description:"提交Tag到仓库, 默认1:已监听; 0: 未监听"` - IssueEvent int8 `orm:"column(issues_events);default(1)" description:"创建/关闭Issue, 默认1:已监听; 0: 未监听"` - NoteEvent int8 `orm:"column(note_events);default(1)" description:"评论了Issue/代码等等, 默认1:已监听; 0: 未监听"` - MergeRequestEvent int8 `orm:"column(merge_requests_events);default(1)" description:"合并请求和合并后, 默认1:已监听; 0: 未监听"` + Id int64 `orm:"pk;auto"` + CveId int64 `orm:"index;column(cve_id)"` + IssueId int64 `orm:"column(issue_id)" description:"issue的id"` + IssueNum string `orm:"size(64);column(issue_num);index" description:"issue编号"` + HookId int64 `orm:"column(hook_id)" decrtiption:"钩子id"` + Owner string `orm:"size(128);column(owner)" description:"仓库地址"` + Repo string `orm:"size(128);column(repo)" description:"仓库路径"` + HookUrl string `orm:"size(512);column(hook_url)" description:"回调地址"` + PushEvent int8 `orm:"column(push_event);default(1)" description:"Push代码到仓库; 默认1:已监听; 0: 未监听"` + TagPushEvent int8 `orm:"column(tag_push_events);default(1)" description:"提交Tag到仓库, 默认1:已监听; 0: 未监听"` + IssueEvent int8 `orm:"column(issues_events);default(1)" description:"创建/关闭Issue, 默认1:已监听; 0: 未监听"` + NoteEvent int8 `orm:"column(note_events);default(1)" description:"评论了Issue/代码等等, 默认1:已监听; 0: 未监听"` + MergeRequestEvent int8 `orm:"column(merge_requests_events);default(1)" description:"合并请求和合并后, 默认1:已监听; 0: 未监听"` + Status int8 `orm:"default(1);column(status)" description:"1:有效; 2:无效"` + CreateTime string `orm:"size(32);column(create_time)"` + UpdateTime string `orm:"size(32);column(update_time);null"` + DeleteTime string `orm:"size(32);column(delete_time);null"` } type GitPackageTable struct { - TableId int64 `orm:"pk;auto;column(table_id)"` + TableId int64 `orm:"pk;auto;column(table_id)"` TableName string `orm:"size(128);column(table_name)" description:"数据库pkginfo下的表名,如:mainline, bringInRely"` + Brands string `orm:"size(256);column(brands)" description:"对应分支信息"` } type GitOpenEuler struct { - GitId int64 `orm:"pk;auto;column(git_id)"` - PackageId int64 `orm:"index;column(package_id)" description:"获取到的包id"` - PackageName string `orm:"column(package_name);size(256)" description:"包名称"` - Version string `orm:"size(64);column(version);index" description:"版本号"` - Release string `orm:"size(128);column(release)" description:"release 版本号"` - OriginUrl string `orm:"size(512);column(origin_url)" description:"gitee上的地址"` - License string `orm:"size(4096);column(license)" description:"license"` - Feature string `orm:"size(128);column(feature)" description:"特性"` - MainTainer string `orm:"size(128);column(main_tainer)" description:"维护人"` - MainTainLevel int8 `orm:"column(main_tain_level);default(1)" description:"软件包维护级别"` - ReleaseTime string `orm:"size(32);column(release_time)" description:"当前版本发布时间"` - UsedTime string `orm:"size(32);column(used_time)" description:"当天减去所用版本的发布日期"` - LatestVersion string `orm:"size(128);column(latest_version)" description:"最新版本号"` - LatestVersionTime string `orm:"size(32);column(latest_version_time)" description:"最新版本发布时间"` - IssueCount int64 `orm:"column(issue_count);default(0)" description:"该软件包仓库下的issue总数"` - TableId int64 `orm:"index;column(table_id)" description:"表id,外键"` - TableName string `orm:"size(128);column(table_name)" description:"数据库pkginfo下的表名,如:mainline, bringInRely"` - Status int8 `orm:"default(0);column(status)" description:"0: 代表新数据; 1:已推送; 2:代表已废弃"` - 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)"` + GitId int64 `orm:"pk;auto;column(git_id)"` + PackageId int64 `orm:"index;column(package_id)" description:"获取到的包id"` + PackageName string `orm:"column(package_name);size(256)" description:"包名称"` + Version string `orm:"size(64);column(version);index" description:"版本号"` + Release string `orm:"size(128);column(release)" description:"release 版本号"` + OriginUrl string `orm:"size(512);column(origin_url)" description:"gitee上的地址"` + License string `orm:"size(4096);column(license)" description:"license"` + Feature string `orm:"size(128);column(feature)" description:"特性"` + MainTainer string `orm:"size(128);column(main_tainer)" description:"维护人"` + MainTainLevel int8 `orm:"column(main_tain_level);default(1)" description:"软件包维护级别"` + ReleaseTime string `orm:"size(32);column(release_time)" description:"当前版本发布时间"` + UsedTime string `orm:"size(32);column(used_time)" description:"当天减去所用版本的发布日期"` + LatestVersion string `orm:"size(128);column(latest_version)" description:"最新版本号"` + LatestVersionTime string `orm:"size(32);column(latest_version_time)" description:"最新版本发布时间"` + IssueCount int64 `orm:"column(issue_count);default(0)" description:"该软件包仓库下的issue总数"` + TableId int64 `orm:"index;column(table_id)" description:"表id,外键"` + TableName string `orm:"size(128);column(table_name)" description:"数据库pkginfo下的表名,如:mainline, bringInRely"` + Status int8 `orm:"default(0);column(status)" description:"0: 代表新数据; 1:已推送; 2:代表已废弃"` + 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)"` +} + +type GitOpenEulerTableRelate struct { + RelateId int64 `orm:"pk;auto;column(relate_id)"` + GitId int64 `orm:"index;column(git_id)" description:"GitOpenEuler,外键"` + Brands string `orm:"size(256);column(brands)" description:"对应分支信息"` + TableName string `orm:"size(256);column(table_name)" description:"数据库pkginfo下的表名,如:mainline, bringInRely"` } + type GitPackageInfo struct { - DetailId int64 `orm:"pk;auto;column(detail_id)"` - GitId int64 `orm:"index;column(git_id)" description:"包id,外键"` - Ids int64 `orm:"index;column(git_ids)" description:"原始数据id来源"` - PackageName string `orm:"column(package_name);size(256)" description:"包名称"` - Version string `orm:"size(64);column(version);index" description:"版本号"` - Release string `orm:"size(128);column(release)" description:"release 版本号"` - OriginUrl string `orm:"size(512);column(origin_url)" description:"上游社区链接"` - License string `orm:"size(4096);column(license)" description:"license"` - Feature string `orm:"size(128);column(feature)" description:"特性"` - MainTainer string `orm:"size(128);column(main_tainer)" description:"维护人"` - MainTainLevel int8 `orm:"column(main_tain_level);default(1)" description:"软件包维护级别"` - GitUrl string `orm:"size(512);column(git_url)" description:"gitee上的地址"` - Summary string `orm:"size(1024);column(summary)" description:"summary"` - Decription string `orm:"size(8092);column(decription)" description:"decription"` - BuildRequired string `orm:"size(4096);column(build_require)" description:"源码包的编译依赖"` - Status int8 `orm:"default(0);column(status)" description:"0: 代表新数据; 1:已推送; 2:代表已废弃"` - 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)"` + DetailId int64 `orm:"pk;auto;column(detail_id)"` + GitId int64 `orm:"index;column(git_id)" description:"包id,外键"` + Ids int64 `orm:"index;column(git_ids)" description:"原始数据id来源"` + PackageName string `orm:"column(package_name);size(256)" description:"包名称"` + Version string `orm:"size(64);column(version);index" description:"版本号"` + Release string `orm:"size(128);column(release)" description:"release 版本号"` + OriginUrl string `orm:"size(512);column(origin_url)" description:"上游社区链接"` + License string `orm:"size(4096);column(license)" description:"license"` + Feature string `orm:"size(128);column(feature)" description:"特性"` + MainTainer string `orm:"size(128);column(main_tainer)" description:"维护人"` + MainTainLevel int8 `orm:"column(main_tain_level);default(1)" description:"软件包维护级别"` + GitUrl string `orm:"size(512);column(git_url)" description:"gitee上的地址"` + Summary string `orm:"size(1024);column(summary)" description:"summary"` + Decription string `orm:"size(8092);column(decription)" description:"decription"` + BuildRequired string `orm:"size(4096);column(build_require)" description:"源码包的编译依赖"` + Status int8 `orm:"default(0);column(status)" description:"0: 代表新数据; 1:已推送; 2:代表已废弃"` + 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)"` } type GitSubPack struct { - SubId int64 `orm:"pk;auto;column(sub_id)"` - DetailId int64 `orm:"index;column(detail_id)" description:"包id,外键"` - Ids int64 `orm:"index;column(ids)" description:"原始数据id来源"` + SubId int64 `orm:"pk;auto;column(sub_id)"` + DetailId int64 `orm:"index;column(detail_id)" description:"包id,外键"` + Ids int64 `orm:"index;column(ids)" description:"原始数据id来源"` SubPackName string `orm:"size(256);column(sub_pack_name)" description:"二进制包名"` } type GitSubPackRequire struct { - RequireId int64 `orm:"pk;auto;column(require_id)"` - SubId int64 `orm:"index;column(sub_id)" description:"包id,外键"` - Ids int64 `orm:"index;column(ids)" description:"原始数据id来源"` + RequireId int64 `orm:"pk;auto;column(require_id)"` + SubId int64 `orm:"index;column(sub_id)" description:"包id,外键"` + Ids int64 `orm:"index;column(ids)" description:"原始数据id来源"` RequireName string `orm:"size(256);column(require_name)" description:"二进制包名"` - Providedby string `orm:"size(4096);column(providedb)" description:"提供该组件的二进制包"` + Providedby string `orm:"size(4096);column(providedb)" description:"提供该组件的二进制包"` } type GitSubPackProvides struct { - ProvideId int64 `orm:"pk;auto;column(provide_id)"` - SubId int64 `orm:"index;column(sub_id)" description:"包id,外键"` - Ids int64 `orm:"index;column(ids)" description:"原始数据id来源"` + ProvideId int64 `orm:"pk;auto;column(provide_id)"` + SubId int64 `orm:"index;column(sub_id)" description:"包id,外键"` + Ids int64 `orm:"index;column(ids)" description:"原始数据id来源"` ProvideName string `orm:"size(256);column(provide_name)" description:"依赖的组件名称"` - Requiredby string `orm:"size(256);column(requiredb)" description:"依赖该组件的二进制包列表"` + Requiredby string `orm:"size(256);column(requiredb)" description:"依赖该组件的二进制包列表"` } type GitSubPackRequiredby struct { - Id int64 `orm:"pk;auto;column(id)"` - ProvideId int64 `orm:"index;column(provide_id)"description:"包id,外键"` + Id int64 `orm:"pk;auto;column(id)"` + ProvideId int64 `orm:"index;column(provide_id)"description:"包id,外键"` Requiredby string `orm:"size(256);column(requiredb)" description:"依赖该组件的二进制包列表"` } - type OriginUpstream struct { - CveId int64 `orm:"pk;auto;column(cve_id)"` - Ids string `orm:"size(256);column(cve_un_ids);unique"description:"唯一编号,根据此字段去重数据, 唯一识别码,可以填cve编号"` - CveNum string `orm:"size(256);column(cve_num);index"description:"cve编号"` - UpdateType string `orm:"size(32);column(update_type);"description:"数据上传类型:insert, update, delete"` - CvePackName string `orm:"size(512);column(cve_packname);index;null"description:"Cve在上游对应的包名"` - PackName string `orm:"size(512);column(git_packname);index;null"description:"Cve对应的openEuler包名称(或者影响的包名)"` - Title string `orm:"size(1024);column(cve_title);null"description:"标题"` + CveId int64 `orm:"pk;auto;column(cve_id)"` + Ids string `orm:"size(256);column(cve_un_ids);unique"description:"唯一编号,根据此字段去重数据, 唯一识别码,可以填cve编号"` + CveNum string `orm:"size(256);column(cve_num);index"description:"cve编号"` + UpdateType string `orm:"size(32);column(update_type);"description:"数据上传类型:insert, update, delete"` + CvePackName string `orm:"size(512);column(cve_packname);index;null"description:"Cve在上游对应的包名"` + PackName string `orm:"size(512);column(git_packname);index;null"description:"Cve对应的openEuler包名称(或者影响的包名)"` + Title string `orm:"size(1024);column(cve_title);null"description:"标题"` AffectProduct string `orm:"size(512);column(affect_porduct);null"description:"Cve影响的组件, 对应"` - CnnvdID string `orm:"size(256);column(cnnvd_id);null"description:"Cnnvd_id"` - CnvdID string `orm:"size(256);column(cnvd_id);null"description:"Cnvd_id"` + CnnvdID string `orm:"size(256);column(cnnvd_id);null"description:"Cnnvd_id"` + CnvdID string `orm:"size(256);column(cnvd_id);null"description:"Cnvd_id"` PublishedDate string `orm:"size(32);column(published_date);null"description:"漏洞发布日期"` - VulStatus string `orm:"size(64);column(vul_status);null"description:"漏洞状态,REJECT, DISPUTED"` - Status int8 `orm:"default(0);column(cve_status)"description:"0:cve新增;1:数据已变化;2:数据已处理"` + VulStatus string `orm:"size(64);column(vul_status);null"description:"漏洞状态,REJECT, DISPUTED"` + Status int8 `orm:"default(0);column(cve_status)"description:"0:cve新增;1:数据已变化;2:数据已处理"` AffectedScope string `orm:"size(512);column(affected_scope);null"description:"影响范围推理"` - Version string `orm:"size(64);column(version);index" description:"包对应的版本号"` - AttackLink string `orm:"size(512);column(attack_link);null"description:"攻击链路推理"` - IsExit int8 `orm:"default(1);column(is_exit)"description:"1: 当前包对应在src-openEuler有对应仓库; 0: 无;2:临时值"` - CreateTime string `orm:"size(32);column(create_time)"` - UpdateTime string `orm:"size(32);column(update_time);null"` - DeleteTime string `orm:"size(32);column(delete_time);null"` + Version string `orm:"size(64);column(version);index" description:"包对应的版本号"` + AttackLink string `orm:"size(512);column(attack_link);null"description:"攻击链路推理"` + IsExit int8 `orm:"default(1);column(is_exit)"description:"1: 当前包对应在src-openEuler有对应仓库; 0: 无;2:临时值"` + CreateTime string `orm:"size(32);column(create_time)"` + UpdateTime string `orm:"size(32);column(update_time);null"` + DeleteTime string `orm:"size(32);column(delete_time);null"` } type OriginUpstreamDesc struct { - DescId int64 `orm:"pk;auto;column(desc_id)"` - CveId int64 `orm:"index;column(cve_id)"description:"OriginUpstream 外键"` + DescId int64 `orm:"pk;auto;column(desc_id)"` + CveId int64 `orm:"index;column(cve_id)"description:"OriginUpstream 外键"` EnDescription string `orm:"size(8192);column(en_desc);null"description:"cve英文描述"` ZhDescription string `orm:"size(8192);column(zh_desc);null"description:"cve中文描述"` } type OriginUpstreamConfig struct { - ConfId int64 `orm:"pk;auto;column(conf_id)"` - CveId int64 `orm:"index;column(cve_id)"description:"OriginUpstream 外键"` - Nodes string `orm:"size(32);column(nodes);null"description:"nodes数组"` + ConfId int64 `orm:"pk;auto;column(conf_id)"` + CveId int64 `orm:"index;column(cve_id)"description:"OriginUpstream 外键"` + Nodes string `orm:"size(32);column(nodes);null"description:"nodes数组"` } type OriginUpstreamConfigNode struct { - NodeId int64 `orm:"pk;auto;column(node_id)"` - ConfId int64 `orm:"index;column(conf_id)"description:"OriginUpstreamConfig 外键"` + NodeId int64 `orm:"pk;auto;column(node_id)"` + ConfId int64 `orm:"index;column(conf_id)"description:"OriginUpstreamConfig 外键"` Operator string `orm:"size(256);column(operator);null"description:"operator"` } @@ -303,150 +322,258 @@ type SecurityReviewer struct { Id int64 `orm:"pk;auto"` NameSpace string `orm:"unique" description:"码云空间地址"` } + type OriginUpstreamConfigNodeCpe struct { - CpeId int64 `orm:"pk;auto;column(cpe_id)"` - NodeId int64 `orm:"index;column(node_id)"description:"OriginUpstreamConfigNode 外键"` - Cpe23Uri string `orm:"size(1024);column(cpe_uri);null"description:"cpe"` + CpeId int64 `orm:"pk;auto;column(cpe_id)"` + NodeId int64 `orm:"index;column(node_id)"description:"OriginUpstreamConfigNode 外键"` + Cpe23Uri string `orm:"size(1024);column(cpe_uri);null"description:"cpe"` CpeMatchString string `orm:"size(1024);column(cpe_match);null"description:"过滤字符串"` - Vulnerable string `orm:"size(64);column(vulner_able);null"description:"易受攻击"` + Vulnerable string `orm:"size(64);column(vulner_able);null"description:"易受攻击"` } type OriginUpstreamImpact struct { - ImpactId int64 `orm:"pk;auto;column(impact_id)"` - CveId int64 `orm:"index;column(cve_id)"description:"OriginUpstream 外键"` - Impact string `orm:"size(32);column(impact);null"description:"包含v2,v3评分数据"` + ImpactId int64 `orm:"pk;auto;column(impact_id)"` + CveId int64 `orm:"index;column(cve_id)"description:"OriginUpstream 外键"` + Impact string `orm:"size(32);column(impact);null"description:"包含v2,v3评分数据"` } type OriginUpstreamImpactScore struct { - ScoreId int64 `orm:"pk;auto;column(score_id)"` - ImpactId int64 `orm:"index;column(impact_id)" description:"OriginUpstreamImpact 外键"` - BaseMetricV3 int8 `orm:"column(base_met_v3);null" description:"v3评分存在为:1; 0:不存在"` - BaseMetricV2 int8 `orm:"column(base_met_v2);null" description:"v2评分存在为:1; 0:不存在"` - CvssV3 int8 `orm:"column(cvss_v3);null" description:"v3评分存在为:1; 0:不存在"` - CvssV2 int8 `orm:"column(cvss_v2);null" description:"v2评分存在为:1; 0:不存在"` - Status int8 `orm:"default(1);column(score_status);null" description:"1:未处理;2:已处理;3:已修改"` + ScoreId int64 `orm:"pk;auto;column(score_id)"` + ImpactId int64 `orm:"index;column(impact_id)" description:"OriginUpstreamImpact 外键"` + BaseMetricV3 int8 `orm:"column(base_met_v3);null" description:"v3评分存在为:1; 0:不存在"` + BaseMetricV2 int8 `orm:"column(base_met_v2);null" description:"v2评分存在为:1; 0:不存在"` + CvssV3 int8 `orm:"column(cvss_v3);null" description:"v3评分存在为:1; 0:不存在"` + CvssV2 int8 `orm:"column(cvss_v2);null" description:"v2评分存在为:1; 0:不存在"` + Status int8 `orm:"default(1);column(score_status);null" description:"1:未处理;2:已处理;3:已修改"` } type OriginUpstreamImpactScoreV3 struct { - V3Id int64 `orm:"pk;auto;column(v3_id)"` - ScoreId int64 `orm:"index;column(score_id)" description:"OriginUpstreamImpactScore 外键"` - BaseScore float64 `orm:"digits(10);decimals(1);column(base_score);null" description:"nvd 基准分"` - VectorString string `orm:"size(256);column(vector_value);null" description:"nvd vector 评分向量值"` - AttackComplexity string `orm:"size(64);column(attack_complexity);null"description:"攻击复杂性"` - AttackVector string `orm:"size(64);column(attack_vector);null"description:"攻击目标"` - AvailabilityImpact string `orm:"size(64);column(availability_impact);null"description:"可用性影响"` - BaseSeverity string `orm:"size(64);column(base_severity);null"description:"严重程度"` - UserInteraction string `orm:"size(64);column(user_interaction);null"description:"用户交互"` - PrivilegesRequired string `orm:"size(64);column(privilege_required);null"description:"所需特权"` - Version string `orm:"size(64);column(version);null"description:"Cvss版本"` - ConfidentialityImpact string `orm:"size(64);column(confidentiality_impact);null"description:"可信性影响"` - IntegrityImpact string `orm:"size(64);column(integrity_impact);null"description:"完整性影响"` - Scope string `orm:"size(64);column(scope);null"description:"范围"` - ImpactScore float64 `orm:"digits(10);decimals(1);column(impact_score);null" description:"nvd 影响评分"` - ExploitabilityScore float64 `orm:"digits(10);decimals(1);column(exploitability_score);null" description:"nvd 可利用性评分"` - CveLevel string `orm:"size(32);column(cve_level);null"description:"致命(Critical) >= 9.0;严重(High)>=7.0&&<=8.9;中等(Medium)>4.0 && <=6.9;一般(Low)<=4.0;其他"` + V3Id int64 `orm:"pk;auto;column(v3_id)"` + ScoreId int64 `orm:"index;column(score_id)" description:"OriginUpstreamImpactScore 外键"` + BaseScore float64 `orm:"digits(10);decimals(1);column(base_score);null" description:"nvd 基准分"` + VectorString string `orm:"size(256);column(vector_value);null" description:"nvd vector 评分向量值"` + AttackComplexity string `orm:"size(64);column(attack_complexity);null"description:"攻击复杂性"` + AttackVector string `orm:"size(64);column(attack_vector);null"description:"攻击目标"` + AvailabilityImpact string `orm:"size(64);column(availability_impact);null"description:"可用性影响"` + BaseSeverity string `orm:"size(64);column(base_severity);null"description:"严重程度"` + UserInteraction string `orm:"size(64);column(user_interaction);null"description:"用户交互"` + PrivilegesRequired string `orm:"size(64);column(privilege_required);null"description:"所需特权"` + Version string `orm:"size(64);column(version);null"description:"Cvss版本"` + ConfidentialityImpact string `orm:"size(64);column(confidentiality_impact);null"description:"可信性影响"` + IntegrityImpact string `orm:"size(64);column(integrity_impact);null"description:"完整性影响"` + Scope string `orm:"size(64);column(scope);null"description:"范围"` + ImpactScore float64 `orm:"digits(10);decimals(1);column(impact_score);null" description:"nvd 影响评分"` + ExploitabilityScore float64 `orm:"digits(10);decimals(1);column(exploitability_score);null" description:"nvd 可利用性评分"` + CveLevel string `orm:"size(32);column(cve_level);null"description:"致命(Critical) >= 9.0;严重(High)>=7.0&&<=8.9;中等(Medium)>4.0 && <=6.9;一般(Low)<=4.0;其他"` } type OriginUpstreamImpactScoreV2 struct { - V2Id int64 `orm:"pk;auto;column(v2_id)"` - ScoreId int64 `orm:"index;column(score_id)" description:"OriginUpstreamImpactScore 外键"` - AcInsufInfo string `orm:"size(64);column(acinsuf_info);null" description:"nvd vector 原始值"` - BaseScore float64 `orm:"digits(10);decimals(1);column(base_score);null" description:"nvd 基准分"` - VectorString string `orm:"size(256);column(vector_value);null" description:"nvd vector 评分向量值"` - AccessComplexity string `orm:"size(64);column(access_complexity);null"description:"攻击复杂性"` - Authentication string `orm:"size(64);column(authentication);null"description:"身份认证"` - AvailabilityImpact string `orm:"size(64);column(availability_impact);null"description:"可用性影响"` - Version string `orm:"size(64);column(version);null"description:"Cvss版本"` - ConfidentialityImpact string `orm:"size(64);column(confidentiality_impact);null"description:"可信性影响"` - IntegrityImpact string `orm:"size(64);column(integrity_impact);null"description:"完整性影响"` - AccessVector string `orm:"size(64);column(access_vector);null"description:"攻击目标"` - UserInteractionRequired string `orm:"size(64);column(user_interaction_required);null"description:"需要用户交互"` - Severity string `orm:"size(64);column(severity);null"description:"严重程度"` - ObtainUserPrivilege string `orm:"size(64);column(obtain_user_privilege);null"description:"获取用户特权"` - ObtainAllPrivilege string `orm:"size(64);column(obtain_all_privilege);null"description:"获取所有特权"` - ObtainOtherPrivilege string `orm:"size(64);column(obtain_other_privilege);null"description:"获取其他特权"` - ImpactScore float64 `orm:"digits(10);decimals(1);column(impact_score);null" description:"nvd 影响评分"` - ExploitabilityScore float64 `orm:"digits(10);decimals(1);column(exploitability_score);null" description:"nvd 可利用性评分"` - CveLevel string `orm:"size(32);column(cve_level);null"description:"致命(Critical) >= 9.0;严重(High)>=7.0&&<=8.9;中等(Medium)>4.0 && <=6.9;一般(Low)<=4.0;其他"` + V2Id int64 `orm:"pk;auto;column(v2_id)"` + ScoreId int64 `orm:"index;column(score_id)" description:"OriginUpstreamImpactScore 外键"` + AcInsufInfo string `orm:"size(64);column(acinsuf_info);null" description:"nvd vector 原始值"` + BaseScore float64 `orm:"digits(10);decimals(1);column(base_score);null" description:"nvd 基准分"` + VectorString string `orm:"size(256);column(vector_value);null" description:"nvd vector 评分向量值"` + AccessComplexity string `orm:"size(64);column(access_complexity);null"description:"攻击复杂性"` + Authentication string `orm:"size(64);column(authentication);null"description:"身份认证"` + AvailabilityImpact string `orm:"size(64);column(availability_impact);null"description:"可用性影响"` + Version string `orm:"size(64);column(version);null"description:"Cvss版本"` + ConfidentialityImpact string `orm:"size(64);column(confidentiality_impact);null"description:"可信性影响"` + IntegrityImpact string `orm:"size(64);column(integrity_impact);null"description:"完整性影响"` + AccessVector string `orm:"size(64);column(access_vector);null"description:"攻击目标"` + UserInteractionRequired string `orm:"size(64);column(user_interaction_required);null"description:"需要用户交互"` + Severity string `orm:"size(64);column(severity);null"description:"严重程度"` + ObtainUserPrivilege string `orm:"size(64);column(obtain_user_privilege);null"description:"获取用户特权"` + ObtainAllPrivilege string `orm:"size(64);column(obtain_all_privilege);null"description:"获取所有特权"` + ObtainOtherPrivilege string `orm:"size(64);column(obtain_other_privilege);null"description:"获取其他特权"` + ImpactScore float64 `orm:"digits(10);decimals(1);column(impact_score);null" description:"nvd 影响评分"` + ExploitabilityScore float64 `orm:"digits(10);decimals(1);column(exploitability_score);null" description:"nvd 可利用性评分"` + CveLevel string `orm:"size(32);column(cve_level);null"description:"致命(Critical) >= 9.0;严重(High)>=7.0&&<=8.9;中等(Medium)>4.0 && <=6.9;一般(Low)<=4.0;其他"` } type OriginUpstreamPoc struct { - PocId int64 `orm:"pk;auto;column(poc_id)"` - CveId int64 `orm:"index;column(cve_id)"description:"OriginUpstream 外键"` - Source string `orm:"size(512);column(source);null"description:"来源"` - Date string `orm:"size(32);column(date);null"description:"日期"` - Path string `orm:"size(512);column(path);null"description:"文件路径"` + PocId int64 `orm:"pk;auto;column(poc_id)"` + CveId int64 `orm:"index;column(cve_id)"description:"OriginUpstream 外键"` + Source string `orm:"size(512);column(source);null"description:"来源"` + Date string `orm:"size(32);column(date);null"description:"日期"` + Path string `orm:"size(512);column(path);null"description:"文件路径"` Dbindex string `orm:"size(512);column(dbindex);null"description:"数据库索引"` - Url string `orm:"size(512);column(url);null"description:"下载链接"` - Desc string `orm:"size(2048);column(desc);null"description:"说明"` + Url string `orm:"size(512);column(url);null"description:"下载链接"` + Desc string `orm:"size(2048);column(desc);null"description:"说明"` } type OriginUpstreamEvent struct { - EventId int64 `orm:"pk;auto;column(event_id)"` - CveId int64 `orm:"index;column(cve_id)"description:"OriginUpstream 外键"` - Title string `orm:"size(512);column(title);null"description:"标题"` - Date string `orm:"size(32);column(date);null"description:"日期"` - Url string `orm:"size(512);column(url);null"description:"连接"` + EventId int64 `orm:"pk;auto;column(event_id)"` + CveId int64 `orm:"index;column(cve_id)"description:"OriginUpstream 外键"` + Title string `orm:"size(512);column(title);null"description:"标题"` + Date string `orm:"size(32);column(date);null"description:"日期"` + Url string `orm:"size(512);column(url);null"description:"连接"` Description string `orm:"size(2048);column(description);null"description:"说明"` } type OriginUpstreamReference struct { - RefId int64 `orm:"pk;auto;column(ref_id)"` - CveId int64 `orm:"index;column(cve_id)"description:"OriginUpstream 外键"` - Name string `orm:"size(512);column(name);null"description:"名称"` + RefId int64 `orm:"pk;auto;column(ref_id)"` + CveId int64 `orm:"index;column(cve_id)"description:"OriginUpstream 外键"` + Name string `orm:"size(512);column(name);null"description:"名称"` Refsource string `orm:"size(512);column(refsource);null"description:"参考来源"` - Url string `orm:"size(512);column(url);null"description:"链接"` - Tags string `orm:"size(2048);column(tags);null"description:"tags"` + Url string `orm:"size(512);column(url);null"description:"链接"` + Tags string `orm:"size(2048);column(tags);null"description:"tags"` } type OriginUpstreamVulType struct { - VulId int64 `orm:"pk;auto;column(vul_id)"` - CveId int64 `orm:"index;column(cve_id)"description:"OriginUpstream 外键"` - Cwe string `orm:"size(256);column(cwe);null"description:"Cwe编号"` + VulId int64 `orm:"pk;auto;column(vul_id)"` + CveId int64 `orm:"index;column(cve_id)"description:"OriginUpstream 外键"` + Cwe string `orm:"size(256);column(cwe);null"description:"Cwe编号"` EnDesc string `orm:"size(2048);column(en_desc);null"description:"英文描述"` ZhDesc string `orm:"size(2048);column(zh_desc);null"description:"中文描述"` } type OriginUpstreamFixSuggest struct { - FixId int64 `orm:"pk;auto;column(fix_id)"` - CveId int64 `orm:"index;column(cve_id)"description:"OriginUpstream 外键"` + FixId int64 `orm:"pk;auto;column(fix_id)"` + CveId int64 `orm:"index;column(cve_id)"description:"OriginUpstream 外键"` Detail string `orm:"size(1024);column(detail);null"description:"细节"` } type OriginUpstreamFixSuggestRef struct { - FixRefId int64 `orm:"pk;auto;column(fix_ref_id)"` - FixId int64 `orm:"index;column(fix_id)"description:"OriginUpstreamFixSuggest 外键"` + FixRefId int64 `orm:"pk;auto;column(fix_ref_id)"` + FixId int64 `orm:"index;column(fix_id)"description:"OriginUpstreamFixSuggest 外键"` Refsource string `orm:"size(512);column(refsource);null"description:"参考文献,包含以下内容"` - Url string `orm:"size(1024);column(url);null"description:"链接"` - Name string `orm:"size(1024);column(name);null"description:"名称"` + Url string `orm:"size(1024);column(url);null"description:"链接"` + Name string `orm:"size(1024);column(name);null"description:"名称"` +} + +//GiteOriginIssue 码云上已经存在的issue +type GiteOriginIssue struct { + Id int64 `orm:"pk;auto"` + IssueId int64 `json:"issue_id" orm:"unique"` + Url string ` description:"issue gitee 链接"` + Number string `orm:"size(50);unique" description:"issue 编号"` + State string `orm:"size(50)" description:"issue 状态"` + Title string `orm:"null" description:"issue 标题"` + CveNumber string `json:"cve_number" description:"CVE 编号"` + Body string `orm:"null;type(text)" description:"issue 主体"` + IssueCreate string `json:"issue_create" description:"issue 创建者"` + IssueAssignee string `json:"issue_assignee" orm:"null" description:"issue 责任人"` + RepoPath string `json:"repo_path" description:"仓库空间地址"` + RepoUrl string `json:"repo_url" description:"仓库码云地址链接"` + IssueType string `json:"issue_type" description:"issue 类型"` + IssueExistTpl bool `json:"issue_exist_tpl" description:"此 issue 是否有对应的模板"` + SecurityHole bool `json:"security_hole" description:"是否为安全漏洞"` + Status int8 `orm:"default(0);column(proc_status)"description:"0:cve新增;1:数据已变化;2:数据已处理"` + IssueCreateAt time.Time `json:"issue_create_at" orm:"null" description:"issue 创建的时间"` + IssueUpdateAt time.Time `json:"issue_update_at" orm:"null" description:"issue 更新的时间"` + IssueFinishAt time.Time `json:"issue_finish_at" orm:"null" description:"issue 关闭的时间"` + GrabTime time.Time `json:"grab_time" orm:"auto_now;type(datetime)" description:"记录当前issue抓取的时间"` + InfProduct string `json:"inf_product" orm:"null" description:"受影响的产品"` //受影响的产品 + RepoDesc string `json:"repo_desc" orm:"null;size(2048)" description:"cve 对组件的描述"` } type OriginUpstreamFixSuggestRefTag struct { - TagId int64 `orm:"pk;auto;column(tag_id)"` - FixRefId int64 `orm:"index;column(fix_ref_id)"description:"OriginUpstreamFixSuggestRef 外键"` - Name string `orm:"size(512);column(name);null"description:"名称"` + TagId int64 `orm:"pk;auto;column(tag_id)"` + FixRefId int64 `orm:"index;column(fix_ref_id)" description:"OriginUpstreamFixSuggestRef 外键"` + Name string `orm:"size(512);column(name);null" description:"名称"` +} + +type OriginExcel struct { + CveId int64 `orm:"pk;auto;column(cve_id)"` + CveNum string `orm:"size(256);column(cve_num)" description:"cve编号"` + CveUrl string `orm:"size(2048);column(cve_url);null" description:"cve下载链接"` + CveVersion string `orm:"size(256);column(cve_version);null" description:"漏洞归属版本"` + PackName string `orm:"size(128);column(pack_name);null" description:"包名"` + ScoreType string `orm:"size(16);column(score_type);null" description:"评分类型:v3"` + NVDScore float64 `orm:"digits(10);decimals(1);column(nvd_score);null" description:"nvd评分"` + CveLevel string `orm:"size(32);column(cve_level);null" description:"致命(Critical);严重(High);中等(Medium);一般(Low);其他"` + CveDesc string `orm:"size(4096);column(cve_desc);null" description:"漏洞简述"` + RepairTime string `orm:"size(32);column(repair_time);null" description:"cve发布时间"` + NVDVector string `orm:"size(256);column(vector_value);null" description:"nvd 评分向量"` + AttackVector string `orm:"size(256);column(attack_vector);null" description:"nvd 3.0评分"` + AccessVector string `orm:"size(256);column(access_vector);null" description:"nvd 2.0 评分"` + AttackComplexity string `orm:"size(64);column(attack_complexity);null"` + AccessComplexity string `orm:"size(64);column(access_complexity);null"` + PrivilegeRequired string `orm:"size(64);column(privilege_required);null"` + UserInteraction string `orm:"size(64);column(user_interaction);null"` + Scope string `orm:"size(64);column(scope);null"` + Confidentiality string `orm:"size(64);column(confidentiality);null"` + Integrity string `orm:"size(64);column(integrity);null"` + Availability string `orm:"size(64);column(availability);null"` + Authentication string `orm:"size(64);column(authentication);null"` + CveStatus int8 `orm:"default(0);column(cve_status);null" description:"0:未处理;1:已修改;2:已处理; 3: 数据错误,不做处理"` + CreateTime string `orm:"type(datetime);column(create_time);null"` + UpdateTime string `orm:"type(datetime);column(update_time);null"` + DeleteTime string `orm:"type(datetime);column(delete_time);null"` + +} + + +type GitRepoGroups struct { + GroupId int64 `orm:"pk;auto;column(group_id)"` + GroupName string `orm:"index"` +} + +//GiteRepo 码云仓库 +type GiteRepo struct { + RepoId int64 `orm:"pk;auto;column(repo_id)"` + GroupId int64 `orm:"index;column(group_id)"description:"GitRepoGroups 外键"` + OrgId int64 + OrgPath string `orm:"size(128);column(org_path);null" description:"组织名称"` + Path string `orm:"size(512);column(path);null" description:"仓库名称"` + Status int8 `orm:"default(0);column(status);null" description:"1: 正常;2:已删除"` + Public bool + Private bool + Fork bool + CreateTime string `orm:"type(datetime);column(create_time);null"` + UpdateTime string `orm:"type(datetime);column(update_time);null"` + DeleteTime string `orm:"type(datetime);column(delete_time);null"` +} + +//GiteMember 码云仓库成员 +type GiteRepoMember struct { + MemBerId int64 `orm:"pk;auto;column(repo_id)"` + GroupId int64 `orm:"index;column(group_id)"description:"GitRepoGroups 外键"` + MemberName string `orm:"size(512);column(member_name);null" description:"成员名称"` + MemberType string `orm:"size(128);column(member_type);null" description:"Maintainer;Committer"` + CreateTime string `orm:"type(datetime);column(create_time);null"` + UpdateTime string `orm:"type(datetime);column(update_time);null"` + DeleteTime string `orm:"type(datetime);column(delete_time);null"` +} + +//GiteRepoBranch 码云仓库分支 +type GiteRepoBranch struct { + Id int64 `orm:"pk;auto"` + RepoId int64 `orm:"index;column(repo_id)"description:"GiteRepo 外键"` + ProtectionUrl string + Name string + Protected string +} + +type ExportRecord struct { + Id int64 `orm:"pk;auto"` + FileName string `orm:"unique"` + CreateTime time.Time `orm:"auto_now_add;type(datetime);column(create_time)"` } func CreateDb() bool { BConfig, err := config.NewConfig("ini", "conf/app.conf") - if err != nil{ + if err != nil { logs.Error("config init error:", err) return false } prefix := BConfig.String("mysql::dbprefix") - InitdbType,_ := beego.AppConfig.Int("initdb") + InitdbType, _ := beego.AppConfig.Int("initdb") if InitdbType == 1 { orm.RegisterModelWithPrefix(prefix, new(OtherUser), new(AdminUser), new(VulnCenter), new(OpenEulerSA), new(Score), new(SecurityNotice), new(Package), new(IssueTemplate), new(ScoreRecord), new(IssueHooks), - new(GitPackageTable), new(GitOpenEuler), new(GitPackageInfo), new(GitSubPack), - new(SecurityReviewer),new(GitSubPackRequire), new(GitSubPackProvides), new(GitSubPackRequiredby), + new(GitPackageTable), new(GitOpenEuler), new(GitPackageInfo), new(GitSubPack),new(GitOpenEulerTableRelate), + new(SecurityReviewer), new(GitSubPackRequire), new(GitSubPackProvides), new(GitSubPackRequiredby), new(IpWhite), new(OriginUpstream), new(OriginUpstreamDesc), new(OriginUpstreamConfig), new(OriginUpstreamConfigNode), - new(OriginUpstreamConfigNodeCpe), new(OriginUpstreamImpact), new(OriginUpstreamImpactScore), - new(OriginUpstreamImpactScoreV3), new(OriginUpstreamImpactScoreV2), - new(OriginUpstreamPoc), new(OriginUpstreamEvent), new(OriginUpstreamReference), new(OriginUpstreamVulType), - new(OriginUpstreamFixSuggest),new(OriginUpstreamFixSuggestRefTag) ,new(OriginUpstreamFixSuggestRef)) + new(OriginUpstreamConfigNodeCpe), new(OriginUpstreamImpact), new(OriginUpstreamImpactScore), + new(OriginUpstreamImpactScoreV3), new(OriginUpstreamImpactScoreV2), + new(OriginUpstreamPoc), new(OriginUpstreamEvent), new(OriginUpstreamReference), new(OriginUpstreamVulType), + new(OriginUpstreamFixSuggest), new(OriginUpstreamFixSuggestRefTag), + new(OriginUpstreamFixSuggestRef), new(GiteOriginIssue), new(OriginExcel), new(ExportRecord),new(GitRepoGroups), + new(GiteRepo),new(GiteRepoMember),new(GiteRepoBranch), + ) logs.Info("table create success!") errosyn := orm.RunSyncdb("default", false, true) if errosyn != nil { @@ -454,4 +581,4 @@ func CreateDb() bool { } } return true -} \ No newline at end of file +} diff --git a/models/uploadcve.go b/models/uploadcve.go index dcc2431424a112d8e1ad0f132f9119f2ea578759..56b0d1fdec955245b9e8823448ee894fc1424d1b 100644 --- a/models/uploadcve.go +++ b/models/uploadcve.go @@ -10,7 +10,7 @@ type OpenSaId struct { Id int64 } -func QueryCveOpeneulerdata(pkgName string, version string) (GitOpenEuler, bool){ +func QueryYamlData(pkgName string, version string)(GitOpenEuler, bool){ o := orm.NewOrm() var goe GitOpenEuler err := o.Raw("select * from cve_git_open_euler where package_name = ? and version = ?", pkgName, version).QueryRow(&goe) @@ -23,6 +23,84 @@ func QueryCveOpeneulerdata(pkgName string, version string) (GitOpenEuler, bool){ } } +func QueryOriginRepo(pkgName string) (GiteRepo, bool) { + o := orm.NewOrm() + var gr GiteRepo + repoOrg, errx := common.GetRepoOrg() + if errx != nil { + logs.Error("pkgName: ", pkgName, ",无法 获取组织, err: ", errx) + return gr, false + } + err := o.Raw("select * from cve_gite_repo where path = ? and org_path = ? and status = ?", pkgName, repoOrg, 1).QueryRow(&gr) + if err != nil { + logs.Info("pkgName", pkgName, "repoOrg", repoOrg, ", cve_gite_repo 无对应数据") + return gr,false + } else { + logs.Info("pkgName", pkgName, "repoOrg", repoOrg, ", cve_gite_repo 查询成功") + return gr,true + } +} + +func QueryRepoMember(groupId int64, memberType string)([]GiteRepoMember, bool){ + o := orm.NewOrm() + var grm []GiteRepoMember + num, err := o.Raw("select * from cve_gite_repo_member where group_id = ? and member_type = ?", groupId, memberType).QueryRows(&grm) + if err != nil || num == 0{ + logs.Info("groupId", groupId, ",memberType", memberType, ", cve_gite_repo_member 无对应数据") + return grm,false + } else { + logs.Info("groupId", groupId, ",memberType", memberType, ", cve_gite_repo_member 查询成功") + return grm,true + } +} + +func QueryCveOpeneulerdata(pkgName string, version string) (GitOpenEuler, bool){ + goe, ok := QueryYamlData(pkgName, version) + if !ok || goe.GitId == 0 { + gr, okrg := QueryOriginRepo(pkgName) + if !okrg || gr.RepoId == 0 { + return goe, ok + } + grm, okgrm := QueryRepoMember(gr.GroupId, "Maintainer") + if !okgrm { + return goe, ok + } + for _, g := range grm { + goe.MainTainer = g.MemberName + break + } + return goe, true + } else { + if goe.MainTainer == "" || len(goe.MainTainer) == 0 { + gr, okrg := QueryOriginRepo(pkgName) + if !okrg || gr.RepoId == 0 { + return goe, ok + } + grm, okgrm := QueryRepoMember(gr.GroupId, "Maintainer") + if !okgrm { + return goe, ok + } + for _, g := range grm { + goe.MainTainer = g.MemberName + break + } + } + } + return goe, ok +} + +func QueryCveOpeneulerDetaildata(pkgName string, version string) (GitPackageInfo, bool){ + o := orm.NewOrm() + var goe GitPackageInfo + err := o.Raw("select * from cve_git_package_info where package_name = ? and version = ?", pkgName, version).QueryRow(&goe) + if err != nil { + logs.Info("pkgName: ", pkgName, ",version: ", version, ", cve_git_package_info 无对应数据") + return goe, false + } else { + logs.Info("pkgName: ", pkgName, ",version: ", version, ", cve_git_package_info 查询成功") + return goe, true + } +} func QueryCveOriginByIds(ids string) (OriginUpstream, bool){ o := orm.NewOrm() diff --git a/models/ymal.go b/models/ymal.go index 7999746abb5cd6fc36f058e55b96d146a81cc5d5..8313eff577f453c26bac5a78ca1d701f95b1f7b9 100644 --- a/models/ymal.go +++ b/models/ymal.go @@ -18,6 +18,11 @@ func GetYamlTable(gt *[]GitPackageTable) (int64, error) { func CreateYamlTable(gt *GitPackageTable) (TableId int64, err error) { o := orm.NewOrm() var localgt GitPackageTable + if gt.TableName == "openEuler_LTS_20.03" { + gt.Brands = "openEuler-20.03-LTS" + } else { + gt.Brands = "master" + } errx := o.Raw("select *"+ " from cve_git_package_table where table_name = ? ", gt.TableName).QueryRow(&localgt) if errx != nil { @@ -33,6 +38,7 @@ func CreateYamlTable(gt *GitPackageTable) (TableId int64, err error) { } else { // 更新 gt.TableId = localgt.TableId + gt.Brands = localgt.Brands if num, err := o.Update(gt); err == nil { logs.Info("update cve_git_package_table success, num: ", num, "TableName: ", gt.TableName) } else { @@ -70,10 +76,41 @@ func GetSingleYaml(ge *GitOpenEuler) (bool, error){ } } +func InsertOpenEulerRelate(getr *GitOpenEulerTableRelate) (id int64, typex string, err error) { + o := orm.NewOrm() + var localge GitOpenEulerTableRelate + errx := o.Raw("select *"+ + " from cve_git_open_euler_table_relate where git_id = ? and table_name = ?", + getr.GitId, getr.TableName).QueryRow(&localge) + if errx != nil { + // 创建 + var relateId int64 + if relateId, err = o.Insert(getr); err == nil { + logs.Info("insert cve_git_open_euler_table_relate success, RelateId: ", relateId, "tableName: ", getr.TableName) + } else { + logs.Error("insert cve_git_open_euler_table_relate failed, ", "tableName: ", getr.TableName, "err: ", err) + return 0, "insert", err + } + return relateId, "insert", nil + } else { + // 更新 + getr.RelateId = localge.RelateId + if _, err := o.Update(getr); err == nil { + logs.Info("update cve_git_open_euler_table_relate success, RelateId: ", getr.RelateId, "tableName: ", getr.TableName) + } else { + logs.Error("update cve_git_open_euler_table_relate failed, ", "tableName: ", getr.TableName, "err: ", err) + return getr.RelateId, "update", err + } + return getr.RelateId, "update", nil + } +} -func CreateYaml(ge *GitOpenEuler) (id int64, typex string, err error) { +func CreateYaml(ge *GitOpenEuler, tableValue GitPackageTable) (id int64, typex string, err error) { o := orm.NewOrm() var localge GitOpenEuler + var getr GitOpenEulerTableRelate + getr.TableName = tableValue.TableName + getr.Brands = tableValue.Brands errx := o.Raw("select *"+ " from cve_git_open_euler where package_name = ? and (version = ? or release = ?)", ge.PackageName, ge.Version, ge.Release).QueryRow(&localge) @@ -88,6 +125,8 @@ func CreateYaml(ge *GitOpenEuler) (id int64, typex string, err error) { logs.Error("insert cve_git_open_euler failed, ", "packName: ", ge.PackageName, "err: ", err) return 0, "insert", err } + getr.GitId = GitId + InsertOpenEulerRelate(&getr) return GitId, "insert", nil } else { // 更新 @@ -100,6 +139,8 @@ func CreateYaml(ge *GitOpenEuler) (id int64, typex string, err error) { logs.Error("update cve_git_open_euler failed, ", "packName: ", ge.PackageName, "err: ", err) return ge.GitId, "update", err } + getr.GitId = ge.GitId + InsertOpenEulerRelate(&getr) return ge.GitId, "update", nil } } diff --git a/routers/router.go b/routers/router.go index 08d8949d20dc82cd2b4a4cbb30099f85b99cd0f8..1ae0b433c418c094199788241f279a4352155340 100644 --- a/routers/router.go +++ b/routers/router.go @@ -54,6 +54,10 @@ func init() { beego.NSInclude(&controllers.HookEventControllers{}, ), ), + beego.NSNamespace("/download/excel",beego.NSInclude( + &controllers.FileController{}, + ), + ), ) beego.AddNamespace(ns) } diff --git a/swagger.zip b/swagger.zip deleted file mode 100644 index a38cc9e5dfe1623ff2df150cead85f8452ae415d..0000000000000000000000000000000000000000 Binary files a/swagger.zip and /dev/null differ diff --git a/task/cve.go b/task/cve.go index 55a334f8568051a7c3ab377dc6db18057d8f4525..0bb41baadcbc8524ca0c24fd5c8b15279820ca0f 100644 --- a/task/cve.go +++ b/task/cve.go @@ -8,6 +8,25 @@ import ( "github.com/astaxie/beego/logs" ) +func ProcCveOriginData(prcnum, days , openeulernum int, cveRef, owner string)(bool, error) { + // 处理api获取的原始数据 + ok, err := taskhandler.GetCveOriginData(prcnum, days, openeulernum, cveRef) + if !ok { + logs.Error("接口上的原始数据处理失败(GetCveOriginData), err: ", err) + } + // 处理excel的原始数据 + okx, errx := taskhandler.GetCveOriginExcelData(prcnum, days, openeulernum, cveRef) + if !okx { + logs.Error("excel数据处理失败(GetCveOriginExcelData), errx: ", errx) + } + // 兼容已创建的issue数据 + oki, erri := taskhandler.GetCveIssueData(prcnum, days, openeulernum, cveRef, owner) + if !oki { + logs.Error("issue数据处理失败(GetCveIssueData), erri: ", erri) + } + return true, nil +} + func ParamsCveOriginData() error{ defer common.Catchs() // 查询需要处理的cve, 1:新增;2:修改 @@ -35,7 +54,8 @@ func ParamsCveOriginData() error{ logs.Error("config cve::openeulernum error:", err) return ok } + owner := BConfig.String("gitee::owner") // 获取表的数据源 - _, errx := taskhandler.GetCveOriginData(prcnum, days, openeulernum, cveRef) + _, errx := ProcCveOriginData(prcnum, days, openeulernum, cveRef, owner) return errx } diff --git a/task/genexcel.go b/task/genexcel.go new file mode 100644 index 0000000000000000000000000000000000000000..05f34548576216aaef0de4e3c08733ef9cd63a02 --- /dev/null +++ b/task/genexcel.go @@ -0,0 +1,39 @@ +// Issues that have been normally closed are exported to excel files +package task + +import ( + "cvevulner/common" + "cvevulner/taskhandler" + "errors" + "github.com/astaxie/beego/config" + "github.com/astaxie/beego/logs" +) + +func GenExcelData() error{ + defer common.Catchs() + // 查询需要处理的cve, 1:新增;2:修改 + BConfig, err := config.NewConfig("ini", "conf/app.conf") + if err != nil{ + logs.Error("config init error:", err) + return err + } + forceRewrite, err := BConfig.Bool("excel::forcerewrite") + if err != nil{ + logs.Error("config excel::forcerewrite error: invalid value is ", forceRewrite) + return errors.New("value is nil") + } + snPrefix := BConfig.String("excel::snprefix") + if snPrefix == "" { + logs.Error("config excel::snprefix error: invalid value is ", snPrefix) + return errors.New("value is nil") + } + snSuffix, err := BConfig.Int64("excel::snsuffix") + if snSuffix == 0 || err != nil { + logs.Error("config excel::snsuffix error: invalid value is ", snSuffix) + return errors.New("value is nil") + } + //excelName := "openEuler." + common.GetCurDate() + ".xlsx" + //errx := taskhandler.GenerateCveExcel(excelName, snPrefix, snSuffix, forceRewrite) + errx := taskhandler.GenerateExcelTask() + return errx +} \ No newline at end of file diff --git a/task/grabissue.go b/task/grabissue.go new file mode 100644 index 0000000000000000000000000000000000000000..cb84268a38ec691d0e8bb4e6c275d8e85b354087 --- /dev/null +++ b/task/grabissue.go @@ -0,0 +1,32 @@ +package task + +import ( + "cvevulner/common" + "cvevulner/taskhandler" + "errors" + "github.com/astaxie/beego/config" + "github.com/astaxie/beego/logs" + "os" +) + +func GetIssueData() error{ + defer common.Catchs() + // 查询需要处理的cve, 1:新增;2:修改 + BConfig, err := config.NewConfig("ini", "conf/app.conf") + if err != nil{ + logs.Error("config init error:", err) + return err + } + owner := BConfig.String("gitee::owner") + if owner == "" { + logs.Error("config gitee::owner error: invalid value is ", owner) + return errors.New("value is nil") + } + giteeToken := os.Getenv("GITEE_TOKEN") + if giteeToken == "" { + logs.Error("获取token失败, 无法获取issue任务") + return errors.New("获取token失败, 无法获取issue任务") + } + errx := taskhandler.GrabIssueByOrg(giteeToken, owner) + return errx +} \ No newline at end of file diff --git a/task/inittask.go b/task/inittask.go index 585de9fe4ea2cc223c7a63ce934317a7bd7d8694..f663e45cf64da2abd0eb87ccb8a8c84e879dacd2 100644 --- a/task/inittask.go +++ b/task/inittask.go @@ -10,7 +10,7 @@ func CheckOriCveTask(oricvecheck string, ch *chan bool) { logs.Info("校验原始cve数据 task start") CheckTask := toolbox.NewTask("CheckOriCve", oricvecheck, CheckOriCve) err := CheckTask.Run() - if err != nil{ + if err != nil { logs.Error("创建校验原始cve数据失败 ,err:", err) return } @@ -19,14 +19,14 @@ func CheckOriCveTask(oricvecheck string, ch *chan bool) { //time.Sleep(time.Minute * 1) logs.Info("校验原始cve数据 task end") *ch <- true - defer toolbox.StopTask() + //defer toolbox.StopTask() } func InitYamlTask(getymal string, ch *chan bool) { logs.Info("获取yaml数据源 task start") YamlTask := toolbox.NewTask("GetYamlData", getymal, GetYamlData) err := YamlTask.Run() - if err != nil{ + if err != nil { logs.Error("创建获取yaml数据源任务失败 ,err:", err) return } @@ -35,14 +35,14 @@ func InitYamlTask(getymal string, ch *chan bool) { //time.Sleep(time.Minute * 1) logs.Info("获取yaml数据源 task end") *ch <- true - defer toolbox.StopTask() + //defer toolbox.StopTask() } func InitCveTask(getcve string, ch *chan bool) { logs.Info("将cve原始数据生成cve库 task start") CveTask := toolbox.NewTask("ParamsCveOriginData", getcve, ParamsCveOriginData) err := CveTask.Run() - if err != nil{ + if err != nil { logs.Error("创建Cve任务失败 ,err:", err) return } @@ -51,14 +51,31 @@ func InitCveTask(getcve string, ch *chan bool) { //time.Sleep(time.Minute * 1) logs.Info("将cve原始数据生成cve库 task end") *ch <- true - defer toolbox.StopTask() + //defer toolbox.StopTask() } -func InitIssueToken(issueoath string) { +func InitIssueTask(getissue string, ch *chan bool) { + logs.Info("获取已经创建的issue数据源 task start") + //taskhandler.GrabIssueByOrg("8457c66db66955376519059b97e33dd1","src-openeuler") + issueTask := toolbox.NewTask("GetIssueData", getissue, GetIssueData) + err := issueTask.Run() + if err != nil { + logs.Error("获取已经创建的issue数据源任务失败 ,err:", err) + return + } + toolbox.AddTask("GetIssueData", issueTask) + toolbox.StartTask() + //time.Sleep(time.Minute * 1) + logs.Info("获取已经创建的issue数据源 task end") + *ch <- true + //defer toolbox.StopTask() +} + +func InitIssueToken(issueoath string, ch *chan bool) { logs.Info("执行获取token任务开始") TokenTask := toolbox.NewTask("GetGiteeToken", issueoath, GetGiteeToken) err := TokenTask.Run() - if err != nil{ + if err != nil { logs.Error("create Issue token task failed ,err:", err) return } @@ -66,14 +83,15 @@ func InitIssueToken(issueoath string) { toolbox.StartTask() //time.Sleep(time.Minute * 1) logs.Info("执行获取token任务结束") - defer toolbox.StopTask() + *ch <- true + //defer toolbox.StopTask() } func CreatTask(createIssue string, ch *chan bool) { logs.Info("执行创建issue任务开始") cIssueTask := toolbox.NewTask("CreateIssue", createIssue, CreateIssue) err := cIssueTask.Run() - if err != nil{ + if err != nil { logs.Error("create Issue task failed ,err:", err) return } @@ -82,12 +100,29 @@ func CreatTask(createIssue string, ch *chan bool) { //time.Sleep(time.Minute * 1) logs.Info("执行创建issue任务结束") *ch <- true - defer toolbox.StopTask() + //defer toolbox.StopTask() +} + +func GenSAExcelTask(genExcel string, ch *chan bool) { + logs.Info("执行issue生成excel任务开始") + genExcelTask := toolbox.NewTask("GenExcelData", genExcel, GenExcelData) + err := genExcelTask.Run() + if err != nil { + logs.Error("create genExcelTask failed ,err:", err) + return + } + toolbox.AddTask("GenExcelData", genExcelTask) + toolbox.StartTask() + //time.Sleep(time.Minute * 1) + logs.Info("执行issue生成excel任务结束") + *ch <- true + //defer toolbox.StopTask() } func InitTask() { + BConfig, err := config.NewConfig("ini", "conf/app.conf") - if err != nil{ + if err != nil { logs.Error("config init error: file:conf/app.conf: ", err) return } @@ -109,6 +144,30 @@ func InitTask() { <-checkch close(checkch) } + // 定时刷新gittoken + gittokenflag, errx := BConfig.Int("crontab::gittokenflag") + if gittokenflag == 1 && errx == nil { + issueoath := BConfig.String("crontab::issueoath") + // 定时刷新token + //go InitIssueToken(issueoath, &ch) + // 从环境变量获取token + gitToken := BConfig.String("gitee::git_token") + if gitToken == "xxx" { + var ch = make(chan bool) + go InitIssueToken(issueoath, &ch) + <- ch + close(ch) + } + } + // 获取已经创建的issue + getissueflag, errxs := BConfig.Int("crontab::getissueflag") + if getissueflag == 1 && errxs == nil { + getissue := BConfig.String("crontab::getissue") + var issuech = make(chan bool) + go InitIssueTask(getissue, &issuech) + <-issuech + close(issuech) + } // 生成cve漏洞库 cveflag, errxs := BConfig.Int("crontab::cveflag") if cveflag == 1 && errxs == nil { @@ -120,20 +179,24 @@ func InitTask() { } // 添加issue taskFlag, errx := BConfig.Int("crontab::issueflag") - if taskFlag == 1 && errx == nil{ - issueoath := BConfig.String("crontab::issueoath") - gitToken := BConfig.String("gitee::git_token") - if gitToken == "xxx" { - InitIssueToken(issueoath) - } + if taskFlag == 1 && errx == nil { var ch = make(chan bool) - //go InitIssueToken(issueoath, &ch) createIssue := BConfig.String("crontab::createissue") go CreatTask(createIssue, &ch) - <- ch + <-ch + close(ch) + } else { + logs.Info("no task") + } + // 将issue生成excel数据 + genexcelflag, errx := BConfig.Int("crontab::genexcelflag") + if genexcelflag == 1 && errx == nil { + var ch = make(chan bool) + genExcel := BConfig.String("crontab::genexcel") + go GenSAExcelTask(genExcel, &ch) + <-ch close(ch) } else { logs.Info("no task") } } - diff --git a/task/issuetask.go b/task/issuetask.go index 9f78c8a5e38cc8576e04b75d1870867cf1cb19f7..8d04fd6cd998d253cc3c1e68ab66bd2f77fb4875 100644 --- a/task/issuetask.go +++ b/task/issuetask.go @@ -9,6 +9,7 @@ import ( "github.com/astaxie/beego/config" "github.com/astaxie/beego/logs" "os" + "strings" ) @@ -95,6 +96,22 @@ func CreateIssue() error{ path := BConfig.String("gitee::path") for index, issueValue := range cveData { logs.Info("当前正在处理第:", index, "条cve数据, cveNum: ", issueValue.CveNum) + // 判断issue是否已经处理过 + goi, oks := models.QueryIssueCveByNum(issueValue.CveNum, issueValue.PackName) + if oks { + if strings.ToLower(goi.State) == "closed" || strings.ToLower(goi.State) == "rejected" { + models.UpdateIssueStatus(issueValue, 2) + logs.Info("cve数据已经已经提交过issue,不需要重复提交, cveData: ", issueValue) + continue + } + } + // 判断cve是否已经处理过 + issueExist := taskhandler.GetCveSecurityNotice(issueValue.CveNum) + if issueExist { + models.UpdateIssueStatus(issueValue, 2) + logs.Info("cve数据已经在官网上展示过,不需要在git上提交issue, cveData: ", issueValue) + continue + } // 处理每一条cve数据 if issueValue.Status == 0 { err := ProcIssue(issueValue , accessToken, owner, path) @@ -129,6 +146,7 @@ func ProcUpdateIssue(issueValue models.VulnCenter, accessToken, owner, path stri lit.NVDVector = sr.NvectorVule lit.CveBrief = issueValue.Description lit.CveLevel = issueValue.CveLevel + path = lit.Repo _, err := taskhandler.UpdateIssueToGit(accessToken, owner, path, issueValue, lit) if err != nil { @@ -152,9 +170,10 @@ func ProcUpdateIssue(issueValue models.VulnCenter, accessToken, owner, path stri func ProcIssue(issueValue models.VulnCenter, accessToken, owner, path string) error{ assignee := "" + brandArry := []string{} sn, err := models.QueryIssueSecurity(issueValue.CveId) - if err == nil { - path = sn.InfluenceComponent + if err == nil && len(sn.CveNum) > 0 { + path = issueValue.PackName logs.Info("查询安全信息:sn: ", sn) // 获取issue处理人 gitYaml, ok := models.QueryCveOpeneulerdata(issueValue.PackName, issueValue.CveVersion) @@ -166,6 +185,15 @@ func ProcIssue(issueValue models.VulnCenter, accessToken, owner, path string) er } } else { assignee = gitYaml.MainTainer + // 查询受影响的分支信息 + gt, errgt := models.QueryCveBrands(gitYaml.GitId) + if errgt == nil{ + for _, t := range gt { + if t.Brands != "" && t.Brands != "master" && len(t.Brands) > 1 { + brandArry = append(brandArry, t.Brands) + } + } + } } } else { logs.Error("获取security 失败, err: ", err, "cveId: ", issueValue.CveId) @@ -176,16 +204,30 @@ func ProcIssue(issueValue models.VulnCenter, accessToken, owner, path string) er logs.Error("获取Score 失败, err: ", err, "cveId: ", issueValue.CveId) return err } - resp, err := taskhandler.CreateIssueToGit(accessToken, owner, path, assignee, issueValue, sc) + branchs := "" + errBrands := errors.New("") + // 获取分支信息 + if len(brandArry) > 0 { + for _, b := range brandArry { + if b != "" && len(b) > 1 { + branchs = branchs + b + "/" + } + } + if branchs != "" && len(branchs) > 1 { + branchs = branchs[:len(branchs) - 1] + } + } else { + branchs, errBrands = taskhandler.GetBranchesInfo(accessToken, owner, path) + if branchs == "" { + logs.Error("获取分支信息失败,CveNum: ", issueValue.CveNum, "path: ", path, ", err: ", errBrands) + } + brandArry = append(brandArry, branchs) + } + resp, err := taskhandler.CreateIssueToGit(accessToken, owner, path, assignee, issueValue, sc, brandArry) if err != nil { logs.Error("创建issue失败, err: ", err, "resp: ", resp, "cveId: ", issueValue.CveId) return err } - // 获取分支信息 - branchs, err := taskhandler.GetBranchesInfo(accessToken, owner, path) - if branchs == "" { - logs.Error("获取分支信息失败,CveNum: ", issueValue.CveNum, "path: ", path) - } // 存储安全公告相关信息 var sec models.SecurityNotice taskhandler.CreateSecNoticeData(&sec, issueValue, path, branchs) diff --git a/taskhandler/common.go b/taskhandler/common.go index baafb6b614c3ed9063e1420329f440557c8de51b..e0f9033671c800d37e0ce5ea601c1a080008d4ed 100644 --- a/taskhandler/common.go +++ b/taskhandler/common.go @@ -4,16 +4,28 @@ import ( "cvevulner/common" "cvevulner/models" "fmt" + "reflect" "strconv" + "strings" ) type GiteeToken struct { - GrantType string - UserName string - Password string - ClientId string + GrantType string + UserName string + Password string + ClientId string ClientSecret string - Scope string + Scope string +} + +func CommentTemplate(assignee, commentCmd, affectedVersion string) string { + //commentTemplate := "" + commentTemplate := "Hey @" + assignee + "\n" + + "以下内容需要您填写, 请复制到评论区回复喔" + "\n" + + "影响性分析说明: \n\n" + "openEuler评分: \n\n" + + "受影响版本排查(受影响/不受影响): \n" + affectedVersion + + "\n也可以参考: " + commentCmd + "\n" + return commentTemplate } func GitOpenEulerData(values map[string]interface{}, ge *models.GitOpenEuler, tb models.GitPackageTable) { @@ -30,9 +42,9 @@ func GitOpenEulerData(values map[string]interface{}, ge *models.GitOpenEuler, tb case int: ge.Feature = strconv.Itoa(values["feature"].(int)) case int64: - ge.Feature = strconv.FormatInt(values["feature"].(int64),10) + ge.Feature = strconv.FormatInt(values["feature"].(int64), 10) case float64: - ge.Feature = strconv.FormatInt(int64(values["feature"].(float64)),10) + ge.Feature = strconv.FormatInt(int64(values["feature"].(float64)), 10) default: ge.Feature = "" } @@ -107,9 +119,9 @@ func GitOpenEulerData(values map[string]interface{}, ge *models.GitOpenEuler, tb case int: ge.UsedTime = strconv.Itoa(values["used_time"].(int)) case int64: - ge.UsedTime = strconv.FormatInt(values["used_time"].(int64),10) + ge.UsedTime = strconv.FormatInt(values["used_time"].(int64), 10) case float64: - ge.UsedTime = strconv.FormatInt(int64(values["used_time"].(float64)),10) + ge.UsedTime = strconv.FormatInt(int64(values["used_time"].(float64)), 10) default: ge.UsedTime = "" } @@ -137,14 +149,13 @@ func GitOpenEulerData(values map[string]interface{}, ge *models.GitOpenEuler, tb } } - func GitOpenEulerInfoData(values map[string]interface{}, gp *models.GitPackageInfo, ge models.GitOpenEuler) { defer common.Catchs() gp.GitId = ge.GitId gp.Ids = 0 if values["pkg_name"] == nil { gp.PackageName = "" - }else { + } else { PackageName := values["pkg_name"].(string) if PackageName != "" { PackageName = common.DeletePreAndSufSpace(PackageName) @@ -171,7 +182,7 @@ func GitOpenEulerInfoData(values map[string]interface{}, gp *models.GitPackageIn } if values["url"] == nil { gp.OriginUrl = "" - }else { + } else { gp.OriginUrl = values["url"].(string) } if values["license"] == nil { @@ -185,9 +196,9 @@ func GitOpenEulerInfoData(values map[string]interface{}, gp *models.GitPackageIn case int: gp.Feature = strconv.Itoa(values["feature"].(int)) case int64: - gp.Feature = strconv.FormatInt(values["feature"].(int64),10) + gp.Feature = strconv.FormatInt(values["feature"].(int64), 10) case float64: - gp.Feature = strconv.FormatInt(int64(values["feature"].(float64)),10) + gp.Feature = strconv.FormatInt(int64(values["feature"].(float64)), 10) default: gp.Feature = "" } @@ -217,43 +228,67 @@ func GitOpenEulerInfoData(values map[string]interface{}, gp *models.GitPackageIn gp.Decription = values["description"].(string) } BuildRequired := "" - if values["buildrequired"].([]interface{}) != nil && len(values["buildrequired"].([]interface{})) > 0{ + if values["buildrequired"].([]interface{}) != nil && len(values["buildrequired"].([]interface{})) > 0 { for _, vx := range values["buildrequired"].([]interface{}) { BuildRequired = BuildRequired + vx.(string) + "," } - gp.BuildRequired = BuildRequired[:len(BuildRequired) - 1] + gp.BuildRequired = BuildRequired[:len(BuildRequired)-1] } else { gp.BuildRequired = BuildRequired } gp.Status = 0 } - type GitTablePackCount struct { - Page int - Size int + Page int + Size int TableName string - Count int64 + Count int64 } func CreateIssueBody(accessToken string, owner string, path string, assignee string, - cve models.VulnCenter, sc models.Score, OpenEulerScore, score, labels string, - its models.IssueTemplate, flag int, issueType, pkgLink string) string{ + cve models.VulnCenter, sc models.Score, openEulerScore, score, labels string, + its models.IssueTemplate, flag int, issueType, pkgLink string, brandArry []string) string { requestBody := "" + scoretype := "" + affectedVersion := "" + if sc.ScoreType == "v2" { + scoretype = "2.0" + } else { + scoretype = "3.0" + } + floatOpenEulerScore, err := strconv.ParseFloat(openEulerScore, 64) + if err != nil { + floatOpenEulerScore = 0.0 + } + cveAnalysis := "" + if its.CveAnalysis != "" && len(its.CveAnalysis) > 1 { + cveAnalysis = strings.Replace(its.CveAnalysis, "\n", "", -1) + //cveAnalysis = strings.Replace(cveAnalysis, "\n", "", 0) + } if flag == 1 { - body := "漏洞编号: " + "
[" + cve.CveNum + "](https://nvd.nist.gov/vuln/detail/"+ cve.CveNum + ")" + "
" + - "
漏洞归属组件:
" + "
"+ path +"
"+ - "
漏洞归属的版本:
" + "
" +cve.CveVersion +"
" + "
CVSS V3.0分值:
" + - "
BaseScore: " + score + " " + cve.CveLevel + "
" + - "
Vector: " + sc.NvectorVule + "
" + "
漏洞描述:
" + - "
" + cve.Description +"
" + "
影响性分析说明:
" + - "
"+its.CveAnalysis +"
" + "
原理分析:
" + "
" + its.PrincipleAnalysis+"
" + - "
openEuler评分:
" + "
"+ OpenEulerScore + "
" + - "
Vector:
" + "
" +its.OpenEulerVector + "
" + - "
受影响版本:
" + "
"+its.AffectedVersion+"
" + - "
规避方案或消减措施:

"+ its.Solution +"
" + - "
受影响的包:

"+ " " +"


" + "@" + assignee + "

" - requestBody = fmt.Sprintf(`{ + if len(brandArry) > 0 { + for i, brand := range brandArry { + if brand == "" || len(brand) < 2 { + continue + } + affectedVersion = affectedVersion + "
" + strconv.Itoa(i + 1) + "." + brand + ":
" + } + } else { + affectedVersion = "
" + "" + "
" + } + if floatOpenEulerScore > 0.0 || (its.OpenEulerVector != "" && len(its.OpenEulerVector) > 1) { + body := "一、漏洞信息" + "
漏洞编号: " + "[" + cve.CveNum + "](https://nvd.nist.gov/vuln/detail/" + cve.CveNum + ")" + "
" + + "
漏洞归属组件: " + path + "
" + + "
漏洞归属的版本: " + cve.CveVersion + "
" + "
CVSS V" + scoretype + "分值:
" + + "
BaseScore: " + score + " " + cve.CveLevel + "
" + + "
Vector: CVSS:" + scoretype + "/" + sc.NvectorVule + "
" + "
漏洞简述:
" + + "
" + cve.Description + "
" + "
二、漏洞分析结构反馈
" + "
影响性分析说明:
" + + "
" + cveAnalysis + "
" + + "
openEuler评分:
" + "
" + openEulerScore + "
" + + "
Vector: CVSS:" + scoretype + "/" + its.OpenEulerVector + "
" + + "
受影响版本排查(受影响/不受影响):
" + affectedVersion + "



" + requestBody = fmt.Sprintf(`{ "access_token": "%s", "repo": "%s", "title": "%s", @@ -263,16 +298,47 @@ func CreateIssueBody(accessToken string, owner string, path string, assignee str "labels": "%s", "security_hole": "false" }`, accessToken, path, cve.CveNum, its.StatusName, body, assignee, labels) + } else { + body := "一、漏洞信息" + "
漏洞编号: " + "[" + cve.CveNum + "](https://nvd.nist.gov/vuln/detail/" + cve.CveNum + ")" + "
" + + "
漏洞归属组件: " + path + "
" + + "
漏洞归属的版本: " + cve.CveVersion + "
" + "
CVSS V" + scoretype + "分值:
" + + "
BaseScore: " + score + " " + cve.CveLevel + "
" + + "
Vector: CVSS:" + scoretype + "/" + sc.NvectorVule + "
" + "
漏洞简述:
" + + "
" + cve.Description + "
" + "
二、漏洞分析结构反馈
" + "
影响性分析说明:
" + + "
" + cveAnalysis + "
" + + "
openEuler评分:
" + "
" + "" + "
" + + "
受影响版本排查(受影响/不受影响):
" + affectedVersion + "



" + requestBody = fmt.Sprintf(`{ + "access_token": "%s", + "repo": "%s", + "title": "%s", + "state": "%s", + "body": "%s", + "assignee": "%s", + "labels": "%s", + "security_hole": "false" + }`, accessToken, path, cve.CveNum, its.StatusName, body, assignee, labels) + } + } else if flag == 2 { - body := "漏洞编号: " + "
[" + cve.CveNum + "](https://nvd.nist.gov/vuln/detail/"+ cve.CveNum + ")" + "
" + - "
漏洞归属组件:
" + "
"+ path +"
"+ - "
漏洞归属的版本:
" + "
" +cve.CveVersion +"
" + "
CVSS V3.0分值:
" + + if len(brandArry) > 0 { + for i, brand := range brandArry { + if brand == "" || len(brand) < 2 { + continue + } + affectedVersion = affectedVersion + "
" + strconv.Itoa(i + 1) + "." + brand + ":
" + } + } else { + affectedVersion = "
" + "" + "
" + } + body := "一、漏洞信息" + "
漏洞编号: " + "[" + cve.CveNum + "](https://nvd.nist.gov/vuln/detail/" + cve.CveNum + ")" + "
" + + "
漏洞归属组件: " + path + "
" + + "
漏洞归属的版本: " + cve.CveVersion + "
" + "
CVSS V" + scoretype + "分值:
" + "
BaseScore: " + score + " " + cve.CveLevel + "
" + - "
Vector: " + sc.NvectorVule + "
" + "
漏洞描述:
" + - "
" + cve.Description +"
" + "
影响性分析说明:
" + - "

" + "
原理分析:
" + "

" + "
openEuler评分:
" + "

" + - "
Vector:
" + "

" + "
受影响版本:
" + "

" + - "
规避方案或消减措施:


" + "
受影响的包:

" + " " +"


" + "@" + assignee + "

" + "
Vector: CVSS:" + scoretype + "/" + sc.NvectorVule + "
" + "
漏洞简述:
" + + "
" + cve.Description + "
" + "
二、漏洞分析结构反馈
" + "
影响性分析说明:
" + + "

" + "
openEuler评分:
" + "

" + + "
受影响版本排查(受影响/不受影响):
" + affectedVersion + "



" requestBody = fmt.Sprintf(`{ "access_token": "%s", "repo": "%s", @@ -284,19 +350,79 @@ func CreateIssueBody(accessToken string, owner string, path string, assignee str "security_hole": "false" }`, accessToken, path, cve.CveNum, issueType, body, assignee, labels) } else { - body := "漏洞编号: " + "
[" + cve.CveNum + "](https://nvd.nist.gov/vuln/detail/"+ cve.CveNum + ")" + "
" + - "
漏洞归属组件:
" + "
"+ path +"
"+ - "
漏洞归属的版本:
" + "
" +cve.CveVersion +"
" + "
CVSS V3.0分值:
" + - "
BaseScore: " + score + " " + cve.CveLevel + "
" + - "
Vector: " + its.NVDVector + "
" + "
漏洞描述:
" + - "
" + cve.Description +"
" + "
影响性分析说明:
" + - "
"+its.CveAnalysis +"
" + "
原理分析:
" + "
" + its.PrincipleAnalysis+"
" + - "
openEuler评分:
" + "
"+ OpenEulerScore + "
" + - "
Vector:
" + "
" +its.OpenEulerVector + "
" + - "
受影响版本:
" + "
"+its.AffectedVersion+"
" + - "
规避方案或消减措施:

"+ its.Solution +"
" + "
受影响的包:

"+ - pkgLink +"


" + "@" + its.Assignee + "

" - requestBody = fmt.Sprintf(`{ + if its.AffectedVersion != "" && len(its.AffectedVersion) > 0 { + brandsGroup := strings.Split(its.AffectedVersion, ",") + if len(brandsGroup) > 0 { + for i, brand := range brandsGroup { + if brand == "" || len(brand) < 2 { + continue + } + affectedVersion = affectedVersion + "
" + strconv.Itoa(i + 1) + "." + brand + "
" + } + } + } else { + affectedVersion = "
" + "" + "
" + } + if floatOpenEulerScore > 0.0 || (its.OpenEulerVector != "" && len(its.OpenEulerVector) > 1) { + if len(cveAnalysis) > 1 { + body := "一、漏洞信息" + "
漏洞编号: " + "[" + cve.CveNum + "](https://nvd.nist.gov/vuln/detail/" + cve.CveNum + ")" + "
" + + "
漏洞归属组件: " + path + "
" + + "
漏洞归属的版本: " + cve.CveVersion + "
" + "
CVSS V" + scoretype + "分值:
" + + "
BaseScore: " + score + " " + cve.CveLevel + "
" + + "
Vector: CVSS:" + scoretype + "/" + its.NVDVector + "
" + "
漏洞简述:
" + + "
" + cve.Description + "
" + "
二、漏洞分析结构反馈
" + "
影响性分析说明:
" + + "
" + cveAnalysis + "
" + + //cveAnalysis + + "
openEuler评分:
" + "
" + openEulerScore + "
" + + "
Vector: CVSS:" + scoretype + "/" + its.OpenEulerVector + "
" + + "
受影响版本排查(受影响/不受影响):
" + affectedVersion + "



" + requestBody = fmt.Sprintf(`{ + "access_token": "%s", + "repo": "%s", + "title": "%s", + "state": "%s", + "body": "%s", + "assignee": "%s", + "labels": "%s", + "security_hole": "false" + }`, accessToken, path, cve.CveNum, its.StatusName, body, its.Assignee, labels) + } else { + body := "一、漏洞信息" + "
漏洞编号: " + "[" + cve.CveNum + "](https://nvd.nist.gov/vuln/detail/" + cve.CveNum + ")" + "
" + + "
漏洞归属组件: " + path + "
" + + "
漏洞归属的版本: " + cve.CveVersion + "
" + "
CVSS V" + scoretype + "分值:
" + + "
BaseScore: " + score + " " + cve.CveLevel + "
" + + "
Vector: CVSS:" + scoretype + "/" + its.NVDVector + "
" + "
漏洞简述:
" + + "
" + cve.Description + "
" + "
二、漏洞分析结构反馈
" + "
影响性分析说明:
" + + "
" + cveAnalysis + "
" + + //cveAnalysis + + "
openEuler评分:
" + "
" + openEulerScore + "
" + + "
Vector: CVSS:" + scoretype + "/" + its.OpenEulerVector + "
" + + "
受影响版本排查(受影响/不受影响):
" + affectedVersion + "



" + requestBody = fmt.Sprintf(`{ + "access_token": "%s", + "repo": "%s", + "title": "%s", + "state": "%s", + "body": "%s", + "assignee": "%s", + "labels": "%s", + "security_hole": "false" + }`, accessToken, path, cve.CveNum, its.StatusName, body, its.Assignee, labels) + } + + } else { + if len(cveAnalysis) > 1 { + body := "一、漏洞信息" + "
漏洞编号: " + "[" + cve.CveNum + "](https://nvd.nist.gov/vuln/detail/" + cve.CveNum + ")" + "
" + + "
漏洞归属组件: " + path + "
" + + "
漏洞归属的版本: " + cve.CveVersion + "
" + "
CVSS V" + scoretype + "分值:
" + + "
BaseScore: " + score + " " + cve.CveLevel + "
" + + "
Vector: CVSS:" + scoretype + "/" + its.NVDVector + "
" + "
漏洞简述:
" + + "
" + cve.Description + "
" + "
二、漏洞分析结构反馈
" + "
影响性分析说明:
" + + "
" + cveAnalysis + "
" + + //cveAnalysis + + "
openEuler评分:
" + "
" + "" + "
" + + "
受影响版本排查(受影响/不受影响):
" + affectedVersion + "



" + requestBody = fmt.Sprintf(`{ "access_token": "%s", "repo": "%s", "title": "%s", @@ -306,6 +432,40 @@ func CreateIssueBody(accessToken string, owner string, path string, assignee str "labels": "%s", "security_hole": "false" }`, accessToken, path, cve.CveNum, its.StatusName, body, its.Assignee, labels) + } else { + body := "一、漏洞信息" + "
漏洞编号: " + "[" + cve.CveNum + "](https://nvd.nist.gov/vuln/detail/" + cve.CveNum + ")" + "
" + + "
漏洞归属组件: " + path + "
" + + "
漏洞归属的版本: " + cve.CveVersion + "
" + "
CVSS V" + scoretype + "分值:
" + + "
BaseScore: " + score + " " + cve.CveLevel + "
" + + "
Vector: CVSS:" + scoretype + "/" + its.NVDVector + "
" + "
漏洞简述:
" + + "
" + cve.Description + "
" + "
二、漏洞分析结构反馈
" + "
影响性分析说明:
" + + "
" + cveAnalysis + "
" + + "
openEuler评分:
" + "
" + "" + "
" + + "
受影响版本排查(受影响/不受影响):
" + affectedVersion + "



" + requestBody = fmt.Sprintf(`{ + "access_token": "%s", + "repo": "%s", + "title": "%s", + "state": "%s", + "body": "%s", + "assignee": "%s", + "labels": "%s", + "security_hole": "false" + }`, accessToken, path, cve.CveNum, its.StatusName, body, its.Assignee, labels) + } + } } return requestBody +} + + +func Duplicate(a interface{}) (ret []interface{}) { + va := reflect.ValueOf(a) + for i := 0; i < va.Len(); i++ { + if i > 0 && reflect.DeepEqual(va.Index(i-1).Interface(), va.Index(i).Interface()) { + continue + } + ret = append(ret, va.Index(i).Interface()) + } + return ret } \ No newline at end of file diff --git a/taskhandler/createissue.go b/taskhandler/createissue.go index fe49426b3e1f6e26e708d366e97bae90af5ed324..407b545a5cf49a4f560bc39b327ee3ac695732d0 100644 --- a/taskhandler/createissue.go +++ b/taskhandler/createissue.go @@ -10,6 +10,7 @@ import ( "github.com/astaxie/beego/config" "github.com/astaxie/beego/logs" "strconv" + "strings" ) func CreateIssueData(issueTemp *models.IssueTemplate, cve models.VulnCenter, sc models.Score, resp map[string]interface{}, @@ -50,7 +51,7 @@ func CreateIssueData(issueTemp *models.IssueTemplate, cve models.VulnCenter, sc } func CreateIssueToGit(accessToken string, owner string, path string, assignee string, - cve models.VulnCenter, sc models.Score) (string, error) { + cve models.VulnCenter, sc models.Score, brandArry []string) (string, error) { defer common.Catchs() var it models.IssueTemplate it.CveId = cve.CveId @@ -66,7 +67,7 @@ func CreateIssueToGit(accessToken string, owner string, path string, assignee st score := strconv.FormatFloat(sc.NVDScore, 'f', 1, 64) OpenEulerScore := strconv.FormatFloat(its.OpenEulerScore, 'f', 1, 64) requestBody := CreateIssueBody(accessToken, owner, path, its.Assignee, - cve, sc, OpenEulerScore, score, labels, its, 1, its.IssueType, "") + cve, sc, OpenEulerScore, score, labels, its, 1, its.IssueType, "", brandArry) logs.Info("isssue_body: ", requestBody) resp, err := util.HttpPatch(url, requestBody) if err != nil { @@ -113,7 +114,7 @@ func CreateIssueToGit(accessToken string, owner string, path string, assignee st url := "https://gitee.com/api/v5/repos/" + owner + "/issues" score := strconv.FormatFloat(sc.NVDScore, 'f', 1, 64) requestBody := CreateIssueBody(accessToken, owner, path, assignee, - cve, sc, "", score, labels, its, 2, issueType, "") + cve, sc, "", score, labels, its, 2, issueType, "", brandArry) logs.Info("isssue_body: ", requestBody) resp, err := util.HttpPost(url, requestBody) if err != nil { @@ -136,10 +137,23 @@ func CreateIssueToGit(accessToken string, owner string, path string, assignee st logs.Info("创建issue 模板的数据成功, issTempId: ", issTempId, "cveNum: ", cve.CveNum) } // 创建issue评论 - errx := CreateIssueComment(accessToken, owner, path, assignee, cve, resp) + affectedVersion := "" + if len(brandArry) > 0 { + for i, brand := range brandArry { + if brand == "" || len(brand) < 2 { + continue + } + affectedVersion = affectedVersion + strconv.Itoa(i + 1) +"." + brand + ":\n" + } + } else { + affectedVersion = affectedVersion + "\n" + } + errx := CreateIssueComment(accessToken, owner, path, assignee, cve, resp, affectedVersion) logs.Info("issue评论创建结果, err: ", errx) // 构建回调 - err = CreateDepositHooks(accessToken, owner, path, cve, resp) + issueNum := resp["number"].(string) + issueId := int64(resp["id"].(float64)) + err = CreateDepositHooks(accessToken, owner, path, cve, issueNum, issueId) if err != nil { logs.Error("创建hooks 失败, cveNum: ", cve.CveNum, "err: ", err) return "", err @@ -162,9 +176,11 @@ func CreateIssueToGit(accessToken string, owner string, path string, assignee st func UpdateIssueToGit(accessToken string, owner string, path string, cve models.VulnCenter, its models.IssueTemplate) (string, error) { //issueType := its.IssueType + logs.Info("更新模板请求参数: cve: ", cve, ",its: ", its, ", owner: ", owner, ",path: ", path) labels := its.IssueLabel pkgList, err := models.QueryPackageByCveId(its.CveId) pkgLink := "" + var brandArray []string if err == nil && len(pkgList) > 0 { for _, p := range pkgList { pkgLink = pkgLink + fmt.Sprintf(`[%v](%v)\r\n`, p.PackName, p.PackUrl) @@ -175,8 +191,12 @@ func UpdateIssueToGit(accessToken string, owner string, path string, score := strconv.FormatFloat(its.NVDScore, 'f', 1, 64) OpenEulerScore := strconv.FormatFloat(its.OpenEulerScore, 'f', 1, 64) var sc models.Score + sc, scok := models.QueryScoreByCveId(cve.CveId) + if !scok { + logs.Error("评分不存在, cve: ", cve) + } requestBody := CreateIssueBody(accessToken, owner, path, its.Assignee, - cve, sc, OpenEulerScore, score, labels, its, 3, its.IssueType, pkgLink) + cve, sc, OpenEulerScore, score, labels, its, 3, its.IssueType, pkgLink, brandArray) logs.Info("isssue_body: ", requestBody) resp, err := util.HttpPatch(url, requestBody) if err != nil { @@ -187,18 +207,31 @@ func UpdateIssueToGit(accessToken string, owner string, path string, logs.Error("创建issue 失败, err: ", ok, "url: ", url) return "", errors.New("创建issue失败") } + // 存储安全公告相关信息 + var sec models.SecurityNotice + CreateSecNoticeData(&sec, cve, path, its.AffectedVersion) + secId, err := models.UpdateSecNotice(&sec) + if err != nil { + logs.Error("更新安全信息失败,CveNum: ", cve.CveNum, ",path: ", path, ",err: ", err) + return "", err + } else { + logs.Info("更新安全信息成功, secId: ", secId, ",cveNum: ", cve.CveNum) + } } return "", nil } func CreateIssueHookData(issHook *models.IssueHooks, cve models.VulnCenter, resp map[string]interface{}, - path, owner string, issresp map[string]interface{}) *models.IssueHooks { + path, owner string, issueNum string, issueId int64) *models.IssueHooks { issHook.CveId = cve.CveId - issHook.IssueId = int64(issresp["id"].(float64)) - issHook.IssueNum = issresp["number"].(string) + issHook.IssueId = issueId + issHook.IssueNum = issueNum issHook.HookId = int64(resp["id"].(float64)) issHook.Owner = owner issHook.Repo = path + issHook.CreateTime = common.GetCurTime() + issHook.UpdateTime = common.GetCurTime() + issHook.Status = 1 issHook.HookUrl = resp["url"].(string) if resp["push_events"].(bool) == true { issHook.PushEvent = 1 @@ -229,28 +262,80 @@ func CreateIssueHookData(issHook *models.IssueHooks, cve models.VulnCenter, resp } func CreateDepositHooks(accessToken string, owner string, path string, - cve models.VulnCenter, issResp map[string]interface{}) error { + cve models.VulnCenter, issueNum string, issueId int64) error { var ih models.IssueHooks ih.CveId = cve.CveId - ih.IssueNum = issResp["number"].(string) - ihs, err := models.GetIssueHook(&ih) - if err { - if accessToken != "" && owner != "" && path != "" { - url := "https://gitee.com/api/v5/repos/" + owner + "/" + path + "/hooks/" + strconv.Itoa(int(ihs.HookId)) - BConfig, err := config.NewConfig("ini", "conf/app.conf") - if err != nil { - logs.Error("config init error:", err) - return err + ih.IssueNum = issueNum + ih.Owner = owner + ih.Status = 1 + ih.Repo = path + BConfig, err := config.NewConfig("ini", "conf/app.conf") + if err != nil { + logs.Error("config init error:", err) + return err + } + //pwd := os.Getenv("hookpwd") + pwd := BConfig.String("hook::hookpwd") + hookurl := BConfig.String("hook::hookurl") + ihs, errh := models.GetIssueHook(&ih) + if errh { + var hookExist = false + for _, wh := range ihs { + if wh.HookUrl == hookurl { + hookExist = true + if accessToken != "" && owner != "" && path != "" { + url := "https://gitee.com/api/v5/repos/" + owner + "/" + path + "/hooks/" + strconv.Itoa(int(wh.HookId)) + push_events := "true" + tag_push_events := "true" + issues_events := "true" + note_events := "true" + merge_requests_events := "true" + requestBody := fmt.Sprintf(`{ + "access_token": "%s", + "url": "%s", + "password": "%s", + "push_events": "%s", + "tag_push_events": "%s", + "issues_events": "%s", + "note_events": "%s", + "merge_requests_events": "%s" + }`, accessToken, hookurl, pwd, push_events, tag_push_events, issues_events, note_events, merge_requests_events) + logs.Info("hook_body: ", requestBody) + resp, err := util.HttpPatch(url, requestBody) + if err != nil { + logs.Error("创建钩子失败, url: ", url, "cveId", cve.CveId, "err: ", err) + return err + } + if _, ok := resp["id"]; !ok { + logs.Error("创建仓库 hook失败, err: ", ok, "url: ", url) + return errors.New("创建仓库 hook失败") + } + // 构建数据 + if resp["password"].(string) == pwd { + var issHook models.IssueHooks + CreateIssueHookData(&issHook, cve, resp, + path, owner, issueNum, issueId) + // 存储issue数据 + hookId, err := models.CreateDepositHooks(&issHook) + if err != nil { + logs.Error("创建仓库 hook数据失败, cveNum: ", cve.CveNum, "err: ", err) + return nil + } else { + logs.Info("创建仓库 hook数据成功, hookId: ", hookId, "cveNum: ", cve.CveNum) + } + } + } } - //pwd := os.Getenv("hookpwd") - pwd := BConfig.String("hook::hookpwd") - hookurl := BConfig.String("hook::hookurl") - push_events := "true" - tag_push_events := "true" - issues_events := "true" - note_events := "true" - merge_requests_events := "true" - requestBody := fmt.Sprintf(`{ + } + if !hookExist { + if accessToken != "" && owner != "" && path != "" { + url := "https://gitee.com/api/v5/repos/" + owner + "/" + path + "/hooks" + push_events := "true" + tag_push_events := "true" + issues_events := "true" + note_events := "true" + merge_requests_events := "true" + requestBody := fmt.Sprintf(`{ "access_token": "%s", "url": "%s", "password": "%s", @@ -260,41 +345,35 @@ func CreateDepositHooks(accessToken string, owner string, path string, "note_events": "%s", "merge_requests_events": "%s" }`, accessToken, hookurl, pwd, push_events, tag_push_events, issues_events, note_events, merge_requests_events) - logs.Info("hook_body: ", requestBody) - resp, err := util.HttpPatch(url, requestBody) - if err != nil { - logs.Error("创建钩子失败, url: ", url, "cveId", cve.CveId, "err: ", err) - return err - } - if _, ok := resp["id"]; !ok { - logs.Error("创建仓库 hook失败, err: ", ok, "url: ", url) - return errors.New("创建仓库 hook失败") - } - // 构建数据 - if resp["password"].(string) == pwd { - var issHook models.IssueHooks - CreateIssueHookData(&issHook, cve, resp, - path, owner, issResp) - // 存储issue数据 - hookId, err := models.CreateDepositHooks(&issHook) + logs.Info("hook_body: ", requestBody) + resp, err := util.HttpPost(url, requestBody) if err != nil { - logs.Error("创建仓库 hook数据失败, cveNum: ", cve.CveNum, "err: ", err) + logs.Error("创建钩子失败, url: ", url, "cveId", cve.CveId, "err: ", err) return err - } else { - logs.Info("创建仓库 hook数据成功, hookId: ", hookId, "cveNum: ", cve.CveNum) + } + if _, ok := resp["id"]; !ok { + logs.Error("创建仓库hook失败, err: ", ok, "url: ", url) + return errors.New("创建仓库hook失败") + } + // 构建数据 + if resp["password"].(string) == pwd { + var issHook models.IssueHooks + CreateIssueHookData(&issHook, cve, resp, + path, owner, issueNum, issueId) + // 存储issue数据 + hookId, err := models.CreateDepositHooks(&issHook) + if err != nil { + logs.Error("创建仓库hook失败, cveNum: ", cve.CveNum, "err: ", err) + return err + } else { + logs.Info("创建仓库 hook数据成功, hookId: ", hookId, "cveNum: ", cve.CveNum) + } } } } } else { if accessToken != "" && owner != "" && path != "" { url := "https://gitee.com/api/v5/repos/" + owner + "/" + path + "/hooks" - BConfig, err := config.NewConfig("ini", "conf/app.conf") - if err != nil { - logs.Error("config init error:", err) - return err - } - pwd := BConfig.String("hook::pwd") - hookurl := BConfig.String("hook::hookurl") push_events := "true" tag_push_events := "true" issues_events := "true" @@ -324,7 +403,7 @@ func CreateDepositHooks(accessToken string, owner string, path string, if resp["password"].(string) == pwd { var issHook models.IssueHooks CreateIssueHookData(&issHook, cve, resp, - path, owner, issResp) + path, owner, issueNum, issueId) // 存储issue数据 hookId, err := models.CreateDepositHooks(&issHook) if err != nil { @@ -340,7 +419,7 @@ func CreateDepositHooks(accessToken string, owner string, path string, } func CreateIssueComment(accessToken, owner, path, Assignee string, - cve models.VulnCenter, issResp map[string]interface{}) error { + cve models.VulnCenter, issResp map[string]interface{}, affectedVersion string) error { issueNum := issResp["number"].(string) if accessToken != "" && owner != "" && path != "" { url := "https://gitee.com/api/v5/repos/" + owner + "/" + path + "/issues/" + issueNum + "/comments" @@ -350,8 +429,9 @@ func CreateIssueComment(accessToken, owner, path, Assignee string, return err } commentCmd := BConfig.String("reflink::comment_cmd") - commentBody := "Hey @" + Assignee + " , Please complete the content of the issue template in the issue comment. Please refer to the format:" + - commentCmd + //commentBody := "Hey @" + Assignee + " , Please complete the content of the issue template in the issue comment. Please refer to the format:" + + // commentCmd + commentBody := CommentTemplate(Assignee, commentCmd, affectedVersion) requestBody := fmt.Sprintf(`{ "access_token": "%s", "body": "%s" @@ -372,11 +452,40 @@ func CreateIssueComment(accessToken, owner, path, Assignee string, return nil } -func CreateSecNoticeData(sec *models.SecurityNotice, iss models.VulnCenter, path, branchs string) { +func CreateSecNoticeData(sec *models.SecurityNotice, iss models.VulnCenter, path, branchVersion string) { + branchs := "" + if branchVersion != "" && len(branchVersion) > 0 { + brandsGroup := strings.Split(branchVersion, ",") + if len(brandsGroup) > 0 { + for _, brand := range brandsGroup { + if brand == "" || len(brand) < 2 { + continue + } + brandList := strings.Split(brand, ":") + if len(brandList) > 1 { + prams := strings.Replace(brandList[1], " ", "", -1) + if prams == "受影响" { + branchs += brandList[0] + "/" + } + } else { + brandList := strings.Split(brand, ":") + if len(brandList) > 1 { + prams := strings.Replace(brandList[1], " ", "", -1) + if prams == "受影响" { + branchs += brandList[0] + "/" + } + } + } + } + } + } + if branchs != "" && len(branchs) > 1 { + branchs = branchs[: len(branchs) - 1] + } sec.CveId = iss.CveId sec.CveNum = iss.CveNum sec.Introduction = "An update for " + path + " is now available for " + branchs - sec.Summary = "An update for " + path + " is now available for " + branchs + //sec.Summary = "An update for " + path + " is now available for " + branchs sec.Theme = sec.Introduction + ";\n\n" + "openEuler Security has rated this" + " update as having a security impact of medium. A Common Vunlnerability" + " Scoring System(CVSS)base score,which gives a detailed severity rating," + diff --git a/taskhandler/cve.go b/taskhandler/cve.go index 85d52510ea3cf84043e5074faedc8d913d1f3bb3..590562257e644ba61a81c385fe10060fb313936c 100644 --- a/taskhandler/cve.go +++ b/taskhandler/cve.go @@ -3,22 +3,33 @@ package taskhandler import ( "cvevulner/common" "cvevulner/models" + "encoding/json" "errors" + "fmt" "github.com/astaxie/beego/logs" + "io/ioutil" + "net/http" + "os" "strconv" "strings" "sync" "time" ) -func UpdateCveGroups(cveData models.OriginUpstream, cveRef string, openeulernum int, CveRes models.VulnCenter, cveDesc models.OriginUpstreamDesc, cveScV3 models.OriginUpstreamImpactScoreV3) (bool, error){ +var GetCveDetailUrl = "http://cve.openeuler.org/cve-security-notice-server/cvedatabase/getByCveId?cveId=%s" +var lockx sync.Mutex +var ewg sync.WaitGroup + +func UpdateExcelCveGroups(cveData models.OriginExcel, cveRef string, openeulerNum int, CveRes models.VulnCenter, + goe models.GitPackageInfo) (bool, error) { var OpenEulId int64 - CveRes.Description = cveDesc.EnDescription - CveRes.CveVersion = cveData.Version - CveRes.RepairTime = cveData.PublishedDate + CveRes.Description = cveData.CveDesc + CveRes.CveVersion = cveData.CveVersion + CveRes.RepairTime = cveData.RepairTime CveRes.PackName = cveData.PackName CveRes.CveUrl = cveRef + cveData.CveNum - CveRes.CveLevel = cveScV3.CveLevel + CveRes.CveLevel = cveData.CveLevel + CveRes.IsExport = 0 if CveRes.Status != 0 && CveRes.Status != 1 { CveRes.Status = 1 } @@ -26,19 +37,19 @@ func UpdateCveGroups(cveData models.OriginUpstream, cveRef string, openeulernum openEusa, operr := models.QueryOpenEulerSAByCveId(CveRes.CveId) if operr == false { var opensa models.OpenEulerSA - os, operr := models.QueryOpenSaLastId() + osx, operr := models.QueryOpenSaLastId() var OpenNumData int if operr == nil { - OpenNumList := strings.Split(os.OpenEulerSANum, "-") - OpenNum, err := strconv.Atoi(OpenNumList[len(OpenNumList) - 1]) + OpenNumList := strings.Split(osx.OpenEulerSANum, "-") + OpenNum, err := strconv.Atoi(OpenNumList[len(OpenNumList)-1]) if err == nil { - OpenNum += 100 + OpenNum += 10 } else { - OpenNum = openeulernum + OpenNum = openeulerNum } OpenNumData = OpenNum } else { - OpenNumData = openeulernum + OpenNumData = openeulerNum } OpenEulerSANum := "openEuler-SA-" + strconv.Itoa(time.Now().Year()) + "-" + strconv.Itoa(OpenNumData) opensa.OpenEulerSANum = OpenEulerSANum @@ -53,63 +64,408 @@ func UpdateCveGroups(cveData models.OriginUpstream, cveRef string, openeulernum } else { OpenEulId = openEusa.OpenId } - scoreRes,scoreerr := models.QueryScoreByCveId(CveRes.CveId) + scoreRes, scoreerr := models.QueryScoreByCveId(CveRes.CveId) if scoreerr { - if scoreRes.NVDScore != cveScV3.BaseScore { + if scoreRes.NVDScore != cveData.NVDScore { var scorecode models.ScoreRecord - scorecode.NVDScore = cveScV3.BaseScore - scorecode.NvectorVule = cveScV3.VectorString + scorecode.NVDScore = cveData.NVDScore + scorecode.NvectorVule = cveData.NVDVector scorecode.Status = 0 scorecode.CveId = CveRes.CveId - scoreid, err :=models.CreateScoreRecord(&scorecode) + scoreid, err := models.CreateScoreRecord(&scorecode) if scoreid > 0 && err == nil { - logs.Info("insert score_record success, id:",scoreid) + logs.Info("insert score_record success, id:", scoreid) } else { return false, errors.New("评分记录数据错误,暂时不处理") } } - scoreRes.NVDScore = cveScV3.BaseScore - scoreRes.NvectorVule = cveScV3.VectorString + scoreRes.NVDScore = cveData.NVDScore + scoreRes.NvectorVule = cveData.NVDVector scoreRes.OpenId = OpenEulId scoreRes.Nstatus = 1 - scoreRes.NattackVector = cveScV3.AttackVector - scoreRes.NattackComplexity = cveScV3.AttackComplexity - scoreRes.NprivilegeRequired = cveScV3.PrivilegesRequired - scoreRes.NuserInteraction = cveScV3.UserInteraction - scoreRes.Nscope = cveScV3.Scope - scoreRes.Nconfidentiality = cveScV3.ConfidentialityImpact - scoreRes.Nintegrity = cveScV3.IntegrityImpact - scoreRes.Navailability = cveScV3.AvailabilityImpact - - }else { + if strings.ToLower(cveData.ScoreType) == "v2" || strings.ToLower(cveData.ScoreType) == "v2.0" { + scoreRes.NaccessVector = cveData.AccessVector + scoreRes.NaccessComplexity = cveData.AccessComplexity + scoreRes.Nauthentication = cveData.Authentication + scoreRes.ScoreType = "v2" + } else { + scoreRes.NattackVector = cveData.AttackVector + scoreRes.NattackComplexity = cveData.AttackComplexity + scoreRes.NprivilegeRequired = cveData.PrivilegeRequired + scoreRes.NuserInteraction = cveData.UserInteraction + scoreRes.Nscope = cveData.Scope + scoreRes.ScoreType = "v3" + } + scoreRes.Nconfidentiality = cveData.Confidentiality + scoreRes.Nintegrity = cveData.Integrity + scoreRes.Navailability = cveData.Availability + } else { var sc models.Score sc.CveNum = cveData.CveNum - sc.NVDScore = cveScV3.BaseScore - sc.OpenEulerScore = cveScV3.BaseScore + sc.NVDScore = cveData.NVDScore + sc.OpenEulerScore = cveData.NVDScore sc.OpenId = OpenEulId - sc.NvectorVule = cveScV3.VectorString - sc.OvectorVule = cveScV3.VectorString + sc.NvectorVule = cveData.NVDVector + sc.OvectorVule = cveData.NVDVector sc.CveId = CveRes.CveId sc.Nstatus = 0 sc.Ostatus = 0 + if strings.ToLower(cveData.ScoreType) == "v2" || strings.ToLower(cveData.ScoreType) == "v2.0" { + sc.NaccessVector = cveData.AccessVector + sc.OaccessVector = cveData.AccessVector + sc.NaccessComplexity = cveData.AccessComplexity + sc.OaccessComplexity = cveData.AccessComplexity + sc.Nauthentication = cveData.Authentication + sc.Oauthentication = cveData.Authentication + sc.ScoreType = "v2" + } else { + sc.NattackVector = cveData.AttackVector + sc.OattackVector = cveData.AttackVector + sc.NattackComplexity = cveData.AttackComplexity + sc.OattackComplexity = cveData.AttackComplexity + sc.NprivilegeRequired = cveData.PrivilegeRequired + sc.OprivilegeRequired = cveData.PrivilegeRequired + sc.OuserInteraction = cveData.UserInteraction + sc.NuserInteraction = cveData.UserInteraction + sc.Oscope = cveData.Scope + sc.Nscope = cveData.Scope + sc.ScoreType = "v3" + } + sc.Nconfidentiality = cveData.Confidentiality + sc.Oconfidentiality = cveData.Confidentiality + sc.Nintegrity = cveData.Integrity + sc.Ointegrity = cveData.Integrity + sc.Navailability = cveData.Availability + sc.Oavailability = cveData.Availability + scid, scerr := models.CreateScore(&sc) + if scerr != nil { + logs.Error("insert cve_score failed cveScV3:", sc) + return false, errors.New("记录评分失败,暂时不处理") + } else { + logs.Info("insert cve_score success scid: ", scid, "CveNum:", cveData.CveNum) + } + } + SecNOtice, secerrx := models.QuerySecNoticeByCveId(CveRes.CveId) + if secerrx { + SecNOtice.InfluenceComponent = cveData.PackName + SecNOtice.OpenId = OpenEulId + SecNOtice.Summary = cveData.PackName + " security update" + SecNOtice.ReferenceLink = cveRef + cveData.CveNum + } else { + var sec models.SecurityNotice + sec.CveNum = cveData.CveNum + sec.OpenId = OpenEulId + sec.InfluenceComponent = cveData.PackName + sec.Status = 0 + sec.AffectStatus = "UnFixed" + sec.CveId = CveRes.CveId + sec.Summary = cveData.PackName + " security update" + sec.ReferenceLink = cveRef + cveData.CveNum + if goe.Decription != "" && len(goe.Decription) > 0 { + sec.Description = goe.Decription + "\n\n" + "Security Fix(es):" + "\n\n" + cveData.CveDesc + } else { + sec.Description = "Security Fix(es):" + "\n\n" + cveData.CveDesc + } + secid, secerr := models.CreateSecurityNotice(&sec) + if secerr != nil { + logs.Error("insert cve_security_notice failed CveNum:", cveData.CveNum) + return false, errors.New("记录SA失败,暂时不处理") + } else { + logs.Info("insert cve_security_notice success secid: , cveNum: ", secid, cveData.CveNum) + } + } + if scoreerr && secerrx { + errx := models.UpdateCveRelat(&CveRes, &SecNOtice, &scoreRes) + if errx != nil { + logs.Error("update (&CveRes, &SecNOtice, &scoreRes) failed CveNum:", cveData.CveNum) + return false, errors.New("数据更新失败, 暂时不处理") + } + } else if scoreerr { + errx := models.UpdateCveRelat1(&CveRes, &SecNOtice) + if errx != nil { + logs.Error("update (&CveRes, &SecNOtice)failed CveNum:", cveData.CveNum) + return false, errors.New("数据更新失败, 暂时不处理") + } + } else { + errx := models.UpdateCveRelat2(&CveRes, &scoreRes) + if errx != nil { + logs.Error("update (&CveRes, &scoreRes) failed CveNum:", cveData.CveNum) + return false, errors.New("数据更新失败, 暂时不处理") + } + } + return true, nil +} + +func InsertCveExcelGroups(cveData models.OriginExcel, cveRef string, openeulerNum int, goe models.GitPackageInfo) (bool, error) { + var vul models.VulnCenter + vul.CveNum = cveData.CveNum + vul.Description = cveData.CveDesc + vul.Status = 0 + vul.CveVersion = cveData.CveVersion + vul.RepairTime = cveData.RepairTime + vul.PackName = cveData.PackName + vul.CveUrl = cveRef + cveData.CveNum + vul.CveLevel = cveData.CveLevel + vul.IsExport = 0 + var sec models.SecurityNotice + sec.CveNum = cveData.CveNum + sec.InfluenceComponent = cveData.PackName + sec.Status = 0 + sec.AffectStatus = "UnFixed" + sec.Summary = cveData.PackName + " security update" + sec.ReferenceLink = cveRef + cveData.CveNum + if goe.Decription != "" && len(goe.Decription) > 0 { + sec.Description = goe.Decription + "\n\n" + "Security Fix(es):" + "\n\n" + cveData.CveDesc + } else { + sec.Description = "Security Fix(es):" + "\n\n" + cveData.CveDesc + } + var sc models.Score + sc.CveNum = cveData.CveNum + sc.NVDScore = cveData.NVDScore + sc.OpenEulerScore = cveData.NVDScore + sc.NvectorVule = cveData.NVDVector + sc.OvectorVule = cveData.NVDVector + sc.Nstatus = 0 + sc.Ostatus = 0 + if strings.ToLower(cveData.ScoreType) == "v2" || strings.ToLower(cveData.ScoreType) == "v2.0" { + sc.NaccessVector = cveData.AccessVector + sc.OaccessVector = cveData.AccessVector + sc.NaccessComplexity = cveData.AccessComplexity + sc.OaccessComplexity = cveData.AccessComplexity + sc.Nauthentication = cveData.Authentication + sc.Oauthentication = cveData.Authentication + sc.ScoreType = "v2" + } else { + sc.NattackVector = cveData.AttackVector + sc.OattackVector = cveData.AttackVector + sc.NattackComplexity = cveData.AttackComplexity + sc.OattackComplexity = cveData.AttackComplexity + sc.NprivilegeRequired = cveData.PrivilegeRequired + sc.OprivilegeRequired = cveData.PrivilegeRequired + sc.OuserInteraction = cveData.UserInteraction + sc.NuserInteraction = cveData.UserInteraction + sc.Oscope = cveData.Scope + sc.Nscope = cveData.Scope sc.ScoreType = "v3" - sc.NattackVector = cveScV3.AttackVector - sc.OattackVector = cveScV3.AttackVector - sc.NattackComplexity = cveScV3.AttackComplexity - sc.OattackComplexity = cveScV3.AttackComplexity - sc.NprivilegeRequired = cveScV3.PrivilegesRequired - sc.OprivilegeRequired = cveScV3.PrivilegesRequired - sc.NuserInteraction = cveScV3.UserInteraction - sc.OuserInteraction = cveScV3.UserInteraction - sc.Nscope = cveScV3.Scope - sc.Oscope = cveScV3.Scope - sc.Nconfidentiality = cveScV3.ConfidentialityImpact - sc.Oconfidentiality = cveScV3.ConfidentialityImpact - sc.Nintegrity = cveScV3.IntegrityImpact - sc.Ointegrity = cveScV3.IntegrityImpact - sc.Navailability = cveScV3.AvailabilityImpact - sc.Oavailability = cveScV3.AvailabilityImpact + } + sc.Nconfidentiality = cveData.Confidentiality + sc.Oconfidentiality = cveData.Confidentiality + sc.Nintegrity = cveData.Integrity + sc.Ointegrity = cveData.Integrity + sc.Navailability = cveData.Availability + sc.Oavailability = cveData.Availability + + var opensa models.OpenEulerSA + //var os models.OpenSaId + osx, operr := models.QueryOpenSaLastId() + var OpenNumData int + if operr == nil { + OpenNumList := strings.Split(osx.OpenEulerSANum, "-") + OpenNum, err := strconv.Atoi(OpenNumList[len(OpenNumList)-1]) + if err == nil { + OpenNum += 10 + } else { + OpenNum = openeulerNum + } + OpenNumData = OpenNum + } else { + OpenNumData = openeulerNum + } + OpenEulerSANum := "openEuler-SA-" + strconv.Itoa(time.Now().Year()) + "-" + strconv.Itoa(int(OpenNumData)) + opensa.OpenEulerSANum = OpenEulerSANum + var scorecode models.ScoreRecord + scorecode.NVDScore = cveData.NVDScore + scorecode.NvectorVule = cveData.NVDVector + scorecode.Status = 0 + cveid, cveerr := models.CreateCveRelat(&vul, &sec, &sc, &opensa, &scorecode) + if cveerr != nil || cveid <= 0 { + logs.Error("insert (&CveRes, &scoreRes, &sec) failed CveNum:", cveData.CveNum) + return false, errors.New("数据插入失败,暂时不处理") + } + return true, nil +} +func UpdateCveGroups(cveData models.OriginUpstream, cveRef string, openeulerNum int, CveRes models.VulnCenter, + cveDesc models.OriginUpstreamDesc, cveScV3 models.OriginUpstreamImpactScoreV3, goe models.GitPackageInfo, + scopeType string, cveScV2 models.OriginUpstreamImpactScoreV2, pkList []string) (bool, error) { + var OpenEulId int64 + CveRes.Description = cveDesc.EnDescription + CveRes.CveVersion = pkList[1] + CveRes.RepairTime = cveData.PublishedDate + CveRes.PackName = pkList[0] + CveRes.CveUrl = cveRef + cveData.CveNum + CveRes.CveLevel = cveScV3.CveLevel + CveRes.IsExport = 0 + if CveRes.Status != 0 && CveRes.Status != 1 { + CveRes.Status = 1 + } + //CveRes.Status = 1 + openEusa, operr := models.QueryOpenEulerSAByCveId(CveRes.CveId) + if operr == false { + var opensa models.OpenEulerSA + osx, operr := models.QueryOpenSaLastId() + var OpenNumData int + if operr == nil { + OpenNumList := strings.Split(osx.OpenEulerSANum, "-") + OpenNum, err := strconv.Atoi(OpenNumList[len(OpenNumList)-1]) + if err == nil { + OpenNum += 10 + } else { + OpenNum = openeulerNum + } + OpenNumData = OpenNum + } else { + OpenNumData = openeulerNum + } + OpenEulerSANum := "openEuler-SA-" + strconv.Itoa(time.Now().Year()) + "-" + strconv.Itoa(OpenNumData) + opensa.OpenEulerSANum = OpenEulerSANum + opensa.CveId = CveRes.CveId + OpenEulerId, OpEerr := models.CreateOpenEulerSA(&opensa) + if OpEerr == nil { + OpenEulId = OpenEulerId + } else { + logs.Error("更新openEulerSa数据表失败") + return false, errors.New("openEulerSA数据错误,暂时不处理") + } + } else { + OpenEulId = openEusa.OpenId + } + scoreRes, scoreerr := models.QueryScoreByCveId(CveRes.CveId) + if scoreerr { + scoreRes.ScoreType = scopeType + vectorString := "" + if scopeType == "v3" { + if cveScV3.VectorString != "" && len(cveScV3.VectorString) > 0 { + index := strings.IndexAny(cveScV3.VectorString, "/") + if index > 0 && strings.ToLower(cveScV3.VectorString)[:4] == "cvss" { + vectorString = cveScV3.VectorString[index+1:] + } else { + vectorString = cveScV3.VectorString + } + } + if scoreRes.NVDScore != cveScV3.BaseScore { + var scorecode models.ScoreRecord + scorecode.NVDScore = cveScV3.BaseScore + scorecode.NvectorVule = vectorString + scorecode.Status = 0 + scorecode.CveId = CveRes.CveId + scoreid, err := models.CreateScoreRecord(&scorecode) + if scoreid > 0 && err == nil { + logs.Info("insert score_record success, id:", scoreid) + } else { + return false, errors.New("评分记录数据错误,暂时不处理") + } + } + scoreRes.NVDScore = cveScV3.BaseScore + scoreRes.NvectorVule = vectorString + scoreRes.OpenId = OpenEulId + scoreRes.Nstatus = 1 + scoreRes.NattackVector = cveScV3.AttackVector + scoreRes.NattackComplexity = cveScV3.AttackComplexity + scoreRes.NprivilegeRequired = cveScV3.PrivilegesRequired + scoreRes.NuserInteraction = cveScV3.UserInteraction + scoreRes.Nscope = cveScV3.Scope + scoreRes.Nconfidentiality = cveScV3.ConfidentialityImpact + scoreRes.Nintegrity = cveScV3.IntegrityImpact + scoreRes.Navailability = cveScV3.AvailabilityImpact + } else { + if cveScV2.VectorString != "" && len(cveScV2.VectorString) > 0 { + index := strings.IndexAny(cveScV2.VectorString, "/") + if index > 0 && strings.ToLower(cveScV2.VectorString)[:4] == "cvss" { + vectorString = cveScV2.VectorString[index+1:] + } else { + vectorString = cveScV2.VectorString + } + } + if scoreRes.NVDScore != cveScV2.BaseScore { + var scorecode models.ScoreRecord + scorecode.NVDScore = cveScV2.BaseScore + scorecode.NvectorVule = vectorString + scorecode.Status = 0 + scorecode.CveId = CveRes.CveId + scoreid, err := models.CreateScoreRecord(&scorecode) + if scoreid > 0 && err == nil { + logs.Info("insert score_record success, id:", scoreid) + } else { + return false, errors.New("评分记录数据错误,暂时不处理") + } + } + scoreRes.NVDScore = cveScV2.BaseScore + scoreRes.NvectorVule = vectorString + scoreRes.OpenId = OpenEulId + scoreRes.Nstatus = 1 + scoreRes.NaccessVector = cveScV2.AccessVector + scoreRes.NaccessComplexity = cveScV2.AccessComplexity + scoreRes.Nconfidentiality = cveScV2.ConfidentialityImpact + scoreRes.Nintegrity = cveScV2.IntegrityImpact + scoreRes.Navailability = cveScV2.AvailabilityImpact + scoreRes.Nauthentication = cveScV2.Authentication + } + } else { + var sc models.Score + sc.CveNum = cveData.CveNum + sc.OpenId = OpenEulId + sc.CveId = CveRes.CveId + sc.Nstatus = 0 + sc.Ostatus = 0 + sc.ScoreType = scopeType + if scopeType == "v3" { + sc.NVDScore = cveScV3.BaseScore + sc.OpenEulerScore = cveScV3.BaseScore + vectorString := "" + if cveScV3.VectorString != "" && len(cveScV3.VectorString) > 0 { + index := strings.IndexAny(cveScV3.VectorString, "/") + if index > 0 && strings.ToLower(cveScV3.VectorString)[:4] == "cvss" { + vectorString = cveScV3.VectorString[index+1:] + } else { + vectorString = cveScV3.VectorString + } + } + sc.NvectorVule = vectorString + sc.OvectorVule = vectorString + sc.NattackVector = cveScV3.AttackVector + sc.OattackVector = cveScV3.AttackVector + sc.NattackComplexity = cveScV3.AttackComplexity + sc.OattackComplexity = cveScV3.AttackComplexity + sc.NprivilegeRequired = cveScV3.PrivilegesRequired + sc.OprivilegeRequired = cveScV3.PrivilegesRequired + sc.NuserInteraction = cveScV3.UserInteraction + sc.OuserInteraction = cveScV3.UserInteraction + sc.Nscope = cveScV3.Scope + sc.Oscope = cveScV3.Scope + sc.Nconfidentiality = cveScV3.ConfidentialityImpact + sc.Oconfidentiality = cveScV3.ConfidentialityImpact + sc.Nintegrity = cveScV3.IntegrityImpact + sc.Ointegrity = cveScV3.IntegrityImpact + sc.Navailability = cveScV3.AvailabilityImpact + sc.Oavailability = cveScV3.AvailabilityImpact + } else { + sc.NVDScore = cveScV2.BaseScore + sc.OpenEulerScore = cveScV2.BaseScore + vectorString := "" + if cveScV2.VectorString != "" && len(cveScV2.VectorString) > 0 { + index := strings.IndexAny(cveScV2.VectorString, "/") + if index > 0 && strings.ToLower(cveScV2.VectorString)[:4] == "cvss" { + vectorString = cveScV2.VectorString[index+1:] + } else { + vectorString = cveScV2.VectorString + } + } + sc.NvectorVule = vectorString + sc.OvectorVule = vectorString + sc.NaccessVector = cveScV2.AccessVector + sc.OaccessVector = cveScV2.AccessVector + sc.NaccessComplexity = cveScV2.AccessComplexity + sc.OaccessComplexity = cveScV2.AccessComplexity + sc.Nauthentication = cveScV2.Authentication + sc.Oauthentication = cveScV2.Authentication + sc.Nconfidentiality = cveScV2.ConfidentialityImpact + sc.Oconfidentiality = cveScV2.ConfidentialityImpact + sc.Nintegrity = cveScV2.IntegrityImpact + sc.Ointegrity = cveScV2.IntegrityImpact + sc.Navailability = cveScV2.AvailabilityImpact + sc.Oavailability = cveScV2.AvailabilityImpact + } scid, scerr := models.CreateScore(&sc) if scerr != nil { logs.Error("insert cve_score failed cveScV3:", cveScV3) @@ -120,20 +476,25 @@ func UpdateCveGroups(cveData models.OriginUpstream, cveRef string, openeulernum } SecNOtice, secerrx := models.QuerySecNoticeByCveId(CveRes.CveId) if secerrx { - SecNOtice.InfluenceComponent = cveData.AffectProduct + SecNOtice.InfluenceComponent = pkList[0] SecNOtice.OpenId = OpenEulId - SecNOtice.Summary = cveData.AffectProduct + " security update" + SecNOtice.Summary = pkList[0] + " security update" SecNOtice.ReferenceLink = cveRef + cveData.CveNum } else { var sec models.SecurityNotice sec.CveNum = cveData.CveNum sec.OpenId = OpenEulId - sec.InfluenceComponent = cveData.AffectProduct + sec.InfluenceComponent = pkList[0] sec.Status = 0 sec.AffectStatus = "UnFixed" sec.CveId = CveRes.CveId - sec.Summary = cveData.AffectProduct + " security update" + sec.Summary = pkList[0] + " security update" sec.ReferenceLink = cveRef + cveData.CveNum + if goe.Decription != "" && len(goe.Decription) > 0 { + sec.Description = goe.Decription + "\n\n" + "Security Fix(es):" + "\n\n" + cveDesc.EnDescription + } else { + sec.Description = "Security Fix(es):" + "\n\n" + cveDesc.EnDescription + } secid, secerr := models.CreateSecurityNotice(&sec) if secerr != nil { logs.Error("insert cve_security_notice failed CveNum:", cveData.CveNum) @@ -164,63 +525,110 @@ func UpdateCveGroups(cveData models.OriginUpstream, cveRef string, openeulernum return true, nil } -func InsertCveGroups(cveData models.OriginUpstream, cveRef string, openeulernum int, cveDesc models.OriginUpstreamDesc, cveScV3 models.OriginUpstreamImpactScoreV3) (bool, error) { +func InsertCveGroups(cveData models.OriginUpstream, cveRef string, openeulerNum int, cveDesc models.OriginUpstreamDesc, + cveScV3 models.OriginUpstreamImpactScoreV3, goe models.GitPackageInfo, + scopeType string, cveScV2 models.OriginUpstreamImpactScoreV2, pkList []string) (bool, error) { var vul models.VulnCenter vul.CveNum = cveData.CveNum vul.Description = cveDesc.EnDescription vul.Status = 0 - vul.CveVersion = cveData.Version + vul.CveVersion = pkList[1] vul.RepairTime = cveData.PublishedDate - vul.PackName = cveData.PackName + vul.PackName = pkList[0] vul.CveUrl = cveRef + cveData.CveNum vul.CveLevel = cveScV3.CveLevel + vul.IsExport = 0 var sec models.SecurityNotice sec.CveNum = cveData.CveNum - sec.InfluenceComponent = cveData.AffectProduct + sec.InfluenceComponent = pkList[0] sec.Status = 0 sec.AffectStatus = "UnFixed" - sec.Summary = cveData.AffectProduct + " security update" + sec.Summary = pkList[0] + " security update" sec.ReferenceLink = cveRef + cveData.CveNum + if goe.Decription != "" && len(goe.Decription) > 0 { + sec.Description = goe.Decription + "\n\n" + "Security Fix(es):" + "\n\n" + cveDesc.EnDescription + } else { + sec.Description = "Security Fix(es):" + "\n\n" + cveDesc.EnDescription + } var sc models.Score sc.CveNum = cveData.CveNum - sc.NVDScore = cveScV3.BaseScore - sc.OpenEulerScore = cveScV3.BaseScore - sc.NvectorVule = cveScV3.VectorString - sc.OvectorVule = cveScV3.VectorString sc.Nstatus = 0 sc.Ostatus = 0 - sc.ScoreType = "v3" - sc.NattackVector = cveScV3.AttackVector - sc.OattackVector = cveScV3.AttackVector - sc.NattackComplexity = cveScV3.AttackComplexity - sc.OattackComplexity = cveScV3.AttackComplexity - sc.NprivilegeRequired = cveScV3.PrivilegesRequired - sc.OprivilegeRequired = cveScV3.PrivilegesRequired - sc.NuserInteraction = cveScV3.UserInteraction - sc.OuserInteraction = cveScV3.UserInteraction - sc.Nscope = cveScV3.Scope - sc.Oscope = cveScV3.Scope - sc.Nconfidentiality = cveScV3.ConfidentialityImpact - sc.Oconfidentiality = cveScV3.ConfidentialityImpact - sc.Nintegrity = cveScV3.IntegrityImpact - sc.Ointegrity = cveScV3.IntegrityImpact - sc.Navailability = cveScV3.AvailabilityImpact - sc.Oavailability = cveScV3.AvailabilityImpact + if scopeType == "v3" { + sc.NVDScore = cveScV3.BaseScore + sc.OpenEulerScore = cveScV3.BaseScore + vectorString := "" + if cveScV3.VectorString != "" && len(cveScV3.VectorString) > 0 { + index := strings.IndexAny(cveScV3.VectorString, "/") + if index > 0 && strings.ToLower(cveScV3.VectorString)[:4] == "cvss" { + vectorString = cveScV3.VectorString[index+1:] + } else { + vectorString = cveScV3.VectorString + } + } + sc.NvectorVule = vectorString + sc.OvectorVule = vectorString + sc.NattackVector = cveScV3.AttackVector + sc.OattackVector = cveScV3.AttackVector + sc.NattackComplexity = cveScV3.AttackComplexity + sc.OattackComplexity = cveScV3.AttackComplexity + sc.NprivilegeRequired = cveScV3.PrivilegesRequired + sc.OprivilegeRequired = cveScV3.PrivilegesRequired + sc.NuserInteraction = cveScV3.UserInteraction + sc.OuserInteraction = cveScV3.UserInteraction + sc.Nscope = cveScV3.Scope + sc.Oscope = cveScV3.Scope + sc.Nconfidentiality = cveScV3.ConfidentialityImpact + sc.Oconfidentiality = cveScV3.ConfidentialityImpact + sc.Nintegrity = cveScV3.IntegrityImpact + sc.Ointegrity = cveScV3.IntegrityImpact + sc.Navailability = cveScV3.AvailabilityImpact + sc.Oavailability = cveScV3.AvailabilityImpact + } else { + sc.NVDScore = cveScV2.BaseScore + sc.OpenEulerScore = cveScV2.BaseScore + vectorString := "" + if cveScV2.VectorString != "" && len(cveScV2.VectorString) > 0 { + index := strings.IndexAny(cveScV2.VectorString, "/") + if index > 0 && strings.ToLower(cveScV2.VectorString)[:4] == "cvss" { + vectorString = cveScV2.VectorString[index+1:] + } else { + vectorString = cveScV2.VectorString + } + } + sc.NvectorVule = vectorString + sc.OvectorVule = vectorString + sc.NaccessVector = cveScV2.AccessVector + sc.OaccessVector = cveScV2.AccessVector + sc.NaccessComplexity = cveScV2.AccessComplexity + sc.OaccessComplexity = cveScV2.AccessComplexity + sc.Nauthentication = cveScV2.Authentication + sc.Oauthentication = cveScV2.Authentication + + sc.Nconfidentiality = cveScV2.ConfidentialityImpact + sc.Oconfidentiality = cveScV2.ConfidentialityImpact + sc.Nintegrity = cveScV2.IntegrityImpact + sc.Ointegrity = cveScV2.IntegrityImpact + sc.Navailability = cveScV2.AvailabilityImpact + sc.Oavailability = cveScV2.AvailabilityImpact + } + sc.ScoreType = scopeType + var opensa models.OpenEulerSA //var os models.OpenSaId - os, operr := models.QueryOpenSaLastId() + osx, operr := models.QueryOpenSaLastId() var OpenNumData int if operr == nil { - OpenNumList := strings.Split(os.OpenEulerSANum, "-") - OpenNum, err := strconv.Atoi(OpenNumList[len(OpenNumList) - 1]) + OpenNumList := strings.Split(osx.OpenEulerSANum, "-") + OpenNum, err := strconv.Atoi(OpenNumList[len(OpenNumList)-1]) if err == nil { - OpenNum += 100 + OpenNum += 10 } else { - OpenNum = openeulernum + OpenNum = openeulerNum } OpenNumData = OpenNum } else { - OpenNumData = openeulernum + OpenNumData = openeulerNum } OpenEulerSANum := "openEuler-SA-" + strconv.Itoa(time.Now().Year()) + "-" + strconv.Itoa(int(OpenNumData)) opensa.OpenEulerSANum = OpenEulerSANum @@ -236,74 +644,187 @@ func InsertCveGroups(cveData models.OriginUpstream, cveRef string, openeulernum return true, nil } -var lockx sync.Mutex - -func GenCveVuler(cveData models.OriginUpstream, cveRef string, openeulernum int) (bool, error){ - if cveData.Ids == "" || cveData.CveNum == ""{ +func GenCveVuler(cveData models.OriginUpstream, cveRef string, openeulernum int) (bool, error) { + if cveData.Ids == "" || cveData.CveNum == "" { logs.Error("当前数据cveNum 为空暂不处理,data: ", cveData) + models.UpdateOriginStatus(common.GetCurTime(), cveData.PackName, cveData.Version, cveData.CveId, 3) return false, errors.New("数据错误,暂时不处理") } cveDesc, ok := models.QueryCveDesc(cveData.CveId) if !ok { logs.Error("当前数据描述为空暂不处理, data: ", cveData) + models.UpdateOriginStatus(common.GetCurTime(), cveData.PackName, cveData.Version, cveData.CveId, 3) return false, errors.New("数据错误,暂时不处理") } cveImpact, ok := models.QueryCveImpact(cveData.CveId) if !ok { logs.Error("cveImpact查询失败, data: ", cveData) + models.UpdateOriginStatus(common.GetCurTime(), cveData.PackName, cveData.Version, cveData.CveId, 3) return false, errors.New("数据错误,暂时不处理") } + scopeType := "v3" + //var cveScV2 models.OriginUpstreamImpactScoreV2 cveScore, ok := models.QueryCveScore(cveImpact.ImpactId, "v3") if !ok { - logs.Error("cveScore, data: ", cveData, ",cveImpact: ", cveImpact) - return false, errors.New("数据错误,暂时不处理") + scopeType = "v2" } cveScV3, ok := models.QueryCveCvssV3(cveScore.ScoreId) if !ok { - logs.Error("cveScore, data: ", cveData, ",cveScore: ", cveScore) + scopeType = "v2" + //logs.Error("cveScore, data: ", cveData, ",cveScore: ", cveScore) + //models.UpdateOriginStatus(common.GetCurTime(), cveData.PackName, cveData.Version, cveData.CveId, 3) + //return false, errors.New("数据错误,暂时不处理") + } + if cveScV3.VectorString == "" || len(cveScV3.VectorString) == 0 || cveScV3.BaseScore == 0.0{ + scopeType = "v2" + } + cveScoreV2, ok2 := models.QueryCveScore(cveImpact.ImpactId, "v2") + if !ok2 { + if scopeType == "v2" { + logs.Error("cveScore, data: ", cveData, ",cveImpact: ", cveImpact) + models.UpdateOriginStatus(common.GetCurTime(), cveData.PackName, cveData.Version, cveData.CveId, 3) + return false, errors.New("数据错误,暂时不处理") + } + } + cveScV2, okV2 := models.QueryCveCvssV2(cveScoreV2.ScoreId) + if !okV2 { + if scopeType == "v2" { + logs.Error("cveScore, data: ", cveData, ",cveScore: ", cveScore) + models.UpdateOriginStatus(common.GetCurTime(), cveData.PackName, cveData.Version, cveData.CveId, 3) + return false, errors.New("数据错误,暂时不处理") + } + } + packNameMap := map[string]string{} + packNameList := []string{} + if cveData.PackName != "" && len(cveData.PackName) > 0 { + packNameList = strings.Split(cveData.PackName, ",") + if len(packNameList) > 0 { + for _, pk := range packNameList { + pkList := strings.Split(pk, "==") + if len(pkList) == 2 { + if _, ok := packNameMap[pkList[0]]; ok { + packNameMap[pkList[0]] += "," + pkList[1] + } else { + packNameMap[pkList[0]] = pkList[1] + } + } + } + } + } + for key, value := range packNameMap { + if key != "" && len(key) > 1 { + pkList := []string{} + pkList = append(pkList, key) + pkList = append(pkList, value) + versionFlag := false + var goe models.GitPackageInfo + if value != "" && len(value) > 0 { + versionList := strings.Split(value, ",") + if len(versionList) > 0 { + for _, ver := range versionList { + if ver != "" && len(ver) > 1 { + goe, ok = models.QueryCveOpeneulerDetaildata(key, pkList[1]) + if ok { + versionFlag = true + break + } else { + logs.Error("未查询到对应的仓库数据, data: ", cveData) + } + } + } + } + } + repoFlag := false + if !versionFlag { + gr, reok := models.QueryOriginRepo(key) + if reok && gr.RepoId > 0 { + repoFlag = true + } + } + if !versionFlag && !repoFlag { + models.UpdateOriginStatus(common.GetCurTime(), cveData.PackName, cveData.Version, cveData.CveId, 4) + } + CveRes, err := models.QueryCveByNum(cveData.CveNum, key, value) + if err { + lockx.Lock() + ok, err := UpdateCveGroups(cveData, cveRef, openeulernum, CveRes, cveDesc, cveScV3, goe, scopeType, cveScV2, pkList) + lockx.Unlock() + if !ok { + logs.Error("更新cve数据失败, cveData: ", cveData, ", err: ", err) + models.UpdateOriginStatus(common.GetCurTime(), cveData.PackName, cveData.Version, cveData.CveId, 3) + return false, errors.New("数据错误,暂时不处理") + } + } else { + lockx.Lock() + ok, err := InsertCveGroups(cveData, cveRef, openeulernum, cveDesc, cveScV3, goe, scopeType, cveScV2, pkList) + lockx.Unlock() + if !ok { + logs.Error("插入cve数据失败, cveData: ", cveData, ", err: ", err) + models.UpdateOriginStatus(common.GetCurTime(), cveData.PackName, cveData.Version, cveData.CveId, 3) + return false, errors.New("数据错误,暂时不处理") + } + } + } + } + models.UpdateOriginStatus(common.GetCurTime(), cveData.PackName, cveData.Version, cveData.CveId, 2) + return true, nil +} + +func SyncCveVuler(cveData models.OriginExcel, cveRef string, openeulerNum int) (bool, error) { + if cveData.CveNum == "" || len(cveData.CveNum) == 0 { + logs.Error("当前数据cveNum 为空暂不处理,data: ", cveData) + models.UpdateOriginExcelStatus(common.GetCurTime(), cveData.CveId, 3) return false, errors.New("数据错误,暂时不处理") } - CveRes, err := models.QueryCveByNum(cveData.CveNum) + goe, ok := models.QueryCveOpeneulerDetaildata(cveData.PackName, cveData.CveVersion) + if !ok { + logs.Error("仓库不存在,暂时不处理,data: ", cveData) + models.UpdateOriginExcelStatus(common.GetCurTime(), cveData.CveId, 4) + return false, errors.New("仓库不存在,暂时不处理") + } + CveRes, err := models.QueryCveByNum(cveData.CveNum, cveData.PackName, cveData.CveVersion) if err { lockx.Lock() - ok, err := UpdateCveGroups(cveData, cveRef, openeulernum, CveRes, cveDesc, cveScV3) + ok, err := UpdateExcelCveGroups(cveData, cveRef, openeulerNum, CveRes, goe) lockx.Unlock() if !ok { logs.Error("更新cve数据失败, cveData: ", cveData, ", err: ", err) + models.UpdateOriginExcelStatus(common.GetCurTime(), cveData.CveId, 3) return false, errors.New("数据错误,暂时不处理") } } else { lockx.Lock() - ok, err := InsertCveGroups(cveData, cveRef, openeulernum, cveDesc, cveScV3) + ok, err := InsertCveExcelGroups(cveData, cveRef, openeulerNum, goe) lockx.Unlock() if !ok { logs.Error("插入cve数据失败, cveData: ", cveData, ", err: ", err) + models.UpdateOriginExcelStatus(common.GetCurTime(), cveData.CveId, 3) return false, errors.New("数据错误,暂时不处理") } } - models.UpdateOriginStatus(common.GetCurTime(), cveData.PackName, cveData.Version, cveData.CveId) + models.UpdateOriginExcelStatus(common.GetCurTime(), cveData.CveId, 2) return true, nil } -func GetCveOriginData(prcnum, days , openeulernum int, cveRef string) (bool, error) { +func GetCveOriginData(prcnum, days, openeulernum int, cveRef string) (bool, error) { defer common.Catchs() //var os []models.OriginUpstream count := 0 beforeTime := common.GetBeforeTime(days) for { - os, num, err := models.QueryOriginCve(beforeTime, prcnum) - if err != nil || num == 0{ + osx, num, err := models.QueryOriginCve(beforeTime, prcnum) + if err != nil || num == 0 { logs.Info("当前无cve原始数据处理, err: ", err, ", 处理时间范围: beforetime: ", beforeTime, "curtime: ", common.GetCurTime()) break } - logs.Info("总共有: ", num, "条的数据需要处理, ", os) - ch := make(chan int, len(os)) - for i, cveData := range os { + logs.Info("总共有: ", num, "条的数据需要处理, ", osx) + ch := make(chan int, len(osx)) + for i, cveData := range osx { count = count + 1 logs.Info("当前正常解析第: ", count, "条数据,i:", i, ", cvenum: ", cveData.Ids) - go func () { + go func() { ok, err := GenCveVuler(cveData, cveRef, openeulernum) if !ok { logs.Error("cveData: ", cveData, "处理失败, err: ", err) @@ -318,3 +839,639 @@ func GetCveOriginData(prcnum, days , openeulernum int, cveRef string) (bool, err } return true, nil } + +func GetCveOriginExcelData(prcnum, days, openeulerNum int, cveRef string) (bool, error) { + defer common.Catchs() + //var os []models.OriginUpstream + count := 0 + beforeTime := common.GetBeforeTime(days) + for { + osx, num, err := models.QueryOriginCveExcel(beforeTime, prcnum) + if err != nil || num == 0 { + logs.Info("当前无excel导入的cve原始数据处理, err: ", err, + ", 处理时间范围: beforetime: ", beforeTime, + "curtime: ", common.GetCurTime()) + break + } + logs.Info("excel总共有: ", num, "条的数据需要处理, ", osx) + ch := make(chan int, len(osx)) + for i, cveData := range osx { + count = count + 1 + logs.Info("当前正常解析第: ", count, "条数据,i:", i, ", cvenum: ", cveData.CveNum) + go func() { + ok, err := SyncCveVuler(cveData, cveRef, openeulerNum) + if !ok { + logs.Error("cveData: ", cveData, "处理失败, err: ", err) + } + ch <- i + }() + } + for i := 0; i < cap(ch); i++ { + <-ch + } + close(ch) + } + return true, nil +} + +func InsertIssueCveGroups(cveData models.GiteOriginIssue, lop models.Loophole, cveRef string, openeulernum int, + cveStatus int8, goe models.GitPackageInfo, owner string) (bool, error) { + var vul models.VulnCenter + vul.CveNum = cveData.CveNumber + vul.Description = lop.RepoDesc + vul.Status = cveStatus + vul.CveVersion = lop.Version + vul.RepairTime = "" + vul.PackName = lop.Components + vul.CveUrl = cveRef + cveData.CveNumber + vul.IsExport = 0 + v2, cvsError := strconv.ParseFloat(lop.CvsScore, 64) + if cvsError != nil { + vul.CveLevel = "Critical" + } + if v2 >= 9.0 { + vul.CveLevel = "Critical" + } else if v2 >= 7.0 && v2 <= 8.9 { + vul.CveLevel = "High" + } else if v2 > 4.0 && v2 <= 6.9 { + vul.CveLevel = "Medium" + } else if v2 <= 4.0 { + vul.CveLevel = "Low" + } + var sec models.SecurityNotice + sec.CveNum = cveData.CveNumber + sec.InfluenceComponent = lop.Components + sec.Status = 0 + sec.AffectStatus = "UnFixed" + sec.Summary = lop.Components + " security update" + sec.Description = goe.Decription + "\n\n" + "Security Fix(es):" + "\n\n" + lop.BriefIntroduction + sec.ReferenceLink = cveRef + cveData.CveNumber + sec.Introduction = "An update for " + lop.Components + " is now available for " + lop.InfProduct + //sec.Summary = "An update for " + path + " is now available for " + branchs + sec.Theme = sec.Introduction + ";\n\n" + "openEuler Security has rated this" + + " update as having a security impact of medium. A Common Vunlnerability" + + " Scoring System(CVSS)base score,which gives a detailed severity rating," + + " is available for each vulnerability from the CVElink(s) in the References section." + sec.AffectProduct = lop.InfProduct + var sc models.Score + sc.CveNum = cveData.CveNumber + nVDScore, nvdError := strconv.ParseFloat(lop.CvsScore, 64) + if nvdError == nil { + sc.NVDScore = nVDScore + } + openEulerScore, openError := strconv.ParseFloat(lop.OpScore, 64) + if openError == nil { + sc.OpenEulerScore = openEulerScore + } + sc.NvectorVule = lop.CvsVector + sc.OvectorVule = lop.OpVector + sc.Nstatus = 0 + sc.Ostatus = 0 + sc.ScoreType = "v3" + vectorN := models.VectorValue{} + ok := vectorN.VctToVectorValue(lop.CvsVector) + if ok { + sc.NattackVector = vectorN.AttackVector + sc.NattackComplexity = vectorN.AttackComplexity + sc.NprivilegeRequired = vectorN.PrivilegesRequired + sc.NuserInteraction = vectorN.UserInteraction + sc.Nscope = vectorN.Scope + sc.Nconfidentiality = vectorN.Confidentiality + sc.Nintegrity = vectorN.Integrity + sc.Navailability = vectorN.Availability + } + vectorO := models.VectorValue{} + okx := vectorO.VctToVectorValue(lop.OpVector) + if okx { + sc.OattackVector = vectorO.AttackVector + sc.OattackComplexity = vectorO.AttackComplexity + sc.OprivilegeRequired = vectorO.PrivilegesRequired + sc.OuserInteraction = vectorO.UserInteraction + sc.Oscope = vectorO.Scope + sc.Oconfidentiality = vectorO.Confidentiality + sc.Ointegrity = vectorO.Integrity + sc.Oavailability = vectorO.Availability + } + + var opensa models.OpenEulerSA + var OpenNumData int + //var os models.OpenSaId + osx, opError := models.QueryOpenSaLastId() + if opError == nil { + OpenNumList := strings.Split(osx.OpenEulerSANum, "-") + OpenNum, err := strconv.Atoi(OpenNumList[len(OpenNumList)-1]) + if err == nil { + OpenNum += 10 + } else { + OpenNum = openeulernum + } + OpenNumData = OpenNum + } else { + OpenNumData = openeulernum + } + OpenEulerSANum := "openEuler-SA-" + strconv.Itoa(time.Now().Year()) + "-" + strconv.Itoa(int(OpenNumData)) + opensa.OpenEulerSANum = OpenEulerSANum + var scorecode models.ScoreRecord + scorecode.NVDScore = nVDScore + scorecode.NvectorVule = lop.CvsVector + scorecode.Status = 0 + cveid, cveError := models.CreateCveRelat(&vul, &sec, &sc, &opensa, &scorecode) + if cveError != nil || cveid <= 0 { + logs.Error("insert (&CveRes, &scoreRes, &sec) failed CveNum:", cveData.CveNumber) + return false, errors.New("数据插入失败,暂时不处理") + } + var issueTemp models.IssueTemplate + issueTemp.CveId = cveid + issueTemp.CveNum = cveData.CveNumber + issueTemp.OwnedComponent = lop.Components + issueTemp.OwnedVersion = lop.Version + issueTemp.NVDScore = nVDScore + issueTemp.OpenEulerScore = openEulerScore + issueTemp.NVDVector = lop.CvsVector + issueTemp.OpenEulerVector = lop.OpVector + issueTemp.CveBrief = lop.BriefIntroduction + issueTemp.CveAnalysis = lop.Influences + issueTemp.PrincipleAnalysis = lop.Principle + issueTemp.AffectedVersion = lop.InfVersion + issueTemp.Solution = lop.AvoidScheme + issueTemp.IssueId = cveData.IssueId + issueTemp.IssueNum = cveData.Number + issueTemp.Assignee = cveData.IssueAssignee + if strings.ToLower(cveData.State) == "open" { + issueTemp.Status = 1 + issueTemp.IssueStatus = 1 + } else if strings.ToLower(cveData.State) == "progressing" { + issueTemp.Status = 2 + issueTemp.IssueStatus = 3 + } else if strings.ToLower(cveData.State) == "closed" { + issueTemp.Status = 3 + issueTemp.IssueStatus = 2 + } else { + issueTemp.Status = 4 + issueTemp.IssueStatus = 6 + } + issueTemp.StatusName = cveData.State + issueTemp.IssueLabel = "cve/Undisclosed" + issueTemp.Owner = cveData.RepoPath + issueTemp.Repo = lop.Repo + if cveData.Title != "" { + issueTemp.Title = cveData.Title + } + issueTemp.IssueType = cveData.IssueType + issueTemp.CveLevel = vul.CveLevel + // 存储issue数据 + issTempId, issError := models.CreateIssueTemplet(&issueTemp) + if issError != nil { + logs.Error("创建issue 模板的数据失败, cveNum: ", cveData.CveNumber, "err: ", issError) + return false, issError + } else { + logs.Info("创建issue 模板的数据成功, issTempId: ", issTempId, "cveNum: ", cveData.CveNumber) + } + if cveData.State != "" && (strings.ToLower(cveData.State) == "open" || strings.ToLower(cveData.State) == "progressing") { + accessToken := os.Getenv("GITEE_TOKEN") + CreateDepositHooks(accessToken, owner, cveData.RepoPath, vul, cveData.Number, cveData.IssueId) + } + return true, nil +} + +func UpdateIssueCveGroups(cveData models.GiteOriginIssue, lop models.Loophole, cveRef string, openeulernum int, + cveStatus int8, goe models.GitPackageInfo, vul models.VulnCenter, owner string) (bool, error) { + //var vul models.VulnCenter + vul.CveNum = cveData.CveNumber + vul.Description = lop.RepoDesc + vul.Status = cveStatus + vul.CveVersion = lop.Version + vul.RepairTime = "" + vul.PackName = lop.Components + vul.CveUrl = cveRef + cveData.CveNumber + vul.IsExport = 0 + var sec models.SecurityNotice + sec.CveNum = cveData.CveNumber + sec.InfluenceComponent = lop.Components + sec.Status = 0 + sec.AffectStatus = "Fixed" + sec.Summary = lop.Components + " security update" + sec.Description = goe.Decription + "\n\n" + "Security Fix(es):" + "\n\n" + lop.BriefIntroduction + sec.ReferenceLink = cveRef + cveData.CveNumber + sec.Introduction = "An update for " + lop.Components + " is now available for " + lop.InfProduct + //sec.Summary = "An update for " + path + " is now available for " + branchs + sec.Theme = sec.Introduction + ";\n\n" + "openEuler Security has rated this" + + " update as having a security impact of medium. A Common Vunlnerability" + + " Scoring System(CVSS)base score,which gives a detailed severity rating," + + " is available for each vulnerability from the CVElink(s) in the References section." + sec.AffectProduct = lop.InfProduct + nVDScore := 0.0 + //var err error + var score models.Score + var scOk bool + score, scOk = models.QueryScoreByCveId(vul.CveId) + if !scOk || score.Id == 0 { + vul.Status = 2 + //var sc models.Score + v2, cvsError := strconv.ParseFloat(lop.CvsScore, 64) + if cvsError != nil { + vul.CveLevel = "Critical" + } + if v2 >= 9.0 { + vul.CveLevel = "Critical" + } else if v2 >= 7.0 && v2 <= 8.9 { + vul.CveLevel = "High" + } else if v2 > 4.0 && v2 <= 6.9 { + vul.CveLevel = "Medium" + } else if v2 <= 4.0 { + vul.CveLevel = "Low" + } + score.CveNum = cveData.CveNumber + var nvdError error + nVDScore, nvdError = strconv.ParseFloat(lop.CvsScore, 64) + if nvdError == nil { + score.NVDScore = nVDScore + } + openEulerScore, openError := strconv.ParseFloat(lop.OpScore, 64) + if openError == nil { + score.OpenEulerScore = openEulerScore + } + score.NvectorVule = lop.CvsVector + score.OvectorVule = lop.OpVector + score.Nstatus = 0 + score.Ostatus = 0 + score.ScoreType = "v3" + vectorN := models.VectorValue{} + ok := vectorN.VctToVectorValue(lop.CvsVector) + if ok { + score.NattackVector = vectorN.AttackVector + score.NattackComplexity = vectorN.AttackComplexity + score.NprivilegeRequired = vectorN.PrivilegesRequired + score.NuserInteraction = vectorN.UserInteraction + score.Nscope = vectorN.Scope + score.Nconfidentiality = vectorN.Confidentiality + score.Nintegrity = vectorN.Integrity + score.Navailability = vectorN.Availability + } + vectorO := models.VectorValue{} + vectOk := vectorO.VctToVectorValue(lop.OpVector) + if vectOk { + score.OattackVector = vectorO.AttackVector + score.OattackComplexity = vectorO.AttackComplexity + score.OprivilegeRequired = vectorO.PrivilegesRequired + score.OuserInteraction = vectorO.UserInteraction + score.Oscope = vectorO.Scope + score.Oconfidentiality = vectorO.Confidentiality + score.Ointegrity = vectorO.Integrity + score.Oavailability = vectorO.Availability + } + } else { + v2 := score.NVDScore + if v2 >= 9.0 { + vul.CveLevel = "Critical" + } else if v2 >= 7.0 && v2 <= 8.9 { + vul.CveLevel = "High" + } else if v2 > 4.0 && v2 <= 6.9 { + vul.CveLevel = "Medium" + } else if v2 <= 4.0 { + vul.CveLevel = "Low" + } + score.CveNum = cveData.CveNumber + score.Nstatus = 2 + var nvdError error + nVDScore, nvdError = strconv.ParseFloat(lop.CvsScore, 64) + if nvdError == nil { + if score.NVDScore != nVDScore { + score.Nstatus = 1 + vul.Status = 1 + } + } + openEulerScore, openError := strconv.ParseFloat(lop.OpScore, 64) + if openError == nil { + score.OpenEulerScore = openEulerScore + } + //sc.NvectorVule = lop.CvsVector + score.OvectorVule = lop.OpVector + + //sc.Ostatus = 0 + score.ScoreType = "v3" + //vectorN := models.VectorValue{} + //ok := vectorN.VctToVectorValue(lop.CvsVector) + //if ok { + // sc.NattackVector = vectorN.AttackVector + // sc.NattackComplexity = vectorN.AttackComplexity + // sc.NprivilegeRequired = vectorN.PrivilegesRequired + // sc.NuserInteraction = vectorN.UserInteraction + // sc.Nscope = vectorN.Scope + // sc.Nconfidentiality = vectorN.Confidentiality + // sc.Nintegrity = vectorN.Integrity + // sc.Navailability = vectorN.Availability + //} + vectorO := models.VectorValue{} + okx := vectorO.VctToVectorValue(lop.OpVector) + if okx { + score.OattackVector = vectorO.AttackVector + score.OattackComplexity = vectorO.AttackComplexity + score.OprivilegeRequired = vectorO.PrivilegesRequired + score.OuserInteraction = vectorO.UserInteraction + score.Oscope = vectorO.Scope + score.Oconfidentiality = vectorO.Confidentiality + score.Ointegrity = vectorO.Integrity + score.Oavailability = vectorO.Availability + } + } + if vul.Status == 0 { + accessToken := os.Getenv("GITEE_TOKEN") + CreateDepositHooks(accessToken, owner, cveData.RepoPath, vul, cveData.Number, cveData.IssueId) + } + //var opensa models.OpenEulerSA + ////var os models.OpenSaId + //os, operr := models.QueryOpenSaLastId() + //var OpenNumData int + //if operr == nil { + // OpenNumList := strings.Split(os.OpenEulerSANum, "-") + // OpenNum, err := strconv.Atoi(OpenNumList[len(OpenNumList) - 1]) + // if err == nil { + // OpenNum += 100 + // } else { + // OpenNum = openeulernum + // } + // OpenNumData = OpenNum + //} else { + // OpenNumData = openeulernum + //} + //OpenEulerSANum := "openEuler-SA-" + strconv.Itoa(time.Now().Year()) + "-" + strconv.Itoa(int(OpenNumData)) + //opensa.OpenEulerSANum = OpenEulerSANum + + cveError := models.UpdateCveRelat(&vul, &sec, &score) + if cveError != nil || vul.CveId == 0 { + logs.Error("UpdateCveRelat(&vul, &sec, &sc) failed CveNum:", cveData.CveNumber, ",err:", cveError) + return false, errors.New("数据插入失败,暂时不处理") + } + if scOk || score.Id > 0 { + if score.NVDScore != nVDScore { + var scorecode models.ScoreRecord + scorecode.NVDScore = score.NVDScore + scorecode.NvectorVule = score.NvectorVule + scorecode.Status = 0 + models.InsertScoreRecord(&scorecode) + } + } + var issueTemp models.IssueTemplate + issueTemp.CveId = vul.CveId + localt, okl := models.GetIssueTemplet(&issueTemp) + if okl && localt.TemplateId > 0 { + issueTemp.CveNum = cveData.CveNumber + issueTemp.OwnedComponent = lop.Components + issueTemp.OwnedVersion = lop.Version + openEulerScore, openError := strconv.ParseFloat(lop.OpScore, 64) + if openError == nil { + issueTemp.OpenEulerScore = openEulerScore + } + issueTemp.OpenEulerVector = lop.OpVector + issueTemp.CveBrief = lop.BriefIntroduction + issueTemp.CveAnalysis = lop.Influences + issueTemp.PrincipleAnalysis = lop.Principle + issueTemp.AffectedVersion = lop.InfVersion + issueTemp.Solution = lop.AvoidScheme + issueTemp.IssueId = cveData.IssueId + issueTemp.IssueNum = cveData.Number + issueTemp.Assignee = cveData.IssueAssignee + if strings.ToLower(cveData.State) == "open" { + issueTemp.Status = 1 + issueTemp.IssueStatus = 1 + } else if strings.ToLower(cveData.State) == "progressing" { + issueTemp.Status = 2 + issueTemp.IssueStatus = 3 + } else if strings.ToLower(cveData.State) == "closed" { + issueTemp.Status = 3 + issueTemp.IssueStatus = 2 + } else { + issueTemp.Status = 4 + issueTemp.IssueStatus = 6 + } + issueTemp.StatusName = cveData.State + issueTemp.Owner = cveData.RepoPath + issueTemp.Repo = lop.Repo + if cveData.Title != "" { + issueTemp.Title = cveData.Title + } + issueTemp.IssueType = cveData.IssueType + issueTemp.CveLevel = vul.CveLevel + } else { + issueTemp.CveNum = cveData.CveNumber + issueTemp.OwnedComponent = lop.Components + issueTemp.OwnedVersion = lop.Version + issueTemp.NVDScore = nVDScore + openEulerScore, openError := strconv.ParseFloat(lop.OpScore, 64) + if openError == nil { + issueTemp.OpenEulerScore = openEulerScore + } + issueTemp.NVDVector = lop.CvsVector + issueTemp.OpenEulerVector = lop.OpVector + issueTemp.CveBrief = lop.BriefIntroduction + issueTemp.CveAnalysis = lop.Influences + issueTemp.PrincipleAnalysis = lop.Principle + issueTemp.AffectedVersion = lop.InfVersion + issueTemp.Solution = lop.AvoidScheme + issueTemp.IssueId = cveData.IssueId + issueTemp.IssueNum = cveData.Number + issueTemp.Assignee = cveData.IssueAssignee + if strings.ToLower(cveData.State) == "open" { + issueTemp.Status = 1 + issueTemp.IssueStatus = 1 + } else if strings.ToLower(cveData.State) == "progressing" { + issueTemp.Status = 2 + issueTemp.IssueStatus = 3 + } else if strings.ToLower(cveData.State) == "closed" { + issueTemp.Status = 3 + issueTemp.IssueStatus = 2 + } else { + issueTemp.Status = 4 + issueTemp.IssueStatus = 6 + } + issueTemp.StatusName = cveData.State + issueTemp.IssueLabel = "cve/Undisclosed" + issueTemp.Owner = cveData.RepoPath + issueTemp.Repo = lop.Repo + if cveData.Title != "" { + issueTemp.Title = cveData.Title + } + issueTemp.IssueType = cveData.IssueType + issueTemp.CveLevel = vul.CveLevel + } + // 存储issue数据 + issTempId, issError := models.CreateIssueTemplet(&issueTemp) + if issError != nil { + logs.Error("创建issue 模板的数据失败, cveNum: ", cveData.CveNumber, "err: ", issError) + return false, issError + } else { + logs.Info("创建issue 模板的数据成功, issTempId: ", issTempId, "cveNum: ", cveData.CveNumber) + } + return true, nil +} + +func GenCveVulerByIssue(cveData models.GiteOriginIssue, cveRef string, openeulernum int, owner string) (bool, error) { + hole, err := cveData.ParseToLoophole() + if err != nil { + logs.Error("数据解析错误,") + models.UpdateCveStatusExportByNum(common.GetCurTime(), cveData.CveNumber, 2, 2, cveData.RepoPath) + models.UpdateCveIssueStatusById(3, cveData.Id) + return false, err + } + goe, ok := models.QueryCveOpeneulerDetaildata(cveData.RepoPath, hole.Version) + if !ok || goe.DetailId == 0 { + logs.Error("获取数据失败,", "Components: ", hole.Components, ",Version: ", hole.Version) + } + if cveData.State != "" && strings.ToLower(cveData.State) == "rejected" { + logs.Info("处理issue状态为拒绝状态的数据:", cveData) + cvd, ok := models.QueryCveByNum(cveData.CveNumber, cveData.RepoPath, hole.Version) + if ok && cvd.CveNum != "" { + lock.Lock() + UpdateIssueCveGroups(cveData, hole, cveRef, openeulernum, 2, goe, cvd, owner) + lock.Unlock() + } else { + lock.Lock() + okx, errx := InsertIssueCveGroups(cveData, hole, cveRef, openeulernum, 2, goe, owner) + lock.Unlock() + if !okx { + logs.Error("数据处理失败, InsertIssueCveGroups, err: ", errx) + return false, err + } + } + models.UpdateCveStatusExportByNum(common.GetCurTime(), cveData.CveNumber, 2, 2, cveData.RepoPath) + models.UpdateCveIssueStatusById(2, cveData.Id) + return true, nil + } else if cveData.State != "" && strings.ToLower(cveData.State) == "closed" { + logs.Info("处理issue状态为关闭状态的数据:", cveData) + cvd, ok := models.QueryCveByNum(cveData.CveNumber, cveData.RepoPath, hole.Version) + if ok && cvd.CveNum != "" { + lock.Lock() + UpdateIssueCveGroups(cveData, hole, cveRef, openeulernum, 2, goe, cvd, owner) + lock.Unlock() + //models.UpdateCveStatusExportByNum(common.GetCurTime(), cveData.CveNumber, 2, 2) + } else { + lock.Lock() + okx, errx := InsertIssueCveGroups(cveData, hole, cveRef, openeulernum, 2, goe, owner) + lock.Unlock() + if !okx { + logs.Error("数据处理失败, InsertIssueCveGroups, err: ", errx) + return false, err + } + } + models.UpdateCveStatusExportByNum(common.GetCurTime(), cveData.CveNumber, 2, 3, cveData.RepoPath) + models.UpdateCveIssueStatusById(2, cveData.Id) + return true, nil + } else { + logs.Info("处理issue状态为开启、处理中状态的数据:", cveData) + cvd, ok := models.QueryCveByNum(cveData.CveNumber, cveData.RepoPath, hole.Version) + if ok && cvd.CveNum != "" { + lock.Lock() + UpdateIssueCveGroups(cveData, hole, cveRef, openeulernum, 1, goe, cvd, owner) + lock.Unlock() + //models.UpdateCveStatusExportByNum(common.GetCurTime(), cveData.CveNumber, 2, 2) + } else { + lock.Lock() + okx, errx := InsertIssueCveGroups(cveData, hole, cveRef, openeulernum, 2, goe, owner) + lock.Unlock() + if !okx { + logs.Error("数据处理失败, InsertIssueCveGroups, err: ", errx) + return false, err + } + } + models.UpdateCveIssueStatusById(2, cveData.Id) + return true, nil + } +} + +func GetCveIssueData(prcnum, days, openeulernum int, cveRef, owner string) (bool, error) { + defer common.Catchs() + count := 0 + for { + gs, num, err := models.QueryOriginCveIssue(prcnum) + if err != nil || num == 0 { + logs.Info("当前无cveissue原始数据处理, err: ", err, + "curtime: ", common.GetCurTime()) + break + } + logs.Info("总共有: ", num, "条的数据需要处理, ", gs) + ch := make(chan int, len(gs)) + for i, cveData := range gs { + count = count + 1 + logs.Info("当前正常解析第: ", count, "条数据,i:", i, ", cvenum: ", cveData.IssueId) + if cveData.CveNumber == "" || len(cveData.CveNumber) == 0 { + logs.Error("数据异常, 不处理, cveData: ", cveData) + models.UpdateCveIssueStatusById(3, cveData.Id) + continue + } + go func() { + ok, err := GenCveVulerByIssue(cveData, cveRef, openeulernum, owner) + if !ok { + logs.Error("cveData: ", cveData, "处理失败, err: ", err) + } + ch <- i + }() + } + for i := 0; i < cap(ch); i++ { + <-ch + } + close(ch) + } + return true, nil +} + +//GetSecurityNotice Go to the CVE official website to obtain the cve data to determine +//whether the cve issue needs to be exported. +func GetCveSecurityNotice(cveNumber string) bool { + resp, err := http.Get(fmt.Sprintf(GetCveDetailUrl, cveNumber)) + if err != nil { + logs.Error(err) + return false + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + logs.Error(err) + return false + } + var detail models.RespCveDetail + err = json.Unmarshal(body, &detail) + if err != nil { + logs.Error(err) + return false + } + if detail.Result != nil && detail.Result.Id > 0 { + return true + } + return false + +} + +//FilterCveExported Filter exportable data +func FilterCveExported() { + data, err := models.GetCanExportVulnCenterData() + if err != nil { + logs.Error(err) + return + } + for _, v := range data { + go func(center models.VulnCenter) { + ewg.Add(1) + defer ewg.Done() + if GetCveSecurityNotice(center.CveNum) { + center.IsExport = 1 + models.UpdateVulnCenter(¢er, "is_export") + } + }(v) + + } + ewg.Wait() +} + +func GenerateExcelTask() error { + FilterCveExported() + tn := time.Now().Format("2006-01-02") + fn := fmt.Sprintf("Cve数据与安全公告%s.xlsx", tn) + err := GenerateCveExcel(fn, "openEuler", 0, true) + if err != nil { + return err + } + er := models.ExportRecord{FileName: fn} + err = er.Insert() + return err +} diff --git a/taskhandler/excel.go b/taskhandler/excel.go new file mode 100644 index 0000000000000000000000000000000000000000..aae25f88910c25a29e11fc2846901d4fe4052ca5 --- /dev/null +++ b/taskhandler/excel.go @@ -0,0 +1,494 @@ +package taskhandler + +import ( + "cvevulner/models" + "errors" + "fmt" + "github.com/360EntSecGroup-Skylar/excelize/v2" + "github.com/astaxie/beego/logs" + "os" + "strconv" + "strings" + "time" +) + +type CveExcel struct { + ExcelName string //excel 名字 + ExcelHandel *excelize.File //excel 文件句柄 + CveSheetIdx int //CVE sheet index + CveSheetName string // CVE sheet Name + SecNoticeSheetIdx int //安全公告index + SecNoticeSheetName string //安全公告sheet名字 + SecNoticePrefix string //安全公告前缀 + SecNoticeSuffixIdx int64 //安全公告后缀起始值 + InfProductSheetName string //CVE 影响的产品 + InfProductSheetIndex int + PackageUrlSheetName string + PackageUrlSheetIndex int +} + +//GenerateCveExcel Generate Excel documents based on data. +//param snPrefix means security notice prefix. +//param snSuffix means security notice suffix append start value. +//param forceRewrite means whether to force the document to be rewritten. +func GenerateCveExcel(excelName, snPrefix string, snSuffix int64, forceRewrite bool) (err error) { + //Query the data to be exported. + count := models.GetCanExportVulnCenterCount() + if count < 1 { + return errors.New("No data to export! ") + } + //init excelClient + ec := CveExcel{} + err = ec.Init(excelName, snPrefix, snSuffix) + if err != nil { + return err + } + mode := ec.InitFileHandle(forceRewrite) + if mode == 0 { + ec.InitSheet() + err = ec.FillHeader() + if err != nil { + logs.Error(err) + } + } + ec.FillContent(count) + //generate excel + return ec.Save(mode) +} + +func (ec *CveExcel) Init(excelName, snPrefix string, snSuffix int64) (err error) { + if excelName == "" || !(strings.HasSuffix(excelName, ".xlsx") || strings.HasSuffix(excelName, "xls")) { + err = errors.New("excel name illegal") + return + } + ec.ExcelName = excelName + ec.SecNoticePrefix = snPrefix + ec.SecNoticeSuffixIdx = snSuffix + ec.CveSheetIdx = 0 + ec.CveSheetName = "CVE" + ec.SecNoticeSheetIdx = 1 + ec.SecNoticeSheetName = "安全公告" + ec.InfProductSheetIndex = 2 + ec.InfProductSheetName = "CVE影响的产品" + ec.PackageUrlSheetIndex = 3 + ec.PackageUrlSheetName = "安全公告升级包链接" + return nil +} + +//InitFileHandle Initialize the file handle. +//param forceRewrite is true it means will create a new file otherwise it means append or new. +//the return value wm is 0 for new creation, and 1 for append. +func (ec *CveExcel) InitFileHandle(forceRewrite bool) (wm int8) { + if forceRewrite { + ec.ExcelHandel = excelize.NewFile() + return 0 + } + s, err := os.Stat(ec.ExcelName) + if err != nil { + ec.ExcelHandel = excelize.NewFile() + return 0 + } + if !s.IsDir() { + file, err := excelize.OpenFile(ec.ExcelName) + if err != nil { + ec.ExcelHandel = excelize.NewFile() + return 0 + } else { + ec.ExcelHandel = file + return 1 + } + } else { + ec.ExcelHandel = excelize.NewFile() + return 0 + } +} + +func (ec *CveExcel) InitSheet() { + ec.SecNoticeSheetIdx = ec.ExcelHandel.NewSheet(ec.SecNoticeSheetName) + ec.InfProductSheetIndex = ec.ExcelHandel.NewSheet(ec.InfProductSheetName) + ec.PackageUrlSheetIndex = ec.ExcelHandel.NewSheet(ec.PackageUrlSheetName) + sn := ec.ExcelHandel.GetSheetName(ec.CveSheetIdx) + ec.ExcelHandel.SetSheetName(sn, ec.CveSheetName) +} + +func (ec *CveExcel) FillHeader() (err error) { + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "A1", "CVE编号") + if err != nil { + return + } + err = ec.ExcelHandel.MergeCell(ec.CveSheetName, "A1", "A2") + if err != nil { + return + } + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "B1", "概要") + if err != nil { + return + } + err = ec.ExcelHandel.MergeCell(ec.CveSheetName, "B1", "B2") + if err != nil { + return + } + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "C1", "Cvss Score") + if err != nil { + return + } + err = ec.ExcelHandel.MergeCell(ec.CveSheetName, "C1", "D1") + if err != nil { + return + } + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "c2", "NVD") + if err != nil { + return + } + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "D2", "OpenEuler") + if err != nil { + return + } + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "E1", "Attack Vector") + if err != nil { + return + } + err = ec.ExcelHandel.MergeCell(ec.CveSheetName, "E1", "F1") + if err != nil { + return + } + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "E2", "NVD") + if err != nil { + return + } + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "F2", "OpenEuler") + if err != nil { + return + } + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "G1", "Attack Complexity") + if err != nil { + return + } + err = ec.ExcelHandel.MergeCell(ec.CveSheetName, "G1", "H1") + if err != nil { + return + } + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "G2", "NVD") + if err != nil { + return + } + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "H2", "OpenEuler") + if err != nil { + return + } + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "I1", "Privileges Required") + if err != nil { + return + } + err = ec.ExcelHandel.MergeCell(ec.CveSheetName, "I1", "J1") + if err != nil { + return + } + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "I2", "NVD") + if err != nil { + return + } + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "J2", "OpenEuler") + if err != nil { + return + } + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "K1", "User Interaction") + if err != nil { + return + } + err = ec.ExcelHandel.MergeCell(ec.CveSheetName, "K1", "L1") + if err != nil { + return + } + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "K2", "NVD") + if err != nil { + return + } + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "L2", "OpenEuler") + if err != nil { + return + } + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "M1", "Scope") + if err != nil { + return + } + err = ec.ExcelHandel.MergeCell(ec.CveSheetName, "M1", "N1") + if err != nil { + return + } + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "M2", "NVD") + if err != nil { + return + } + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "N2", "OpenEuler") + if err != nil { + return + } + + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "O1", "Confidentiality") + if err != nil { + return + } + err = ec.ExcelHandel.MergeCell(ec.CveSheetName, "O1", "P1") + if err != nil { + return + } + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "O2", "NVD") + if err != nil { + return + } + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "P2", "OpenEuler") + if err != nil { + return + } + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "Q1", "Integrity") + if err != nil { + return + } + err = ec.ExcelHandel.MergeCell(ec.CveSheetName, "Q1", "R1") + if err != nil { + return + } + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "Q2", "NVD") + if err != nil { + return + } + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "R2", "OpenEuler") + if err != nil { + return + } + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "S1", "Availability") + if err != nil { + return + } + err = ec.ExcelHandel.MergeCell(ec.CveSheetName, "S1", "T1") + if err != nil { + return + } + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "S2", "NVD") + if err != nil { + return + } + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "T2", "OpenEuler") + if err != nil { + return + } + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "U1", "评分类型") + if err != nil { + return + } + err = ec.ExcelHandel.MergeCell(ec.CveSheetName, "U1", "U2") + if err != nil { + return + } + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "V1", "安全公告") + if err != nil { + return + } + err = ec.ExcelHandel.MergeCell(ec.CveSheetName, "V1", "V2") + if err != nil { + return + } + err = ec.ExcelHandel.SetCellValue(ec.CveSheetName, "W1", "公告时间") + if err != nil { + return + } + err = ec.ExcelHandel.MergeCell(ec.CveSheetName, "W1", "W2") + if err != nil { + return + } + //安全公告表头生成 + sh := []interface{}{"公告编号", "CVE编号", "简介", "概要", "主题", "描述", "影响组件", "影响产品", "影响包名", "参考", "公告时间"} + err = ec.ExcelHandel.SetSheetRow(ec.SecNoticeSheetName, "A1", &sh) + if err != nil { + return err + } + ih := []interface{}{"CVE编号", "影响的产品", "包", "状态"} + err = ec.ExcelHandel.SetSheetRow(ec.InfProductSheetName, "A1", &ih) + if err != nil { + return err + } + ph := []interface{}{"包名", "包下载链接"} + err = ec.ExcelHandel.SetSheetRow(ec.PackageUrlSheetName, "A1", &ph) + if err != nil { + return err + } + return nil +} + +func (ec *CveExcel) FillContent(count int64) { + pageSize := 50 + pageCount := count / int64(pageSize) + if count%int64(pageSize) > 0 { + pageCount += 1 + } + for i := int64(0); i < pageCount; i++ { + off := i * int64(pageSize) + err := ec.handleWriteContent(off, pageSize) + if err != nil { + logs.Error(err) + } + } +} + +func (ec *CveExcel) handleWriteContent(off int64, size int) (err error) { + list, err := models.GetCanExportCveData(off, size) + if err != nil { + return err + } + lz := len(list) + if lz > 0 { + for _, v := range list { + if v.Num == 1 { + ec.setContentRow(v) + } else if v.Num > 1 { + //处理CVE_NUM 重复 + //1.根据cve_num 获取issue_tpl 如果所有的issue_status ==2 0r issue_status == 6 则可以导出数据 + list, err := models.GetIssueTplByCveNum(v.CveNum) + if err != nil { + logs.Error(err) + continue + } + mergerList := make([]string, 0) + canMerger := true + for _, t := range list { + if t.Status != 3 && t.Status != 4 { + canMerger = false + break + } + if t.IssueStatus == 2 { + mergerList = append(mergerList, strconv.FormatInt(t.CveId,10)) + } + + } + //2.从issue_status == 2 的模板数据中找到评分最高的对应的ExcelExport数据 + if canMerger && len(mergerList)>0{ + canExport, err := models.GetCanExportCveDataSameNum(strings.Join(mergerList, ",")) + if err != nil { + logs.Error(err) + } + ep := canExport[0] + if len(canExport)>1{ + canExport = canExport[1:] + for _,ex := range canExport { + ep.Introduction = ep.Introduction+"\n"+ex.Introduction + ep.Summary = ep.Summary+"\n"+ex.Summary + ep.Theme = ep.Theme+"\n"+ex.Theme + ep.Description = ep.Description+"\n"+ex.Description + ep.OwnedComponent = ep.OwnedComponent+"\n"+ex.OwnedComponent + ep.InfluenceComponent = ep.InfluenceComponent+"\n"+ex.InfluenceComponent + ep.AffectProduct = ep.AffectProduct+"\n"+ex.AffectProduct + } + + } + ec.setContentRow(ep) + } + } + + } + } + return nil +} + +func (ec *CveExcel) setContentRow(v models.ExcelExport) { + pkg, err := models.GetCvePackageList(v.SecId) + if err != nil { + logs.Error(err) + } + if v.PublicDate == "" { + v.PublicDate = time.Now().Format("2006-01-02") + } + pkgStr := getPkgStr(pkg) + cve := []interface{}{v.CveNum, v.CveBrief, v.NVDScore, v.OpenEulerScore, v.NattackVector, v.OattackVector, + v.NattackComplexity, v.OattackComplexity, v.NprivilegeRequired, v.OprivilegeRequired, v.NuserInteraction, + v.OuserInteraction, v.Nscope, v.Oscope, v.Nconfidentiality, v.Oconfidentiality, v.Nintegrity, v.Ointegrity, + v.Navailability, v.Oavailability, v.ScoreType, v.OpenEulerSANum, v.PublicDate} + err = ec.FillCveSheetRow(cve) + if err != nil { + logs.Error(err) + } + sn := []interface{}{v.OpenEulerSANum, v.CveNum, v.Introduction, v.Summary, v.Theme, v.Description, v.InfluenceComponent, + v.AffectProduct, pkgStr, v.ReferenceLink, v.PublicDate} + err = ec.FillSecurityNoticeSheet(sn) + if err != nil { + logs.Error(err) + } + ap := []interface{}{v.CveNum, v.AffectProduct, v.InfluenceComponent, v.AffectStatus} + err = ec.FillAffectProductSheet(ap) + if err != nil { + logs.Error(err) + } + for _, v := range pkg { + pk := []interface{}{v.PackName, v.PackUrl} + err := ec.FillPackageSheet(pk) + if err != nil { + logs.Error(err) + } + } +} + +func getPkgStr(pkg []models.Package) string { + pkgStr := "" + if len(pkg) == 0 { + return pkgStr + } + var ps []string + for _, v := range pkg { + if v.PackName != "" { + ps = append(ps, v.PackName) + } + } + return strings.Join(ps, ";\n") +} + +func (ec *CveExcel) FillCveSheetRow(row []interface{}) (err error) { + rows, err := ec.ExcelHandel.GetRows(ec.CveSheetName) + if err != nil { + return err + } + idx := len(rows) + 1 + axis := fmt.Sprintf("A%d", idx) + err = ec.ExcelHandel.SetSheetRow(ec.CveSheetName, axis, &row) + return err +} + +func (ec *CveExcel) FillSecurityNoticeSheet(row []interface{}) (err error) { + rows, err := ec.ExcelHandel.GetRows(ec.SecNoticeSheetName) + if err != nil { + return err + } + idx := len(rows) + 1 + axis := fmt.Sprintf("A%d", idx) + err = ec.ExcelHandel.SetSheetRow(ec.SecNoticeSheetName, axis, &row) + return err +} + +func (ec *CveExcel) FillAffectProductSheet(row []interface{}) (err error) { + rows, err := ec.ExcelHandel.GetRows(ec.InfProductSheetName) + if err != nil { + return err + } + idx := len(rows) + 1 + axis := fmt.Sprintf("A%d", idx) + err = ec.ExcelHandel.SetSheetRow(ec.InfProductSheetName, axis, &row) + return err +} + +func (ec *CveExcel) FillPackageSheet(row []interface{}) (err error) { + rows, err := ec.ExcelHandel.GetRows(ec.PackageUrlSheetName) + if err != nil { + return err + } + idx := len(rows) + 1 + axis := fmt.Sprintf("A%d", idx) + err = ec.ExcelHandel.SetSheetRow(ec.PackageUrlSheetName, axis, &row) + return err +} + +func (ec *CveExcel) Save(md int8) error { + if md == 0 { + return ec.ExcelHandel.SaveAs(ec.ExcelName) + } else { + return ec.ExcelHandel.Save() + } +} diff --git a/taskhandler/grabissue.go b/taskhandler/grabissue.go index bfb6154160667c3e8530a8077bfba1699b01bb68..42fe6e95e22ba1d909d32962cf17a76950bfa37e 100644 --- a/taskhandler/grabissue.go +++ b/taskhandler/grabissue.go @@ -1,23 +1,30 @@ package taskhandler import ( + "cvevulner/models" + "cvevulner/util" "encoding/json" "fmt" "github.com/astaxie/beego/logs" "io/ioutil" "net/http" + "strings" "sync" ) const ( - GiteOrgInfoUrl = `https://gitee.com/api/v5/orgs/%v?access_token=%v` //get gitee org info - GiteOrgReposUrl = `https://gitee.com/api/v5/orgs/%v/repos?access_token=%v&type=all&page=%v&per_page=%v`//get all repository - GiteRepoIssuesUrl = `https://gitee.com/api/v5/repos/{owner}/{repo}/issues` - perPage =50 + GiteOrgInfoUrl = `https://gitee.com/api/v5/orgs/%v?access_token=%v` //get gitee org info + GiteOrgReposUrl = `https://gitee.com/api/v5/orgs/%v/repos?access_token=%v&type=all&page=%v&per_page=%v` //get all repository + GiteRepoIssuesUrl = `https://gitee.com/api/v5/repos/%v/%v/issues?state=%v&sort=created&direction=desc&page=%v&per_page=%v` //get issue list + GiteRepoBranch = `https://gitee.com/api/v5/repos/%v/%v/branches?access_token=%v` + RepoInfoUrl = "https://api.openeuler.org/pkgmanagedebug/packages/packageInfo?table_name=mainline&pkg_name=%s" + perPage = 50 + IssueType = "CVE和安全问题" ) var wg sync.WaitGroup +//var mu sync.Mutex type OrgInfo struct { Id int32 `json:"id,omitempty"` Login string `json:"login,omitempty"` @@ -34,17 +41,34 @@ type OrgInfo struct { PrivateRepos int64 `json:"private_repos,omitempty"` } +// 获取所有分支 +type Branch struct { + Name string `json:"name,omitempty"` + Protected bool `json:"protected,omitempty"` + ProtectionUrl string `json:"protection_url,omitempty"` +} + +type PackageInfo struct { + Code string + Msg string + Data Info +} + +type Info struct { + Description string +} + //GrabIssueByOrg grab issue by org name -func GrabIssueByOrg(accToken, org string) { +func GrabIssueByOrg(accToken, org string) error { orgInfo, err := GetOrgInfo(accToken, org) if err != nil { logs.Error(err) - return + return err } reposNum := orgInfo.PublicRepos + orgInfo.PrivateRepos if reposNum <= 0 { - logs.Info(fmt.Sprintf("%v cantain %v repository,grab issue finish!",org,reposNum)) - return + logs.Info(fmt.Sprintf("%v cantain %v repository,grab issue finish!", org, reposNum)) + return err } pageSize := reposNum / int64(perPage) if reposNum%int64(perPage) > 0 { @@ -52,15 +76,93 @@ func GrabIssueByOrg(accToken, org string) { } var i int64 for i = 1; i <= pageSize; i++ { - wg.Add(1) - //load org repository list + go GetOrgRepos(accToken, org, i) } wg.Wait() + logs.Info("grab issue finish...") + return nil } //GrabIssueByRepo grab issue by repository -func GrabIssueByRepo(accToken, owner, repo, state string, page int) { +func GrabIssueByRepo(accToken, owner, repo, state string) { + page := 1 + product, err := getInfProduct(accToken, owner, repo) + if err != nil { + logs.Error(err) + } + desc := GetRepoDescription(repo) + for { + list, err := GetIssueList(accToken, owner, repo, state, page) + if err != nil { + logs.Error(err) + break + } + handleIssueList(list, product,desc) + if len(list) < perPage { + break + } + page++ + } +} +func getInfProduct(token string, owner string, repo string) (infPro string, err error) { + resp, err := http.Get(fmt.Sprintf(GiteRepoBranch, owner, repo, token)) + if err != nil { + return "", err + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return "", err + } + var branchList []Branch + err = json.Unmarshal(body, &branchList) + if err != nil { + return "", err + } + for _, v := range branchList { + if strings.HasSuffix(v.Name, "-LTS") { + infPro = v.Name + break + } + } + return +} + +func handleIssueList(list []models.HookIssue, product,desc string) { + if len(list) == 0 { + return + } + //var gil []models.GiteOriginIssue + for _, v := range list { + if v.IssueType == IssueType { + item := models.GiteOriginIssue{IssueId: v.Id, Url: v.HtmlUrl, + Number: v.Number, State: v.State, Title: v.Title, + IssueType: v.IssueType, SecurityHole: v.SecurityHole, + IssueCreateAt: v.CreateAt, IssueUpdateAt: v.UpdateAt, + IssueFinishAt: v.FinishedAt, IssueCreate: v.User.Login, + IssueAssignee: v.Assignee.Login, RepoPath: v.Repository.Path, + RepoUrl: v.Repository.Url, InfProduct: product,RepoDesc: desc} + vt := util.TrimString(v.Title) + if strings.HasPrefix(vt, "CVE") { + item.CveNumber = vt + } else if v.Body != "" { + //通过正则表达式去body中截取 稍后完善 + sm := util.RegexpCveNumber.FindAllStringSubmatch(v.Body, -1) + if len(sm) > 0 && len(sm[0]) > 0 { + item.CveNumber = util.TrimString(sm[0][1]) + } + } + //vb := util.TrimString(v.Body) + vb := strings.ReplaceAll(v.Body, ":", ":") + item.Body = vb + item.IssueExistTpl = models.IssueExistByNumber(v.Number) + err := item.InsertOrUpdate() + if err != nil { + logs.Error("insert or update issue fail:", err) + } + } + } } func GetOrgInfo(accToken, org string) (OrgInfo, error) { @@ -78,6 +180,66 @@ func GetOrgInfo(accToken, org string) (OrgInfo, error) { return oi, err } -func GetOrgRepos(accToken,org string) { +func GetOrgRepos(accToken, org string, page int64) { + wg.Add(1) + defer wg.Done() + resp, err := http.Get(fmt.Sprintf(GiteOrgReposUrl, org, accToken, page, perPage)) + if err != nil { + logs.Error(err) + return + } + defer resp.Body.Close() + var reps []models.HookRepository + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + logs.Error(err) + return + } + err = json.Unmarshal(body, &reps) + if err != nil { + logs.Error(err) + return + } + for _, v := range reps { + GrabIssueByRepo(accToken, org, v.Name, "all") + } +} + +func GetIssueList(accToken, owner, repo, state string, page int) (issueList []models.HookIssue, err error) { + resp, err := http.Get(fmt.Sprintf(GiteRepoIssuesUrl, owner, repo, state, page, perPage)) + if err != nil { + return issueList, err + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return issueList, err + } + err = json.Unmarshal(body, &issueList) + return +} +func GetRepoDescription(repo string) (desc string) { + if repo == "" { + return "" + } + url := fmt.Sprintf(RepoInfoUrl, repo) + resp, err := http.Get(url) + if err != nil { + return "" + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return "" + } + var pkg PackageInfo + err = json.Unmarshal(body, &pkg) + if err != nil { + return "" + } + if pkg.Code == "2001" { + return pkg.Data.Description + } + return "" } diff --git a/taskhandler/oricvecheck.go b/taskhandler/oricvecheck.go index 8fae63598e10fb7968303952061f72393281f4bd..d1196c9ad5ef6325b5f8068681b7819297d1d4a7 100644 --- a/taskhandler/oricvecheck.go +++ b/taskhandler/oricvecheck.go @@ -4,6 +4,7 @@ import ( "cvevulner/common" "cvevulner/models" "github.com/astaxie/beego/logs" + "strings" ) func CheckCveOriginData(prcnum int) (string, error) { @@ -29,13 +30,25 @@ func CheckCveOriginData(prcnum int) (string, error) { count = count + 1 logs.Info("当前正常解析第: ", count, "条数据,i:", i, ", cvenum: ", cveData.Ids) go func() { - gits, ok := models.QueryCveOpeneulerdata(cveData.PackName, cveData.Version) - if !ok { - models.UpdateOriginExist(common.GetCurTime(), cveData.PackName, cveData.Version, cveData.CveId, 0) - logs.Info("不存在,还原: ", cveData, ", gits: ", gits) - } else { - models.UpdateOriginExist(common.GetCurTime(), cveData.PackName, cveData.Version, cveData.CveId, 1) - logs.Info("加入到cve漏洞中: ", cveData, ", gits: ", gits) + packNameList := []string{} + if cveData.PackName != "" && len(cveData.PackName) > 0 { + packNameList = strings.Split(cveData.PackName, ",") + } + if len(packNameList) > 0 { + for _, pk := range packNameList { + pkList := strings.Split(pk, "==") + if len(pkList) == 2 { + gits, ok := models.QueryCveOpeneulerdata(pkList[0], pkList[1]) + if !ok { + models.UpdateOriginExist(common.GetCurTime(), cveData.PackName, cveData.Version, cveData.CveId, 0) + logs.Info("不存在,还原: ", cveData, ", gits: ", gits) + break + } else { + models.UpdateOriginExist(common.GetCurTime(), cveData.PackName, cveData.Version, cveData.CveId, 1) + logs.Info("加入到cve漏洞中: ", cveData, ", gits: ", gits) + } + } + } } ch <- i }() diff --git a/taskhandler/yaml.go b/taskhandler/yaml.go index e46b65d5b95d184dd8e3aa5fbf8dd29da3696ba5..608ca1d3de7d5fe1173de045c29a0823e2bf7ad0 100644 --- a/taskhandler/yaml.go +++ b/taskhandler/yaml.go @@ -8,6 +8,7 @@ import ( "errors" "github.com/astaxie/beego/logs" "strconv" + "strings" "sync" ) @@ -188,163 +189,195 @@ func ProcPackDetail(url string, values map[string]interface{}, tableValue models ok, _ := models.GetSingleYaml(&ge) if ok { logs.Info("第 ", i, "条数据, PackageName: ", ge.PackageName, "已经存在,不需要再次插入") + gpinfo, okinfo := models.QueryCveOpeneulerDetaildata(ge.PackageName, ge.Version) + if !okinfo && gpinfo.DetailId == 0 { + _, pierr := GetPackageInfo(url, tableValue, ge) + if pierr != nil { + logs.Error("获取包详情失败, url: ", url, ", PackageName: ", ge.PackageName, ",version: ", ge.Version, ",err: ", pierr) + return ge.PackageName, pierr + } + } return ge.PackageName, nil } - git_id, typex, err := models.CreateYaml(&ge) + git_id, typex, err := models.CreateYaml(&ge, tableValue) if git_id > 0 && err == nil { logs.Info("第 ", i, "条数据, PackageName: ", ge.PackageName, typex, "成功, git_id: ", git_id) } else { logs.Error("第 ", i, "条数据, PackageName: ", ge.PackageName, typex, "失败, err: ", err) + if strings.ContainsAny(string(err.Error()), "Duplicate entry") { + ok, _ := models.GetSingleYaml(&ge) + if ok { + logs.Info("第 ", i, "条数据, PackageName: ", ge.PackageName, "已经存在,不需要再次插入") + gpinfo, okinfo := models.QueryCveOpeneulerDetaildata(ge.PackageName, ge.Version) + if !okinfo && gpinfo.DetailId == 0 { + _, pierr := GetPackageInfo(url, tableValue, ge) + if pierr != nil { + logs.Error("获取包详情失败, url: ", url, ", PackageName: ", ge.PackageName, ",version: ", ge.Version, ",err: ", pierr) + return ge.PackageName, pierr + } + } + return ge.PackageName, nil + } + } return "", err } if typex == "insert" && git_id > 0 { - subcompUrl := url + "/packages/packageInfo" + "?table_name=" + tableValue.TableName + "&pkg_name=" + ge.PackageName - body, err:= util.HttpGetCom(subcompUrl) - var respBody map[string]interface{} - if err == nil && body != nil { - err =json.Unmarshal(body, &respBody) - if err != nil { - logs.Error(err) - return "", err - } - } else { - logs.Error( "http 请求失败, subcompUrl: ", subcompUrl) + _, pierr := GetPackageInfo(url, tableValue, ge) + if pierr != nil { + logs.Error("获取包详情失败, url: ", url, ", PackageName: ", ge.PackageName, ",version: ", ge.Version, ",err: ", pierr) + return ge.PackageName, pierr + } + } + return "", nil +} + +func GetPackageInfo(url string, tableValue models.GitPackageTable, ge models.GitOpenEuler) (string, error){ + subcompUrl := url + "/packages/packageInfo" + "?table_name=" + tableValue.TableName + "&pkg_name=" + ge.PackageName + body, err:= util.HttpGetCom(subcompUrl) + var respBody map[string]interface{} + if err == nil && body != nil { + err =json.Unmarshal(body, &respBody) + if err != nil { + logs.Error(err) return "", err } - logs.Info(respBody) - if respBody["code"].(string) == "2001"{ - if respBody["data"] == nil || respBody["data"] == "" { - logs.Error("获取包详情失败, subcompUrl: ", subcompUrl) + } else { + logs.Error( "http 请求失败, subcompUrl: ", subcompUrl) + return "", err + } + logs.Info(respBody) + if respBody["code"].(string) == "2001"{ + if respBody["data"] == nil || respBody["data"] == "" { + logs.Error("获取包详情失败, subcompUrl: ", subcompUrl) + return "", errors.New("数据错误") + } + var gp models.GitPackageInfo + GitOpenEulerInfoData(respBody["data"].(map[string]interface{}), &gp, ge) + detailid, typex, err := models.CreateYamlDetail(&gp, ge) + if detailid >0 && typex == "insert" && err == nil { + subdata := respBody["data"].(map[string]interface{}) + if subdata["subpack"] == nil { + return "", err + } + if subdata == nil || subdata["subpack"] == nil || len(subdata["subpack"].([]interface{})) == 0 { return "", errors.New("数据错误") } - var gp models.GitPackageInfo - GitOpenEulerInfoData(respBody["data"].(map[string]interface{}), &gp, ge) - detailid, typex, err := models.CreateYamlDetail(&gp, ge) - if detailid >0 && typex == "insert" && err == nil { - subdata := respBody["data"].(map[string]interface{}) - if subdata["subpack"] == nil { - return "", err + subpack := subdata["subpack"].([]interface{}) + for _, packValuex := range subpack { + logs.Info("yaml packValuex: ", packValuex) + if packValuex == nil || packValuex == "" || len(packValuex.(map[string]interface{})) == 0 { + continue } - if subdata == nil || subdata["subpack"] == nil || len(subdata["subpack"].([]interface{})) == 0 { - return "", errors.New("数据错误") + packValue := packValuex.(map[string]interface{}) + var gb models.GitSubPack + gb.DetailId = gp.DetailId + switch packValue["id"].(type) { + case string: + gb.Ids, _ = strconv.ParseInt(packValue["id"].(string), 10, 64) + case int: + gb.Ids = packValue["id"].(int64) + case int64: + gb.Ids = packValue["id"].(int64) + case float64: + gb.Ids = int64(packValue["id"].(float64)) + default: + gb.Ids = 0 } - subpack := subdata["subpack"].([]interface{}) - for _, packValuex := range subpack { - logs.Info("yaml packValuex: ", packValuex) - if packValuex == nil || packValuex == "" || len(packValuex.(map[string]interface{})) == 0 { - continue - } - packValue := packValuex.(map[string]interface{}) - var gb models.GitSubPack - gb.DetailId = gp.DetailId - switch packValue["id"].(type) { - case string: - gb.Ids, _ = strconv.ParseInt(packValue["id"].(string), 10, 64) - case int: - gb.Ids = packValue["id"].(int64) - case int64: - gb.Ids = packValue["id"].(int64) - case float64: - gb.Ids = int64(packValue["id"].(float64)) - default: - gb.Ids = 0 - } - if packValue["name"] == nil { - gb.SubPackName = "" - } else { - gb.SubPackName = packValue["name"].(string) - } - SubId, typex, err := models.CreateYamlSubPack(&gb) - if SubId > 0 && typex == "insert" && err == nil { - if packValue["provides"] != nil && len(packValue["provides"].([]interface{})) > 0{ - provides := packValue["provides"].([]interface{}) - for _, provValuex := range provides { - logs.Info("yaml provValuex: ", provValuex) - if provValuex == nil || provValuex == "" || len(provValuex.(map[string]interface{})) == 0 { - continue - } - provValue := provValuex.(map[string]interface{}) - var gs models.GitSubPackProvides - gs.SubId = SubId - switch provValue["id"].(type) { - case string: - gs.Ids, _ = strconv.ParseInt(provValue["id"].(string), 10, 64) - case int: - gs.Ids = provValue["id"].(int64) - case int64: - gs.Ids = provValue["id"].(int64) - case float64: - gs.Ids = int64(provValue["id"].(float64)) - default: - gs.Ids = 0 - } - if provValue["name"] == nil { - gs.ProvideName = "" - } else { - gs.ProvideName = provValue["name"].(string) - } + if packValue["name"] == nil { + gb.SubPackName = "" + } else { + gb.SubPackName = packValue["name"].(string) + } + SubId, typex, err := models.CreateYamlSubPack(&gb) + if SubId > 0 && typex == "insert" && err == nil { + if packValue["provides"] != nil && len(packValue["provides"].([]interface{})) > 0{ + provides := packValue["provides"].([]interface{}) + for _, provValuex := range provides { + logs.Info("yaml provValuex: ", provValuex) + if provValuex == nil || provValuex == "" || len(provValuex.(map[string]interface{})) == 0 { + continue + } + provValue := provValuex.(map[string]interface{}) + var gs models.GitSubPackProvides + gs.SubId = SubId + switch provValue["id"].(type) { + case string: + gs.Ids, _ = strconv.ParseInt(provValue["id"].(string), 10, 64) + case int: + gs.Ids = provValue["id"].(int64) + case int64: + gs.Ids = provValue["id"].(int64) + case float64: + gs.Ids = int64(provValue["id"].(float64)) + default: + gs.Ids = 0 + } + if provValue["name"] == nil { + gs.ProvideName = "" + } else { + gs.ProvideName = provValue["name"].(string) + } - gs.Requiredby = "" - ProvideId, typexx, err := models.CreateYamlSubPackProvides(&gs) - if ProvideId > 0 && typexx == "insert" && err == nil { - if provValue["requiredby"] != nil && len(provValue["requiredby"].([]interface{})) > 0{ - requiredby := provValue["requiredby"].([]interface{}) - for _, reqValue := range requiredby { - if reqValue != nil && reqValue.(string) != "" { - var gr models.GitSubPackRequiredby - gr.ProvideId = gs.ProvideId - gr.Requiredby = reqValue.(string) - Id, typexy, err := models.CreateYamlSubPackRequiredb(&gr) - logs.Info("CreateYamlSubPackRequiredb", Id, typexy, err) - } + gs.Requiredby = "" + ProvideId, typexx, err := models.CreateYamlSubPackProvides(&gs) + if ProvideId > 0 && typexx == "insert" && err == nil { + if provValue["requiredby"] != nil && len(provValue["requiredby"].([]interface{})) > 0{ + requiredby := provValue["requiredby"].([]interface{}) + for _, reqValue := range requiredby { + if reqValue != nil && reqValue.(string) != "" { + var gr models.GitSubPackRequiredby + gr.ProvideId = gs.ProvideId + gr.Requiredby = reqValue.(string) + Id, typexy, err := models.CreateYamlSubPackRequiredb(&gr) + logs.Info("CreateYamlSubPackRequiredb", Id, typexy, err) } } } } } - if packValue["requires"] != nil && len(packValue["requires"].([]interface{})) > 0{ - requires := packValue["requires"].([]interface{}) - for _, reqValuexx := range requires { - logs.Info("reqValuexx: ", reqValuexx) - if reqValuexx == nil || reqValuexx == "" || len(reqValuexx.(map[string]interface{})) == 0 { - continue - } - reqValuex := reqValuexx.(map[string]interface{}) - reqStr := "" - if reqValuex["providedby"] != nil && len(reqValuex["providedby"].([]interface{})) > 0{ - providedby := reqValuex["providedby"].([]interface{}) - for _, reqValue := range providedby { - if reqValue != nil && reqValue.(string) != "" { - reqStr = reqStr + reqValue.(string) + "," - } + } + if packValue["requires"] != nil && len(packValue["requires"].([]interface{})) > 0{ + requires := packValue["requires"].([]interface{}) + for _, reqValuexx := range requires { + logs.Info("reqValuexx: ", reqValuexx) + if reqValuexx == nil || reqValuexx == "" || len(reqValuexx.(map[string]interface{})) == 0 { + continue + } + reqValuex := reqValuexx.(map[string]interface{}) + reqStr := "" + if reqValuex["providedby"] != nil && len(reqValuex["providedby"].([]interface{})) > 0{ + providedby := reqValuex["providedby"].([]interface{}) + for _, reqValue := range providedby { + if reqValue != nil && reqValue.(string) != "" { + reqStr = reqStr + reqValue.(string) + "," } } - if reqStr != "" { - reqStr = reqStr[:len(reqStr) -1] - } - var gs models.GitSubPackRequire - gs.SubId = SubId - switch reqValuex["id"].(type) { - case string: - gs.Ids, _ = strconv.ParseInt(reqValuex["id"].(string), 10, 64) - case int: - gs.Ids = reqValuex["id"].(int64) - case int64: - gs.Ids = reqValuex["id"].(int64) - case float64: - gs.Ids = int64(reqValuex["id"].(float64)) - default: - gs.Ids = 0 - } - if reqValuex["name"] == nil { - gs.RequireName = "" - } else { - gs.RequireName = reqValuex["name"].(string) - } - gs.Providedby = reqStr - RequireId, typexx, err := models.CreateYamlSubPackRequires(&gs) - logs.Info("CreateYamlSubPackRequires", RequireId, typexx, err) } + if reqStr != "" { + reqStr = reqStr[:len(reqStr) -1] + } + var gs models.GitSubPackRequire + gs.SubId = SubId + switch reqValuex["id"].(type) { + case string: + gs.Ids, _ = strconv.ParseInt(reqValuex["id"].(string), 10, 64) + case int: + gs.Ids = reqValuex["id"].(int64) + case int64: + gs.Ids = reqValuex["id"].(int64) + case float64: + gs.Ids = int64(reqValuex["id"].(float64)) + default: + gs.Ids = 0 + } + if reqValuex["name"] == nil { + gs.RequireName = "" + } else { + gs.RequireName = reqValuex["name"].(string) + } + gs.Providedby = reqStr + RequireId, typexx, err := models.CreateYamlSubPackRequires(&gs) + logs.Info("CreateYamlSubPackRequires", RequireId, typexx, err) } } } diff --git a/tests/createrepo.go b/tests/createrepo.go new file mode 100644 index 0000000000000000000000000000000000000000..01ff0d44242060083e4fe12e43958b80a34c9d37 --- /dev/null +++ b/tests/createrepo.go @@ -0,0 +1,97 @@ +package test + +import ( + "cvevulner/common" + "cvevulner/models" + "cvevulner/util" + "errors" + "fmt" + "github.com/astaxie/beego/logs" + "github.com/astaxie/beego/orm" + "os" +) + +func QueryOriginCveExcelData() ([]models.OriginExcel, int64, error) { + o := orm.NewOrm() + var coe []models.OriginExcel + num, err := o.Raw("select cve_id,cve_num,cve_url, cve_version, pack_name," + + "score_type,nvd_score,cve_level,cve_desc,repair_time,vector_value,attack_vector,access_vector,attack_complexity,"+ + "access_complexity,privilege_required,user_interaction,scope,confidentiality,integrity,availability,authentication," + + "cve_status,create_time from cve_origin_excel GROUP BY pack_name").QueryRows(&coe) + if err == nil && num > 0 { + logs.Info("cve_origin_excel 查询结果: ", num) + } else { + logs.Info("当前无新增或者更新的cve, cur_time:", common.GetCurTime(), "err: ", err) + } + return coe, num, err +} + +func UpdateExcelDataPkName(originPackName, packName string) (id int64) { + o := orm.NewOrm() + _ = o.Raw("UPDATE cve_origin_excel SET pack_name = ?" + + " WHERE pack_name = ?", packName, originPackName).QueryRow() + return +} + +func CreateRepo() { + coe, num, err := QueryOriginCveExcelData() + if err == nil && num > 0 { + for _, qc := range coe { + PostRepo(qc.PackName) + } + } +} + +func PostRepo(packName string) error{ + url := "https://gitee.com/api/v5/user/repos" + accessToken := os.Getenv("GITEE_TOKEN") + requestBody := fmt.Sprintf(`{ + "access_token": "%s", + "name": "%s", + "has_issues": "true", + "has_wiki": "true", + "can_comment": "true", + "auto_init": "true", + "path": "%s", + "private": "false" + }`, accessToken, packName, packName) + logs.Info("isssue_body: ", requestBody) + resp, err := util.HttpPost(url, requestBody) + if err != nil { + logs.Error("创建",packName,"失败, err: ", err) + return err + } + if _, ok := resp["id"]; !ok { + logs.Error("创建issue 失败, err: ", ok, "url: ", url) + return errors.New("创建仓库失败") + } + errb := CreateBrand(packName) + logs.Info(errb) + return nil +} + +func CreateBrand(packName string) error{ + url := "https://gitee.com/api/v5/repos/zhangjianjun_code/" + packName + "/branches" + accessToken := os.Getenv("GITEE_TOKEN") + requestBody := fmt.Sprintf(`{ + "access_token": "%s", + "refs": "master", + "branch_name": "openEuler-20.03-LTS" + }`, accessToken) + logs.Info("isssue_body: ", requestBody) + resp, err := util.HttpPost(url, requestBody) + if err != nil { + logs.Error("创建分支:openEuler-20.03-LTS",packName,"失败, err: ", err) + return err + } + if _, ok := resp["id"]; !ok { + logs.Error("创建分支:openEuler-20.03-LTS 失败, err: ", ok, "url: ", url) + return errors.New("创建分支失败") + } + + return nil +} + +func Init() { + CreateRepo() +} \ No newline at end of file diff --git a/tests/createrepo_test.go b/tests/createrepo_test.go new file mode 100644 index 0000000000000000000000000000000000000000..01ff0d44242060083e4fe12e43958b80a34c9d37 --- /dev/null +++ b/tests/createrepo_test.go @@ -0,0 +1,97 @@ +package test + +import ( + "cvevulner/common" + "cvevulner/models" + "cvevulner/util" + "errors" + "fmt" + "github.com/astaxie/beego/logs" + "github.com/astaxie/beego/orm" + "os" +) + +func QueryOriginCveExcelData() ([]models.OriginExcel, int64, error) { + o := orm.NewOrm() + var coe []models.OriginExcel + num, err := o.Raw("select cve_id,cve_num,cve_url, cve_version, pack_name," + + "score_type,nvd_score,cve_level,cve_desc,repair_time,vector_value,attack_vector,access_vector,attack_complexity,"+ + "access_complexity,privilege_required,user_interaction,scope,confidentiality,integrity,availability,authentication," + + "cve_status,create_time from cve_origin_excel GROUP BY pack_name").QueryRows(&coe) + if err == nil && num > 0 { + logs.Info("cve_origin_excel 查询结果: ", num) + } else { + logs.Info("当前无新增或者更新的cve, cur_time:", common.GetCurTime(), "err: ", err) + } + return coe, num, err +} + +func UpdateExcelDataPkName(originPackName, packName string) (id int64) { + o := orm.NewOrm() + _ = o.Raw("UPDATE cve_origin_excel SET pack_name = ?" + + " WHERE pack_name = ?", packName, originPackName).QueryRow() + return +} + +func CreateRepo() { + coe, num, err := QueryOriginCveExcelData() + if err == nil && num > 0 { + for _, qc := range coe { + PostRepo(qc.PackName) + } + } +} + +func PostRepo(packName string) error{ + url := "https://gitee.com/api/v5/user/repos" + accessToken := os.Getenv("GITEE_TOKEN") + requestBody := fmt.Sprintf(`{ + "access_token": "%s", + "name": "%s", + "has_issues": "true", + "has_wiki": "true", + "can_comment": "true", + "auto_init": "true", + "path": "%s", + "private": "false" + }`, accessToken, packName, packName) + logs.Info("isssue_body: ", requestBody) + resp, err := util.HttpPost(url, requestBody) + if err != nil { + logs.Error("创建",packName,"失败, err: ", err) + return err + } + if _, ok := resp["id"]; !ok { + logs.Error("创建issue 失败, err: ", ok, "url: ", url) + return errors.New("创建仓库失败") + } + errb := CreateBrand(packName) + logs.Info(errb) + return nil +} + +func CreateBrand(packName string) error{ + url := "https://gitee.com/api/v5/repos/zhangjianjun_code/" + packName + "/branches" + accessToken := os.Getenv("GITEE_TOKEN") + requestBody := fmt.Sprintf(`{ + "access_token": "%s", + "refs": "master", + "branch_name": "openEuler-20.03-LTS" + }`, accessToken) + logs.Info("isssue_body: ", requestBody) + resp, err := util.HttpPost(url, requestBody) + if err != nil { + logs.Error("创建分支:openEuler-20.03-LTS",packName,"失败, err: ", err) + return err + } + if _, ok := resp["id"]; !ok { + logs.Error("创建分支:openEuler-20.03-LTS 失败, err: ", ok, "url: ", url) + return errors.New("创建分支失败") + } + + return nil +} + +func Init() { + CreateRepo() +} \ No newline at end of file diff --git a/tests/excel_test.go b/tests/excel_test.go new file mode 100644 index 0000000000000000000000000000000000000000..87b3acf08d6fb5b6b3f505b7dbfbe25307819fea --- /dev/null +++ b/tests/excel_test.go @@ -0,0 +1,15 @@ +package test + +import ( + "cvevulner/taskhandler" + "testing" +) + +func TestGenerateCveExcel(t *testing.T) { + err := taskhandler.GenerateCveExcel("test.xlsx", "op-2020-10-", 1002, false) + if err != nil { + t.Error(err) + } +} + + diff --git a/tests/grabissue_test.go b/tests/grabissue_test.go new file mode 100644 index 0000000000000000000000000000000000000000..33ce14270ba5b0e2ecdeacfa135bc04ea917e9ec --- /dev/null +++ b/tests/grabissue_test.go @@ -0,0 +1,11 @@ +package test + +import ( + "cvevulner/taskhandler" + "testing" +) + +func TestGrabIssueByOrg(t *testing.T) { + taskhandler.GrabIssueByOrg("8457c66db66955376519059b97e33dd1","src-openeuler") +} + diff --git a/tests/parsepayload_test.go b/tests/parsepayload_test.go new file mode 100644 index 0000000000000000000000000000000000000000..984cc44bc7e150e5237dd1a3e374c8406d5d29cc --- /dev/null +++ b/tests/parsepayload_test.go @@ -0,0 +1,22 @@ +package test + +import ( + "cvevulner/util" + "fmt" + "testing" +) + +func TestExtractCommentAnalysisAllValue(t *testing.T) { + tStr := `笑笑笑笑笑笑笑笑笑的方式是否士大夫十分 + 受影响版本排查(受影响/不受影响): + 1.openEuler-20-LTS:受影响 + 2.openEuler-22-LTS:受影响 + 3.openEuler-23-LTS:不受影响 + 4.openEuler-23-LTS: + 影响性分析说明:影响firefox的张昌使用 + openEuler评分: + BaseScore: 6.5 MEDIUM + Vector: CVSS:3.0/AV:N/AC:M/Au:N/UI:R/S:U/C:N/I:N/A:H` + value := util.ExtractCommentAnalysisAllValue(tStr) + t.Log(fmt.Sprintf("%#v", value)) +} diff --git a/util/parsepayload.go b/util/parsepayload.go index 174789aac273e95406f669cef048383366565924..fa8e6c2a3be3077253649c49f6cf2f00f639ae83 100644 --- a/util/parsepayload.go +++ b/util/parsepayload.go @@ -3,35 +3,99 @@ package util import ( "fmt" "regexp" + "sort" "strings" "sync" ) +const ( + KwAnalysisDesc = "影响性分析说明:" + KwOpenEulerScore = "openEuler评分:" + KwEffectVersion = "受影响版本排查(受影响/不受影响):" +) + +var ( + LAC = "LAC" //漏洞组件标签 + LN = "LN" //漏洞编号标签 + LAV = "LAV" //漏洞版本标签 + CVS = "CVS" //cvss 3.0分值标签 + CVV = "CVV" //cvss 3.1向量标签 + LD = "LD" //漏洞描述标签 + IAD = "IAD" //影响分析说明标签 + PA = "PA" //原理分析标签 + OES = "OES" //openEuler评分标签 + OEV = "OEV" //openEuler向量标签 + IV = "IV" //影响的版本标签 + CPMM = "CPMM" //规避方案措施 + IW = "IW" //影响的包 + CommentKeys = []string{KwAnalysisDesc, KwOpenEulerScore, KwEffectVersion} +) + var ( - LAC = "LAC" //漏洞组件标签 - LN = "LN" //漏洞编号标签 - LAV = "LAV" //漏洞版本标签 - CVS = "CVS" //cvss 3.0分值标签 - CVV = "CVV" //cvss 3.1向量标签 - LD = "LD" //漏洞描述标签 - IAD = "IAD" //影响分析说明标签 - PA = "PA" //原理分析标签 - OES = "OES" //openEuler评分标签 - OEV = "OEV" //openEuler向量标签 - IV = "IV" //影响的版本标签 - CPMM = "CPMM" //规避方案措施 - IW = "IW" //影响的包 + CvsScoreV3 = "v3" + CvsScoreV2 = "v2" + RegexpCveNumber = regexp.MustCompile(`漏洞编号[::](?s:(.*?))漏洞归属组件[::]`) + RegexpCveNumberLink = regexp.MustCompile(`\[(.*?)\]\((.*?)\)`) + RegexpCveComponents = regexp.MustCompile(`漏洞归属组件[::](?s:(.*?))漏洞归属[的]版本[::]`) + RegexpCveVersion = regexp.MustCompile(`漏洞归属[的]版本[::](?s:(.*?))CVSS V[23].0分值[::]`) + RegexpCveScore = regexp.MustCompile(`CVSS V[23].0分值[::](?s:(.*?))漏洞[简描]述[::]`) + //RegexpCveScore = regexp.MustCompile(`CVSS V3.0分值[::](?s:(.*?))Vector[::]`) + //RegexpCveVector = regexp.MustCompile(`Vector[::](?s:(.*?))(漏洞简述[::])`) + RegexpCveBriefDesc = regexp.MustCompile(`漏洞[简描]述[::](?s:(.*?))影响性分析说明[::]`) + RegexpCveInfluencesDesc = regexp.MustCompile(`影响性分析说明[::](?s:(.*?))原理分析[::]`) + RegexpCveInfluencesDescNew = regexp.MustCompile(`影响性分析说明[::](?s:(.*?))openEuler评分[::]`) + RegexpCvePrincipleDesc = regexp.MustCompile(`原理分析[::](?s:(.*?))openEuler评分[::]`) + RegexpCveOpScore = regexp.MustCompile(`openEuler评分[::](?s:(.*?))受影响版本[::]`) + RegexpCveOpScoreNew = regexp.MustCompile(`openEuler评分[::](?s:(.*?))受影响版本排查(受影响/不受影响)[::]`) + //RegexpCveOpScore1 = regexp.MustCompile(`openEuler评分[::](?s:(.*?))受影响版本[::]`) + //RegexpCveOpVector = regexp.MustCompile(`openEulerVector[::](?s:(.*?))受影响版本[::]`) + RegexpCveInfluencesVersion = regexp.MustCompile(`受影响版本[::](?s:(.*?))规避方案或消减措施[::]`) + RegexpCveInfluencesVersionNew = regexp.MustCompile(`受影响版本排查(受影响/不受影响)[::](?s:(.*?))$`) + RegexpCvePlannedMeasures = regexp.MustCompile(`规避方案或消减措施[::](?s:(.*?))受影响的包[::]`) + RegexpCvePlannedMeasures1 = regexp.MustCompile(`规避方案或消减措施[::](?s:(.*?))$`) + RegexpCveInfluencesPkg = regexp.MustCompile(`受影响的包[::](?s:(.*?))$`) + RegexpDigital = regexp.MustCompile(`(\d){1,}(\.\d+)?`) + //`/AV:[NLAP]/AC:[HL]/PR:[NLH]/UI:[NR]/S:[UC]/C:[NLH]/I:[HNL]/A:[LNH]` + RegexpVector = regexp.MustCompile(`AV:[NLAP](?s:(.*?))/A:[LNH]`) + RegexpVectorV2 = regexp.MustCompile(`AV:[LAN](?s:(.*))/Au:[MSN](?s:(.*))/A:[NPC]`) + RegexpScoreTypeV2 = regexp.MustCompile(`(?mi)^CVSS v2.0分值\s*`) + RegexpScoreTypeV3 = regexp.MustCompile(`(?mi)^CVSS v3.0分值\s*`) + RegexpIsNewTpl = regexp.MustCompile(`(?mi)^原理分析[::]\s*`) + RegexpIsNewTpl2 = regexp.MustCompile(`(?mi)^规避方案或消减措施[::]\s*`) + regexpEffectVersion = regexp.MustCompile(`(?mi)[\d]{1,}\.(.*?)[::]受影响`) + regexpNoEffectVersion = regexp.MustCompile(`(?mi)[\d]{1,}\.(.*?)[::]不受影响`) ) -var VectorMap map[string]map[string]string -var mutex sync.Mutex +var ( + VectorMapV2 map[string]map[string]string + VectorMap map[string]map[string]string + mutex sync.Mutex +) + +type CommentAnalysis struct { + KeyName string + KeyIdx int + KeyValue string +} +type CaSlice []CommentAnalysis +func (a CaSlice) Len() int { + return len(a) +} +func (a CaSlice) Swap(i, j int){ + a[i], a[j] = a[j], a[i] +} +func (a CaSlice) Less(i, j int) bool { + return a[j].KeyIdx > a[i].KeyIdx +} func init() { - //pattenStr := `/AV:[NL]/AC:[HL]/PR:[NH]/UI:N/S:U/C:[LH]/I:[HN]/A:[LNH]` + //pattenStr := `/AV:[NLAP]/AC:[HL]/PR:[NLH]/UI:[NR]/S:[UC]/C:[NLH]/I:[HNL]/A:[LNH]` VectorMap = make(map[string]map[string]string) mAv := make(map[string]string) mAv["N"] = "Network" mAv["L"] = "Local" + mAv["A"] = "Adjacent" + mAv["P"] = "Physical" VectorMap["AV"] = mAv mAc := make(map[string]string) mAc["H"] = "High" @@ -40,26 +104,95 @@ func init() { mPr := make(map[string]string) mPr["H"] = "High" mPr["N"] = "None" + mPr["L"] = "Low" VectorMap["PR"] = mPr mUi := make(map[string]string) mUi["N"] = "None" + mUi["R"] = "Require" VectorMap["UI"] = mUi mS := make(map[string]string) mS["U"] = "Unchanged" + mS["C"] = "Changed" VectorMap["S"] = mS mC := make(map[string]string) mC["H"] = "High" mC["L"] = "Low" + mC["N"] = "None" VectorMap["C"] = mC mI := make(map[string]string) mI["H"] = "High" mI["N"] = "None" + mI["L"] = "Low" VectorMap["I"] = mC mA := make(map[string]string) mA["H"] = "High" mA["L"] = "Low" - mI["N"] = "None" + mA["N"] = "None" VectorMap["A"] = mA + VectorMapV2 = make(map[string]map[string]string) + //AV:L/AC:L/Au:N/C:C/I:C/A:C + mAv2 := make(map[string]string) + mAv2["L"] = "Local" + mAv2["A"] = "AdjacentNetwork" + mAv2["N"] = "Network" + VectorMapV2["AV"] = mAv2 + mAc2 := make(map[string]string) + mAc2["H"] = "High" + mAc2["M"] = "Medium" + mAc2["L"] = "Low" + VectorMapV2["AC"] = mAc2 + mAu := make(map[string]string) + mAu["M"] = "Multiple" + mAu["S"] = "Single" + mAu["N"] = "None" + VectorMapV2["Au"] = mAu + mCi := make(map[string]string) + mCi["N"] = "None" + mCi["P"] = "Partial" + mCi["C"] = "Complete" + VectorMapV2["C"] = mCi + mII := make(map[string]string) + mII["N"] = "None" + mII["P"] = "Partial" + mII["C"] = "Complete" + VectorMapV2["I"] = mII + mAi := make(map[string]string) + mAi["N"] = "None" + mAi["P"] = "Partial" + mAi["C"] = "Complete" + VectorMapV2["A"] = mAi +} + +//GenerateCommentAnalysis Generate analytical entities based on comments. +func GenerateCommentAnalysis(content string) (ca CaSlice) { + if content == "" { + return + } + for _, v := range CommentKeys { + if strings.Contains(content, v) { + cm := CommentAnalysis{KeyName: v} + index := strings.Index(content, v) + cm.KeyIdx = index + ca = append(ca, cm) + } + } + //sort ca item by key index + if len(ca) > 0 { + //sort by index + sort.Sort(ca) + //extract keyword value + for k, _ := range ca { + if k == len(ca)-1 { + start := ca[k].KeyIdx + len(ca[k].KeyName) + ca[k].KeyValue = content[start:] + } else { + start := ca[k].KeyIdx + len(ca[k].KeyName) + end := ca[k+1].KeyIdx + ca[k].KeyValue = content[start:end] + } + } + } + return ca } //ParseCommentContent extract comment content based on tags. @@ -74,22 +207,38 @@ func ParseCommentContent(content string, label string) (res string, ok bool) { } func ParseCommentVector(content string) string { - pattenStr := `/AV:[NL]/AC:[HL]/PR:[NH]/UI:N/S:U/C:[LH]/I:[HN]/A:[LNH]` - ret := regexp.MustCompile(pattenStr) - sm := ret.Find([]byte(content)) + sm := RegexpVector.Find([]byte(content)) return string(sm) +} + +func ExtractVector(body, scoreType string) string { + if body == "" { + return body + } + if scoreType == CvsScoreV2 { + rvs := RegexpVectorV2.Find([]byte(body)) + if rv := string(rvs); rv != "" { + return rv + } + } else { + rvs := RegexpVector.Find([]byte(body)) + if rv := string(rvs); rv != "" { + return rv + } + } + return "" } -func ReadVmValue(kstr string) (value string) { - if kstr == "" { +func ReadVmValue(kStr string) (value string) { + if kStr == "" { return "" } - if !strings.Contains(kstr, ":") { + if !strings.Contains(kStr, ":") { return "" } - kstr = TrimString(kstr) - sKs := strings.Split(kstr, ":") + kStr = TrimString(kStr) + sKs := strings.Split(kStr, ":") if len(sKs) != 2 { return "" } @@ -101,6 +250,26 @@ func ReadVmValue(kstr string) (value string) { return } +func ReadVmValueV2(kStr string) (value string) { + if kStr == "" { + return "" + } + if !strings.Contains(kStr, ":") { + return "" + } + kStr = TrimString(kStr) + sKs := strings.Split(kStr, ":") + if len(sKs) != 2 { + return "" + } + mutex.Lock() + defer mutex.Unlock() + if _, ok := VectorMapV2[sKs[0]]; ok { + value = VectorMapV2[sKs[0]][sKs[1]] + } + return +} + func VctToMap(vct string) (vctMap map[string]string, ok bool) { if vct == "" { return nil, false @@ -153,14 +322,86 @@ func ParseCommentWithAllLabel(content string) map[string]string { if ok { res["solution"] = s } - s,ok =ParseCommentContent(content,IW) + s, ok = ParseCommentContent(content, IW) if ok { - res["issue_package"]=s + res["issue_package"] = s } return res } +func ExtractCommentAnalysisAllValue(content string) map[string]string { + res := make(map[string]string, 0) + ca := GenerateCommentAnalysis(content) + if len(ca) > 0 { + value ,ext:= ExtractCommentValue(ca, KwAnalysisDesc) + if ext { + res["cve_analysis"] = TrimStringNR(value) + } + value,ext = ExtractCommentValue(ca, KwEffectVersion) + if ext { + value = ExtractCommentEffectVersion(value) + //if value != "" { + res["affected_version"] = value + //} + } + value ,ext= ExtractCommentValue(ca, KwOpenEulerScore) + if ext { + score, vector := ExtractCommentOpenEulerScore(value) + //if score != ""{ + res["openeuler_score"] = score + //} + //if vector != "" { + res["openeuler_vector"] = vector + //} + } + } + return res +} + +func ExtractCommentEffectVersion(str string) string { + var res []string + match := regexpEffectVersion.FindAllStringSubmatch(str, -1) + match2 := regexpNoEffectVersion.FindAllStringSubmatch(str, -1) + if len(match) > 0 { + for _, v := range match { + if len(v) > 1 { + res = append(res, TrimString(v[1])+":受影响") + } + } + } + if len(match2) >0 { + for _, v := range match2 { + if len(v) > 1 { + res = append(res, TrimString(v[1])+":不受影响") + } + } + } + if len(res) > 0 { + return strings.Join(res, ",") + } + return "" +} + +func ExtractCommentValue(ca CaSlice, keyWord string) (string,bool) { + for _, v := range ca { + if v.KeyName == keyWord { + return v.KeyValue,true + } + } + return "",false +} + +func ExtractCommentOpenEulerScore(str string) (score, vector string){ + str = TrimString(str) + score = ExtractDigital(str) + vector = ExtractVector(str,CvsScoreV3) + if vector == ""{ + vector = ExtractVector(str,CvsScoreV2) + } + return +} + func genCommentRegexpStr(label string) string { return fmt.Sprintf(`\[%s\](?s:(.*?))\[/%s\]`, label, label) } @@ -169,5 +410,35 @@ func TrimString(str string) string { str = strings.Replace(str, " ", "", -1) str = strings.Replace(str, "\n", "", -1) str = strings.Replace(str, "\r", "", -1) + str = strings.Replace(str, "\t", "", -1) return str } + +func TrimStringNR(str string) string { + str = strings.Replace(str, "\n", "", -1) + str = strings.Replace(str, "\r", "", -1) + str = strings.Replace(str, "\t", "", -1) + return str +} + +func ExtractDigital(body string) string { + if body == "" { + return body + } + sds := RegexpDigital.FindAllStringSubmatch(body, -1) + if len(sds) > 0 { + return sds[0][0] + } + return "" +} + +func GetCveNumber(ov string) string { + if v := RegexpCveNumberLink.Find([]byte(ov)); len(v) > 0 { + sv := string(v) + start := strings.Index(sv, "[") + 1 + end := strings.Index(sv, "]") + return sv[start:end] + } else { + return ov + } +}