极狐GitLab 集成 sonarqube 实践指南

极狐GitLab 集成 sonarqube 实践指南

首页休闲益智Project Cat更新时间:2024-05-04
背景场景外部扫描器选型 SonarQube-CE快速入门

直接在.gitlab-ci.yml文件中填入如下内容,触发扫描,即可在漏洞报告中查看结果。

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

以下仓库参考:

使用方法

参考dvwa仓库中的配置方法。

SonarQube-CE部署环境变量配置

在project级别中,settings - CI/CD - Variables中添加如下2个变量指向SonarQube服务。

.gitlab-ci.yml配置

在待扫描仓库中增加.gitlab-ci.yml配置文件,如下,不建议直接把敏感信息如快速入门那样配置在ci文件中。

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

然后进行扫描即可得到扫描结果。

报告总览

特定issue展现image

文件定位image

SonarQube说明SonarQube原理

docker方式部署 SonarQube-CE 7.6

根据文章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端导出json格式的报告,因此部署支持的旧版本中的最后一个版本,即7.6版。

PgSql

参考docker 安装SonarQube 步骤以及遇到的坑进行部署,

创建工作目录

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

创建网络

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 \ postgresSonarQube

创建工作目录

mkdir -p /data/sonarqube_dir

修改系统参数

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

运行测试容器

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

拷贝必须文件到本地,并修改权限为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

启动SonarQube,其中SONARQUBE_jdbc_URL的IP地址需要修改为实际PgSql数据库的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 ),默认用户名密码为admin/admin,在My Account - Security中生成Token。

部署使用sonar-scanner

参考SonarScanner下载最新版的扫描器。

解压后,进入bin目录,执行如下命令即可完成扫描,扫描完成后可以去SonarQube中查看扫描结果。

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

如果想要在本地生成json格式报告,则增加如下参数

-Dsonar.report.export.path=report.json \ -Dsonar.analysis.mode=preview 扫描器制作json 格式转换

基于以上内容,关键是把扫描结果转化为极狐GitLab旗舰版所识别的json格式。

json 样本

SonarQube扫描结果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报告展现issue样本

{ "category": "test", "message": "这个问题不怎么严重", "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" } ] }转换器 converter.py

转码程序采用python,编写converter.py文件,内容如下:

# 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

基于环境变量进行扫描

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.jsonDockerfile

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 /构建与推送

制作好的镜像已经推送到DockerHub中,采用前文使用方法中所说的内容即可实现扫描。

docker build -t satomic/sonarscanner:v6 . docker push satomic/sonarscanner:v6findbugs支持安装插件Server端安装Findbugs插件

到SonarQube的容器内部

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上检查是否安装成功,出现如下画面即表示可以。

配置Java默认规则

在sonar UI上进行如下配置,这样Java的默认规则就是Findbugs了

Java maven 扫描器制作

因为扫描Java项目需要代码经过编译,所以需要对扫描器配置maven扫描能力。理论上,通过在Dockerfile中添加安装maven包即可,但是失败,因此直接在前述步骤构建出的镜像中操作完后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

此时,考虑到参数暴露的问题,仅仅把如下4个参数内置到扫描器内部,因此修改scan.sh文件如下

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 /

构建出最新镜像

docker build -t satomic/sonarscanner:v9-mvn . docker push satomic/sonarscanner:v9-mvn使用.gitlab-ci.yml更新

为了支持Findbug的触发,需要使用如下配置

# 正常情况下应该配置在settings设置的环境变量中,而不是如此明文暴露 variables: sonar_host_url: http://1.13.160.207:9000 sonar_login: 333f3410ce3e575d559329e8f3d0a5d4ec8a499d sonarqube: artifacts: reports: sast: - gl-sast-report.json script: # 通过在此动态生成 sonar-project.properties 配置,而无需侵入源码仓库 # 同同时可以提高自由度 - 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 # 创建构建物目录 - mkdir -p target/classes # 此命令是否执行成功依赖mvn配置的合理性,需要实际仓库的研发介入,配合配置的可用性,默认可访问官方mvn库的外网环境问题不大,内网则不太可能编译成功 - mvn compile # 查看编译产物 - tree target/classes # 执行sonar扫描 - /scan.sh # 查看报告生成大小 - ls -l .scannerwork/report.json image: name: satomic/sonarscanner:v9-mvn扫描结果

参考

问题与风险

文章转自:《》https://note.youdao.com/ynoteshare/index.html?id=05b5ba9c1c49628901ebd1eadece97cd&type=note&_time=1703486325797

查看全文
大家还看了
也许喜欢
更多游戏

Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved