diff --git a/.github/workflows/run_opensca_scan.yml b/.github/workflows/run_opensca_scan.yml new file mode 100644 index 00000000..aa1299ce --- /dev/null +++ b/.github/workflows/run_opensca_scan.yml @@ -0,0 +1,32 @@ +name: OpenSCA Scan + +on: + push: + branches: + - master + pull_request: + branches: + - master + workflow_dispatch: + + +jobs: + opensca_scan: + name: OpenSCA Scan + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + sparse-checkout: | + cmd/ + opensca/ + go.mod + main.go + - name: Run OpenSCA Scan + uses: XmirrorSecurity/opensca-scan-action@v1 + with: + token: ${{ secrets.OPENSCA_TOKEN }} + proj: ${{ secrets.OPENSCA_PROJECT_ID }} + need-artifact: true + out: "outputs/results.json,outputs/result.html" diff --git a/README.md b/README.md index 38a7917d..ff556b6b 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ ## 下载安装 -1. 从 [github](https://github.com/XmirrorSecurity/OpenSCA-cli/releases) 或 [gitee](https://gitee.com/XmirrorSecurity/OpenSCA-cli/releases) 下载对应系统架构的可执行文件压缩包 +1. 从 [github](https://github.com/XmirrorSecurity/OpenSCA-cli/releases) 或 [gitee](https://gitee.com/XmirrorSecurity/OpenSCA-cli/releases) 或 [gitcode](https://gitcode.com/XmirrorSecurity/OpenSCA-cli/releases) 下载对应系统架构的可执行文件压缩包 2. 或者下载源码编译(需要 `go 1.18` 及以上版本) @@ -70,10 +70,14 @@ git clone https://github.com/XmirrorSecurity/OpenSCA-cli.git opensca && cd opensca && go build // gitee linux/mac git clone https://gitee.com/XmirrorSecurity/OpenSCA-cli.git opensca && cd opensca && go build + // gitcode linux/mac + git clone https://gitcode.com/XmirrorSecurity/OpenSCA-cli.git opensca && cd opensca && go build // github windows git clone https://github.com/XmirrorSecurity/OpenSCA-cli.git opensca ; cd opensca ; go build // gitee windows git clone https://gitee.com/XmirrorSecurity/OpenSCA-cli.git opensca ; cd opensca ; go build + // gitcode windows + git clone https://gitcode.com/XmirrorSecurity/OpenSCA-cli.git opensca ; cd opensca ; go build ``` 默认生成当前系统架构的程序,如需生成其他系统架构可配置环境变量后编译 @@ -191,25 +195,25 @@ docker run -ti --rm -v ${PWD}:/src opensca/opensca-cli -token ${put_your_token_h ### 漏洞库字段说明 -| 字段 | 描述 | 是否必填 | -| :------------------ | :-------------------------------- | :------- | -| `vendor` | 组件厂商 | 否 | -| `product` | 组件名 | 是 | -| `version` | 漏洞影响版本 | 是 | -| `language` | 组件语言 | 是 | -| `name` | 漏洞名 | 否 | -| `id` | 自定义编号 | 是 | -| `cve_id` | cve 编号 | 否 | -| `cnnvd_id` | cnnvd 编号 | 否 | -| `cnvd_id` | cnvd 编号 | 否 | -| `cwe_id` | cwe 编号 | 否 | -| `description` | 漏洞描述 | 否 | -| `description_en` | 漏洞英文描述 | 否 | -| `suggestion` | 漏洞修复建议 | 否 | -| `attack_type` | 攻击方式 | 否 | -| `release_date` | 漏洞发布日期 | 否 | -| `security_level_id` | 漏洞风险评级(1~4 风险程度递减) | 否 | -| `exploit_level_id` | 漏洞利用评级(0:不可利用,1:可利用) | 否 | +| 字段 | 描述 | 是否必填 | +| :------------------ | :--------------------------------------- | :------- | +| `vendor` | 组件厂商 | 否 | +| `product` | 组件名 | 是 | +| `version` | 漏洞影响版本(必须为范围,不能填单个版本) | 是 | +| `language` | 组件语言 | 是 | +| `name` | 漏洞名 | 否 | +| `id` | 自定义编号 | 是 | +| `cve_id` | cve 编号 | 否 | +| `cnnvd_id` | cnnvd 编号 | 否 | +| `cnvd_id` | cnvd 编号 | 否 | +| `cwe_id` | cwe 编号 | 否 | +| `description` | 漏洞描述 | 否 | +| `description_en` | 漏洞英文描述 | 否 | +| `suggestion` | 漏洞修复建议 | 否 | +| `attack_type` | 攻击方式 | 否 | +| `release_date` | 漏洞发布日期 | 否 | +| `security_level_id` | 漏洞风险评级(1~4 风险程度递减) | 否 | +| `exploit_level_id` | 漏洞利用评级(0:不可利用,1:可利用) | 否 | 本地漏洞库中`language`字段设定值包含`java、javascript、golang、rust、php、ruby、python` diff --git a/cmd/format/dpsbom.go b/cmd/format/dpsbom.go new file mode 100644 index 00000000..59be656b --- /dev/null +++ b/cmd/format/dpsbom.go @@ -0,0 +1,117 @@ +package format + +import ( + "archive/zip" + "crypto/md5" + "crypto/sha1" + "crypto/sha256" + "encoding/hex" + "encoding/json" + "errors" + "fmt" + "hash" + "io" + "path/filepath" + "strings" + + "github.com/xmirrorsecurity/opensca-cli/v3/cmd/detail" + "github.com/xmirrorsecurity/opensca-cli/v3/opensca/model" +) + +func DpSbomZip(report Report, out string) { + zipFile := out + if !strings.HasSuffix(out, ".zip") { + zipFile = out + ".zip" + } + jsonName := filepath.Base(out) + if !strings.HasSuffix(jsonName, ".json") { + jsonName = jsonName + ".json" + } + outWrite(zipFile, func(w io.Writer) error { + doc := pdSbomDoc(report) + if doc.Hashes.HashFile == "" { + return errors.New("hash file is required") + } + + var h hash.Hash + switch strings.ToLower(doc.Hashes.Algorithm) { + case "sha-256": + h = sha256.New() + case "sha-1": + h = sha1.New() + case "md5": + h = md5.New() + case "": + return errors.New("hash algorithm is required") + default: + return fmt.Errorf("unsupported hash algorithm: %s", doc.Hashes.Algorithm) + } + + tojson := func(w io.Writer) error { + encoder := json.NewEncoder(w) + encoder.SetIndent("", " ") + return encoder.Encode(doc) + } + + zipfile := zip.NewWriter(w) + defer zipfile.Close() + + sbomfile, err := zipfile.Create(jsonName) + if err != nil { + return err + } + err = tojson(sbomfile) + if err != nil { + return err + } + + hashfile, err := zipfile.Create(doc.Hashes.HashFile) + if err != nil { + return err + } + err = tojson(h) + if err != nil { + return err + } + hashstr := hex.EncodeToString(h.Sum(nil)[:]) + hashfile.Write([]byte(hashstr)) + + return nil + }) +} + +func pdSbomDoc(report Report) *model.DpSbomDocument { + + doc := model.NewDpSbomDocument(report.TaskInfo.AppName, "opensca-cli") + + report.DepDetailGraph.ForEach(func(n *detail.DepDetailGraph) bool { + + if n.Name == "" { + return true + } + + lics := []string{} + for _, lic := range n.Licenses { + lics = append(lics, lic.ShortName) + } + doc.AppendComponents(func(dsp *model.DpSbomPackage) { + dsp.Identifier.Purl = n.Purl() + dsp.Name = n.Name + dsp.Version = n.Version + dsp.License = lics + }) + + children := []string{} + for _, c := range n.Children { + if c.Name == "" { + continue + } + children = append(children, c.Purl()) + } + doc.AppendDependencies(n.Purl(), children) + + return true + }) + + return doc +} diff --git a/cmd/format/save.go b/cmd/format/save.go index f6bb4488..8d2ee382 100644 --- a/cmd/format/save.go +++ b/cmd/format/save.go @@ -39,6 +39,12 @@ func Save(report Report, output string) { switch filepath.Ext(out) { case ".html": Html(genReport(report), out) + case ".zip": + if strings.HasSuffix(out, ".dpsbom.zip") { + DpSbomZip(report, out) + } else { + Json(genReport(report), out) + } case ".json": if strings.HasSuffix(out, ".spdx.json") { SpdxJson(report, out) @@ -48,9 +54,13 @@ func Save(report Report, output string) { CycloneDXJson(report, out) } else if strings.HasSuffix(out, ".swid.json") { SwidJson(report, out) + } else if strings.HasSuffix(out, ".dpsbom.json") { + DpSbomZip(report, out) } else { Json(genReport(report), out) } + case ".dpsbom": + DpSbomZip(report, out) case ".dsdx": Dsdx(report, out) case ".spdx": diff --git a/cmd/format/statis.go b/cmd/format/statis.go index 14911f51..98296333 100644 --- a/cmd/format/statis.go +++ b/cmd/format/statis.go @@ -7,7 +7,7 @@ import ( ) // Statis 统计概览信息 -func Statis(report Report) string { +func Statis(report Report) (string, string) { // 组件风险统计 key:0代表组件总数 depStatic := map[int]int{ @@ -50,10 +50,11 @@ func Statis(report Report) string { return true }) - - return fmt.Sprintf("Components:%d C:%d H:%d M:%d L:%d\n"+ - "Vulnerabilities:%d C:%d H:%d M:%d L:%d", - depStatic[0], depStatic[1], depStatic[2], depStatic[3], depStatic[4], - vulStatic[0], vulStatic[1], vulStatic[2], vulStatic[3], vulStatic[4], - ) + if vulStatic[0] != 0 { + return fmt.Sprintf("Components:%d C:%d H:%d M:%d L:%d", + depStatic[0], depStatic[1], depStatic[2], depStatic[3], depStatic[4]), + fmt.Sprintf("\nVulnerabilities:%d C:%d H:%d M:%d L:%d", + vulStatic[0], vulStatic[1], vulStatic[2], vulStatic[3], vulStatic[4]) + } + return fmt.Sprintf("Components: %d", depStatic[0]), "" } diff --git a/cmd/ui/ui.go b/cmd/ui/ui.go index a7af9048..5db85c6b 100644 --- a/cmd/ui/ui.go +++ b/cmd/ui/ui.go @@ -93,8 +93,9 @@ func OpenUI(report format.Report) { } func TaskInfo(report format.Report) *tview.TextView { + dep, vul := format.Statis(report) info := tview.NewTextView(). - SetText(format.Statis(report)) + SetText(fmt.Sprintf("%s\n%s", dep, vul)) info.SetTextColor(tcell.ColorBlue) return info } diff --git a/docs/Contributing_Guideline-v1.0.md b/docs/Contributing_Guideline-v1.0.md index 0676e407..1af1b22a 100644 --- a/docs/Contributing_Guideline-v1.0.md +++ b/docs/Contributing_Guideline-v1.0.md @@ -78,4 +78,4 @@ We appreciate all the contributions to OpenSCA. Thanks again for your interest in OpenSCA and your support for our solution to open source vulnerabilities. -For the Chinese version of our contributing guideline, please check [贡献指南(中文版)v1.0](./Contributing_Guideline-v1.0-zh_CN.md)。 +For the Chinese version of our contributing guideline, please check [贡献指南(中文版)v1.0](./Contributing_Guideline-v1.0-zh_CN.md)。 diff --git a/docs/Integrations/IDE_Plugins-zh_CN.md b/docs/Integrations/IDE_Plugins-zh_CN.md index e69de29b..4d5c6c26 100644 --- a/docs/Integrations/IDE_Plugins-zh_CN.md +++ b/docs/Integrations/IDE_Plugins-zh_CN.md @@ -0,0 +1,110 @@ +[返回目录](/docs/README-zh-CN.md) / [English](./IDE_Plugins.md) + +- [Visual Studio Code](#visual-studio-code) + - [安装插件](#安装插件) + - [使用插件](#使用插件) + - [插件功能](#插件功能) + - [插件执行流程](#插件执行流程) + - [运行扫描](#运行扫描) +- [Jetbrains IDEs](#jetbrains-ides) + - [安装插件](#安装插件-1) + - [使用插件](#使用插件-1) + - [插件功能](#插件功能-1) + - [插件执行流程](#插件执行流程-1) + - [运行扫描](#运行扫描-1) + + +# Visual Studio Code + +## 安装插件 + +- **安装方法 一**:在 [VS Marketplace](https://marketplace.visualstudio.com/items?itemName=xmirror.opensca) 中安装(推荐) + + 在VS Code中左边栏打开扩展->扩展的搜索框中输入“OpenSCA Xcheck”,点击“Install” + + xcheck_market + +- **安装方法二**:在[OpenSCA 官网](https://opensca.xmirror.cn/pages/plug-in)下载插件安装 + + - 从OpenSCA平台下载 “OpenSCA-Xcheck.vsix”; + - 打开VS Code,依次操作:左边栏打开扩展->扩展顶栏的更多操作->“从VSIX安装”->找到并安装“OpenSCA-Xcheck.vsix”; + +- **安装方法三**:[下载源码](https://github.com/XmirrorSecurity/)自行编译安装 + + - 环境要求: + + - node v18及以上版本 + - 系统支持MacOS、Windows、Linux + + - 从[gitee](https://gitee.com/XmirrorSecurity/OpenSCA-VSCode-plugin)或[github](https://github.com/XmirrorSecurity/OpenSCA-VSCode-plugin/)下载源码 + + * 全局安装vsce + + ``` + npm install --global @vscode/vsce + ``` + + * 执行打包命令 + + ``` + vsce package + ``` + +## 使用插件 + +### 插件功能 + +- 开始检测:点击操作栏的“Run”,开始检测当前项目内的组件漏洞风险情况; +- 停止检测:点击操作栏的“Stop”,停止检测当前项目内的组件漏洞风险情况; +- 清除检测结果:点击操作栏的“Clean”,清除当前项目的检测结果; +- 连接配置:点击操作栏的“Test”按钮,配置平台Url及Token信息,点击“测试连接”按钮可测试连接配置是否正确,连接成功后就可以开始检测啦; +- 设置:点击操作栏的“Setting”,查看OpenSCA Xcheck相关设置信息。 +- 使用说明:点击操作栏的“Instructions”,查看OpenSCA Xcheck相关使用说明。 +- 查看更多:点击操作栏的“See more”,跳转到[opensca.xmirror.cn](https://opensca.xmirror.cn)查看OpenSCA Xcheck 更多相关信息。 + +xcheck_function + +### 插件执行流程 + +xcheck流程图 + +### 运行扫描 + +点击OpenSCA Xcheck可打开OpenSCA窗口。首先在配置界面中配置服务器参数(参考:插件功能-设置),然后在OpenSCA窗口中点击“Run”(参考:插件功能-开始检测) + +# Jetbrains IDEs + +## 安装插件 + +- **安装方法一**:从 [Jetbrains 插件市场](https://plugins.jetbrains.com/plugin/18246-opensca-xcheck) 中安装(推荐) + + 以IntelliJ IDEA为例:在IDE中依次点击“File|Settings|Plugins|Marketplace”,在搜索框中输入“OpenSCA Xcheck”,点击“Install” + + ![xcheck_market](/resources/xcheck_marketplace.jpg) + +- **安装方法二**:在[OpenSCA平台](https://opensca.xmirror.cn/pages/plug-in )下载插件安装 + + 以IntelliJ IDEA为例:将下载下来的插件安装包拖入适配的IDE中即可 + +- **安装方法三**:[下载源码](https://github.com/XmirrorSecurity/OpenSCA-intellij-plugin )自行编译安装 + + 使用IntelliJ IDEA打开下载到本地的源码,需要配置运行环境:`jDK11`,待Gradle导入依赖和插件,在Gradle中执行`intellij`插件的`buildPlugin`任务,构建的安装包存放于当前项目下*build/distributions*目录下,将此目录下的安装包拖入当前IDE中即可 + +## 使用插件 + +### 插件功能 + +- 配置:点击File|Settings|Other Settings|OpenSCA Setting或点击OpenSCA窗口中的`Setting`按钮,在配置界面中配置连接服务器Url和Token +- 测试连接:在OpenSCA配置界面中,配置服务器Url和Token之后点击`测试连接`按钮可验证Url和Token是否有效 +- 运行:点击OpenSCA窗口中的`Run`按钮,可对当前项目进行代码评估 +- 停止:如果正在对当前项目代码评估,那么`Stop`按钮是可用的,点击Stop按钮可结束当前评估任务 +- 清除:如果OpenSCA窗口中的Xcheck子窗口已有评估结果,点击`Clean`按钮可清除Xcheck子窗口中所有结果 +![xcheck_function](/resources/xcheck_function.jpg) + +### 插件执行流程 + +![xcheck流程图](/resources/xcheck_process.jpg) + +### 运行扫描 + +点击 `View` > `Tool Windows` > `OpenSCA` 可打开OpenSCA窗口。首先在OpenSCA配置界面中配置服务器参数(参考:插件功能-配置),然后在OpenSCA窗口中点击“运行”(参考:插件功能-运行) \ No newline at end of file diff --git a/docs/Integrations/IDE_Plugins.md b/docs/Integrations/IDE_Plugins.md index e69de29b..9ec0ddfc 100644 --- a/docs/Integrations/IDE_Plugins.md +++ b/docs/Integrations/IDE_Plugins.md @@ -0,0 +1,108 @@ +[Go Back](/docs/README.md) | [简体中文](./IDE_Plugins-zh_CN.md) + +- [Visual Studio Code](#visual-studio-code) + - [Install Plugin](#install-plugin) + - [Using the Plugin](#using-the-plugin) + - [Plugin Features](#plugin-features) + - [Plugin Execution Process](#plugin-execution-process) + - [Running a Scan](#running-a-scan) +- [JetBrains IDEs](#jetbrains-ides) + - [Installing the Plugin](#installing-the-plugin) + - [Using the Plugin](#using-the-plugin-1) + - [Plugin Features](#plugin-features-1) + - [Plugin Execution Process](#plugin-execution-process-1) + - [Running a Scan](#running-a-scan-1) + +# Visual Studio Code + +## Install Plugin + +- **Option 1**:Install from [VS Marketplace](https://marketplace.visualstudio.com/items?itemName=xmirror.opensca) + + In VS Code, open Extensions in the left sidebar -> enter "OpenSCA Xcheck" in the extension search box, click "Install" + + xcheck_market + +- **Option 2**:Download from [OpenSCA Official Web Site](https://opensca.xmirror.cn/pages/plug-in) + + - Download "OpenSCA-Xcheck.vsix" from the OpenSCA official website; + - Open VS Code, open Extensions in the left sidebar -> more actions in the top bar of the extension -> "Install from VSIX" -> find and install "OpenSCA-Xcheck.vsix"; + +- **Option 3**:Build from source code + + - Requirements: + - node v18 and above + + - Clone the repository from [github](https://github.com/XmirrorSecurity/OpenSCA-VSCode-plugin/) or [gitee](https://gitee.com/XmirrorSecurity/OpenSCA-VSCode-plugin) + + * Install vsce + + ``` + npm install --global @vscode/vsce + ``` + + * Package + + ``` + vsce package + ``` + +## Using the Plugin + +### Plugin Features + +- **Start Scan**: Click the "Run" button in the action bar to start scanning for vulnerabilities in the components of the current project. +- **Stop Scan**: Click the "Stop" button in the action bar to stop the ongoing scan for vulnerabilities in the current project. +- **Clear Scan Results**: Click the "Clean" button in the action bar to clear the scan results of the current project. +- **Connection Configuration**: Click the "Test" button in the action bar to configure the platform URL and Token information. Click the "Test Connection" button to verify if the connection configuration is correct. Once the connection is successful, you can start scanning. +- **Settings**: Click the "Setting" button in the action bar to view the settings related to OpenSCA Xcheck. +- **Instructions**: Click the "Instructions" button in the action bar to view the user manual for OpenSCA Xcheck. +- **See More**: Click the "See more" button in the action bar to visit [opensca.xmirror.cn](https://opensca.xmirror.cn) for more information about OpenSCA Xcheck. + +![xcheck_function](https://opensca.xmirror.cn/docs/img/vscode_02.jpg) + +### Plugin Execution Process + +![xcheck_flow](https://opensca.xmirror.cn/docs/assets/img/xcheck_process.7083b869.jpg) + +### Running a Scan + +Click on OpenSCA Xcheck to open the OpenSCA window. First, configure the server parameters in the configuration interface (refer to: Plugin Features - Settings), then click “Run” in the OpenSCA window (refer to: Plugin Features - Start Scan). + +# JetBrains IDEs + +## Installing the Plugin + +- **Method 1**: Install from the [JetBrains Plugin Marketplace](https://plugins.jetbrains.com/plugin/18246-opensca-xcheck) (Recommended) + + For example, in IntelliJ IDEA: go to `File | Settings | Plugins | Marketplace`, search for "OpenSCA Xcheck" in the search box, and click "Install". + + ![xcheck_market](https://opensca.xmirror.cn/docs/img/xcheck_marketplace.jpg) + +- **Method 2**: Download the plugin from the [OpenSCA Platform](https://opensca.xmirror.cn/pages/plug-in) and install it manually + + For example, in IntelliJ IDEA: drag the downloaded plugin package into the IDE. + +- **Method 3**: [Download the source code](https://github.com/XmirrorSecurity/OpenSCA-intellij-plugin) and compile it yourself + + Open the downloaded source code in IntelliJ IDEA. Configure the runtime environment: `JDK11`. After Gradle imports dependencies and plugins, execute the `buildPlugin` task of the `intellij` plugin in Gradle. The built package will be located in the `build/distributions` directory of the project. Drag this package into the IDE to install it. + +## Using the Plugin + +### Plugin Features + +- **Configuration**: Click `File | Settings | Other Settings | OpenSCA Setting` or click the `Setting` button in the OpenSCA window to configure the server URL and Token in the configuration interface. +- **Test Connection**: After configuring the server URL and Token in the OpenSCA configuration interface, click the `Test Connection` button to verify if the URL and Token are valid. +- **Run**: Click the `Run` button in the OpenSCA window to perform a code assessment on the current project. +- **Stop**: If a code assessment is ongoing for the current project, the `Stop` button will be enabled. Click the `Stop` button to end the current assessment task. +- **Clear**: If the Xcheck sub-window in the OpenSCA window already has assessment results, click the `Clean` button to clear all results in the Xcheck sub-window. + +![xcheck_function](https://opensca.xmirror.cn/docs/img/xcheck_function.jpg) + +### Plugin Execution Process + +![xcheck_flow](https://opensca.xmirror.cn/docs/img/xcheck_process.jpg) + +### Running a Scan + +Click `View > Tool Windows > OpenSCA` to open the OpenSCA window. First, configure the server parameters in the OpenSCA configuration interface (refer to: Plugin Features - Configuration), then click the "Run" button in the OpenSCA window (refer to: Plugin Features - Run). \ No newline at end of file diff --git a/docs/README-zh-CN.md b/docs/README-zh-CN.md index 048a3e4a..d338e057 100644 --- a/docs/README-zh-CN.md +++ b/docs/README-zh-CN.md @@ -8,7 +8,7 @@ - [安装](./User_Guide/Installation-zh_CN.md) - [扫描](./User_Guide/Scanning/) - [依赖分析](./User_Guide/Scanning/Dependency_Analysis-zh_CN.md) - - [连接漏洞库](./User_Guide/Scanning/Connectiong_to_Vulnerability_Databases-zh_CN.md) + - [连接漏洞库](./User_Guide/Scanning/Vulnerability_Analysis-zh_CN.md) - [查看结果](./User_Guide/Viewing_Results-zh_CN.md) - [生成报告](./User_Guide/Generating_Reports/) - [SBOM](./User_Guide/Generating_Reports/SBOM-zh_CN.md) diff --git a/docs/README.md b/docs/README.md index 51adf9bb..20cf6861 100644 --- a/docs/README.md +++ b/docs/README.md @@ -8,7 +8,7 @@ - [Installation](./User_Guide/Installation.md) - [Scanning](./User_Guide/Scanning/) - [Dependency Analysis](./User_Guide/Scanning/Dependency_Analysis.md) - - [Connecting to Vulnerability Databases](./User_Guide/Scanning/Connectiong_to_Vulnerability_Databases.md) + - [Connecting to Vulnerability Databases](./User_Guide/Scanning/Vulnerability_Analysis.md) - [Viewing Results](./User_Guide/Viewing_Results.md) - [Generating Reports](./User_Guide/Generating_Reports/) - [Software Bill of Materials (SBOM)](./User_Guide/Generating_Reports/SBOM.md) diff --git a/docs/Troubleshooting-zh_CN.md b/docs/Troubleshooting-zh_CN.md index e69de29b..490657e1 100644 --- a/docs/Troubleshooting-zh_CN.md +++ b/docs/Troubleshooting-zh_CN.md @@ -0,0 +1 @@ +[返回目录](/docs/README-zh-CN.md) / [English](./Troubleshooting.md) \ No newline at end of file diff --git a/docs/Troubleshooting.md b/docs/Troubleshooting.md index e69de29b..6b3f4a8f 100644 --- a/docs/Troubleshooting.md +++ b/docs/Troubleshooting.md @@ -0,0 +1 @@ +[Go Back](/docs/README.md) | [中文](./Troubleshooting-zh_CN.md) \ No newline at end of file diff --git a/docs/User_Guide/Configuration-and-Parameters-zh_CN.md b/docs/User_Guide/Configuration-and-Parameters-zh_CN.md new file mode 100644 index 00000000..8fccb92b --- /dev/null +++ b/docs/User_Guide/Configuration-and-Parameters-zh_CN.md @@ -0,0 +1,123 @@ +[返回目录](/docs/README-zh-CN.md) | [English](./Configuration-and-Parameters.md) + +- [命令行参数](#命令行参数) +- [配置文件说明](#配置文件说明) +- [漏洞数据库配置示例](#漏洞数据库配置示例) +- [漏洞数据库字段说明](#漏洞数据库字段说明) + + +# 命令行参数 + +| 参数 | 描述 | 使用示例 | +| --------- | -------------------------------------------- | ------------------------ | +| `config` | 指定配置文件路径 | `-config config.json` | +| `path` | 指定检测项目路径, 支持 http(s)/ftp/file 协议 | `-path ./foo` | +| `out` | 根据后缀生成报告 | `-out out.json,out.html` | +| `log` | 指定日志文件路径 | `-log my_log.txt` | +| `token` | 云端服务`token` | `-token xxx` | +| `proj` | saas项目`token` | `-proj xxx` | +| `version` | 显示版本信息 | `-version` | +| `help` | 显示帮助信息 | `-help` | + +# 配置文件说明 + +配置文件使用 `json` 格式,支持以下字段: +> 默认会从目标检测路径中查找配置文件, 否则使用[默认配置文件](/config.json)。 可通过 `-config` 参数指定配置文件路径。 + +- `path`: `String` 检测目标路径, 支持 http(s)/ftp/file 协议 +- `out`: `String` 报告输出路径, 通过后缀名识别文件类型, 支持 html/json/xml/csv/sqlite/cdx/spdx/swid/dsdx +- `optional`: `Object` 可选配置项 + - `ui`: `Boolean` 是否启用交互式界面, 默认为 `false` + - `dedup`: `Boolean` 是否启用组件去重(相同组件仅保留一条记录,组件路径合并), 默认为 `false` + - `dir`: `Boolean` 是否仅检测目录(跳过压缩包), 默认为 `false` + - `vuln`: `Boolean` 是否仅保留漏洞组件, 默认为 `false` + - `progress`: `Boolean` 是否显示进度条, 默认为 `true` + - `dev`: `Boolean` 是否保留开发组件, 默认为 `true` + - `tls`: `Boolean` 开启 TLS 证书验证, 默认为 `false` + - `proxy`: `String` 代理地址, 默认为空 +- `repo`: `Object` 组件仓库配置 + - `maven`: `Array` maven 镜像/私服仓库配置 + - `url`: `String` 仓库地址 + - `user`: `String` 用户名 + - `pass`: `String` 密码 + - `npm`: `Array` npm 镜像/私服仓库配置 + - `url`: `String` 仓库地址 + - `user`: `String` 用户名 + - `pass`: `String` 密码 + - `composer`: `Array` composer 镜像/私服仓库配置 + - `url`: `String` 仓库地址 + - `user`: `String` 用户名 + - `pass`: `String` 密码 +- `origin`: `Object` 漏洞数据源配置 + - `url`: `String` 漏洞数据源地址 + - `token`: `String` 云端漏洞数据库个人访问令牌 + - `proj`: `String` 项目访问令牌, 若置空则同步结果至"快速检测", 若无此字段(注释或删除)则不将结果同步至 OpenSCA SaaS + - `json`: `String` JSON 格式漏洞数据库路径 + - `mysql`: `Object` MySQL 数据库漏洞数据源配置 + - `dsn`: `String` 数据库连接字符串 + - `table`: `String` 数据表名 + - `sqlite`: `Object` SQLite 数据库漏洞数据源配置 + - `dsn`: `String` 数据库连接字符串 + - `table`: `String` 数据表名 + +# 漏洞数据库配置示例 + +```json +{ + // ... + "origin": { + // json 文件 + "json": "vuln-db.json", + // MySQL + "mysql": { + // user:password@tcp(ip:port)/dbname + "dns": "opensca:opensca@tcp(3306:127.0.0.1)/opensca", + "table": "vuln" + } + "sqlite": { + "dns": "vuln.db", + "table": "vuln" + } + } + +} +``` + +# 漏洞数据库字段说明 + +| 字段 | 描述 | 是否必填 | +| :------------------ | :-------------------------------- | :------- | +| `vendor` | 组件厂商 | 否 | +| `product` | 组件名 | 是 | +| `version` | 漏洞影响版本 | 是 | +| `language` | 组件语言 | 是 | +| `name` | 漏洞名 | 否 | +| `id` | 自定义编号 | 是 | +| `cve_id` | cve 编号 | 否 | +| `cnnvd_id` | cnnvd 编号 | 否 | +| `cnvd_id` | cnvd 编号 | 否 | +| `cwe_id` | cwe 编号 | 否 | +| `description` | 漏洞描述 | 否 | +| `description_en` | 漏洞英文描述 | 否 | +| `suggestion` | 漏洞修复建议 | 否 | +| `attack_type` | 攻击方式 | 否 | +| `release_date` | 漏洞发布日期 | 否 | +| `security_level_id` | 漏洞风险评级 | 否 | +| `exploit_level_id` | 漏洞利用评级 | 否 | + +- `language` 可选值: `java` `javascript` `golang` `rust` `php` `ruby` `python` +- `version` 描述可使用以下格式: + | 符号 | 描述 (`x`为检出的组件版本) | + | ------------- | -------------------------------- | + | `[a,b]` | `a<=x<=b` | + | `(a,b)` | `aa` | + | `{a,b,c,...}` | `x=a` 或 `x=b` 或 `x=c` 或 `...` | + > 同时位于多个范围需要用`||`连接,例如: `[a,b)||(b,c]`代表`a<=x + > 也可以区间和集合混用: `(0,b)||{c,d}||[e,)`代表`x=e` +- `security_level_id` 可选值: `1` `2` `3` `4`, 分别对应严重、高危、中危、低危 +- `exploit_level_id` 可选值 `0`:不可利用 `1`:可利用 \ No newline at end of file diff --git a/docs/User_Guide/Parameter_Explanations-zh_CN.md b/docs/User_Guide/Configuration-and-Parameters.md similarity index 100% rename from docs/User_Guide/Parameter_Explanations-zh_CN.md rename to docs/User_Guide/Configuration-and-Parameters.md diff --git a/docs/User_Guide/Docker-zh_CN.md b/docs/User_Guide/Docker-zh_CN.md index e69de29b..8ec6c799 100644 --- a/docs/User_Guide/Docker-zh_CN.md +++ b/docs/User_Guide/Docker-zh_CN.md @@ -0,0 +1 @@ +[返回目录](/docs/README-zh-CN.md) / [English](./Docker.md) \ No newline at end of file diff --git a/docs/User_Guide/Generating_Reports/Reports-zh_CN.md b/docs/User_Guide/Generating_Reports/Reports-zh_CN.md index e69de29b..3e25ca0e 100644 --- a/docs/User_Guide/Generating_Reports/Reports-zh_CN.md +++ b/docs/User_Guide/Generating_Reports/Reports-zh_CN.md @@ -0,0 +1,129 @@ +[返回目录](/docs/README-zh-CN.md) / [English](./Reports.md) + +- [生成报告](#生成报告) +- [使用 OpenSCA-cli 生成报告](#使用-opensca-cli-生成报告) + - [基本命令](#基本命令) + - [示例](#示例) +- [使用 json2excel 脚本生成 Excel 格式报告](#使用-json2excel-脚本生成-excel-格式报告) + - [需求](#需求) + - [安装脚本](#安装脚本) + - [使用方法](#使用方法) + +# 生成报告 + +OpenSCA 支持生成多种格式的报告, 包括 JSON(`.json`), XML(`.xml`), HTML(`.html`), SQLite(`.sqlite`), CSV(`.csv`), SARIF(`.sarif`) + +> CSV 格式报告仅包含依赖关系, 不包含漏洞信息. 若需要包含漏洞信息的 Excel 格式报告, 可通过 [json2excel](https://github.com/XmirrorSecurity/OpenSCA-cli/blob/master/scripts/json2excel.py) 脚本, 将 JSON 格式报告转换为 Excel 格式报告. + +此外, OpenSCA 提供 SaaS 服务, 同步扫描结果后, 可以在 [OpenSCA SaaS Console](https://opensca.xmirror.cn/console) 查看和下载报告. + +# 使用 OpenSCA-cli 生成报告 + +## 基本命令 + +OpenSCA-cli 使用 `-out` 参数指定报告输出路径, 使用后缀名指定报告格式. + +```shell +opensca-cli -path {项目路径} -out {报告路径}.{报告格式} +``` + +`-out` 参数支持指定多个报告路径, 使用半角逗号(`,`)分隔. + +```shell +opensca-cli -path {项目路径} -out {报告路径1}.{报告格式1},{报告路径2}.{报告格式2} +``` + +## 示例 + + + + + + + + + + + + + + + + + + +
生成 JSON 格式报告生成 XML 格式报告生成 HTML 格式报告生成 SQLite 格式报告生成 CSV 格式报告生成 SARIF 格式报告
+ +```shell +opensca-cli -path ~/workscapce/myproject -out ~/workscapce/myproject/report.json +``` + + + +```shell +opensca-cli -path ~/workscapce/myproject -out ~/workscapce/myproject/report.xml +``` + + + +```shell +opensca-cli -path ~/workscapce/myproject -out ~/workscapce/myproject/report.html +``` + + + +```shell +opensca-cli -path ~/workscapce/myproject -out ~/workscapce/myproject/report.sqlite +``` + + + +```shell +opensca-cli -path ~/workscapce/myproject -out ~/workscapce/myproject/report.csv +``` + + + +```shell +opensca-cli -path ~/workscapce/myproject -out ~/workscapce/myproject/report.sarif +``` + +
+ +# 使用 json2excel 脚本生成 Excel 格式报告 + +## 需求 + +- Python 3.6+ +- pandas + +## 安装脚本 + +```shell +# 下载脚本 +wget https://raw.githubusercontent.com/XmirrorSecurity/OpenSCA-cli/master/scripts/json2excel.py + +# 安装依赖 +pip install pandas +``` + +## 使用方法 + +**修改 json2excel.py** + +修改 json2excel.py 文件中的以下内容: + +- 将 "result.json" 修改为你的 JSON 格式报告路径 +- 将 "result.xlsx" 修改为你的 Excel 格式报告路径 + +```python +# ... +if __name__ == "__main__": + json2excel("result.json", "result.xlsx") +``` + +**运行脚本** + +```shell +python json2excel.py +``` diff --git a/docs/User_Guide/Generating_Reports/Reports.md b/docs/User_Guide/Generating_Reports/Reports.md index e69de29b..12f471c7 100644 --- a/docs/User_Guide/Generating_Reports/Reports.md +++ b/docs/User_Guide/Generating_Reports/Reports.md @@ -0,0 +1 @@ +[Go Back](/docs/README.md) | [简体中文](./Reports-zh_CN.md) diff --git a/docs/User_Guide/Generating_Reports/SBOM-zh_CN.md b/docs/User_Guide/Generating_Reports/SBOM-zh_CN.md index e69de29b..66ec2593 100644 --- a/docs/User_Guide/Generating_Reports/SBOM-zh_CN.md +++ b/docs/User_Guide/Generating_Reports/SBOM-zh_CN.md @@ -0,0 +1,133 @@ +[返回目录](/docs/README-zh-CN.md) / [English](./SBOM.md) + +- [SBOM 清单](#sbom-清单) +- [生成 SBOM 清单](#生成-sbom-清单) + - [基本命令](#基本命令) + - [示例](#示例) +- [转换 SBOM 清单](#转换-sbom-清单) + - [基本命令](#基本命令-1) + - [示例](#示例-1) + + +# SBOM 清单 + +OpenSCA 支持生成多种格式的 SBOM 清单, 包括 [DSDX](https://opensca.xmirror.cn/resources/particulars?id=133), [SPDX](https://spdx.dev/), [CycloneDX](https://cyclonedx.org/) 和 [SWID](https://csrc.nist.gov/projects/Software-Identification-SWID). + +除了生成 SBOM, OpenSCA 还支持将 SBOM 作为输入, 生成漏洞报告或转换为其他格式的 SBOM 清单. + +此外, OpenSCA 提供 SaaS 服务, 同步扫描结果后, 可以在 [OpenSCA SaaS Console](https://opensca.xmirror.cn/console) 查看和下载 SBOM 清单. + +支持的 SBOM 格式: + +| SBOM 清单 | 文件后缀 | +| ----------- | -------------------------------- | +| `DSDX` | `.dsdx` `.dsdx.json` `.dsdx.xml` | +| `SPDX` | `.spdx` `.spdx.json` `.spdx.xml` | +| `CycloneDX` | `.cdx.json` `.cdx.xml` | +| `SWID` | `.swid.json` `.swid.xml` | + +# 生成 SBOM 清单 + +## 基本命令 + +OpenSCA-cli 使用 `-out` 参数指定 SBOM 清单输出路径, 使用后缀名指定 SBOM 清单格式. + +```shell +opensca-cli -path {项目路径} -out {SBOM路径}.{SBOM格式} +``` + +`-out` 参数支持指定多个 SBOM 路径, 使用半角逗号(`,`)分隔. + +```shell +opensca-cli -path {项目路径} -out {SBOM路径1}.{SBOM格式1},{SBOM路径2}.{SBOM格式2} +``` + +也可以同时生成 SBOM 清单和漏洞报告. + +```shell +opensca-cli -path {项目路径} -out {SBOM路径}.{SBOM格式},{报告路径}.{报告格式} +``` + +## 示例 + + + + + + + + + + + + + + +
生成 JSON 格式 DSDX 清单生成 JSON 格式 SPDX 清单生成 JSON 格式 CycloneDX 清单生成 JSON 格式 SWID 清单
+ +```shell +opensca-cli -path ~/workscapce/myproject -out ~/workscapce/myproject/sbom.dsdx.json +``` + + + +```shell +opensca-cli -path ~/workscapce/myproject -out ~/workscapce/myproject/sbom.spdx.json +``` + + + +```shell +opensca-cli -path ~/workscapce/myproject -out ~/workscapce/myproject/sbom.cdx.json +``` + + + +```shell +opensca-cli -path ~/workscapce/myproject -out ~/workscapce/myproject/sbom.swid.json +``` + +
+ +# 转换 SBOM 清单 + +## 基本命令 + +```shell +opensca-cli -path {SBOM路径}.{SBOM格式} -out {SBOM路径}.{SBOM格式} +``` + +> 注意: SPDX 和 SWID 格式的 SBOM 清单不包含组件语言信息或包管理器坐标, 在转换时可能会丢失部分信息. + +## 示例 + + + + + + + + + + + + +
DSDX 转 SPDXDSDX 转 CycloneDXDSDX 转 SWID
+ +```shell +opensca-cli -path ~/workscapce/myproject/sbom.dsdx.json -out ~/workscapce/myproject/sbom.spdx.json +``` + + + +```shell +opensca-cli -path ~/workscapce/myproject/sbom.dsdx.json -out ~/workscapce/myproject/sbom.cdx.json +``` + + + +```shell +opensca-cli -path ~/workscapce/myproject/sbom.dsdx.json -out ~/workscapce/myproject/sbom.swid.json +``` + +
diff --git a/docs/User_Guide/Generating_Reports/SBOM.md b/docs/User_Guide/Generating_Reports/SBOM.md index e69de29b..f37b2b91 100644 --- a/docs/User_Guide/Generating_Reports/SBOM.md +++ b/docs/User_Guide/Generating_Reports/SBOM.md @@ -0,0 +1 @@ +[Go Back](/docs/README.md) | [简体中文](./SBOM-zh_CN.md) diff --git a/docs/User_Guide/Installation-zh_CN.md b/docs/User_Guide/Installation-zh_CN.md index e69de29b..88cb4fbc 100644 --- a/docs/User_Guide/Installation-zh_CN.md +++ b/docs/User_Guide/Installation-zh_CN.md @@ -0,0 +1,55 @@ +[返回目录](/docs/README-zh-CN.md) | [English](./Installation.md) + +# 一键安装 + +- Windows(需要 PowerShell) + ```powershell + iex "&{$(irm https://raw.githubusercontent.com/XmirrorSecurity/OpenSCA-cli/master/scripts/install.ps1)}" + + # 如果在下载中遇到网络问题,可尝试使用以下命令 + iex "&{$(irm https://gitee.com/XmirrorSecurity/OpenSCA-cli/raw/master/scripts/install.ps1)} gitee" + ``` +- Linux/MacOS + ```shell + curl -sSL https://raw.githubusercontent.com/XmirrorSecurity/OpenSCA-cli/master/scripts/install.sh | sh + + # 如果在下载中遇到网络问题,可尝试使用以下命令 + curl -sSL https://gitee.com/XmirrorSecurity/OpenSCA-cli/raw/master/scripts/install.sh | sh -s -- gitee + ``` + +# 使用包管理器安装 + +- Windows 通过 [Winget](https://github.com/microsoft/winget-cli) 安装 + ```shell + winget install opensca-cli + ``` +- Windows 通过 [Scoop](https://scoop.sh/) 安装 + ```shell + scoop bucket add extras + scoop install extras/opensca-cli + ``` +- MacOS/Linux 通过 [Homebrew](https://brew.sh/) 安装 + ```shell + brew install opensca-cli + ``` + +# 手动安装 + +从 [Github Release](https://github.com/XmirrorSecurity/OpenSCA-cli/releases) 或 [Gitee Release](https://gitee.com/XmirrorSecurity/OpenSCA-cli/releases/) 下载对应系统和处理器架构的压缩包,解压到任意目录即可使用。 + +# 从源码构建 + +依赖 Go 1.18+ + +- 克隆此仓库 + ```shell + git clone https://github.com/XmirrorSecurity/OpenSCA-cli.git opensca && cd opensca + ``` +- 编译 + ```shell + go build + ``` + 使用此命令会生成当前系统和处理器架构的可执行文件,如需生成其他系统架构可配置环境变量后编译 + - 禁用CGO_ENABLED CGO_ENABLED=0 + - 指定操作系统 GOOS=${OS} \\ darwin,liunx,windows + - 指定体系架构 GOARCH=${arch} \\ amd64,arm64 diff --git a/docs/User_Guide/Scanning/Connectiong_to_Vulnerability_Databases-zh_CN.md b/docs/User_Guide/Scanning/Connectiong_to_Vulnerability_Databases-zh_CN.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/User_Guide/Scanning/Connectiong_to_Vulnerability_Databases.md b/docs/User_Guide/Scanning/Connectiong_to_Vulnerability_Databases.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/User_Guide/Scanning/Dependency_Analysis-zh_CN.md b/docs/User_Guide/Scanning/Dependency_Analysis-zh_CN.md index e69de29b..bd1e236b 100644 --- a/docs/User_Guide/Scanning/Dependency_Analysis-zh_CN.md +++ b/docs/User_Guide/Scanning/Dependency_Analysis-zh_CN.md @@ -0,0 +1,146 @@ +[返回目录](/docs/README-zh-CN.md) / [English](./Dependency_Analysis.md) + +- [依赖分析](#依赖分析) +- [使用 OpenSCA-cli 进行依赖分析](#使用-opensca-cli-进行依赖分析) + - [分析本地项目目录](#分析本地项目目录) + - [基本命令](#基本命令) + - [示例](#示例) + - [分析依赖特征文件](#分析依赖特征文件) + - [基本命令](#基本命令-1) + - [示例](#示例-1) + - [分析远程项目](#分析远程项目) + - [基本命令](#基本命令-2) + - [示例](#示例-2) + - [分析 SBOM](#分析-sbom) + +# 依赖分析 + +OpenSCA 通过扫描项目依赖特征文件(动态或静态解析),生成项目依赖关系, 帮助用户了解项目的依赖关系,以便更好地管理项目。 + +所谓动态解析是指调用包管理器,获取项目依赖关系;静态解析是通过模拟包管理器的行为,获取项目依赖关系。动态解析的结果通常更加准确,但依赖包管理器;静态解析在某些情况下可能与动态解析结果有出入,但是不需要安装包管理器。 + +> 若未指定漏洞数据库,则仅分析依赖关系,不进行漏洞分析。 + +支持的语言和包管理器详见 [关于 OpenSCA](/docs/About_OpenSCA-zh_CN.md) + +# 使用 OpenSCA-cli 进行依赖分析 + +## 分析本地项目目录 + +### 基本命令 + + ```shell + opensca-cli -path {项目路径} -out {报告名称}.dsdx,{报告名称}.spdx + ``` + +### 示例 + + + + + + + + + + +
分析 `~/workspace/myproject` 目录分析 `~/workspace/myproject` 目录并生成报告
+ +```shell +opensca-cli -path ~/workspace/myproject +``` + + +```shell +opensca-cli -path ~/workspace/myproject -out ~/workspace/myproject/report.html +``` + +
+ + ## 分析依赖特征文件 + +### 基本命令 + + ```shell + opensca-cli -path {依赖特征文件路径} + ``` + +### 示例 + + + + + + + + + + +
分析 `~/workspace/myproject/package.json` 文件分析 `~/workspace/myproject/package.json` 文件并生成报告
+ +```shell +opensca-cli -path ~/workspace/myproject/package.json +``` + + + +```shell +opensca-cli -path ~/workspace/myproject/package.json -out ~/workspace/myproject/report.html +``` + +
+ +## 分析远程项目 + +### 基本命令 + + ```shell + opensca-cli -path {项目地址} + ``` + +### 示例 + + + + + + + + + + + + + + +
分析 ftp 目录分析 ftp 特征文件分析 http(s) 目录分析 http(s) 特征文件
+ +```shell +opensca-cli -path ftp://example.com/project +``` + + + +```shell +opensca-cli -path ftp://example.com/project/package.json +``` + + + +```shell +opensca-cli -path https://example.com/project +``` + + + +```shell +opensca-cli -path https://example.com/project/package.json +``` + +
+ +## 分析 SBOM + +OpenSCA 支持将 SBOM 文件作为输入,进行依赖分析, 详见 [SBOM](/docs/User_Guide/Generating_Reports/SBOM-zh_CN.md) + + diff --git a/docs/User_Guide/Scanning/Vulnerability_Analysis-zh_CN.md b/docs/User_Guide/Scanning/Vulnerability_Analysis-zh_CN.md new file mode 100644 index 00000000..3d18b7c3 --- /dev/null +++ b/docs/User_Guide/Scanning/Vulnerability_Analysis-zh_CN.md @@ -0,0 +1,175 @@ +[返回目录](/docs/README-zh-CN.md) / [English](./Vulnerability_Analysis.md) + +- [连接到漏洞数据库](#连接到漏洞数据库) +- [分析漏洞](#分析漏洞) + - [使用 OpenSCA SaaS 漏洞库](#使用-opensca-saas-漏洞库) + - [基本命令](#基本命令) + - [示例](#示例) + - [使用 OpenSCA 本地漏洞库](#使用-opensca-本地漏洞库) + - [使用 json 文件](#使用-json-文件) + - [使用 MySQL 数据库](#使用-mysql-数据库) + - [使用 SQLite 数据库](#使用-sqlite-数据库) + +# 连接到漏洞数据库 + +OpenSCA 支持通过连接到漏洞数据库来获取漏洞信息。目前支持的漏洞数据库有: + +- 在线 + - [OpenSCA SaaS](https://opensca.xmirror.cn) +- 本地 + - OpenSCA 本地漏洞库 + - json 文件 + - MySQL 数据库 + - SQLite 数据库 + +关于漏洞数据库的配置,请参考[配置文件说明](../Configuration-and-Parameters-zh_CN.md#漏洞数据库配置示例)。 + +# 分析漏洞 + +在扫描时,OpenSCA 会根据配置文件中的漏洞数据库连接信息,自动连接到漏洞数据库,获取漏洞信息。在扫描完成后,OpenSCA 会将扫描结果与漏洞数据库中的漏洞信息进行对比,生成漏洞报告。 + +## 使用 OpenSCA SaaS 漏洞库 + +OpenSCA 默认云端漏洞库地址为 `https://opensca.xmirror.cn` ,使用云端漏洞库需要先[注册](https://opensca.xmirror.cn/register)并获取 token + + +### 基本命令 + +```shell +opensca-cli -path {项目路径} -token {token} +``` + +### 示例 + + + + + + + + + + + + + + + +
在命令行中传入 token使用用户名密码登录,自动获取 token(仅本次命令生效)将 token 写入配置文件将检测结果同步至 OpenSCA SaaS 进行管理
+ +```shell +opensca-cli -path ~/workspace/myproject -token ************* +``` + + + +```shell +opensca-cli -path ~/workspace/myproject -login +# 安装提示输入用户名密码 +``` + + + +编辑配置文件 config.json, 将 token 填入 `origin.token` 从 [这里](https://raw.githubusercontent.com/XmirrorSecurity/OpenSCA-cli/master/config.json) 获取配置文件模板 + +```json + // ... + + "origin": { + + // opensca web service url + "url": "https://opensca.xmirror.cn", + // opensca web service token + "token": "", + + // ... +``` + +执行 opensca-cli 命令时,不再需要传入 token + +```shell +opensca-cli -path ~/workspace/myproject -config ~/workspace/myproject/config.json +``` + + + +使用 OpenSCA SaaS 方便进行项目管理、团队协作、漏洞跟踪等,并获得更详细的漏洞信息、许可证信息以及最新的漏洞情报和修复建议。 + +* 使用 `-proj` 传入空值,可将结果同步至快速检测(方便个人查看) + ```shell + opensca-cli -path ~/workspace/myproject -token ************* -proj "" + ``` +* 使用 `-proj` 传入项目 id, 可将结果同步至项目管理(支持团队协作) + ```shell + opensca-cli -path ~/workspace/myproject -token ************* -proj ************ + ``` + +
+ +## 使用 OpenSCA 本地漏洞库 + +OpenSCA 本地漏洞库暂未开放,敬请期待 + +## 使用 json 文件 + +按照 [漏洞数据库配置示例](../Configuration-and-Parameters-zh_CN.md#漏洞数据库配置示例) 配置好本地数据库后,在配置文件中指定 json 文件作为漏洞数据源: + +```json + // ... + + "origin": { + + "json": "/path/to/vulnerability.json" + + // ... +``` + +使用 OpenSCA-cli 分析漏洞 + +```shell +opensca-cli -path {项目路径} -config {配置文件路径} +``` + +## 使用 MySQL 数据库 + +按照 [漏洞数据库配置示例](../Configuration-and-Parameters-zh_CN.md#漏洞数据库配置示例) 配置好本地数据库后,在配置文件中指定 MySQL 数据库作为漏洞数据源: + +```json + // ... + + "origin": { + + "mysql": { + "dsn": "user:password@tcp(ip:port)/database_name", + "table": "vulnerability" + } + + // ... +``` + +使用 OpenSCA-cli 分析漏洞 + +```shell +opensca-cli -path {项目路径} -config {配置文件路径} +``` + +## 使用 SQLite 数据库 + +按照 [漏洞数据库配置示例](../Configuration-and-Parameters-zh_CN.md#漏洞数据库配置示例) 配置好本地数据库后,在配置文件中指定 SQLite 数据库作为漏洞数据源: + +```json + // ... + + "origin": { + + "dsn": "/path/to/vulnerability.db", + "table": "vulnerability" + + // ... +``` + +使用 OpenSCA-cli 分析漏洞 + +```shell +opensca-cli -path {项目路径} -config {配置文件路径} +``` diff --git a/docs/User_Guide/Parameter_Explanations.md b/docs/User_Guide/Scanning/Vulnerability_Analysis.md similarity index 100% rename from docs/User_Guide/Parameter_Explanations.md rename to docs/User_Guide/Scanning/Vulnerability_Analysis.md diff --git a/docs/User_Guide/Viewing_Results-zh_CN.md b/docs/User_Guide/Viewing_Results-zh_CN.md index e69de29b..ae72e6b8 100644 --- a/docs/User_Guide/Viewing_Results-zh_CN.md +++ b/docs/User_Guide/Viewing_Results-zh_CN.md @@ -0,0 +1 @@ +[返回目录](/docs/README-zh-CN.md) / [English](./Viewing_Results.md) \ No newline at end of file diff --git a/main.go b/main.go index 780b1828..0ab392ca 100644 --- a/main.go +++ b/main.go @@ -88,8 +88,9 @@ func main() { } // 打印概览信息 - fmt.Println("\n\nComplete!\n" + format.Statis(report)) - logs.Info("\nComplete!\n" + format.Statis(report)) + dep, vul := format.Statis(report) + fmt.Println("\nComplete!\n" + dep + vul) + logs.Info("\nComplete!\n" + dep + vul) // 发送检测报告 if err := format.Saas(report); err != nil { diff --git a/opensca/common/repo.go b/opensca/common/repo.go index a38e5ab5..da0b9f49 100644 --- a/opensca/common/repo.go +++ b/opensca/common/repo.go @@ -53,16 +53,17 @@ func DownloadUrlFromRepos(route string, do func(repo RepoConfig, r io.Reader), r resp, err := HttpDownloadClient.Do(req) if err != nil { logs.Warn(err) - return false + continue } - defer resp.Body.Close() - defer io.Copy(io.Discard, resp.Body) if resp.StatusCode != 200 { logs.Warnf("%d %s", resp.StatusCode, url) + io.Copy(io.Discard, resp.Body) + resp.Body.Close() } else { logs.Debugf("%d %s", resp.StatusCode, url) do(repo, resp.Body) + resp.Body.Close() return true } diff --git a/opensca/model/dpsbom.go b/opensca/model/dpsbom.go new file mode 100644 index 00000000..1786bbf4 --- /dev/null +++ b/opensca/model/dpsbom.go @@ -0,0 +1,112 @@ +package model + +import "time" + +type DpSbomDocument struct { + // 文档名称 + DocumentName string `json:"DocumentName"` + // 文档版本 + DocumentVersion string `json:"DocumentVersion"` + // 文档创建/更新时间 yyyy-MM-ddTHH:mm:ssTZD + DocumentTime string `json:"DocumentTime"` + // 文档格式 + BomFormat string `json:"BomFormat"` + // 生成工具 + Tool string `json:"tool"` + // sbom签名信息 + Hashes DpSbomHashes `json:"Hashes"` + // 组件列表 + Packages []DpSbomPackage `json:"Packages"` + // 依赖关系 + Dependencies []DpSbomDependencies `json:"Dependencies"` +} + +type DpSbomPackage struct { + Name string `json:"ComponentName"` + Version string `json:"ComponentVersion"` + + Identifier struct { + Purl string `json:"PURL"` + } `json:"ComponentIdentifier"` + + License []string `json:"License"` + + Author []map[string]string `json:"Author"` + Provider []map[string]string `json:"Provider"` + Hash DpSbomHash `json:"ComponentHash"` + + // 组件信息更新时间 yyyy-MM-ddTHH:mm:ssTZD + Timestamp string `json:"Timestamp"` +} + +type DpSbomDependencies struct { + Ref string `json:"Ref"` + DependsOn []struct { + Target string `json:"Target"` + } `json:"DependsOn"` +} + +func newDependencies(ref string, dependsOn []string) DpSbomDependencies { + deps := DpSbomDependencies{Ref: ref} + deps.DependsOn = make([]struct { + Target string "json:\"Target\"" + }, len(dependsOn)) + for i, d := range dependsOn { + deps.DependsOn[i].Target = d + } + return deps +} + +type DpSbomHashes struct { + Algorithm string `json:"Algorithm"` + HashFile string `json:"HashFile,omitempty"` + DigitalFile string `json:"DigitalFile,omitempty"` +} + +type DpSbomHash struct { + Algorithm string `json:"Algorithm,omitempty"` + Hash string `json:"Hash,omitempty"` +} + +func NewDpSbomDocument(name, creator string) *DpSbomDocument { + version := "1.0.0" + timestamp := time.Now().Format("2006-01-02T15:04:05MST") + return &DpSbomDocument{ + DocumentName: name, + DocumentVersion: version, + DocumentTime: timestamp, + BomFormat: "DP-SBOM-1.0", + Tool: creator, + Hashes: DpSbomHashes{ + Algorithm: "SHA-256", + HashFile: "sha256.txt", + }, + Dependencies: []DpSbomDependencies{}, + } +} + +func (doc *DpSbomDocument) AppendComponents(fn func(*DpSbomPackage)) { + c := DpSbomPackage{} + if fn != nil { + fn(&c) + } + if c.Timestamp == "" { + c.Timestamp = time.Now().Format("2006-01-02T15:04:05MST") + } + if c.Author == nil { + c.Author = []map[string]string{} + } + if c.Provider == nil { + c.Provider = []map[string]string{} + } + doc.Packages = append(doc.Packages, c) +} + +func (doc *DpSbomDocument) AppendDependencies(parentId string, childrenIds []string) { + if doc.Dependencies == nil { + doc.Dependencies = []DpSbomDependencies{} + } + if len(childrenIds) > 0 { + doc.Dependencies = append(doc.Dependencies, newDependencies(parentId, childrenIds)) + } +} diff --git a/opensca/sca/filter/filter.go b/opensca/sca/filter/filter.go index 35092b77..0c493640 100644 --- a/opensca/sca/filter/filter.go +++ b/opensca/sca/filter/filter.go @@ -69,10 +69,11 @@ var ( ) var ( - SbomSpdx = filterFunc(strings.HasSuffix, ".spdx") - SbomDsdx = filterFunc(strings.HasSuffix, ".dsdx") - SbomJson = filterFunc(strings.HasSuffix, ".json") - SbomXml = filterFunc(strings.HasSuffix, ".xml") + SbomSpdx = filterFunc(strings.HasSuffix, ".spdx") + SbomDsdx = filterFunc(strings.HasSuffix, ".dsdx") + SbomJson = filterFunc(strings.HasSuffix, ".json") + SbomXml = filterFunc(strings.HasSuffix, ".xml") + SbomDbSbom = filterFunc(strings.HasSuffix, ".dbsbom") // SbomRdf = filterFunc(strings.HasSuffix, ".rdf") ) diff --git a/opensca/sca/javascript/npm.go b/opensca/sca/javascript/npm.go index 9a04d3cb..b2f7c3e8 100644 --- a/opensca/sca/javascript/npm.go +++ b/opensca/sca/javascript/npm.go @@ -143,7 +143,11 @@ func ParsePackageJsonWithNode(pkgjson *PackageJson, nodeMap map[string]*PackageJ subjs = npmOrigin(name, version) } if subjs == nil { - return nil + // 部分投毒组件会从官方库下架 这种构造一个虚拟的PacakgeJson保证检出 + subjs = &PackageJson{ + Name: name, + Version: version, + } } var dep *model.DepGraph if dev { diff --git a/opensca/sca/sbom/dpsbom.go b/opensca/sca/sbom/dpsbom.go new file mode 100644 index 00000000..c3a70c3f --- /dev/null +++ b/opensca/sca/sbom/dpsbom.go @@ -0,0 +1,65 @@ +package sbom + +import ( + "encoding/json" + "io" + + "github.com/xmirrorsecurity/opensca-cli/v3/opensca/model" +) + +func ParseDpSbomJson(f *model.File) *model.DepGraph { + doc := &model.DpSbomDocument{} + f.OpenReader(func(reader io.Reader) { + json.NewDecoder(reader).Decode(doc) + }) + return parseDpSbomDoc(f, doc) +} + +func parseDpSbomDoc(f *model.File, doc *model.DpSbomDocument) *model.DepGraph { + + if doc == nil { + return nil + } + + depIdMap := map[string]*model.DepGraph{} + _dep := model.NewDepGraphMap(func(s ...string) string { + return s[0] + }, func(s ...string) *model.DepGraph { + vendor, name, version, language := model.ParsePurl(s[0]) + return &model.DepGraph{ + Vendor: vendor, + Name: name, + Version: version, + Language: language, + } + }).LoadOrStore + + for _, pkg := range doc.Packages { + dep := _dep(pkg.Identifier.Purl) + dep.Licenses = pkg.License + depIdMap[pkg.Identifier.Purl] = dep + } + + for _, dependOn := range doc.Dependencies { + parent, ok := depIdMap[dependOn.Ref] + if !ok { + continue + } + for _, dep := range dependOn.DependsOn { + child, ok := depIdMap[dep.Target] + if !ok { + continue + } + parent.AppendChild(child) + } + } + + root := &model.DepGraph{Path: f.Relpath()} + for _, dep := range depIdMap { + if len(dep.Parents) == 0 { + root.AppendChild(dep) + } + } + + return root +} diff --git a/opensca/sca/sbom/dsdx.go b/opensca/sca/sbom/dsdx.go index 2d5a610d..690f7dc0 100644 --- a/opensca/sca/sbom/dsdx.go +++ b/opensca/sca/sbom/dsdx.go @@ -31,7 +31,7 @@ func ParseDsdxXml(f *model.File) *model.DepGraph { func parseDsdxDoc(f *model.File, doc *model.DsdxDocument) *model.DepGraph { - if doc == nil || doc.DSDXVersion == "" { + if doc == nil || len(doc.Components) == 0 { return nil } @@ -76,7 +76,7 @@ func parseDsdxDoc(f *model.File, doc *model.DsdxDocument) *model.DepGraph { // ReadDsdx 读取dsdx文件 func ReadDsdx(f *model.File) *model.DsdxDocument { - dsdx := &model.DsdxDocument{} + dsdx := &model.DsdxDocument{Dependencies: model.DsdxDependencies{}} // 记录依赖关系 dependencies := map[string][]string{} diff --git a/opensca/sca/sbom/sca.go b/opensca/sca/sbom/sca.go index 3950d955..8d0c41ce 100644 --- a/opensca/sca/sbom/sca.go +++ b/opensca/sca/sbom/sca.go @@ -25,10 +25,14 @@ func (sca Sca) Sca(ctx context.Context, parent *model.File, files []*model.File, if filter.SbomDsdx(file.Relpath()) { call(file, ParseDsdx(file)) } + if filter.SbomDbSbom(file.Relpath()) { + call(file, ParseDpSbomJson(file)) + } if filter.SbomJson(file.Relpath()) { call(file, ParseSpdxJson(file)) call(file, ParseCdxJson(file)) call(file, ParseDsdxJson(file)) + call(file, ParseDpSbomJson(file)) } if filter.SbomXml(file.Relpath()) { call(file, ParseSpdxXml(file)) diff --git a/resources/wechat.png b/resources/wechat.png index d7109733..25460759 100644 Binary files a/resources/wechat.png and b/resources/wechat.png differ diff --git a/resources/xcheck_function.jpg b/resources/xcheck_function.jpg new file mode 100644 index 00000000..6a666cb1 Binary files /dev/null and b/resources/xcheck_function.jpg differ diff --git a/resources/xcheck_marketplace.jpg b/resources/xcheck_marketplace.jpg new file mode 100644 index 00000000..ae20a3ed Binary files /dev/null and b/resources/xcheck_marketplace.jpg differ diff --git a/resources/xcheck_process.jpg b/resources/xcheck_process.jpg new file mode 100644 index 00000000..f7952ebe Binary files /dev/null and b/resources/xcheck_process.jpg differ diff --git a/scripts/install.sh b/scripts/install.sh index f4d052d1..e25552ed 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -70,7 +70,7 @@ install() { printf " Adding OpenSCA-cli to PATH: " case "$current_shell" in "bash") - printf "'export PATH=%S/.config/opensca-cli:\$PATH >> ~/.bashrc'\n" "$HOME" + printf "'export PATH=%s/.config/opensca-cli:\$PATH >> ~/.bashrc'\n" "$HOME" echo "export PATH=$HOME/.config/opensca-cli:\$PATH" >> ~/.bashrc ;; "zsh") diff --git a/scripts/json2excel.py b/scripts/json2excel.py index bb54a85f..66040a96 100644 --- a/scripts/json2excel.py +++ b/scripts/json2excel.py @@ -186,12 +186,10 @@ def json2excel(input: str, output: str): vuls[vuln.id] = vuln writer = pd.ExcelWriter(output) # 保存组件 - dep_df = pd.DataFrame([d.raw() for d in deps]) - dep_df.columns = Dependency.col_name() + dep_df = pd.DataFrame([d.raw() for d in deps], columns=Dependency.col_name()) dep_df.to_excel(writer, sheet_name="Dependencies", index=False) # 保存漏洞 - vul_df = pd.DataFrame([v.raw() for v in vuls.values()]) - vul_df.columns = Vulnerability.col_name() + vul_df = pd.DataFrame([v.raw() for v in vuls.values()], columns=Vulnerability.col_name()) vul_df.to_excel(writer, sheet_name="Vulnerabilities", index=False) writer.close()