背景:

Dev已经习惯使用Sonarqube进行静态代码扫描,现准备进行阶段审计看下使用效果怎么样。

PS:
1. Sonarqube根据Key来唯一标示项目。
2. Resolution 里面的False Positive(误报)和 Won’t fix(暂不处理)会自动继承:
- 如果一个问题本次标记为False Positive 或者 Won’t fix
- 以后此项目进行分析时此问题自动标记。
- 其他项目(Key不同)还是会报此问题。
logo
logo

思路:

Dev正常进行开发过程的静态代码扫描,SCM对项目主干(master)代码进行轮询静态代码扫描。
1. 主干代码静态代码扫描时Project Key增加统一标志来区分Dev开发过程扫描:
- 例如:修改maven pom文件 artifactId增加 master/admin/scm 后缀
2. 更新Dev开发过程项目标记规则到主干。

同步不同项目标记规则:

  1. 安装Issue resolver插件:
    • Export and import resolved issues (false-positive and won’t fix) from SonarQube projects.
  2. 更新dev项目标记规则到主干项目:
    - web端操作方法:
    logo
    logo

Comment and share

参考链接:

系统环境:

  • Gradle: 2.10
  • Sonarqube: 6.3.1

背景:

1
2
3
公司使用java语言开发Android项目,使用Gradle作为构建工具。
默认的Sonarway java规则也可以进行静态代码扫描。
希望增加业界常用的Android lint规则进行扫描,本文记录配置使用方法。

Sonarqube 安装 Android lint插件

logo
点击Quality Profiles查看Android Lint规则
logo


Sonarqube 配置Android项目扫描规则

我们配置一个新的Quality Profiles/java用于Android项目扫描。

新规则 包含Java Sonar way的Bugs、Vulnerabilities 和 Android Lint的Code Smells
logo
logo
logo
logo
logo
logo
logo


本地配置使用

  • 配置系统gradle.properties增加下面内容 (~/.gradle/gradle.properties)
1
2
3
systemProp.sonar.host.url=http://ip:9000
#----- Security (when 'sonar.forceAuthentication' is set to 'true')
systemProp.sonar.login=个人token
  • 修改项目build.gradle 相应位置增加下面配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
apply plugin: "org.sonarqube"
buildscript {
repositories {
maven{url "https://plugins.gradle.org/m2/"}
}
dependencies {
classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.5"
}
}
sonarqube {
androidVariant 'fullDebug'
properties {
property "sonar.projectName", "项目名称"
property "sonar.projectKey", "项目Key"
property "sonar.projectDescription", "项目描述"
property "sonar.projectVersion", "项目版本"
property "sonar.profile", "Android(上面新建的profile名称)"
property "sonar.android.lint.report", "./build/outputs/lint-results-debug.xml"
}
}
  • 执行gradle lintDebug 生成lint-results-debug.xml

  • 执行gradle Sonarqube 构建、分析、上传

Comment and share

Analyzing Source Code

参考链接:官方文档

本文只涉及maven和sonar-scanner方式,其它请参考上面链接。

Maven

适合Maven项目

  1. 在sonarqube平台上面个人账户生成token。
  2. 在本机的mvn配置settings.xml 增加下面配置
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <profile>
    <id>sonar</id>
    <activation>
    <activeByDefault>true</activeByDefault>
    </activation>
    <properties>
    <sonar.host.url>http://ip:9000</sonar.host.url>
    <sonar.login>第一步生成的token值</sonar.login>
    </properties>
    </profile>
  3. 代码库执行打包:mvn clean install
  4. 代码库进行分析并上传sonarqube平台:mvn sonar:sonar

PS:

1
2
3
4
5
6
7
8
9
10
11
12
如果代码库pom文件配置如下
<groupId>ggg</groupId>
<artifactId>aaa</artifactId>
<version>1.0.0</version>
<name>nnn</name>
那么分析上传到sonarqube平台:
对应的项目key为ggg:aaa
对应的项目名称为nnn
对应的版本为:1.0.0
注意
   不要找错项目了。
   同一个key指向的项目永远显示的是最新的一次代码分析结果。

Sonar-scanner

适合所有项目

  1. 下载Sonar-scanner,设置环境变量,配置/conf/sonar-scanner.properties
    1
    2
    3
    4
    5
    6
    7
    #Configure here general information about the environment, such as SonarQube DB details for example
    #No information about specific project should appear here
    #----- Default SonarQube server
    sonar.host.url=http://ip:9000
    #----- Default source code encoding
    sonar.sourceEncoding=UTF-8
    sonar.login=个人账户生成的token
  2. 在项目根目录增加sonar-project.properties,内容如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # must be unique in a given SonarQube instance
    sonar.projectKey=ggg:aaa #对应的项目key为ggg:aaa
    # this is the name and version displayed in the SonarQube UI. Was mandatory prior to SonarQube 6.1.
    sonar.projectName=nnn #对应的项目名称为nnn
    sonar.projectVersion=1.0.0 #对应的版本为:1.0.0
    # Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows.
    # This property is optional if sonar.modules is set.
    sonar.sources=.
    sonar.java.binaries=target/classes #配置为项目具体的class目录,如果不配置的话只进行源代码分析
    # Encoding of the source code. Default is default system encoding
    #sonar.sourceEncoding=UTF-8
  3. 执行扫描分析:
    Build(可以不执行构建)
    sonar-scanner

API

点击:http://ip:9000/web_api/ ,查看Sonarqube支持的web_api。

以Python2.7 为例简单介绍api使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import requests

s = requests.session()
user_info = {'login': 'username', 'password': 'pass'}
api_url = 'http://ip:9000/api'
# 登录
res_login = s.post(
'%s/authentication/login' % api_url, data=user_info)
# 获取指定项目未解决Bugs详情
res_bugs = s.get(
'%s/issues/search' % api_url, params={'componentKeys': 'ggg:aaa', 'types': 'BUG', 'resolved': 'false', 'ps': 500})
# 解析结果获取未解决bugs总数
total_bugs = res_bugs.json()[u'paging'][u'total']
# 获取指定项目新增未解决Bugs详情
res_new_bugs = s.get(
'%s/issues/search' % api_url, params={'componentKeys': 'ggg:aaa', 'types': 'BUG', 'resolved': 'false', 'ps': 500, 'sinceLeakPeriod': 'true'})
# 解析结果获取新增bugs总数
new_bugs = res_new_bugs.json()[u'paging'][u'total']
# 登出
res_logout = s.post(
'%s/authentication/logout' % api_url)

Comment and share

关联LDAP:

登录Sonarqube服务器,修改安装目录下的conf\sonar.properties文件。

1
2
3
4
5
6
7
8
9
10
11
12
# LDAP configuration
# General Configuration
sonar.security.realm=LDAP
ldap.url=ldap://ip:389
ldap.bindDn=cn=Manager,dc=xxx,dc=xxx,dc=xxx
ldap.bindPassword=xxx

# User Configuration
ldap.user.baseDn=ou=People,dc=xxx,dc=xxx,dc=xxx
ldap.user.request=(&(objectClass=inetOrgPerson)(uid={0}))
ldap.user.realNameAttribute=cn
ldap.user.emailAttribute=mail

然后重启Sonarqube服务,即可使用LDAP账户进行登录。


下面配置涉及下图:
logo

插件:

  • 参考链接:官方文档
  • 插件安装、更新有两种方法:
    1. 手动下载后,上传到Sonarqube服务器安装目录下的\extensions\plugins,然后重启Sonarqube服务。
    2. 管理员账户登录Sonarqube,点击Administration - System - Update Center,进行安装or更新插件。(推荐!)

配置邮件发送:

  1. 使用管理员账户登录Sonarqube,
  2. 点击:Administration - General Settings
  3. 找到Email配置区域,涉及以下几个SMTP配置:
    1
    2
    3
    4
    5
    6
    7
    8
    # 下面以QQ邮箱为例
    SMTP port 465
    SMTP host smtp.exmail.qq.com
    From address xxx@qq.com
    Email prefix [SONARQUBE]
    Secure connection ssl
    SMTP password 对应上面账户的密码
    SMTP username xxx@qq.com

权限相关:

因为Sonarqube是为了发现代码问题,所以会在结果中展示源代码。为了代码安全,需要对权限进行配置。

Force user authentication

1
2
3
使用管理员账户登录Sonarqube,点击Administration - General Settings - security
Force user authentication ☑️ 强制必须登录后才能使用
Default user group sonar-users 默认新用户所在组

Users

1
2
3
4
使用管理员账户登录Sonarqube,点击Administration - Security - Users
此页面可以创建、修改、删除用户。
此页面还可以调整用户所在组信息。
如果是关联了LDAP,那么用户只有先使用LDAP账户登录后,才能在此查看到。

Groups

1
2
3
4
5
6
使用管理员账户登录Sonarqube,点击Administration - Security - Groups
此页面可以创建、删除组。
此页面还可以调整组用户。
默认存在下面2个组:
sonar-administrators
sonar-users

Global Permissions

1
2
3
4
5
6
7
使用管理员账户登录Sonarqube,点击Administration - Security - Global Permissions
此页面配置组用户的全局权限:
Administer System 系统管理员 sonar-administrators
Administer Quality Profiles 可以配置Quality Profiles sonar-administrators
Administer Quality Gates 可以配置Quality Gates sonar-administrators
Execute Analysis 可以执行代码库分析 sonar-users 或者 创建的组
Create Projects 可以上传新代码库分析 sonar-users 或者 创建的组

Permission Templates

1
2
3
4
5
6
7
8
使用管理员账户登录Sonarqube,点击Administration - Security - Permission Templates
此页面配置项目模版权限。
此页面还可以设置默认模版(新项目自动设置为默认模版权限)。
Browse 查看项目状态
See Source Code 查看项目源代码
Administer Issues 对此项目的问题进行判断、评论、更改状态
Administer 项目管理员
Execute Analysis 执行代码库分析

Project PermissionsGrant

配置项目权限,有下面两种方法:

  1. 只需要项目管理员权限即可
    1
    2
    3
    点击项目界面 - Administration - Permissions
    可以增加、删除、更新组or个人对此项目权限
    可以使用权限模版对此项目进行赋权
  2. 需要系统管理员权限
    1
    2
    3
    使用管理员账户登录Sonarqube,点击Administration - Projects - Management
    此界面展示所有项目,找到需要修改项目后。
    点击最右边的Actions,进行权限修改or使用权限模版进行权限更新。

规则配置:

配置扫描使用的规则
logo

Comment and share

参考链接:

PS:

  • Sonarqube自带了轻量级的H2数据库,测试和跑少量项目是没有问题的。基于后期的性能、运维、扩展等考虑,我们选择使用Mysql数据库。
  • Sonarqube自带了web server,也可以使用Tomcat来进行加载。基于以往的使用经验默认的web server足够使用,我们选择默认。

搭建环境

  • OS: Windows Server 2012 R2
  • JDK: 1.8.0_71
  • DB: Mysql 5.6.26
  • Sonar: 6.3.1

搭建步骤

  1. 安装JDK

    1
    2
    3
    4
    C:\Users\Administrator>java -version
    java version "1.8.0_71"
    Java(TM) SE Runtime Environment (build 1.8.0_71-b15)
    Java HotSpot(TM) 64-Bit Server VM (build 25.71-b15, mixed mode)
  2. 安装Mysql

    1
    2
    C:\Users\Administrator>mysql -V
    mysql Ver 14.14 Distrib 5.6.26, for Win64 (x86_64)
  3. 创建数据库和用户

    1
    2
    3
    4
    5
    6
    7
    8
    # 创建sonar数据库
    CREATE DATABASE sonar CHARACTER SET utf8 COLLATE utf8_general_ci;
    # 创建sonar用户
    CREATE USER 'sonar' IDENTIFIED BY 'passwd';
    # 赋予sonar用户对sonar数据库权限
    GRANT ALL ON sonar.* TO 'sonar'@'%' IDENTIFIED BY 'passwd';
    GRANT ALL ON sonar.* TO 'sonar'@'localhost' IDENTIFIED BY 'passwd';
    FLUSH PRIVILEGES;
  4. 安装Sonarqube

    • 解压缩sonarqube-6.3.1.zip到D:\scm\sonarqube-6.3.1

    • 修改配置D:\scm\sonarqube-6.3.1\conf\sonar.properties

      • sonar.jdbc.username=sonar
      • sonar.jdbc.password=passwd
      • sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance
      • sonar.web.host=本机IP
      • sonar.web.context=
      • sonar.web.port=9000
      • sonar.web.http.maxThreads=500
    • 配置Sonarqube windows服务

      1. 以管理员身份运行D:\scm\sonarqube-6.3.1\bin\windows-x86-64\InstallNTService.bat创建服务
        logo
      2. 配置Administrator账户运行Sonarqube服务
        logo
      3. 启动Sonarqube服务
        • 建议使用上面配置的windows service启动
        • 也可以直接运行D:\scm\sonarqube-6.3.1\bin\windows-x86-64\StartSonar.bat
  5. 网页端登陆配置Sonarqube

    • http://搭建机器ip:9000
    • 用户名/密码:admin

PS1:

在安装的过程中遇到问题:

  • 运行InstallNTService.bat生成系统服务的时候没有使用管理员身份;
  • Sonarqube服务创建成功,但是启动的时候失败;
    1
    2
    3
    4
    2017.06.20 14:34:50 ERROR web[][o.a.c.c.C.[.[.[/]] Exception sending context initialized event to listener instance of class org.sonar.server.platform.web.PlatformServletContextListener
    org.sonar.api.utils.MessageException: Current version is too old. Please upgrade to Long Term Support version firstly.
    2017.06.20 14:34:50 ERROR web[][o.a.c.c.StandardContext] One or more listeners failed to start. Full details will be found in the appropriate container log file
    2017.06.20 14:34:50 ERROR web[][o.a.c.c.StandardContext] Context [] startup failed due to previous errors
  • 查看发现mysql数据库sonar已经有了很多表;

解决方法:

  1. 删除sonar数据库里面的表,删除Sonarqube服务
  2. 安装上面过程:先以管理员身份运行InstallNTService.bat,然后配置Administrator账户运行Sonarqube服务
  3. 重新启动Sonarqube服务即可。

PS2:

如果Mysql数据库启用了binarylog的话,请设置为row格式。否则在启动Sonarqube的时候创建数据库表会报下面错误:

1
2
Error updating database.  Cause: java.sql.SQLException: Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging. InnoDB is limited to row-logging when transaction isolation level is READ COMMITTED or READ UNCOMMITTED.

Comment and share

参考链接:


静态代码分析:

  • 定义:不运行计算机程序的条件下,进行程序分析的方法。
  • 目的:验证代码是否满足规范性、安全性、可靠性、可维护性等指标,发现代码缺陷并提高代码的质量。
  • 范围:源代码(主要)、编译产生的字节码。
  • 常用技术:
    • 词法分析:通过正则表达式匹配将源代码转换成标记序列。
    • 语法分析:判断源程序结构上是否正确,通过使用上下文无关语法将相关符号整理为语法树。
    • 语义分析:对结构上正确的源程序进行上下文有关性质的审查。
    • 抽象语法树:将程序组织成树形结构,树中相关节点代表了程序中的相关代码。
    • 控制流分析:生成有向控制流图,用节点表示基本代码块,节点间的有向边代表控制流路径,反向边表示可能存在的循环;还可生成函数调用关系图,表示函数间的嵌套关系。
    • 无效代码分析:根据控制流图可分析孤立的节点部分为无效代码。
      数据流分析:对控制流图进行遍历,记录变量的初始化点和引用点,保存切片相关数据信息。
    • 污点分析:基于数据流图判断源代码中哪些变量可能受到攻击,是验证程序输入、识别代码表达缺陷的关键。
    • 缺陷模式匹配:缺陷模式匹配事先从代码分析经验中收集足够多的共性缺陷模式,将待分析代码与已有的共性缺陷模式进行模式匹配,从而完成软件的安全分析。

Java开源静态代码分析工具对比:

工具 源代码分析 字节码分析 定位 官网地址 版本 其它语言支持
Checkstyle Y 验证符合编码规则 http://checkstyle.sourceforge.net 7.8.2(2017.6.18)
FindBugs Y 发现Bugs http://findbugs.sourceforge.net 3.0.1(2015.3.6)
PMD Y 发现缺陷 https://pmd.github.io 5.8.0(2017.6.24) Y
Sonarqube Y Y 持续质量平台 https://www.sonarqube.org 6.3.1(2017.4.12) Y

PS:

1
2
3
4
5
6
7
最初Sonarqube只是做静态代码分析结果聚类展示。
后来随项目的发展,考虑到静态代码分析工具发展的不可控性(毕竟不属于自身项目),Sonarqube开始也涉及静态代码分析。
在此过程中,Sonarqube借鉴了Checkstyle、FindBugs、PMD的规则方法。
所以,本篇所指的Sonarqube既包含静态代码分析SonarJava(主要)又包含结果展示。
以上参考下面链接:
https://groups.google.com/forum/#!topic/sonarqube/9M0iZ4OILVM
https://blog.sonarsource.com/sonarqube-java-analyzer-the-only-rule-engine-you-need/

Checkstyle:

官网:检查规则

主要涉及以下几个方面:

  • 注解
  • javadoc注释
  • 命名规范
  • 文件头
  • 导入包规范
  • 尺寸设置
  • 空格
  • 正则表达式
  • 修饰符
  • 代码块
  • 编码问题
  • 类设计问题
  • 重复、度量以及一些杂项

FindBugs:

官网:检查规则

主要涉及以下几个方面:

  • Multithreaded correctness - 如多线程编程时常见的同步、线程调度问题。
  • Performance - 如由变量定义、方法调用导致的代码低效问题。
  • Internationalization - 如错误的字符串转换带来的国际化问题。
  • code vulnerabilities - 可能受到的恶意攻击,如访问权限修饰符的定义等。
  • possible bugs - 可能导致错误的代码,如空指针引用,常见代码错误,序列化错误。
  • Bad practice - 如命名不规范(类名应以大写字母开头),没有finally来关闭IO流,不检查方法返回值等。
  • Correctness - 正确性问题,如instanceof永远返回false。

PMD:

官网:Java检查规则

主要涉及以下几个方面:

  • Possible bugs - empty try/catch/finally/switch statements
  • Dead code - unused local variables, parameters and private methods
  • Suboptimal code - wasteful String/StringBuffer usage
  • Overcomplicated expressions - unnecessary if statements, for loops that could be while loops
  • Duplicate code - copied/pasted code means copied/pasted bugs

Sonarqube

官网:Java检查规则

主要涉及以下几个方面:

  • Bugs
  • Vulnerability
  • Code Smell

VS:

规则覆盖:

  • 目前Sonarqube自带的SonarJava插件检查规则几乎包含了Checkstyle、FindBugs、PMD的规则。
  • 在具体的一些问题上面,几款工具各有千秋。
  • 存在同一个问题几款工具分别对其进行不同标注情况。

结果输出展示:

  • Checkstyle、FindBugs、PMD 运行结果输出支持Xml和Html格式。
  • Sonarqube 运行结果存入数据库,web端展示。支持和上次结果对比。可视化做的很赞!

工具更新:

  • FindBugs已经很久不更新了。
  • Checkstyle、PMD、Sonarqube更新频率都挺高的。

检查范围:

  • FindBugs 只对编译产生的class文件进行检查
  • Checkstyle、PMD 只对源代码进行插件
  • Sonarqube:
    • 对于所有支持的编程语言,SonarQube 都提供源了代码的静态分析功能;
    • 对于某些特定的编程语言,SonarQube 提供了对编译后代码的静态分析功能,比如 java 中的 class file 和 jar 和 C# 中的 dll file 等;
    • 对于某些特定的编程语言,SonarQube 还可以提供对于代码的动态分析功能,比如 java 和 C# 中的单元测试的执行等。

结论:

  • 推荐使用Sonarqube来进行Java代码静态扫描。
  • 自带的SonarJava插件规则已经够用,建议直接上手使用。
  • 在使用过程中可以补充Checkstyle、FindBugs、PMD相应规则到Sonar检查。

Comment and share

  • page 1 of 1
Author's picture

Weilong

    Write something about work-life:

PM


Shenzhen