一、Sonarqube简述
Sonarqube是一个静态代码扫描工具,通过在代码开发早期阶段的检测扫描,发现代码中存在的问题,提升代码的安全性、可靠性及可维护性,Sonarqube可以和现有的开发工具进行集成,目前支持30多种不同的编程语言,相关资料可以在官方网站可查看:https://docs.sonarsource.com/sonarqube/latest/。Sonarqube由扫描器Scanner、服务器SonarbueServer以及数据库服务器组成。
二、Sonarqube安装与部署
Sonarqube服务器对安装的硬件、软件均有一定的要求,可以在官网https://docs.sonarsource.com/sonarqube/latest/setup-and-upgrade/installation-requirements/server-host/进行查看,特别注意JDK的版本。我这里安装时的关键信息如下:
1、服务器:windows 10 64位
2、Sonarqube版本号:社区版本,sonarqube-10.6
3、JDK版本:Java 17
(一)安装数据库
默认情况下,Sonarqube有一个内嵌的数据库,但是该数据库仅用于测试,通过官方的网站介绍可以看到目前支持的数据库有PostgreSQL、MicrosoftSQLServer、Oracle,相关的版本可以在官网查看。这里我是用于测试,就使用内置的数据库即可。
(二)安装服务器
从官网下载发行版本,包括linux版本、windows版本、MACOS版本等,根据自己的需求下载,然后解压到指定的目录,配置数据库信息,然后启动服务。
1、下载sonarqube并解压:
2、进入windows-x86-64文件夹,双击StartSonar.bat启动服务,看到如下提示后,表示服务运行正常:
说明:一定要确保sonarqube版本、java版本匹配,否则报错:
jvm 1 | Unrecognized VM option 'UseConcMarkSweepGC'
jvm 1 | Error: Could not create the Java Virtual Machine.
jvm 1 | 2024.07.28 15:56:26 WARN app[][o.s.a.p.AbstractManagedProcess] Process exited with exit value [es]: 1
jvm 1 | Error: A fatal exception has occurred. Program will exit.
jvm 1 | 2024.07.28 15:56:26 INFO app[][o.s.a.SchedulerImpl] Process[es] is stopped
jvm 1 | 2024.07.28 15:56:26 INFO app[][o.s.a.SchedulerImpl] Waiting for Elasticsearch to be up and running
jvm 1 | 2024.07.28 15:56:26 INFO app[][o.s.a.SchedulerImpl] SonarQube is stopped
wrapper | <-- Wrapper Stopped
3、登录Sonarqube服务器:
登录地址:http://127.0.0.1:9000/
默认登录信息:admin/admin,首次登录时,根据提示进行密码修改。
登录后界面如下:
4、进行汉化操作:
在Administration——Marketplace中搜索chinese,找到Chinse Pack,点击install进行安装,完成后页面提示进行重启,重启后即可进行汉化。
5、几个重要的菜单介绍:
(1)项目:可以创建一个项目信息,并且查看项目信息
(2)问题:显示当前所有的问题,或者分配给我的问题
(3)代码规则:在该页面展示了当前支持的语言,以及每种语言支持的检测规则,依据代码语言、整洁代码属性、软件质量、严重性、类型、标准等进行分类。比如我比较关注的是代码的安全性,那么在“标准”中可以看到SonarSource、2021年度OWASPTOP10等,如下:
(4)质量配置:在质量配置中定义了每种语言应用的规则集合,可以在这里针对每种语言自定义质量配置,并且设置其应用的项目,或者设置为默认的质量配置,如下为Java的质量配置,其有一个默认的配置为Sonar way,一共有512条规则:
(5)质量门禁
质量门禁是一系列基于指标的布尔表达式。它可以帮助我们实时了解项目是否已经满足生产要求了。在这里可以设置门禁的条件,以及该门禁适用的项目,默认的门禁条件包括:
(a)新代码零问题
(b)已复审所有安全热点
(c)新代码已被充分测试,其测试的覆盖率 大于等于80%
(d)新代码只有有限的重复,其重复行的比例小于等于3.0%
默认情况下Sonar way为默认的质量门禁,没有指定质量门禁的项目均会应用该质量门禁。
可以通过左上角的“创建”按钮,根据自己的需求去定义新的质量门禁。
三、使用Sonarqube进行代码质量测试
下面使用Sonarqube进行质量扫描。可以在IDEA中集成sonarlint插件,在编码过程中实时进行代码质量检测,也可以在项目完成后提交到流水线过程中进行检测,也可以在项目编码完成后通过sonar-scanner对项目进行检测,并将检测结果上传到sonarqube服务器进行展示。
下面通过sonnar-scanner进行扫描:
1、在官网下载SonarScannerCLI,我下载的是Windows x64,下载地址:https://docs.sonarsource.com/sonarqube/latest/analyzing-source-code/scanners/sonarscanner/
2、配置sonar-scanner.properties
在conf目录中找到sonar-scanner.properties文件,在其中配置必要的信息,包括sonar.host.url、sonar.login、sonar.password等,如下:
3、配置环境变量
将\bin\sonar-scanner.bat所在的目录添加到环境变量中,如下:
通过sonnar-scanner -v查看版本信息,表示配置完成。
4、配置待扫描的项目信息
(1)准备一个待扫描的项目,我从GIT上下载了一份Hello-Java-Sec-1.7的源代码,该项目为Java代码的靶机。
(2)在项目在根目录中手工添加一个sonar-project.properties文件,内容如下:
# projectKey是SonarQube 实例的唯一标识
sonar.projectKey=javasec02
# projectName通常与projectKey保持一致
sonar.projectName=javasec02
# 代码相对于 sonar-project.properties 文件路径,默认为.
sonar.sources=.
# 对于java代码,必须指定classes的路径,里面可以没有内容,但是必须指定
sonar.java.binaries=target/classes
经过如上的配置后,sonnar-scanner扫描后会将结果同步到sonarqube,并根据projectKey创建一个项目,不需要手工提交在sonarqube中提前创建项目。
5、在sonar-project.properties路径下执行sonar-scanner进行扫描:
扫描结束:
6、在sonarqube中查看结果:
可以看到在javasec02右上角有一个“正常”的标识,其为质量门禁的标识,由于当前为第一扫描,代码未发现变化,对于新的代码未发现任何的质量问题,因此显示正常。但是仍然可以看到代码中存在2个安全性问题、100个可可靠性问题等。
四、调整质量配置与质量门禁
现在假设我有一个代码质量的需求,我特别关注Java代码的安全性,因此可以在质量配置中创建一个Java的质量配置,启用我需要的安全规则,并设置为默认,然后在质量门禁中,创建一个新的质量门禁,调整门禁的条件,选择其应用的项目,或者设置为默认的质量门禁即可。
Sonarqube的思想遵循“编码时清理”(Clean as You Code),每次在有新增的代码时,将会对新增的代码进行扫描,并且应用质量门禁,确保每次新增或者代码变化均不引入新的问题,而对于存量的问题则进行逐步修复。
1、现在在上面的代码基础之上,我们引入一个新的文件,在controller中增加一个TestController.sqltest的文件,添加一些存在SQL Injection的问题代码:
2、我们再次使用sonar-scanner进行扫描,并查看结果,可以看到在新增的代码中检测到了问题:
3、现在我想关注安全类的问题,不需要使用默认的配置,先配置质量配置:
(1)在“质量配置”菜单中点击“创建”,选择语言为Java,名称自定义为Java安全配置:
创建后如下:
(2)当前激活的规则数量为0,并且未应用到项目中。现在手工激活安全相关的规则,点击“667禁用规则”会跳转到代码规则中,我在“标准”中将2021年度OWASPTOP10全部激活:
(3)再回到质量配置中,看到已经有64条规则被激活,并且在右上角可以下拉,设置为默认。
4、现在配置质量门禁
(1)在质量门禁菜单中点击“创建”,自定义名字为:qulitity_gatekeeper_test,可以得到一个内置的质量门禁,然后点击下面的“解锁编辑”后可以进行质量门禁的编辑,可以新增条件,或者删除条件,调整条件的阈值等,如下:
这里把代码覆盖率调整为0,还可以根据自己的需求,添加Vulnerabilities的数量、等级等条件。说明:这里的条件,我理解是满足条件时,质量门禁检查失败。
(2)设置质量门禁为默认
(3)再次进行代码扫描,可以看到两个条件失败(不再检查代码的覆盖率),结果如下:
顺便看一下扫描的日志中调用 的质量配置为java安全配置,如下:
五、根据代码质量进行代码质量优化
可以看到结果中显示有1个问题、安全热点审查率为0%,接下来我们开始进行代码的修复。
1、问题修复
点击问题
这里给出了问题的位置、问题原因、修复方法等内容,我们通过IDEA回到源代码中,将这里的sqlpass引用一个变量,完成修复,如下:
2、继续查看安全热点审查,点击可以看到详细信息,这里因为使用了SQL语句拼接,因此这里存在SQL Injection的问题,如下:
现在回到IDEA代码中,调整为参数预编译的方式:
3、再次扫描,并查看结果,还有一个低优先级的问题:
对于该问题我想忽略处理,因此可以点击“复审”,然后手工设置为安全,如下:
4、再次查看项目信息,现在质量门禁已经通过,如下:
六、在编码过程中实时进行代码质量检查
经过上面的步骤已经可以手工将项目进行提交扫描,并且对于变化的代码通过质量门禁进行检查了,但是如果在程序开发过程中,希望再检查再进一步前置,可以在开发工具中集成sonarlint插件,然后对于代码的变化进行实时的检查。现在我们在IDEA中去安装sonarlint,通过sonarlint与sonarqube的联动,完成代码在开发工具中的实时检查。
1、安装sonarlint插件
在Marketplace中搜索sonarlint,进行安装即可
2、配置sonarlint插件
(1)配置与sonarqube的连接:
这里配置连接信息,我使用的是http://127.0.0.1:9000
这里sonarlint会自动打开sonarqube的页面,让用户确认是否获取token,也可以在sonarqube界面手工配置一个token,然后使用。
(2)接下来配置projectKey,直接手工选择,点击确认后sonarlint会自动从sonarqube同步扫描信息过来。
(3)现在在IDEA中修改代码,我将SQL语句查询还原为参数拼接,未使用预编译:
可以看到在IDEA中进行了提示。
(4)现在在IDEA中将SQL语句参数拼接修改为参数预编译:
可以看到右上角的提示变为正常的了,无告警信息。
七、总结
本篇为sonarqube的安装及代码质量扫描的简要说明,这是近期作者在工作中需要用到的,因此进行了学习记录,在这里我们使用的是sonar-scanner进行扫描,并在IDEA中安装sonarlint插件,通过实时扫描与项目整体扫描相结合的方式,提高代码质量。不过还存在的问题是,目前我们还在使用代码仓库及Jenkins流水线,还需要进一步优化,以使得在进行代码合并的时候完成代码质量检测,以避免将存在问题的代码引入生产环境中。