整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          這五款牛逼的 IDEA 插件,堪稱代碼質(zhì)量檢查利器

          著業(yè)務(wù)的發(fā)展,系統(tǒng)會(huì)越來越龐大,原本簡(jiǎn)單穩(wěn)定的功能,可能在不斷迭代后復(fù)雜度上升,潛在的風(fēng)險(xiǎn)也隨之暴露,導(dǎo)致最終服務(wù)不穩(wěn)定,造成業(yè)務(wù)價(jià)值的損失。而為了減少這種情況,其中一種比較好的方式就是提高代碼質(zhì)量,比如通過代碼審查,從而降低錯(cuò)誤風(fēng)險(xiǎn),但是,代碼審查難度大,代碼缺陷、漏洞不易發(fā)現(xiàn),且審查工作隨著代碼量增加而增加,審查效率低。

          工欲善其事,必先利其器,因此,這篇文章給大家介紹幾種檢查代碼質(zhì)量的利器,Alibaba Java Coding Guidelines、CheckStyle、PMD、FindBugs、SonarLint,讓你在關(guān)注代碼質(zhì)量的同時(shí),減少 code review 的工作量,提高 code review 的效率,并通過代碼質(zhì)量分析去反向提升我們的代碼編寫能力

          一、Alibaba Java Coding Guidelines

          1、整體介紹:

          Alibaba Java Coding Guidelines 專注于Java代碼規(guī)范,目的是讓開發(fā)者更加方便、快速規(guī)范代碼格式。該插件在掃描代碼后,將不符合規(guī)約的代碼按 Blocker、Critical、Major 三個(gè)等級(jí)顯示出來,并且大部分可以自動(dòng)修復(fù),它還基于 Inspection 機(jī)制提供了實(shí)時(shí)檢測(cè)功能,編寫代碼的同時(shí)也能快速發(fā)現(xiàn)問題所在。

          阿里巴巴規(guī)約掃描包括:

          • OOP規(guī)約
          • 并發(fā)處理
          • 控制語(yǔ)句
          • 命名規(guī)約
          • 常量定義
          • 注釋規(guī)范

          2、安裝步驟:

          File > Settings > Plugins > Marketplace 搜索 “Alibaba Java Coding Guidelines”,按照提示進(jìn)行安裝,然后重啟即可。

          3、使用說明:

          3.1、運(yùn)行方式:

          (1)可以Tools > 阿里編碼規(guī)約 > 編碼規(guī)約掃描

          (2)在編輯界面或者項(xiàng)目區(qū)域點(diǎn)擊右鍵,在右鍵菜單中選擇“編碼規(guī)約掃描”即可:

          3.2、菜單功能:

          • 編碼規(guī)約掃描:開始掃描代碼
          • 打開/關(guān)閉實(shí)時(shí)檢測(cè)功能:實(shí)時(shí)檢測(cè)代碼,一般機(jī)器性能比較好的話可以開啟這項(xiàng)功能
          • 切換語(yǔ)言至英文:中英文切換

          3.3、運(yùn)行結(jié)果:

          掃描完成后顯示結(jié)果如下,我們可以看到掃描結(jié)果主要分為 Blocker(阻擋者)、Critical(嚴(yán)重問題)、Major(主要的)三個(gè)大類,它們表示的是問題的嚴(yán)重程度,嚴(yán)重程度由高到低為:Blocker > Critical > Major,至于每一類中都會(huì)包含什么樣的問題,圖中的內(nèi)容已經(jīng)說明了一切。

          選中其中的一個(gè)問題項(xiàng)目,會(huì)出現(xiàn)如下內(nèi)容(如果當(dāng)前鼠標(biāo)點(diǎn)擊的是最終項(xiàng),右邊區(qū)域顯示的是其它的內(nèi)容,后面會(huì)再講到):

          (1)指定區(qū)域搜索同一類問題:

          當(dāng)點(diǎn)擊③處的按鈕時(shí),會(huì)彈出如下按鈕:

          這里選擇掃描區(qū)域,來掃描鼠標(biāo)選中的同類問題。如果按照默認(rèn)選擇,那么運(yùn)行后的結(jié)果就如下圖所示:

          這里我們可以看到,顯示了整個(gè)Project中的所有該類的問題。

          (2)預(yù)覽具體的不規(guī)范代碼:

          如果點(diǎn)擊的是最終的問題點(diǎn)或者問題所在的類文件,那顯示的就是如下界面,預(yù)覽該處不規(guī)范的代碼。

          3.4、工具欄功能介紹:

          • Rerun Inspection: 重新運(yùn)行一次掃描
          • Close:關(guān)閉真?zhèn)€AJCG面板
          • Expand All:展開結(jié)果的樹狀結(jié)構(gòu),整個(gè)結(jié)果是樹狀結(jié)構(gòu)的。
          • Collapse All:收起結(jié)果的樹狀結(jié)構(gòu)
          • Go Pre Problem:選擇上一個(gè)問題
          • Go Next Problem:選擇下一個(gè)問題
          • Help:幫助
          • Group by Serverity:(不知道如何描述)
          • Group by derectory:按目錄分組/按類名分組間切換
          • Filter resoled items:過濾掉已經(jīng)解決的項(xiàng)
          • Autoscroll to Source:自動(dòng)滾動(dòng)到源碼
          • Export:導(dǎo)出,可以導(dǎo)出為XML和HTML兩種格式
          • Edit Settings:編輯設(shè)置

          二、CheckStyle:

          1、整體介紹:

          CheckStyle 側(cè)重檢查編碼格式和代碼風(fēng)格規(guī)范,如命名規(guī)范、Javadoc注釋規(guī)范、空格規(guī)范、size度量(如過長(zhǎng)的方法)、重復(fù)代碼、多余Imports等,從而有效約束開發(fā)人員更好地遵循代碼編寫規(guī)范。Checkstyle主要是文法層面的代碼編寫規(guī)范的分析,對(duì)bug幾乎沒什么發(fā)現(xiàn)能力。

          Checkstyle插件中默認(rèn)內(nèi)置有2個(gè)執(zhí)行代碼檢查的配置文件(Sun Checks 和 Sun Checks),但是這兩個(gè)文件檢查的非常詳細(xì)嚴(yán)格,即使優(yōu)秀的開源項(xiàng)目也會(huì)檢查出來有非常多的錯(cuò)誤告信息,所以需要導(dǎo)入我們自定義的配置文件。

          2、安裝步驟:

          通過 File > Settings > Plugins > Marketplace 搜索 “CheckStyle”,按照提示進(jìn)行安裝,然后重啟即可。

          3、使用說明:

          可以看到基本都是一些縮進(jìn)啥的編碼規(guī)范,可以不用太關(guān)注

          三、PMD

          1、整體介紹:

          PMD側(cè)重面向安全編碼規(guī)則,且具備一定的數(shù)據(jù)流分析和路徑分析能力,能力比CheckStyle稍微強(qiáng)點(diǎn),并且 PMD 支持自定義規(guī)則,PMD可以直接使用的規(guī)則包括以下內(nèi)容:

          • 潛在的bug:空的try/catch/finally/switch語(yǔ)句
          • 未使用的代碼(Dead code):未使用的變量、參數(shù)、私有方法等
          • 可選的代碼String/StringBuffer的濫用
          • 復(fù)雜的表達(dá)式:不必須的if語(yǔ)句、可被while替代的for循環(huán)
          • 重復(fù)的代碼:拷貝/粘貼代碼意味著拷貝/粘貼bugs
          • 循環(huán)體創(chuàng)建新對(duì)象:盡量不要在循環(huán)體內(nèi)實(shí)例化新對(duì)象
          • 資源關(guān)閉:Connect,Result,Statement等使用之后確保關(guān)閉掉

          2、安裝步驟:

          通過 File > Settings > Plugins > Marketplace 搜索 “PMDPlugin”,按照提示進(jìn)行安裝,然后重啟即可

          3、使用說明:

          • 參考文章:http://wjhsh.net/andy-songwei-p-11830812.html

          3.1、運(yùn)行方式:

          (1)從Tools菜單中啟動(dòng):

          通過 Tools > Run PMD 可以看到如下的界面,如果通過該方式啟動(dòng),掃描的范圍就是整個(gè)項(xiàng)目中的文件了。

          • Pre Defined:預(yù)定義的規(guī)則,也就是插件自帶的檢測(cè)規(guī)則。后面展開的列表中列出了所有的規(guī)則列表,想掃描哪一種類型的問題,點(diǎn)擊即可。其中“All”表示使用所有的規(guī)則。
          • Custom Rules:自定義的檢測(cè)規(guī)則,PMD允許用戶根據(jù)需要自定義檢查規(guī)則,默認(rèn)這里是不可點(diǎn)擊的,需要在設(shè)置中導(dǎo)入自定義規(guī)則文件后方可選擇。

          (2)從右鍵菜單中啟動(dòng):

          在文件或者編輯器中點(diǎn)擊右鍵,也可以看到“Run PMD”選項(xiàng),如果通過該方式啟動(dòng), 檢測(cè)范圍取決于鼠標(biāo)或光標(biāo)當(dāng)前所選中的區(qū)域。

          3.2、運(yùn)行結(jié)果:

          運(yùn)行后會(huì)出現(xiàn)如上所示的面板,左邊工具欄,鼠標(biāo)停留在上面會(huì)提示其功能;右邊顯示了檢測(cè)結(jié)果,當(dāng)點(diǎn)擊具體某一問題項(xiàng)時(shí),會(huì)跳轉(zhuǎn)到對(duì)應(yīng)的源碼中。

          3.3、配置檢測(cè)規(guī)則:

          通過 File > Settings > Other Settings > PMD 可以打開檢測(cè)規(guī)則的設(shè)置界面:

          在 “RuleSets(規(guī)則設(shè)置)” 界面可以管理自定義的檢測(cè)規(guī)則。因?yàn)樵趯?shí)際工作中,可能需要根據(jù)實(shí)際情況自定義檢測(cè)規(guī)則,就可以通過這里導(dǎo)入,如果要使用它,需要在啟動(dòng)PMD進(jìn)行檢測(cè)時(shí)選擇該自定義規(guī)則。

          點(diǎn)擊“Options”選項(xiàng)卡,在其中可以配置一些檢測(cè)規(guī)則選項(xiàng):

          其中重點(diǎn)需要留意的是“Skip TestSource”這一項(xiàng),因?yàn)樵陧?xiàng)目中有不少Android Studio自動(dòng)生成的測(cè)試代碼,如下所示,選擇上述選項(xiàng)后可以將其過濾掉。

          四、FindBugs:

          1、整體介紹:

          FindBugs 側(cè)重于發(fā)現(xiàn)代碼中存在的bug,如運(yùn)行時(shí)錯(cuò)誤檢測(cè)(空指針檢查、未合理關(guān)閉資源、字符串相同判斷錯(cuò)(==,而不是equals)等),它可以簡(jiǎn)單高效全面地幫助我們發(fā)現(xiàn)程序代碼中存在的bug以及潛在隱患,針對(duì)各種問題,它提供了簡(jiǎn)單的修改意見供我們參考

          2、安裝步驟:

          通過 File > Settings > Plugins > Marketplace 搜索 “FindBugs”,按照提示進(jìn)行安裝,然后重啟即可

          3、使用說明:

          FindBugs 可以分析單個(gè)文件、包下面的所有文件、整個(gè)module下的文件、整個(gè)project下的文件,右鍵想要分析的文件名/包名/module/project

          分析完之后就會(huì)出現(xiàn)結(jié)果面板

          點(diǎn)擊對(duì)應(yīng)的item在右邊會(huì)定位到具體的代碼,這是根據(jù)提示進(jìn)行處理修改就行

          4、附:常見的錯(cuò)誤信息

          4.1、Bad practice 代碼壞習(xí)慣:

          4.2、Dodgy code 糟糕的代碼:

          4.3、Internationalization 代碼國(guó)際化相關(guān):

          4.4、Performance 代碼性能相關(guān):

          4.5、Experimental:

          4.6、Malicious code vulnerability 惡意破壞代碼相關(guān):

          4.7、Multithreaded correctness 多線程代碼正確性相關(guān):

          4.8、Correctness 代碼正確性相關(guān):

          五、SonarLint:

          1、整體介紹:

          sonar 比 Findbugs 高了一個(gè)層級(jí),它不僅關(guān)注常規(guī)靜態(tài)BUG,還關(guān)注到了如代碼質(zhì)量、包與包、類與類之間的依賴情況,代碼耦合情況,類、方法、文件的復(fù)雜度,代碼中是否包含大量復(fù)制粘貼的代碼,關(guān)注的是項(xiàng)目代碼整體的健康情況。sonar 有兩種使用方式:插件和客戶端,sonar 的插件名稱為 sonarLint

          2、安裝步驟:

          通過 File > Settings > Plugins > Marketplace 搜索 “SonarLint”,按照提示進(jìn)行安裝,然后重啟即可

          3、使用說明:

          右鍵項(xiàng)目或者文件進(jìn)行如上圖所示操作,執(zhí)行之后可以看到如下信息,如果代碼中有不合理的地方會(huì)在report中顯示,同時(shí)點(diǎn)擊錯(cuò)誤的地方在右邊會(huì)給出建議的修改供參考。

          4、配置 SonarLint 服務(wù)端:

          4.1、配置 Sonar 服務(wù)器:

          sonarLint 插件的使用場(chǎng)景是自用自審,但 sonar 也提供了平臺(tái)版本,使用場(chǎng)景則是他審,sonar 平臺(tái)的搭建就不在這篇文章介紹了,感興趣的讀者可以自己上網(wǎng)查看,我們這里主要介紹如何在 sonarLint 插件中配置關(guān)聯(lián) sonar 平臺(tái)服務(wù)器的工程,進(jìn)行本地檢查:

          點(diǎn)擊新增按鈕,輸入Configuration Name,配置sonarlint 服務(wù)器的地址,然后下拉框選擇 Login/Password,輸入 sonarlint服務(wù)器的賬號(hào)密碼

          4.2、具體 Sonar工程配置:

          配置完服務(wù)器之后,需要針對(duì)具體工程進(jìn)行配置,點(diǎn)擊 connection下拉框,選擇上面配置好的服務(wù)器連接,然后點(diǎn)擊 Search in list,找到對(duì)應(yīng)的工程:

          4.3、使用 SonarLint 檢查:

          配置完上面兩步之后,接下來就可以選擇要進(jìn)行檢查的類或者目錄進(jìn)行 sonarlint 檢查了(跟第3點(diǎn)的使用方式一致),同時(shí),在 commit 代碼的時(shí)候,勾選 “Perform Sonarlint analysis”,會(huì)針對(duì)你要提交的代碼進(jìn)行sonarlint檢查

          總結(jié)

          • 檢查代碼規(guī)范的話,直接使用 Alibaba Java Coding Guidelines 就可以了
          • 找 BUG 的話,使用 PMD、Findbugs、SonarLint 相互補(bǔ)充:
            • PMD 自定義能力強(qiáng),用來自定義項(xiàng)目BUG規(guī)則非常好用
            • Findbugs 找 BUG 能力很強(qiáng),我們拿找到的BUG給新員工培訓(xùn)也很好。
            • SonarLint 規(guī)則豐富,比 Findbugs 能覆蓋到更全的場(chǎng)景

          onarSource目前提供三類產(chǎn)品,分別是SonarLint、SonarQube以及SonarCloud。三類產(chǎn)品雖然應(yīng)用場(chǎng)景不同,但都給開發(fā)人員提供了靜態(tài)代碼分析(SAST)的能力,也就是在不運(yùn)行程序的情況下通過一系列程序分析技術(shù)持續(xù)對(duì)代碼進(jìn)行理解與檢測(cè),發(fā)現(xiàn)代碼中存在的漏洞。

          SonarSource的愿景是希望從根本上改變組織交付軟件的方式,幫助研發(fā)人員交付清潔代碼,即安全、健壯且可以發(fā)展的代碼。

          "代碼重構(gòu)/改善代碼質(zhì)量"這件事情比作投資:“我們擁有的這種方法的美妙之處在于它不再花費(fèi);對(duì)于相同的投資,你有很好的代碼,以后你會(huì)有更大的投資回報(bào),所以一開始的‘正確’就尤為重要,這是使軟件成為資產(chǎn)而非負(fù)債所需的唯一步驟

          靜態(tài)代碼掃描工具目前市場(chǎng)現(xiàn)狀

          在整個(gè)的開發(fā)鏈條中還有其他工具也可以檢測(cè)軟件中存在的漏洞,比如IAST,DAST,F(xiàn)UZZ。這些動(dòng)態(tài)測(cè)試工具受限于檢測(cè)漏洞的原理,往往需要較高的使用條件,比如需要準(zhǔn)備軟件的運(yùn)行環(huán)境、需要在測(cè)試過程中與軟件進(jìn)行交互來觸發(fā)軟件的功能、需要準(zhǔn)備大量的測(cè)試用例。

          而基于不同理念所產(chǎn)生的靜態(tài)分析工具則沒有此類限制,只需要接觸源代碼即可完成分析。這樣的天然優(yōu)勢(shì)給予了靜態(tài)代碼分析類工具更廣闊的市場(chǎng)空間,使得靜態(tài)代碼分析類工具更有可能成為走向研發(fā)者市場(chǎng),成為一類具備普適性的研發(fā)效能工具。SonarSource的成功路徑也從側(cè)面證明了這一點(diǎn)。然而當(dāng)我們把目光聚焦在國(guó)內(nèi)市場(chǎng),并沒有發(fā)現(xiàn)類似SonarSource的企業(yè)。在中國(guó),靜態(tài)分析類工具仍然處在一個(gè)突破使用場(chǎng)景和市場(chǎng)空間的過程中,究其原因,我們認(rèn)為以下三個(gè)方面的問題可能能夠做一些說明:

          落地成本高

          目前國(guó)內(nèi)市場(chǎng)上常見的靜態(tài)代碼分析工具具備較高的使用門檻。從開始接觸到成功落地往往需要較多的適配與培訓(xùn)工作,需要企業(yè)投入較多的時(shí)間與人力成本。在研發(fā)工具接受程度與使用習(xí)慣還未養(yǎng)成的中國(guó)市場(chǎng),這些先決條件往往成為勸退企業(yè)的第一道門檻,導(dǎo)致了很多有相關(guān)需求的中小型企業(yè)望而卻步。

          傳統(tǒng)產(chǎn)品形態(tài)老舊,缺乏現(xiàn)代化集成能力

          從用途來說,靜態(tài)代碼分析工具屬于軟件研發(fā)體系的支撐性工具,其使用場(chǎng)景往往會(huì)隨著軟件研發(fā)體系的變化而變化。

          目前國(guó)內(nèi)市場(chǎng)主流的靜態(tài)代碼分析工具仍然停留在傳統(tǒng)的客戶端軟件時(shí)代,用戶通過上傳代碼進(jìn)行集中式的分析與結(jié)果展示。當(dāng)用戶需要在現(xiàn)代化的研發(fā)體系(如模塊化DevOps敏捷流水線)中去使用相關(guān)能力時(shí),這種傳統(tǒng)的軟件形態(tài)往往會(huì)帶來較多的麻煩,導(dǎo)致落地成本的提升和自動(dòng)化程度的降低。

          目前國(guó)外走在前沿的分析類工具,如SonarQube、 Snyk和Coverity均采用了解耦式的模塊化設(shè)計(jì),方便用戶進(jìn)行流水線集成和自動(dòng)化調(diào)度。

          分析精度較差

          隨著軟件產(chǎn)業(yè)的飛速發(fā)展,過去二十年間用戶對(duì)于靜態(tài)代碼分析類工具的需求也在不斷提升。從最早期進(jìn)行代碼風(fēng)格的管理,到嵌入式時(shí)代對(duì)于代碼質(zhì)量的合規(guī)要求,到今天對(duì)于安全漏洞的治理。軟件的復(fù)雜程度日益提升,靜態(tài)代碼分析工具試圖解決的問題也越發(fā)復(fù)雜。現(xiàn)有的工具在面對(duì)復(fù)雜的軟件安全漏洞時(shí),分析精度直線下降,誤報(bào)率往往超過50%。過高的誤報(bào)率帶來的是使用成本的大幅提升,同時(shí)也造就了靜態(tài)代碼分析類工具落地成本高,使用復(fù)雜的刻板印象。能否解決好復(fù)雜代碼場(chǎng)景的分析精度問題,是決定SAST類工具接受程度的核心難題。

          SonarSource的解決方案

          SonarSource提供的一整套解決方案會(huì)在開發(fā)過程的整個(gè)生命周期,以及每個(gè)階段執(zhí)行檢查。整套解決方案的核心理念是“Clean as You Code”。在開發(fā)者完成一部分新的代碼之后,可以將代碼推給掃描工具,并對(duì)這一部分的代碼的品質(zhì)進(jìn)行分析和評(píng)價(jià),以保證開發(fā)者的代碼一直保持滿足標(biāo)準(zhǔn)的狀態(tài)。這個(gè)標(biāo)準(zhǔn)的狀態(tài)通過“Quality Gate”來嚴(yán)格把守,它是發(fā)布前的最后一道檢查,只有滿足所有的要求才能發(fā)布到生產(chǎn)環(huán)境中,比如代碼覆蓋率,可靠性評(píng)級(jí)等等。開發(fā)人員可以設(shè)置自己的標(biāo)準(zhǔn),也可以使用SonarSource提供的默認(rèn)標(biāo)準(zhǔn)“SonarWay”。

          三類產(chǎn)品

          SonarLint

          SonarLint是一個(gè)IDE擴(kuò)展,可幫助開發(fā)人員在編寫代碼時(shí)檢測(cè)和修復(fù)質(zhì)量問題。就像Grammarly拼寫檢查器一樣,SonarLint會(huì)實(shí)時(shí)提供反饋,以便在提交代碼之前修復(fù)它們。此外,SonarLint會(huì)提供詳細(xì)的規(guī)則描述和最佳實(shí)踐來展示代碼問題的原因與解決方案,開發(fā)人員可以在編碼的同時(shí)學(xué)習(xí)提高自己的技能。

          SonarQube

          公司主打的SAST產(chǎn)品。產(chǎn)品是分離式的架構(gòu),一側(cè)為SonarQube平臺(tái),可以在web端查看掃描結(jié)果;另一側(cè)是SonarScanner,這是公司十多年來構(gòu)建的代碼分析引擎,內(nèi)含5000多條規(guī)則積累。此外SonarQube 并不是簡(jiǎn)單地將各種質(zhì)量檢測(cè)工具的結(jié)果直接展現(xiàn)給客戶,而是通過不同的算法來對(duì)這些結(jié)果進(jìn)行再加工,最終以量化的方式來衡量代碼質(zhì)量,并進(jìn)行管理。

          SonarCloud

          公司推出的SaaS云服務(wù),針對(duì)開源項(xiàng)目進(jìn)行分析檢測(cè)。基本功能和普通的SonarQube差不多,但提供更多的SaaS級(jí)別的服務(wù)。

          三類問題

          上述三種產(chǎn)品本質(zhì)上共同解決了三類代碼問題,分別是代碼可靠性,代碼安全性以及技術(shù)負(fù)債(代碼可維護(hù)性)。

          代碼可靠性

          分析引擎可以針對(duì)代碼中的Bug以及開發(fā)路徑存在的問題進(jìn)行檢測(cè)。Bug通常是指一種編碼錯(cuò)誤,可能會(huì)導(dǎo)致程序運(yùn)行時(shí)出現(xiàn)錯(cuò)誤或意外。

          代碼安全性檢測(cè)

          SonarQube可以展示代碼中的安全熱點(diǎn)(Security Hotspots),也就是一些敏感代碼,但它們不會(huì)影響整體應(yīng)用程序安全性,也不需要研發(fā)人員立刻進(jìn)行修復(fù)。但是事后審查的判斷是有必要的,因?yàn)檠邪l(fā)人員可能也會(huì)發(fā)現(xiàn)這些“敏感地帶”會(huì)存在風(fēng)險(xiǎn)。除了安全熱點(diǎn)以外,分析引擎還可以針對(duì)安全漏洞(Vulnerabilities)進(jìn)行檢測(cè),安全漏洞是需要立即修復(fù)的,它們會(huì)嚴(yán)重影響應(yīng)用程序安全性。這樣的分類方式進(jìn)一步降低了誤報(bào)率,對(duì)研發(fā)人員更加友好。

          分析引擎主要檢測(cè)的安全漏洞分為兩類。第一種是安全注入問題,第二種是安全配置問題。

          技術(shù)負(fù)債(代碼可維護(hù)性檢測(cè))

          分析引擎可以檢測(cè)代碼異味,也就是代碼可維護(hù)性的問題。通常它們使代碼混亂且難以維護(hù),換而言之,維護(hù)人員不知道如何修復(fù)這段代碼,最壞的情況是原來的問題還沒有修復(fù),就引入新的問題。代碼異味包括“七宗罪”,分別是不遵循代碼標(biāo)準(zhǔn),潛在缺陷,糟糕的復(fù)雜度分布,重復(fù),注釋不足或過多,缺乏單元測(cè)試,糟糕的設(shè)計(jì)

          這七點(diǎn)也是檢測(cè)技術(shù)負(fù)債的標(biāo)準(zhǔn)(技術(shù)負(fù)債是指修復(fù)代碼異味所花費(fèi)的精力)。

          對(duì)于修復(fù)技術(shù)負(fù)債的問題,SonarSource也有著自己獨(dú)到的解決方案。通常來說,主動(dòng)對(duì)整個(gè)代碼庫(kù)的修復(fù)是費(fèi)時(shí)費(fèi)力的,也可能會(huì)產(chǎn)生功能回歸風(fēng)險(xiǎn)。然而程序員總是會(huì)在老代碼的基礎(chǔ)上進(jìn)行新的修改。所以SonarSource的產(chǎn)品只對(duì)于新的代碼或者是在老代碼上做過修改的代碼進(jìn)行掃描分析,也就是在不引入新的問題的同時(shí)逐漸對(duì)代碼庫(kù)進(jìn)行修復(fù),逐漸改進(jìn)軟件的質(zhì)量。實(shí)際上就算沒有主動(dòng)去修復(fù)老的代碼,通過SonarSource的解決方案,也會(huì)被逐漸地被動(dòng)修復(fù)。據(jù)估計(jì),第一年后整體代碼的大約20%的問題將會(huì)被修復(fù),兩年后大約35%的代碼問題會(huì)被修復(fù),5年后大約50%的代碼問題會(huì)被修復(fù)。

          銷售模式

          三款產(chǎn)品中SonarLint和SonarCloud是開源免費(fèi)的。除了SonarCloud定制的私人服務(wù)需要付費(fèi)之外,公司主要的收入來源來自SonarQube,一共有四個(gè)版本,分別是社區(qū)版,研發(fā)者版,企業(yè)版和數(shù)據(jù)中心版。除了版本之間功能的不同之外,SonarQube的收費(fèi)模式是根據(jù)可分析的最大代碼行數(shù)每年收l(shuí)icense費(fèi)用。

          社區(qū)版是完全免費(fèi)的,它實(shí)際上覆蓋了SonarQube絕大部分功能,包括支持大多數(shù)語(yǔ)言,對(duì)代碼質(zhì)量和簡(jiǎn)單安全問題檢測(cè)的能力,超過50種的插件等等。但問題是社區(qū)版不支持一個(gè)項(xiàng)目多分支的形式,這會(huì)導(dǎo)致一次掃描產(chǎn)生多個(gè)項(xiàng)目結(jié)果,增加管理的難度。

          研發(fā)者版本起價(jià)是150美金一年,可使用的最大代碼限制行數(shù)是10萬(wàn)行,已經(jīng)可以滿足一般研發(fā)人員日常的檢測(cè)需求。此外,增加了C/C++語(yǔ)言的覆蓋,增加了分支分析的能力,增強(qiáng)了安全分析的能力,尤其是針對(duì)注入這個(gè)問題可以做到深度精確分析。

          企業(yè)版起價(jià)2萬(wàn)美金一年,可使用的最大代碼限制行數(shù)是100萬(wàn)行。除了支持全部的27種語(yǔ)言之外,還提供了可以配置的SAST引擎功能,提供OWASP/SANS安全報(bào)告的能力。還賦能企業(yè)產(chǎn)出組合管理的能力。

          數(shù)據(jù)中心版本起價(jià)10萬(wàn)美金一年,可使用的最大代碼限制行數(shù)是200萬(wàn)行。這個(gè)版本對(duì)高可用性和橫向擴(kuò)展性有更好的支持。

          此外,三個(gè)收費(fèi)版本的產(chǎn)品價(jià)格均會(huì)隨著最大代碼限制行數(shù)的增加而提高。

          歷史沿革

          2006年,F(xiàn)reddy Mallet意識(shí)到代碼質(zhì)量管理至關(guān)重要。代碼的缺陷最終會(huì)反映到軟件交付的質(zhì)量上,導(dǎo)致各種各樣的威脅與損失,比如數(shù)據(jù)泄露,隱私威脅,財(cái)產(chǎn)損失,甚至是對(duì)人物理上帶來的傷害。Freddy Mallet認(rèn)為市場(chǎng)上需要一種提供自動(dòng)化代碼審查的產(chǎn)品。Freddy Mallet與好友Simon Brandhof通過集成Java的最佳開源工具在2007年開始了對(duì)Sonar平臺(tái)的開發(fā)。Olivier Gaudin隨后加入團(tuán)隊(duì),SonarSource于2008年成立。

          2010年,SonarSource實(shí)現(xiàn)了公司的第一個(gè)里程碑——Sonar平臺(tái)被社區(qū)和企業(yè)接受,每月下載量超過2K次。各種插件的集成讓Sonar備受好評(píng)。公司隨后加大研發(fā)力度,在2013年正式推出SonarQube。

          2016年,SonarSource從Insight Venture Partners籌集了4500萬(wàn)美元投資,以進(jìn)一步加速增長(zhǎng)。Richard Wells,MD和Insight Partners副總裁Matt Gatto加入公司董事會(huì)。此時(shí)的SonarQube已經(jīng)完成了多次迭代,支持了大量的語(yǔ)言和規(guī)則,代碼質(zhì)量分析的能力已經(jīng)逐漸體現(xiàn)出優(yōu)勢(shì)。

          2018年,第一個(gè)SaaS平臺(tái)SonarCloud基于市場(chǎng)需求和用戶需求推出。在此之前的兩年中,SonarSource也納入了一些與代碼安全性相關(guān)的檢測(cè)能力,但是一直沒有辦法做到高精度的分析。

          直到2020年,SonarSource收購(gòu)RIPS。RIPS Technologies首席執(zhí)行官兼聯(lián)合創(chuàng)始人Johannes Dahse博士加入SonarSource擔(dān)任研發(fā)主管。RIPS Technologies是一家致力于創(chuàng)新安全測(cè)試技術(shù)的公司,以從頭構(gòu)建了其一流的 PHP 代碼分析引擎而聞名。它的團(tuán)隊(duì)在構(gòu)建高效的代碼分析解決方案方面有著悠久的歷史,他們的引擎甚至可以檢測(cè)復(fù)雜和深層嵌套的漏洞。這次收購(gòu)讓SonarSource語(yǔ)言覆蓋的廣度和RIPS檢測(cè)的深度相結(jié)合,最終實(shí)現(xiàn)了多種語(yǔ)言上對(duì)安全漏洞的精準(zhǔn)分析檢測(cè)。這也標(biāo)志著SonarSource正式走入了安全性SAST的領(lǐng)域。

          2022年,Sonar從新的和現(xiàn)有的投資者那里籌集了4.12億美元,估值為47億美元。該公司將利用這筆投資來擴(kuò)大銷售團(tuán)隊(duì),以實(shí)現(xiàn)10億美元的收入。

          核心團(tuán)隊(duì)

          創(chuàng)始團(tuán)隊(duì)初識(shí)

          聯(lián)合創(chuàng)始人兼CEO Olivier Gaudin來自瑞士日內(nèi)瓦,于1998年畢業(yè)于法國(guó)國(guó)立應(yīng)用科學(xué)學(xué)院(INSA)的應(yīng)用數(shù)學(xué)工程專業(yè)。因?yàn)橥ㄟ^軟件更容易去計(jì)算和模擬數(shù)學(xué)理論的最后結(jié)果,所以O(shè)livier選擇了偏計(jì)算機(jī)的方向,主攻Java語(yǔ)言。曾經(jīng)在IT行業(yè),金融行業(yè),建筑行業(yè)工作過。

          在一次代碼審查任務(wù)中,Olivier發(fā)現(xiàn)自己很難讀懂自己下屬寫的代碼,開始在自己的團(tuán)隊(duì)內(nèi)部開始設(shè)置一些基本的編寫規(guī)范。同時(shí),F(xiàn)reddy和Simon也被同樣的問題困擾,他們正在試圖尋找一種自動(dòng)化的工具來解決這個(gè)問題,但是并沒有找到。Freddy和Simon當(dāng)時(shí)已經(jīng)在IT咨詢公司Hortis共事了幾年,分別擔(dān)任CTO和高級(jí)Java研發(fā)員。Freddy有著二十多年軟件相關(guān)工作經(jīng)驗(yàn),包括軟件研發(fā),軟件基礎(chǔ)架構(gòu)設(shè)計(jì),軟件咨詢。Simon也有著十幾年的開發(fā)經(jīng)驗(yàn),兩人率先開始研發(fā)Sonar平臺(tái)。

          后來,Olivier遇到了Freddy和Simon,被二人的想法吸引并于2007年加入了他們團(tuán)隊(duì)。有一次,他詢問了Freddy和Simon對(duì)“干凈的代碼”的理解,發(fā)現(xiàn)三個(gè)人產(chǎn)生了分歧。這更加堅(jiān)定了他們做出一套被行業(yè)認(rèn)可的代碼規(guī)范的想法,三人便于2008年創(chuàng)立SonarSource。

          新成員的加入

          Andrea Malagodi(CTO)

          Andrea來自于瑞士日內(nèi)瓦,于2003年畢業(yè)于歐洲工商管理學(xué)院的金融專業(yè)。曾在摩根大通擔(dān)任首席技術(shù)官和技術(shù)負(fù)責(zé)人 25 年。工作的同時(shí)又在2018年攻讀完成了美國(guó)斯坦福大學(xué)的創(chuàng)新科技項(xiàng)目。Andrea于2021年加入SonarSource,他的加入可以幫助SonarSource建立應(yīng)對(duì)強(qiáng)勁增長(zhǎng)所需的基礎(chǔ)設(shè)施。

          Gordon Pothier(CFO)

          Gordon來自美國(guó)馬塞諸塞州,于2000年畢業(yè)于本特利大學(xué)的金融MBA項(xiàng)目。他曾在軟件安全公司 Carbon Black擔(dān)任財(cái)務(wù)副總裁兼首席財(cái)務(wù)官,該公司于2019年被VMWare收購(gòu)。他也曾擔(dān)任過領(lǐng)先的應(yīng)用程序安全初創(chuàng)公司Onapsis的首席財(cái)務(wù)官,于2021年加入SonarSource。Gordon在這一領(lǐng)域有著十多年的經(jīng)驗(yàn),有著非常廣的人脈與資源。

          Manish Gupta (CMO)

          Gupta于2022年加入SonarSource,之前曾擔(dān)任Redis的首席營(yíng)銷官,最近擔(dān)任Oracle的Java和GraalVM全球營(yíng)銷副總裁,在他任職期間領(lǐng)導(dǎo)了這兩家公司實(shí)現(xiàn)了多倍增長(zhǎng)。他的經(jīng)驗(yàn)將有助于SonarSource實(shí)現(xiàn)10億美元的收入目標(biāo)。

          未來發(fā)展

          市場(chǎng)教育方面

          Olivier曾在一次采訪中表示,“我們希望更多研發(fā)人員使用我們的產(chǎn)品,要知道全球有大約7000多萬(wàn)的研發(fā)人員。這是我們?cè)诖酥皬臎]有遇到過的挑戰(zhàn),我認(rèn)為我們的產(chǎn)品已經(jīng)準(zhǔn)備好了,剩下的工作就是安全意識(shí)上的教育和啟發(fā)”。

          實(shí)際上,SonarSource從很早的時(shí)候就開始嘗試進(jìn)行安全意識(shí)教育的工作。比如每年12月,會(huì)在Twitter上發(fā)布24個(gè)面向研發(fā)人員的安全問題解謎挑戰(zhàn),并為成功解謎者提供獎(jiǎng)勵(lì)。這些安全問題都是SonarSource團(tuán)隊(duì)在本年中花費(fèi)大量時(shí)間研究和理解現(xiàn)實(shí)世界中的漏洞。公司正在嘗試通過各種形式增加與用戶之間的互動(dòng)來傳遞安全意識(shí)。

          產(chǎn)品創(chuàng)新方面

          SonarSource希望在未來可以提高分析引擎的掃描的速度以及對(duì)代碼安全問題深度分析的能力。SonarSource會(huì)繼續(xù)為開發(fā)人員增加價(jià)值,優(yōu)化SonarLint的能力,讓研發(fā)人員在IDE側(cè)有更好的無(wú)摩擦開發(fā)體驗(yàn)。

          參考資料

          • SonarSource官網(wǎng),PitchBook,The Forrester
          • https://zhuanlan.zhihu.com/p/532943997
          • https://www.zjdz.gov.cn/dzj/dzj/aqzx/20220113/16876.html
          • https://techcrunch.com/2022/04/26/sonarsource-raises-412m-to-scan-codebases-for-bugs-and-vulnerabilities/?guccounter=1&guce_referrer=aHR0cHM6Ly9hZ2g4MnJubTVsLmZlaXNodS5jbi8&guce_referrer_sig=AQAAAIQbF0gtoD9VOAE5IfLTjzV2QBs3SNa9EGp-EP7xPkX9JfgAyngs0Tt
          • https://www.usine-digitale.fr/article/sonarsource-leve-375-millions-d-euros-pour-detecter-les-erreurs-dans-le-code.N1997837
          • https://zhuanlan.zhihu.com/p/497718625
          • https://www.mordorintelligence.com/industry-reports/application-security-market
          • https://blog.csdn.net/libin95188/article/details/123038727
          • https://www.likecs.com/show-204321455.html#sc=1948
          • https://www.sonarsource.com/blog/code-security-now-theres-a-tool-for-developers/
          • https://www.sonarsource.com/plans-and-pricing/?gads_campaign=North-America-Sonar&gads_ad_group=Sonar&gads_keyword=sonarsource&gclid=EAIaIQobChMIscGv8tD1-wIVHBitBh2WnAXtEAAYASABEgKJrvD_BwE
          • https://ecapital.vc/news/rips-technologies-sold-to-sonarsource/?cookie-state-change=1670567160629
          • https://console.dev/interviews/sonarsource-olivier-gaudin/
          • https://www.challenges.fr/classements/fortune/olivier-gaudin-freddy-mallet-et-simon-brandhof_3328
          • https://www.pme.ch/business/2022/01/24/le-logiciel-libre-etait-pour-nous-une-evidence

          場(chǎng)景


          • 極狐GitLab旗艦版已經(jīng)具備掃描能力,但是某些場(chǎng)景下掃描能力偏弱,所以希望集成第三方掃描工具作為補(bǔ)充。但是,單純的通過Runner調(diào)用的方式,只是松散的集成,無(wú)法真正形成「深度集成」的體驗(yàn)。
          • 若可以「在極狐GitLab的漏洞報(bào)告中展現(xiàn)第三方掃描工具的掃描結(jié)果」,那么,對(duì)于集成的體驗(yàn)則會(huì)提升很多。本文即針對(duì)此目的進(jìn)行展開說明。


          外部掃描器選型 SonarQube-CE


          • 以非常流行的掃描工具SonarQube社區(qū)版為例加以說明。


          快速入門


          直接在.gitlab-ci.yml文件中填入如下內(nèi)容,觸發(fā)掃描,即可在漏洞報(bào)告中查看結(jié)果。

          
          variables:
            sonar_host_url: http://1.13.160.207:9000
            sonar_login: 333f3410ce3e575d559329e8f3d0a5d4ec8a499d
          
          sonarqube:
            artifacts:
              reports:
                sast:
                - gl-sast-report.json
            script:
            - "/scan.sh"
            image:
               name: satomic/sonarscanner:v6
          


          以下倉(cāng)庫(kù)參考:

          • Java: https://jihudemo.online/demo/standard-demo/hello-order/hairou-app-downsteam/-/security/vulnerability_report
          • cpp: https://jihudemo.online/demo/standard-demo/hello-order/cpp-example/-/security/vulnerability_report
          • Python: https://jihudemo.online/mumutech/dev-backend/bigdata/funny-toolkits/-/security/vulnerability_report
          • PHP: https://jihudemo.online/mumutech/dev-backend/dvwa/-/security/vulnerability_report


          使用方法

          參考dvwa倉(cāng)庫(kù)中的配置方法。


          SonarQube-CE部署

          • 公網(wǎng)環(huán)境中已經(jīng)部署好SonarQube,可以忽略部署過程,繼續(xù)往下。
          • 若為私網(wǎng)環(huán)境,參考下文部署章節(jié)。


          環(huán)境變量配置

          在project級(jí)別中,settings - CI/CD - Variables中添加如下2個(gè)變量指向SonarQube服務(wù)。

          • sonar_host_url: http://1.13.160.207:9000
          • sonar_login: 333f3410ce3e575d559329e8f3d0a5d4ec8a499d


          .gitlab-ci.yml配置

          在待掃描倉(cāng)庫(kù)中增加.gitlab-ci.yml配置文件,如下,不建議直接把敏感信息如快速入門那樣配置在ci文件中。

          sonarqube:
            artifacts:
              reports:
                sast:
                - gl-sast-report.json
            script:
            - "/scan.sh"
            image:
               name: satomic/sonarscanner:v6
          

          然后進(jìn)行掃描即可得到掃描結(jié)果。

          報(bào)告總覽

          特定issue展現(xiàn)image

          文件定位image


          SonarQube說明

          SonarQube原理

          docker方式部署 SonarQube-CE 7.6

          根據(jù)文章How to get the sonar-report.json file created with sonarqube?、How to get sonar-report.json file to display sonar issues at gerrit level itself中所言,從7.7版本開始,不支持在scanner端導(dǎo)出json格式的報(bào)告,因此部署支持的舊版本中的最后一個(gè)版本,即7.6版。


          PgSql

          參考Docker 安裝SonarQube 步驟以及遇到的坑進(jìn)行部署,

          創(chuàng)建工作目錄

          
          mkdir -p /home/sonar/postgres/postgresql
          mkdir -p /home/sonar/postgres/data
          

          創(chuàng)建網(wǎng)絡(luò)

          docker network create sonarqube-network

          部署pg

          docker run --name postgres -d -p 5432:5432 --network sonarqube-network \
          -v /home/sonar/postgres/postgresql:/var/lib/postgresql \
          -v /home/sonar/postgres/data:/var/lib/postgresql/data \
          -v /etc/localtime:/etc/localtime:ro \
          -e POSTGRES_USER=sonar \
          -e POSTGRES_PASSWORD=sonar \
          -e POSTGRES_DB=sonar \
          -e TZ=Asia/Shanghai \
          --restart always \
          --privileged=true \
          --network-alias postgres \
          postgres

          SonarQube

          創(chuàng)建工作目錄

          mkdir -p /data/sonarqube_dir
          

          修改系統(tǒng)參數(shù)

          echo "vm.max_map_count=262144" > /etc/sysctl.conf
          sysctl -p
          

          運(yùn)行測(cè)試容器

          docker run -d --name sonartest sonarqube:7.6-community
          

          拷貝必須文件到本地,并修改權(quán)限為777

          docker cp sonartest:/opt/sonarqube/conf /data/sonarqube_dir
          docker cp sonartest:/opt/sonarqube/data /data/sonarqube_dir
          docker cp sonartest:/opt/sonarqube/logs /data/sonarqube_dir
          docker cp sonartest:/opt/sonarqube/extensions /data/sonarqube_dir
          
          chmod -R 777 /data/sonarqube_dir/
          

          刪除容器

          docker stop sonartest
          docker rm sonartest
          

          啟動(dòng)SonarQube,其中SONARQUBE_JDBC_URL的IP地址需要修改為實(shí)際PgSql數(shù)據(jù)庫(kù)的IP

           docker run -itd --name sonar -p 9000:9000 \
           -e ALLOW_EMPTY_PASSWORD=yes \
           -e SONARQUBE_DATABASE_USER=sonar \
           -e SONARQUBE_DATABASE_NAME=sonar \
           -e SONARQUBE_DATABASE_PASSWORD=sonar \
           -e SONARQUBE_JDBC_URL="jdbc:postgresql://192.168.1.4:5432/sonar" \
           --privileged=true \
           --network sonarqube-network \
           --restart always \
           -v /data/sonarqube_dir/logs:/opt/sonarqube/logs \
           -v /data/sonarqube_dir/conf:/opt/sonarqube/conf \
           -v /data/sonarqube_dir/data:/opt/sonarqube/data \
           -v /data/sonarqube_dir/extensions:/opt/sonarqube/extensions\
           sonarqube:7.6-community
          


          生成token

          登錄SonarQube UI地址( http://IP:9000 ),默認(rèn)用戶名密碼為admin/admin,在My Account - Security中生成Token。


          部署使用sonar-scanner

          參考SonarScanner下載最新版的掃描器。

          解壓后,進(jìn)入bin目錄,執(zhí)行如下命令即可完成掃描,掃描完成后可以去SonarQube中查看掃描結(jié)果。

          ./sonar-scanner \
          -Dsonar.host.url=http://1.13.160.207:9000 \
          -Dsonar.login=333f3410ce3e575d559329e8f3d0a5d4ec8a499d \
          -Dsonar.projectKey=my:test \
          -Dsonar.sources=/path_to_codes
          

          如果想要在本地生成json格式報(bào)告,則增加如下參數(shù)

          -Dsonar.report.export.path=report.json \
          -Dsonar.analysis.mode=preview
          


          掃描器制作

          json 格式轉(zhuǎn)換

          基于以上內(nèi)容,關(guān)鍵是把掃描結(jié)果轉(zhuǎn)化為極狐GitLab旗艦版所識(shí)別的json格式。

          json 樣本

          SonarQube掃描結(jié)果issue樣本

          {
              "key": "AX-Gc4tIjhpt-OIbVVk0",
              "component": "my:fuck:fuck/dvwa/includes/DBMS/MySQL.php",
              "line": 70,
              "startLine": 70,
              "endLine": 70,
              "message": "Extract this nested ternary operation into an independent statement.",
              "severity": "MAJOR",
              "rule": "php:S3358",
              "status": "OPEN",
              "isNew": False,
              "creationDate": "2022-03-14T11:22:52+0800"
          }
          

          極狐GitLab報(bào)告展現(xiàn)issue樣本

          {
            "category": "test",
            "message": "這個(gè)問題不怎么嚴(yán)重",
            "cve": "python-webhook/MicroService/Service.py:960662f9bd521d32692b07bd8d5b10538924c23c37cec891847f40e436c5c2f:B104",
            "severity": "Medium",
            "confidence": "Medium",
            "scanner": {
              "id": "test",
              "name": "test"
            },
            "location": {
              "file": "python-webhook/MicroService/Service.py",
              "start_line": 26,
              "end_line": 28
            },
            "identifiers": [
              {
                "type": "bandit_test_id",
                "name": "Bandit Test ID B104",
                "value": "B104",
                "url": "https://bandit.readthedocs.io/en/latest/plugins/b104_hardcoded_bind_all_interfaces.htl"
              }
            ]
          }

          轉(zhuǎn)換器 converter.py

          轉(zhuǎn)碼程序采用python,編寫converter.py文件,內(nèi)容如下:

          # coding=utf-8
          # Copyright 2022 Xuefeng Yin, All Rights Reserved
          
          from datetime import datetime
          import json
          import hashlib
          
          f = open(".scannerwork/report.json", "r")
          
          report = json.loads(f.read())
          issues = report.get("issues")
          
          
          # {u'INFO': 50, u'BLOCKER': 3, u'MAJOR': 5724, u'CRITICAL': 1089, u'MINOR': 1103}
          severitys_mapper = {
              "INFO": "info",
              "BLOCKER":"Unknown",
              "MAJOR":"High",
              "CRITICAL":"Critical",
              "MINOR":"Low",
          }
          
          
          # = issue.get("")
          def conv(issue):
          
              component = issue.get("component")
              startLine = issue.get("startLine")
              endLine = issue.get("endLine")
              message = issue.get("message")
              severity = issue.get("severity")
              rule = issue.get("rule")
          
            	# "": ,
              ret = {
                  "category": "sast",
                  "message": message,
                  "cve": "",
                  "severity": severitys_mapper.get(severity, "Unknown"),
                  "confidence": severitys_mapper.get(severity, "Unknown"),
                  "scanner": {
                      "id": "sonarqube",
                      "name": "sonarqube"
                  },
                  "location": {
                      "file": component.split(":")[-1],
                      "start_line": startLine,
                      "end_line": endLine
                  },
                  "identifiers": [
                      {
                          "type": rule,
                          "name": rule,
                          "value": rule,
                          "url": ""
                      }
                  ]
              }
          
              id = hashlib.sha256(json.dumps(ret, sort_keys=True)).hexdigest()
              ret["id"] = id
          
              return ret
          
          
          
          dateTimeObj = datetime.now()
          timeStr = dateTimeObj.strftime("%Y-%m-%dT%H:%M:%S")
          
          gl_sast_report = {
            "version": "3.0.0",
            "vulnerabilities": [],
            "remediations": [],
            "scan": {
              "scanner": {
                "id": "sonarqube",
                "name": "SonarQube",
                "url": "https://docs.sonarqube.org/",
                "vendor": {
                  "name": "GitLab"
                },
                "version": "1.7.0"
              },
              "type": "sast",
              "start_time": timeStr,
              "end_time": timeStr,
              "status": "success"
            }
          }
          
          
          
          for i, issue in enumerate(issues[:]):
              #print("Issue No. %s ---------------------" % i)
              #print("SonarQube: %s" % issue)
              issue_gitlab = conv(issue)
              #print("GitLab: %s" % issue_gitlab)
              gl_sast_report["vulnerabilities"].append(issue_gitlab)
          
          
          gl_sast_report_file = open("gl-sast-report.json", "w")
          gl_sast_report_file.write(json.dumps(gl_sast_report, indent=4, sort_keys=True))
          gl_sast_report_file.close()


          scan.sh

          基于環(huán)境變量進(jìn)行掃描

          pwd
          /sonar-scanner-4.7.0.2747-linux/bin/sonar-scanner -Dsonar.host.url=$sonar_host_url -Dsonar.login=$sonar_login -Dsonar.projectKey=my:test -Dsonar.sources=. -Dsonar.report.export.path=report.json -Dsonar.analysis.mode=preview
          ls -l
          ls -l .scannerwork
          python /sonar-scanner-4.7.0.2747-linux/bin/converter.py
          ls -l gl-sast-report.json


          Dockerfile

          • 基于ubuntu:18.04制作掃描器
          • 默認(rèn)沒有python環(huán)境,安裝python環(huán)境
          • 拷貝提前下載好的sonar-scanner到鏡像內(nèi)
          • 設(shè)定默認(rèn)工作目錄
          • 復(fù)制轉(zhuǎn)換器
          from ubuntu:18.04
          run apt update -y
          run apt install python -y
          add sonar-scanner-4.7.0.2747-linux.tar .
          workdir ./sonar-scanner-4.7.0.2747-linux/bin
          add converter.py .
          add scan.sh /

          構(gòu)建與推送

          制作好的鏡像已經(jīng)推送到DockerHub中,采用前文使用方法中所說的內(nèi)容即可實(shí)現(xiàn)掃描。

          docker build -t satomic/sonarscanner:v6 .
          docker push satomic/sonarscanner:v6


          Findbugs支持

          安裝插件

          Server端安裝Findbugs插件

          • 參考SonarQube的使用-集成Findbugs

          到SonarQube的容器內(nèi)部

          docker exec -it sonar bash
          

          在插件路徑中下載findbugs的jar包

          cd /opt/sonarqube/extensions/plugins
          wget https://github.com/spotbugs/sonarfindbugs/releases/download/3.10.0/sonar-findbugs-plugin-3.10.0.jar

          然后重啟sonar即可

          docker restart sonar

          然后到sonar的UI上檢查是否安裝成功,出現(xiàn)如下畫面即表示可以。


          配置Java默認(rèn)規(guī)則

          在sonar UI上進(jìn)行如下配置,這樣Java的默認(rèn)規(guī)則就是Findbugs了


          Java maven 掃描器制作

          因?yàn)閽呙鐹ava項(xiàng)目需要代碼經(jīng)過編譯,所以需要對(duì)掃描器配置maven掃描能力。理論上,通過在Dockerfile中添加安裝maven包即可,但是失敗,因此直接在前述步驟構(gòu)建出的鏡像中操作完后commit出鏡像。操作步驟如下:

          安裝軟件包列表

          apt install openjdk-11-jdk-headless -y
          apt install maven -y
          apt install git
          apt install wget
          apt install unzip
          apt install zip
          apt install vim
          apt install tree
          

          commit命令

          docker commit 100fd2c54f0a satomic/sonarscanner:v7-mvn
          

          此時(shí),考慮到參數(shù)暴露的問題,僅僅把如下4個(gè)參數(shù)內(nèi)置到掃描器內(nèi)部,因此修改scan.sh文件如下

          • sonar.host.url SonarQube Server地址
          • sonar.login token
          • sonar.report.export.path 本地report.json路徑
          • sonar.analysis.mode=preview 本地預(yù)覽模式
          pwd
          /sonar-scanner-4.7.0.2747-linux/bin/sonar-scanner -X -Dsonar.host.url=$sonar_host_url -Dsonar.login=$sonar_login -Dsonar.report.export.path=report.json -Dsonar.analysis.mode=preview
          ls -l
          ls -l .scannerwork
          python /sonar-scanner-4.7.0.2747-linux/bin/converter.py
          ls -l gl-sast-report.json
          

          再更新如上的scan.sh文件,所以Dockerfile更新為

          from satomic/sonarscanner:v7-mvn
          add scan.sh /
          

          構(gòu)建出最新鏡像

          docker build -t satomic/sonarscanner:v9-mvn .
          docker push satomic/sonarscanner:v9-mvn


          使用

          .gitlab-ci.yml更新

          為了支持Findbug的觸發(fā),需要使用如下配置

          # 正常情況下應(yīng)該配置在settings設(shè)置的環(huán)境變量中,而不是如此明文暴露
          variables:
            sonar_host_url: http://1.13.160.207:9000
            sonar_login: 333f3410ce3e575d559329e8f3d0a5d4ec8a499d
          
          sonarqube:
            artifacts:
              reports:
                sast:
                - gl-sast-report.json
            script:
            # 通過在此動(dòng)態(tài)生成 sonar-project.properties 配置,而無(wú)需侵入源碼倉(cāng)庫(kù)
            # 同同時(shí)可以提高自由度
            - echo -e "sonar.projectKey=JavaProj\nsonar.projectName=JavaProj\nsonar.projectVersion=1.0\nsonar.sourceEncoding=UTF-8\nsonar.language=java\nsonar.sources=.\nsonar.java.binaries=./target/classes\nsonar.language=java\nsonar.ce.javaOpts=-Xmx2560m -Xms853m -XX:+HeapDumpOnOutOfMemoryError" > sonar-project.properties
            # 檢查生成的配置是否正常
            - cat sonar-project.properties
            # 創(chuàng)建構(gòu)建物目錄
            - mkdir -p target/classes
            # 此命令是否執(zhí)行成功依賴mvn配置的合理性,需要實(shí)際倉(cāng)庫(kù)的研發(fā)介入,配合配置的可用性,默認(rèn)可訪問官方mvn庫(kù)的外網(wǎng)環(huán)境問題不大,內(nèi)網(wǎng)則不太可能編譯成功
            - mvn compile
            # 查看編譯產(chǎn)物
            - tree target/classes
            # 執(zhí)行sonar掃描
            - /scan.sh
            # 查看報(bào)告生成大小
            - ls -l .scannerwork/report.json
            image:
               name: satomic/sonarscanner:v9-mvn

          掃描結(jié)果

          參考

          • JavaVulnerableLab Fingbugs報(bào)告 / GitHub原始倉(cāng)庫(kù)
          • Vulnerability Java Samples Fingbugs報(bào)告 / GitHub原始倉(cāng)庫(kù)


          問題與風(fēng)險(xiǎn)

          • 從SonarQube 7.7版本開始不支持在scanner端直接生成json報(bào)告。
          • 7.7之前的版本的報(bào)告中也未包含特別詳細(xì)的信息。


          文章轉(zhuǎn)自:《》https://note.youdao.com/ynoteshare/index.html?id=05b5ba9c1c49628901ebd1eadece97cd&type=note&_time=1703486325797


          主站蜘蛛池模板: 99精品一区二区免费视频 | 精品一区二区三区免费视频| 无码一区二区三区视频| 人妻无码久久一区二区三区免费| 亚洲一区爱区精品无码| 免费播放一区二区三区| 国产经典一区二区三区蜜芽| 海角国精产品一区一区三区糖心| 波多野结衣一区二区免费视频| 91福利国产在线观看一区二区| 日本高清不卡一区| 国产日韩精品视频一区二区三区| 国产在线一区二区视频| 亚洲V无码一区二区三区四区观看| 国产99久久精品一区二区| 国产无人区一区二区三区| 国产自产在线视频一区| 日韩成人无码一区二区三区| 亚洲片国产一区一级在线观看| 久久久久人妻精品一区蜜桃| 在线精品一区二区三区电影| 插我一区二区在线观看| 无码人妻精品一区二区三区久久久| 一区二区三区在线观看免费| 亚洲一区二区三区四区视频 | 无码精品视频一区二区三区| 亚洲AV成人精品日韩一区 | 色国产精品一区在线观看| 国产拳头交一区二区| 麻豆一区二区三区精品视频| 内射白浆一区二区在线观看 | 波多野结衣高清一区二区三区| 国产自产对白一区| 久久久久成人精品一区二区| 国产伦精品一区二区三区视频猫咪| 亚洲精品伦理熟女国产一区二区| 中文字幕精品一区二区精品 | 国产乱码精品一区二区三区中文| 午夜福利无码一区二区| 无码国产精品一区二区免费模式| 国产成人一区二区三区电影网站|