做CI的兄弟基本上都会用到代码质量检查,下面从五个部分给大家讲一下我的sonarqube代码质量检测实战经验,欢迎指正交流
一、需求
二、sonarqube介绍
三、部署
四、SonarQube使用
五、使用中遇到的问题
一、需求
-
1. 代码质量检查,研发TL想知道团队成员代码质量情况,团队人多后每个人的代码风格和代码水平不一通过sonar检测能做到代码基准的一个把控。
-
2. master代码质量是基准,可以理解master分支的sonar检测是通过的,分支代码质量检查和master代码进行比对,我们是master上线。
-
- sonar检测后把结果发送通知给对应的开发和其TL,开发能及时知道自己开发代码是否有问题
二、sonarqube 介绍
SonarQube 使所有开发人员能够编写更干净、更安全的代码。
SonarQube 是一种自动代码审查工具,用于检测代码中的错误、漏洞和代码异味。它可以与您现有的工作流程集成,以实现跨项目分支和拉取请求的持续代码检查。
SonarQube 是一个用于代码质量管理的开源平台,用于管理源代码的质量。通过插件形式,可以支持包括 java, C#, C/C++, PL/SQL, Cobol, JavaScrip, Groovy 等等二十几种编程语言的代码质量管理与检测。
sonarqube 版本介绍
个人觉得社区版加上插件就够用了。
sonarqube分为社区版,开发者,企业版和数据中心版4种
版本功能比较统计:
社区版:在CI / CD中采用代码质量的起点
开发者版:最大应用程序安全性跨分支机构和PR的最大值
企业版:管理您的应用程序组合,在企业级别启用代码质量和安全性。
数据中心版:高可用性,适用于全球部署
版本列表,官网资料:https://www.sonarqube.org/downloads/
架构
sonarQube: web界面管理平台
1)展示所有的项目代码的质量数据。
2)配置质量规则、管理项目、配置通知、配置SCM等。
sonarScanner: 代码扫描工具
专门用来扫描和分析项目代码。支持20+语言。
代码扫描和分析完成之后,会将扫描结果存储到数据库当中,在sonarQube平台可以看到扫描数据。
工作流程
工作流程介绍
1.开发人员在IDE中开发和合并代码,并将代码签入到DevOps平台。
2.持续集成工具(如jenkins)检查、构建和运行单元测试,集成SonarQube扫描仪分析结果。
3.扫描程序将结果发布到SonarQube服务器,该服务器通过SonarQube界面、电子邮件、IDE内通知(通过SonarLint)和拉入或合并请求的装饰(使用Developer Edition及更高版本时)向开发人员提供反馈。
SonarQube主要作用
编写整洁代码
把出现在代码里的新问题都解决掉,就可以创建并维护一个干净的代码基础。即使是遗留项目,保持新代码的整洁,也能最终获得一个值得骄傲的代码基础。
修复代码缺陷
缺陷图例和默认质量阈都是基于新代码周期的 - 当前周期就是处理问题的时间。主要的关注点是上一个版本,通常会选择30天作为一个周期。
加强质量阈
项目的质量阈是在发布到生产环境之前所需要达到的一系列的条件标准。质量阈可以确保下一个版本的代码质量总能高于上一个版本。
Sonar的优点
(1)支持所有语言的检测。一个工具,搞定所有。
(2)灵活扩展,插拔式使用。自定义的代码检测规则,可自定义插件,独立打成JAR包放到SONARQUBE插件目录下,重启即生效,开发使用非常方便。而且自带UT验证框架,开发效率高。
(3)规则支持多租户隔离。租户可定制自己的规则集。
(4)生态强大,业界有诸多插件,与jenkins友好集成。
(5)部署使用便捷。
(6)架构松耦合,通过与maven/jenkins等集成,将代码扫描的计算消耗迁移到业务或者构建方的资源上,极大的提升了自身的吞吐能力。
衡量代码质量的几个指标
1.Bugs Bug是出现了明显错误或是高度近似期望之外行为的代码。
2.漏洞 漏洞是指代码中可能出现被黑客利用的潜在风险点。
3.安全热点 安全敏感代码需要手工审核,以便判断是否存在安全漏洞。
4.异味 代码异味会困扰代码的维护者并降低他们的开发效率。主要的衡量标准是修复它们所需的时间。
5.重复率 新代码中的重复行密度 (%),重复行数,重复代码块
6.行数 程序中代码的行数
可以根据需要创建自己的质量阈,如果公司单测覆盖率低或者基本没有单元测试可以把单元测试覆盖率检查规则去了。下图是自定义的代码检测规则:
三、部署
部署
部署之前先说两个插件,一是汉化国人毕竟中文看着舒服,二是多分支扫描支持
-
- 汉化插件
增加 sonar-l10n-zh-plugin-version.jar 到 /opt/sonarqube/extensions/plugins/ 重启启动sonarqube 即可
-
- 多分支检查插件(注意sonarqube的版本要和插件版本兼容)
2.1、下载对应版本的Community Branch Plugin插件,我们使用的sonarqube:9.6.1-community
,因此下载对应的1.12.0 版本的插件。
SonarQube Version | Plugin Version |
---|---|
9.8+ | 1.14.0 |
9.7 | 1.13.0 |
9.1-9.6 | 1.12.0 |
9.0 | 1.9.0 |
8.9 | 1.8.1 |
8.7 - 8.8 | 1.7.0 |
8.5 - 8.6 | 1.6.0 |
8.2 - 8.4 | 1.5.0 |
8.1 | 1.4.0 |
7.8 - 8.0 | 1.3.2 |
7.4 - 7.7 | 1.0.2 |
2.2、将下载的jar包放到拷贝到/opt/sonarqube/extensions/plugins
目录。
2.3、添加sonar.web.javaAdditionalOpts=-javaagent:./extensions/plugins/sonarqube-community-branch-plugin-1.12.0.jar=web
和sonar.ce.javaAdditionalOpts=-javaagent:./extensions/plugins/sonarqube-community-branch-plugin-1.12.0.jar=ce
到/opt/sonarqube/conf/sonar.properties
。
2.4、重启SonarQube,接受关于使用第三方插件的警告。
2.5、检查安装情况,查看插件配置,进入Administration—>General Settings—>Housekeeping
。基本上不用设置,保持默认即可。
-
- 容器化部署 Dockerfile
FROM docker.io/library/sonarqube:9.6.1-community ADD ./sonarqube-community-branch-plugin-1.12.0.jar /opt/sonarqube/extensions/plugins/ ADD ./sonar-l10n-zh-plugin-9.6.jar /opt/sonarqube/extensions/plugins/ ADD ./sonar-findbugs-plugin-4.2.2.jar /opt/sonarqube/extensions/plugins/
build 镜像,基于官方镜像把汉化和多分支扫描插件都打进去
docker build -t harbor.xxx.com/docker-admin/sonarqube:9.6.1-community-zh . docker push harbor.xxx.com/docker-admin/sonarqube:9.6.1-community-zh
有镜像后通过docker方式或者k8s pod部署都可以的,推荐通过k8s的方式部署。
四、SonarQube使用
多分支扫描
分支代码的质量是和master分支代码质量对比
首先需要扫描master代码的质量,然后再扫描分支的代码质量
master分支ci 触发代码扫描sonar scanner 配置。
`cat /opt/sonar-scanner/conf/sonar-scanner.properties sonar.host.url=http://sonarqube.sonarqube:9000 sonar.login=xxxxxxxx sonar.projectKey=webapp-tomcat sonar.projectName=webapp-tomcat sonar.projectVersion=master_fsfwe135 sonar.sourceEncoding=UTF-8 sonar.ws.timeout=60 sonar.exclusions=**/target/**/*.tar.gz,**/target/**/*.war, *.py, *.tar.gz, *.war, *.sh sonar.java.source=1.8 sonar.java.binaries=**/* sonar.sources=.`
其他分支ci 触发代码扫描sonarscanner 配置,这里的分支名是:create_session
`cat /opt/sonar-scanner/conf/sonar-scanner.properties sonar.host.url=http://sonarqube.sonarqube:9000 sonar.login=xxxxxxxx sonar.projectKey=webapp-tomcat sonar.projectName=webapp-tomcat sonar.projectVersion=master_fsfwe135 sonar.sourceEncoding=UTF-8 sonar.ws.timeout=60 sonar.exclusions=**/target/**/*.tar.gz,**/target/**/*.war, *.py, *.tar.gz, *.war, *.sh sonar.java.source=1.8 sonar.java.binaries=**/* sonar.sources=. sonar.pullrequest.base=master sonar.pullrequest.branch=create_session sonar.pullrequest.key=create_session`
运行之后的效果图,出现错误,说明create_session分支如果要merge到master分支带来bug,建议研发修复
注意:
a. 上面的配置文件没有跟着项目走,是全局的配置
b. 每个项目在跑sonar-scanner之前都会通过CI提前生成sonar-scanner.properties文件,然后在容器运行的sonar-scanner进行代码质量检查
质量检查不通过发送IM告警
master和其他分支代码检查不通过发送告警给开发者和开发者TL 这里使用sonarqube的API结合python实现
首先需要生成token
其次知道API怎么用,拉到web页面右最下方,API帮助文档入口
第三拿到api接口,获取project sonar scan之后的 project_status
直接上伪代码
#/usr/bin/env python # coding: utf-8 import requests import sys import json import time from requests.auth import HTTPBasicAuth `
`token = 'xxxxxxx'`
` # projectKey 最好是模块名,见名知意 project_key=sys.argv[1] pull_request=sys.argv[2] build_user=sys.argv[3] #接口api url = f'https://sonarqube.xxxx.com/api/qualitygates/project_status?projectKey={project_key}' #展示页面,发送消息提醒,后在im里可以直接点击该链接进入sonarqube server web端 durl = f'https://sonarqube.xxxxx.com/dashboard?id={project_key}' #默认url和durl对应的结果是master分支,如果不是master分支,加上pullRequest也即与master分支对别之后的结果。 if pull_request != "master": url = url + f'&pullRequest={pull_request}' durl = durl + f'&pullRequest={pull_request}' #获取开发的leader,这个根据自己家公司api实现即可 def get_user_leader(build_user): return leader def check_scanner_result(): is_ok="OK" try: # sleep 5s ,scan后会有个入库时间有延迟,所以sleep 5s time.sleep(5) #获取scanner结果是否通过代码质量检查 r = requests.get(url % (), auth=HTTPBasicAuth(token, "")).json() is_ok = r['projectStatus']['status'] except: # master 分支没有构建 sys.exit(0) userlist="" #发送IM文案 msg=f"OK: 分支:{pull_request} sonar 代码质量检查通过\n具体请见URL:{durl} \n构建者:{build_user}" if is_ok !="OK": msg=f"ERROR: 分支:{pull_request} sonar 代码质量检查不通过\n具体请见URL:{durl} \n构建者:{build_user}" leader=get_user_leader(build_user) userlist=build_user+","+leader #发送消息,这块也是根据自己家公司api实现即可 content = str(msg) sendmsg(content, userlist) #运行 check_scanner_result()
代码质量检查不通过阻断CI流程
不要sonarqube刚加入CI流程后就阻断CI流程,建议bypass先运行一段时间
和开发团队达成共识,然后在做决定
五、使用中遇到的问题
排除某些规则
和研发达成共识,某些策略可以忽略 比如 css的S4649规则:
调整如下:
排除某些文件不扫描
项目中包含Criteria.java 结尾的文件不扫码
某些项目编译出错,错误如下
ERROR: Error during SonarScanner execution java.lang.IllegalStateException: Can not execute Findbugs at org.sonar.plugins.findbugs.FindbugsExecutor.execute(FindbugsExecutor.java:188) at org.sonar.plugins.findbugs.FindbugsSensor.execute(FindbugsSensor.java:130) at org.sonar.scanner.sensor.AbstractSensorWrapper.analyse(AbstractSensorWrapper.java:64) at org.sonar.scanner.sensor.ModuleSensorsExecutor.execute(ModuleSensorsExecutor.java:88) at org.sonar.scanner.sensor.ModuleSensorsExecutor.lambda$execute$1(ModuleSensorsExecutor.java:61) at org.sonar.scanner.sensor.ModuleSensorsExecutor.withModuleStrategy(ModuleSensorsExecutor.java:79) at org.sonar.scanner.sensor.ModuleSensorsExecutor.execute(ModuleSensorsExecutor.java:61) at org.sonar.scanner.scan.SpringModuleScanContainer.doAfterStart(SpringModuleScanContainer.java:81) at org.sonar.core.platform.SpringComponentContainer.startComponents(SpringComponentContainer.java:188) at org.sonar.core.platform.SpringComponentContainer.execute(SpringComponentContainer.java:167) at org.sonar.scanner.scan.SpringProjectScanContainer.scan(SpringProjectScanContainer.java:396) at org.sonar.scanner.scan.SpringProjectScanContainer.scanRecursively(SpringProjectScanContainer.java:392) at org.sonar.scanner.scan.SpringProjectScanContainer.doAfterStart(SpringProjectScanContainer.java:361) at org.sonar.core.platform.SpringComponentContainer.startComponents(SpringComponentContainer.java:188) at org.sonar.core.platform.SpringComponentContainer.execute(SpringComponentContainer.java:167) at org.sonar.scanner.bootstrap.SpringGlobalContainer.doAfterStart(SpringGlobalContainer.java:135) at org.sonar.core.platform.SpringComponentContainer.startComponents(SpringComponentContainer.java:188) at org.sonar.core.platform.SpringComponentContainer.execute(SpringComponentContainer.java:167) at org.sonar.batch.bootstrapper.Batch.doExecute(Batch.java:72) at org.sonar.batch.bootstrapper.Batch.execute(Batch.java:66) at org.sonarsource.scanner.api.internal.batch.BatchIsolatedLauncher.execute(BatchIsolatedLauncher.java:46) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.base/java.lang.reflect.Method.invoke(Unknown Source) at org.sonarsource.scanner.api.internal.IsolatedLauncherProxy.invoke(IsolatedLauncherProxy.java:60) at com.sun.proxy.$Proxy0.execute(Unknown Source) at org.sonarsource.scanner.api.EmbeddedScanner.doExecute(EmbeddedScanner.java:189) at org.sonarsource.scanner.api.EmbeddedScanner.execute(EmbeddedScanner.java:138) at org.sonarsource.scanner.cli.Main.execute(Main.java:112) at org.sonarsource.scanner.cli.Main.execute(Main.java:75) at org.sonarsource.scanner.cli.Main.main(Main.java:61) Caused by: java.lang.IllegalStateException: One (sub)project contains Java source files that are not compiled (/data/data/jenkins-node/workspace/weapp-tomcat_master). sonar.java.binaries was set to **/* Sonar JavaResourceLocator.classFilesToAnalyze was empty at org.sonar.plugins.findbugs.FindbugsConfiguration.buildMissingCompiledCodeException(FindbugsConfiguration.java:153) at org.sonar.plugins.findbugs.FindbugsConfiguration.initializeFindbugsProject(FindbugsConfiguration.java:123) at org.sonar.plugins.findbugs.FindbugsExecutor.execute(FindbugsExecutor.java:117) ... 31 more ERROR: ERROR: Re-run SonarScanner using the -X switch to enable full debug logging.
错误原因:当安装Findbugs插件后,JSP的默认profiles被设置为FindBugs Security JSP。
Findbugs分析的不是java源代码,而是编译后的class文件。通过下图进行配置忽略未编译的jsp文件。
下面是全局配置,对所有项目都生效:
针对某些项目生效:
在CI时针对该模块配置文件sonar-scanner.properties
单独写上 sonar.findbugs.allowuncompiledcode=true
今天只要你给我的文章点赞,我私藏的网安学习资料一样免费共享给你们,来看看有哪些东西。
网络安全学习资源分享:
给大家分享我自己学习的一份全套的网络安全学习资料,希望对想学习 网络安全的小伙伴们有帮助!
零基础入门
对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。
【点击免费领取】CSDN大礼包:《黑客&网络安全入门&进阶学习资源包》
1.学习路线图
攻击和防守要学的东西也不少,具体要学的东西我都写在了上面的路线图,如果你能学完它们,你去接私活完全没有问题。
2.视频教程
网上虽然也有很多的学习资源,但基本上都残缺不全的,这是我自己录的网安视频教程,上面路线图的每一个知识点,我都有配套的视频讲解。【点击领取视频教程】
技术文档也是我自己整理的,包括我参加大型网安行动、CTF和挖SRC漏洞的经验和技术要点,电子书也有200多本【点击领取技术文档】
(都打包成一块的了,不能一一展开,总共300多集)
3.技术文档和电子书
技术文档也是我自己整理的,包括我参加大型网安行动、CTF和挖SRC漏洞的经验和技术要点,电子书也有200多本【点击领取书籍】
4.工具包、面试题和源码
“工欲善其事必先利其器”我为大家总结出了最受欢迎的几十款款黑客工具。涉及范围主要集中在 信息收集、Android黑客工具、自动化工具、网络钓鱼等,感兴趣的同学不容错过。
最后就是我这几年整理的网安方面的面试题,如果你是要找网安方面的工作,它们绝对能帮你大忙。
这些题目都是大家在面试深信服、奇安信、腾讯或者其它大厂面试时经常遇到的,如果大家有好的题目或者好的见解欢迎分享。
参考解析:深信服官网、奇安信官网、Freebuf、csdn等
内容特点:条理清晰,含图像化表示更加易懂。
内容概要:包括 内网、操作系统、协议、渗透测试、安服、漏洞、注入、XSS、CSRF、SSRF、文件上传、文件下载、文件包含、XXE、逻辑漏洞、工具、SQLmap、NMAP、BP、MSF…
👋全套《黑客&网络安全入门&进阶学习资源包》👇👇👇
这份完整版的学习资料已经上传CSDN,也可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费
】