源码集成代码分析工具
初识TCA任务执行机制
- TCA server在接收到开启分析的请求后根据所选规则生成对应的task_request,每个task_request对应一个工具的任务
- TCA server将
task_request
分发到能够执行该工具的机器 - TCA client在收到task_request后提取出本次任务的工具名也就是其中的
task_name
字段,字段对应于工具的name
字段 - TCA client按照
task_name
在client中的tool目录查找对应python启动脚本 - 执行python启动脚本中的内容
添加分析工具(以 tca_ql_php 为例)
根据上述的任务机制添加工具需要做到以下几点
- 让server知道存在
tca_ql_php
工具及其所含的规则 - 让server知道哪些客户端可以执行
tca_ql_php
工具 - client下载/找到工具所在目录及需要的环境
- 让client知道
tca_ql_php
对应的启动脚本是什么
如何让Server知道存在相应工具
找到
server/projects/main/apps/scan_conf/management/commands/open_source
目录创建工具json文件,json文件名尽量对应工具名称方便查看
json文件内容为(以 tca_ql_php 为例)
[
{
"name": "tca_ql_php",
"display_name": "Hades_PHP(展示名称用于前端展示使用)",
"description": "工具描述",
"license": "工具license",
"libscheme_set": [], # 暂时不需要
"task_processes": [
"analyze",
"datahandle",
"compile"
], # 工具进程,包含compile编译, analyze分析, datahandle数据处理
"scan_app": "codelint", # 代码分析统一为codelint
"scm_url": "", # 暂时为空
"run_cmd": "",
"envs": null, # 是否需要特殊环境,这里无需填写
"build_flag": false, # 是否需要编译命令才能运行
"checkrule_set": [ # 工具包含的规则
{
"real_name": "deser", # 规则名
"display_name": "反序列化漏洞", # 规则前端展示,考虑各工具规则名可能晦涩难懂,设置展示名称方便查找
"severity": "error", # 规则等级 从上到下分为 fatal, error, warning, info 四个等级
"category": "security", # 规则类别。correctness 功能 security安全 performance性能 usability可用性 accessibility无障碍化 i18n国际化 convention代码风格 other其他
"rule_title": "反序列化漏洞", # 一句话概括规则简介
"rule_params": null, # 规则参数
"languages": [ # 支持语言
"php"
],
"solution": "", # 建议的解决方法
"owner": "",
"labels": [],
"description": "", # 规则详细介绍
}
]
}
]
- 在
server/projects/main/
目录执行python manage.py loadcheckers --dir open_source tca_ql_php
加载工具进入数据库
tca_ql_php
工具
让server知道哪些客户端可以执行- 进入节点管理页面
- 选择其中一台机器 工具进程配置,勾选其工具进程
client下载/找到工具所在目录及需要的环境
- 找到puppy-tool-config若没有额外配置则为默认代码库https://github.com/TCATools/puppy-tools-config.git
- 修改其中的 ini 配置文件,每个操作系统对应一个ini
- 以 tca_ql_php 为例需要做以下修改
; env_path 主要填写存放工具文件所在的相对目录,一般都存放/拉取在tools下,会在工具执行前加载到环境变量中提供使用
[env_path]
ZEUS_HOME : Zeus
HADES_HOME : Hades
; toolz_url
[tool_url] 主要填写工具的git仓库,这里因为 tca_ql_php 直接使用tools下的目录所以不用再进行额外拉取也无需再写
CPPCHECK : ${base_value:git_url}/linux-cppcheck-1.78
; 各工具配置 以 tca_ql_php 为例
; env_path 填写上面需要加载的环境变量
; env_value 通用环境变量,一般无需填写如果有需求需要现在 [env_value] 中定义好再填写
; path 工具所在目录填写上面的定义
; tool_url 工具git仓库,使用本地相对目录故为空
[tca_ql_php]
env_path : ZEUS_HOME;HADES_HOME
env_value :
path : ${env_path:ZEUS_HOME};${env_path:HADES_HOME}
tool_url :
tca_ql_php
对应的启动脚本是什么
让client知道以上述步骤在
client/tool
目录添加脚本tca_ql_php.py
作为启动脚本 注:启动脚本必须与工具名称相同编写脚本
脚本编写规范
以tca_ql_php
为例
from task.codelintmodel import CodeLintModel
from util.logutil import LogPrinter
from util.subprocc import SubProcController
logger = LogPrinter()
class TcaQlPHP(CodeLintModel):
# 代码分析工具集成基类CodeLintModel
def __init__(self, params):
logger.info("找到工具了Q_Q")
super().__init__(params)
def compile(self, params):
logger.info("开始编译了Q_Q")
build_cmd = params.get('build_cmd', None) # 从params中获取编译命令, params内容可以在最后附录查看
lang = "php"
do_some_things()
def analyze(self, params):
logger.info("开始分析了Q_Q")
lang = "php"
HADES_HOME = envs.get("HADES_HOME", None)
output_json = "result.json"
sp = SubProcController(
command=["Hades", "analyze", "test.php", "-o", output_json],
cwd=HADES_HOME,
stdout_line_callback=subprocc_log,
stderr_line_callback=subprocc_log,
)
sp.wait() # 执行工具分析命令
issues = []
# 工具结果输出到output_json,具体工具可能有所不同
if os.path.exists(output_json):
with open(output_json, "r") as result_reader:
result = json.load(result_reader)
issues.extend(result)
return issues
tool = TcaQlPHP # 必须,必须包含tool变量并且为该工具的类
- 脚本必须包含analyze方法,如果有配置编译进程也需要相应的compile方法来做编译相关工作,datahandle函数不用自定义基类方法已经够用了。方法执行顺序为 compile -> analyze -> datahandle
- params参数为
task_request
中的task_params
字段,具体字段将在最后附录进行说明 - anlyze方法必须有返回值,返回值为issue列表,issue格式为
{
"path": "文件相对路径",
"line": "行号,int类型",
"column": "列号, int类型,如果工具没有输出列号信息,可以用0代替",
"msg": "提示信息",
"rule": "规则名称,可以根据需要输出不同的规则名",
"refs": [
{
"line": "回溯行号",
"msg": "提示信息",
"tag": "用一个词简要标记该行信息,比如uninit_member,member_decl等,如果没有也可以都写成一样的",
"path": "回溯行所在文件绝对路径"
},
...
]
}
说明:
refs:可选,记录问题回溯路径信息。比如当前文件的回溯路径其他的3行代码,可以将这三行的路径及提示信息,按顺序添加到refs数组中。
PR
如果有意公开您添加的工具欢迎发起PR
注:别忘了puppy-tool-config 也需要PR
附录
params 表格
字段 | 说明 | 类型 |
---|---|---|
scan_languages | 语言 | 字符串列表如 ["python", "php"] |
pre_cmd | 编译前置命令 | 字符串 |
build_cmd | 编译命令 | 字符串 |
envs | 额外环境变量 | 字符串 |
scm_last_revision | 上次成功分析的代码版本,增量使用 | 字符串 |
incr_scan | 是否为增量分析 | bool |
rules | 规则名称列表,只有规则名 | 字符串列表 |
rule_list | 详细的规则列表包含规则名和规则参数等 | 字典列表 |
checktool | 工具详细信息,执行一般用不到 | 字典 |
path_filters | 过滤路径 | 字典 |
scm_url | 代码库url | 字符串 |
source_dir | 代码库本地目录 | 字符串 |
work_dir | 本次任务的work_dir目录 | 字符串 |
project_id | 分析项目id | int |
repo_id | 仓库id | int |
task_id | 任务id | int |
job_id | 本次分析的id | int |