kondukto-io/kdt
GitHub: kondukto-io/kdt
Invicti ASPM 平台的开源命令行工具,用于在 CI/CD 流水线中自动化管理应用安全扫描并执行安全发布标准。
Stars: 29 | Forks: 12
# KDT
KDT 是一个开源的命令行界面,用于 [Invicti ASPM](https://kondukto.io),这是一个应用程序安全态势管理 (ASPM) 平台。KDT 使用 [Go](https://golang.org) 编写,通过其公开的 API 与 Invicti ASPM 引擎进行交互。
使用 KDT,您可以列出 **Invicti ASPM** 中的项目及其扫描,使用特定的应用程序安全工具触发扫描,导入扫描结果,管理 SBOM 文件,并在扫描结果不满足指定的发布标准时中断发布。KDT 旨在与 CI/CD pipeline 无缝集成,以实现自动化的 DevSecOps 工作流。
## 什么是 Invicti ASPM?
[Invicti ASPM](https://kondukto.io) 是一个应用程序安全态势管理 (ASPM) 平台,可帮助您集中化并自动化整个 AppSec 漏洞管理流程。它提供:
- 应用程序的安全健康集中监控
- DevSecOps pipeline 集成
- 自动化的 AppSec 工作流编排
- 发布标准强制执行
- SBOM 管理
## 目录
- [安装](#installation)
- [配置](#configuration)
- [全局 Flags](#global-flags)
- [命令](#commands)
- [健康检查](#health-checks)
- [Scan 命令](#scan-command)
- [Release 命令](#release-command)
- [List 命令](#list-commands)
- [Create 命令](#create-commands)
- [Update 命令](#update-commands)
- [SBOM 命令](#sbom-commands)
- [Endpoint 命令](#endpoint-commands)
- [Status 命令](#status-command)
- [Project 命令](#project-commands)
- [Scan Parameters 命令](#scan-parameters-commands)
- [高级用法示例](#advanced-usage-examples)
- [Exit Codes](#exit-codes)
- [贡献](#contributing)
## 安装
您可以通过以下几种方法安装 KDT:
### 使用 curl (Linux/macOS)
**使用 sudo(全局安装):**
```
curl -sSL https://cli.kondukto.io | sudo sh
```
**不使用 sudo(用户级安装):**
```
curl -sSL https://cli.kondukto.io | sh
```
### Windows
从 [Releases](https://github.com/kondukto-io/kdt/releases) 下载最新的 `kdt-cli.exe`。
### 使用 Go
如果您有 Go 环境:
```
go get github.com/kondukto-io/kdt
```
### 从源码构建
```
git clone https://github.com/kondukto-io/kdt.git
cd kdt
go build . -o kdt
```
或者直接:
```
make all
```
## 配置
KDT 需要 Invicti ASPM 的 host URL 和 API token 进行身份验证。API token 可以在 Invicti ASPM UI 的 **Integrations > API Tokens** 下创建。
### 配置方法
#### 1. 环境变量
```
export INVICTI_ASPM_HOST=https://your-invicti-aspm-instance.com
export INVICTI_ASPM_TOKEN=your_api_token_here
```
为了持久化生效,您可以将它们添加到您的 shell 配置文件(`~/.bashrc`、`~/.zshrc`、`~/.profile`)中。
#### 2. 配置文件
默认位置:`$HOME/.kdt.yaml`
```
host: https://your-invicti-aspm-instance.com
token: your_api_token_here
insecure: false
verbose: false
```
您可以指定自定义的配置文件:
```
kdt --config=/path/to/config.yaml list projects
```
#### 3. 命令行 Flags
```
kdt --host https://your-invicti-aspm-instance.com --token your_api_token list projects
```
**配置优先级:** 命令行 flags > 环境变量 > 配置文件
## 全局 Flags
这些 flags 可以与任何 KDT 命令一起使用:
| Flag | 描述 | 默认值 |
|------|-------------|---------|
| `--config` | 配置文件的路径 | `$HOME/.kdt.yaml` |
| `--host` | Invicti ASPM 服务器 host URL | - |
| `--token` | Invicti ASPM API token | - |
| `--insecure` | 跳过 TLS 证书验证(生产环境不推荐) | `false` |
| `-v, --verbose` | 启用详细日志记录以进行调试 | `false` |
| `--exit-code` | 覆盖 exit code | `0` |
**示例:**
```
kdt --config=prod-config.yaml --verbose scan -p MyProject -t semgrep -b main
```
## 命令
### 健康检查
#### 验证连接
测试与 Invicti ASPM 服务的连通性:
```
kdt ping
```
#### 验证 API Token
验证您的 API token 是否有效:
```
kdt ping -a
```
### Scan 命令
`scan` 命令是触发安全扫描和导入扫描结果的主要命令。
#### Scan Flags
| Flag | 缩写 | 描述 | 默认值 |
|------|-------|-------------|---------|
| `--async` | - | 异步运行扫描(非阻塞) | `false` |
| `--project` | `-p` | 项目名称或 ID | - |
| `--tool` | `-t` | 扫描器工具名称 | - |
| `--scan-id` | `-s` | 要重启的 Scan ID | - |
| `--branch` | `-b` | 分支名称 | - |
| `--file` | `-f` | 要导入的扫描结果文件 | - |
| `--image` | `-I` | 要扫描的容器镜像 | - |
| `--agent` | `-a` | 用于基于 agent 扫描器的 agent 名称 | - |
| `--meta` | `-m` | 元数据 | - |
| `--scan-tag` | - | 扫描的标签 | - |
| `--env` | - | 环境:`production`, `staging`, `develop`, `feature` | - |
| `--timeout` | - | 等待扫描完成的分钟数(0 = 无超时) | `0` |
| `--release-timeout` | - | 等待发布标准检查的分钟数 | `5` |
#### Pull Request 扫描 Flags
| Flag | 缩写 | 描述 |
|------|-------|-------------|
| `--merge-target` | `-M` | PR 扫描的目标分支 |
| `--pr-number` | - | 用于 PR decoration 的 PR 编号 |
| `--pr-decoration-scanner-types` | - | 用于 PR decoration 的扫描器类型(例如,`all`, `sast`, `dast`, `sca`) |
| `--override` | - | 覆盖 PR 扫描的旧分析结果 |
| `--no-decoration` | - | 禁用 PR decoration(已弃用) |
#### Fork 扫描 Flags
| Flag | 缩写 | 描述 |
|------|-------|-------------|
| `--fork-scan` | `-B` | 基于默认分支启用 fork 扫描 |
| `--fork-source` | - | fork 扫描的源分支 |
| `--override-fork-source` | - | 覆盖项目的 fork 源分支 |
#### 阈值 Flags
如果漏洞超过阈值则中断构建:
| Flag | 描述 |
|------|-------------|
| `--threshold-crit` | 最大严重漏洞数 |
| `--threshold-high` | 最大高危漏洞数 |
| `--threshold-med` | 最大中危漏洞数 |
| `--threshold-low` | 最大低危漏洞数 |
| `--threshold-risk` | 如果风险分数增加则失败 |
| `--break-by-scanner-type` | 仅针对特定扫描器类型中断 |
#### 项目创建 Flags
在扫描期间自动创建项目:
| Flag | 缩写 | 描述 |
|------|-------|-------------|
| `--create-project` | - | 如果未找到项目则创建 |
| `--project-name` | - | 新项目的名称 |
| `--repo-id` | `-r` | 仓库 URL 或 ID |
| `--alm-tool` | `-A` | ALM 工具名称(例如,`github`、`gitlab`) |
| `--team` | `-T` | 团队名称 |
| `--labels` | `-l` | 逗号分隔的标签 |
| `--product-name` | `-P` | 产品名称 |
| `--default-branch` | - | 默认分支 | `main` |
| `--disable-clone` | - | 禁用仓库克隆 |
| `--criticality-level` | - | 业务关键性:4=重大, 3=高, 2=中, 1=低, 0=无, -1=自动 |
| `--feature-branch-retention` | - | 保留 feature 分支的天数 |
| `--feature-branch-infinite-retention` | - | 永不删除 feature 分支 |
| `--scope-include-empty` | - | 包含没有路径的漏洞 |
| `--scope-included-paths` | - | 用于 mono-repo 范围的逗号分隔路径 |
| `--scope-included-files` | - | 用于界定范围的逗号分隔文件名 |
#### 自定义参数
| Flag | 缩写 | 描述 |
|------|-------|-------------|
| `--params` | - | 自定义扫描器参数(格式:`key:value`) |
| `--incremental-scan` | `-i` | 启用增量扫描(仅限 Semgrep 导入) |
#### 扫描示例
**1. 通过 Scan ID 重启现有扫描:**
```
kdt scan -s 5da6cafa5ab6e436faf643dc
```
**2. 使用项目和工具触发扫描:**
```
kdt scan -p MyProject -t semgrep -b main
```
**3. 从文件导入扫描结果:**
```
kdt scan -p MyProject -t checkmarx -b develop -f results.xml
```
**4. 带有阈值的扫描(中断构建):**
```
kdt scan -p MyProject -t trivy -b main \
--threshold-crit 0 \
--threshold-high 5 \
--threshold-med 10
```
**5. 异步扫描(非阻塞):**
```
kdt scan -p MyProject -t gosec -b main --async
```
**6. 容器镜像扫描:**
```
kdt scan -p MyProject -t trivy \
--image myapp:latest \
-b main
```
**7. Pull request 扫描:**
```
kdt scan -p MyProject -t semgrep \
-b feature/new-feature \
-M main \
--pr-number 123
```
**8. Fork 扫描(feature 分支对比默认分支):**
```
kdt scan -p MyProject -t semgrep \
-b feature/test \
--fork-scan \
--env feature
```
**9. 创建项目并扫描:**
```
kdt scan -p NewProject -t semgrep -b main \
--create-project \
--repo-id https://github.com/org/repo \
--alm-tool github \
--team security
```
**10. 自定义参数:**
```
kdt scan -p MyProject -t semgrep -b develop \
--params=ruleset_type:2 \
--params=ruleset_options.ruleset:/custom/rules/
```
**11. 风险阈值(防止倒退):**
```
kdt scan -p MyProject -t sonarqube -b main --threshold-risk
```
**12. 增量扫描:**
```
kdt scan -p MyProject -t semgrep -b main \
-f semgrep-results.json \
--incremental-scan
```
### Release 命令
检查项目是否满足发布标准。
#### Release Flags
| Flag | 缩写 | 描述 |
|------|-------|-------------|
| `--project` | `-p` | 项目名称或 ID(必填) |
| `--branch` | `-b` | 分支名称(默认:项目的默认分支) |
| `--timeout` | - | 等待标准检查的分钟数 | `5` |
| `--sast` | - | 检查 SAST 标准 |
| `--dast` | - | 检查 DAST 标准 |
| `--sca` | - | 检查 SCA 标准 |
| `--iac` | - | 检查 IaC 标准 |
| `--cs` | - | 检查 Code Security 标准 |
| `--iast` | - | 检查 IAST 标准 |
| `--pentest` | - | 检查渗透测试标准 |
| `--mast` | - | 检查 MAST 标准 |
| `--sbom` | - | 检查 SBOM 标准 |
#### Release 示例
**1. 检查所有发布标准:**
```
kdt release -p MyProject -b main
```
**2. 仅检查特定标准:**
```
kdt release -p MyProject -b main --sast --sca
```
**3. 输出详细日志:**
```
kdt -v release -p MyProject -b main --sast --dast
```
**4. 使用自定义超时:**
```
kdt release -p MyProject -b main --timeout 10
```
### List 命令
#### 列出项目
```
kdt list projects
```
您可以选择传递一个名称作为位置参数来过滤项目:
```
kdt list projects MyProject
```
#### 列出扫描
**Flags:**
- `-p, --project`:项目名称或 ID(必填)
**示例:**
```
kdt list scans -p MyProject
```
#### 列出扫描器
查看所有可用的扫描器:
```
kdt list scanners
```
**Flags:**
| Flag | 缩写 | 描述 |
|------|-------|-------------|
| `--type` | `-t` | 按扫描器类型过滤(例如 `sast`、`dast`、`sca`) |
| `--labels` | `-l` | 按逗号分隔的扫描器标签过滤 |
**示例:**
```
# 仅列出 SAST scanners
kdt list scanners --type sast
# 列出具有特定标签的 scanners
kdt list scanners --labels docker,kdt
```
**示例输出:**
```
Name ID Type Trigger Labels Flags Status
---- -- ---- ------- ------ ----- ------
gosec 60eec8a83e9e5e6e2ae52d06 sast new scan docker,kdt
semgrep 60eec8a53e9e5e6e2ae52d05 sast rescan template,docker,kdt
trivy 60eec8a73e9e5e6e2ae52d07 sca new scan docker,kdt,container
```
#### 列出 Agents
```
kdt list agents
```
#### 列出产品
```
kdt list products
```
**Flags:**
- `-n, --name`:按名称搜索产品
**示例:**
```
kdt list products --name mobile
```
### Create 命令
#### 创建项目
**Flags:**
| Flag | 缩写 | 描述 |
|------|-------|-------------|
| `--repo-id` | `-r` | 仓库 URL 或 ID(必填) |
| `--project-name` | - | 项目名称 |
| `--alm-tool` | `-a` | ALM 工具名称 |
| `--team` | `-t` | 团队名称 |
| `--labels` | `-l` | 逗号分隔的标签 |
| `--product-name` | `-P` | 产品名称 |
| `--force-create` | - | 如果仓库 URL 已被其他项目使用则忽略 |
| `--overwrite` `-w` | 创建时将项目重命名为此值(字符串) |
| `--default-branch` | - | 默认分支 | `main` |
| `--disable-clone` | - | 禁用仓库克隆 |
| `--fork-source` | - | feature 分支的源分支 |
| `--criticality-level` | - | 业务关键性(0-4,-1=自动) |
| `--feature-branch-retention` | - | 保留 feature 分支的天数 |
| `--feature-branch-infinite-retention` | - | 永不删除 feature 分支 |
| `--scope-include-empty` | - | 包含没有路径的漏洞 |
| `--scope-included-paths` | - | 用于 mono-repo 范围的路径 |
| `--scope-included-files` | - | 用于界定范围的文件名 |
**示例:**
**1. 从仓库创建项目:**
```
kdt create project \
--repo-id https://github.com/kondukto-io/kdt \
--alm-tool github \
--labels GDPR,Internal \
--team security
```
**2. 使用自定义名称创建:**
```
kdt create project \
--repo-id https://gitlab.com/org/app \
--project-name MyCustomName \
--alm-tool gitlab \
--default-branch develop
```
**3. 关联产品创建:**
```
kdt create project \
--repo-id https://github.com/org/repo \
--alm-tool github \
--product-name "Mobile Apps" \
--criticality-level 4
```
**4. 带有范围设定的 Mono-repo:**
```
kdt create project \
--repo-id https://github.com/org/monorepo \
--project-name backend-api \
--alm-tool github \
--scope-included-paths "services/api,shared/common" \
--scope-included-files "package.json,go.mod"
```
#### 创建团队
**Flags:**
- `-n, --name`:团队名称(必填)
- `-r, --responsible`:负责人用户名
**示例:**
```
kdt create team --name "security-team" --responsible "john.doe"
```
#### 创建标签
**Flags:**
- `-n, --name`:标签名称(必填)
- `-c, --color`:十六进制格式的标签颜色(默认:`000000`)
**示例:**
```
# 使用默认颜色创建标签
kdt create label --name "GDPR"
# 使用自定义颜色创建标签
kdt create label --name "Critical" --color "FF0000"
```
#### 创建产品
**Flags:**
- `-n, --name`:产品名称(必填)
- `-p, --projects`:逗号分隔的项目名称或 ID
**示例:**
```
# 创建空 product
kdt create product --name "mobile-apps"
# 创建带有 projects 的 product
kdt create product --name "web-services" --projects "api-service,web-app,auth-service"
```
### Update 命令
#### 更新项目
更新现有项目的属性。
**Flags:**
| Flag | 描述 |
|------|-------------|
| `--project-id` | 要更新的项目 ID 或名称 |
| `--criticality-level` | 业务关键性:4=重大, 3=高, 2=中, 1=低, 0=无, -1=自动 |
| `--label` | 逗号分隔的标签名称。**覆盖**项目现有的标签 |
**示例:**
**1. 更新业务关键性:**
```
kdt update project --project-id MyProject --criticality-level 4
```
**2. 替换项目标签:**
```
kdt update project --project-id MyProject --label "Internal,Sensitive Data,Payment"
```
### SBOM 命令
#### 导入 SBOM
导入软件物料清单(CycloneDX 格式)。
**Flags:**
| Flag | 缩写 | 描述 |
|------|-------|-------------|
| `--file` | `-f` | SBOM 文件路径(JSON 格式,必填) |
| `--project` | `-p` | 项目名称或 ID |
| `--repo-id` | `-r` | 仓库 URL 或 ID |
| `--branch` | `-b` | 分支名称 |
| `--sbom-type` | `-s` | 类型:`source_dir`, `image`, `application`, `os`, `container` |
| `--allow-empty` | `-a` | 允许空组件 |
**示例:**
**1. 为项目导入 SBOM:**
```
kdt sbom import \
-f cyclonedx-sbom.json \
-p MyProject \
-b main
```
**2. 使用特定类型导入:**
```
kdt sbom import \
-f sbom.json \
-p MyProject \
-b main \
--sbom-type image
```
**3. 使用仓库 ID 导入:**
```
kdt sbom import \
-f sbom.json \
--repo-id https://github.com/org/repo \
-b main
```
### Endpoint 命令
#### 导入 Endpoint
导入 API endpoint 定义(Swagger/OpenAPI)。
**Flags:**
| Flag | 缩写 | 描述 |
|------|-------|-------------|
| `--file` | `-f` | Endpoint 文件路径(必填) |
| `--project` | `-p` | 项目名称或 ID(必填) |
**示例:**
```
kdt endpoint import -f swagger.json -p MyProject
```
### Status 命令
查询项目状态和漏洞数量。
**Flags:**
| Flag | 缩写 | 描述 |
|------|-------|-------------|
| `--project` | `-p` | 项目名称或 ID |
| `--branch` | `-b` | 分支名称 |
| `--event` | `-e` | 事件 ID |
| `--threshold-crit` | - | 严重阈值 |
| `--threshold-high` | - | 高危阈值 |
| `--threshold-med` | - | 中危阈值 |
| `--threshold-low` | - | 低危阈值 |
| `--threshold-risk` | - | 风险阈值 |
**示例:**
**1. 获取项目状态:**
```
kdt status -p MyProject -b main
```
**2. 检查带有阈值的状态:**
```
kdt status -p MyProject -b main \
--threshold-crit 0 \
--threshold-high 5
```
**3. 通过事件 ID 查询:**
```
kdt status -e 5da6cafa5ab6e436faf643dc
```
### Project 命令
#### 检查项目可用性
检查项目中是否存在 ALM。
**Flags:**
| Flag | 缩写 | 描述 |
|------|-------|-------------|
| `--alm-tool` | `-a` | ALM 工具名称 |
| `--repo-id` | `-r` | 仓库 URL 或 ID |
**示例:**
```
kdt project available \
--alm-tool github \
--repo-id https://github.com/kondukto-io/kdt
```
如果可用返回 exit code 0,如果不可用返回 -1 (255)。
### Scan Parameters 命令
#### 删除扫描参数
从 Invicti ASPM 中删除扫描参数**及其关联的漏洞**。它通过项目、工具以及(可选的)分支和元数据来识别扫描参数。
**Flags:**
| Flag | 缩写 | 描述 |
|------|-------|-------------|
| `--project` | `-p` | 项目名称或 ID(必填) |
| `--tool` | `-t` | 扫描参数的工具名称(必填) |
| `--branch` | `-b` | 扫描参数的分支 |
| `--meta` | `-m` | 扫描参数的元数据 |
| `--force` | `-f` | 确认删除(必填) |
**示例:**
```
kdt scanparams delete -p MyProject -t semgrep -b main --force
```
## 高级用法示例
### CI/CD Pipeline 集成
#### GitHub Actions
```
- name: Run Security Scan
run: |
kdt scan \
-p ${{ github.event.repository.name }} \
-t semgrep \
-b ${{ github.ref_name }} \
--threshold-crit 0 \
--threshold-high 10
```
#### GitLab CI
```
security_scan:
script:
- kdt scan -p ${CI_PROJECT_NAME} -t trivy -b ${CI_COMMIT_BRANCH} --threshold-crit 0
```
#### Jenkins
```
stage('Security Scan') {
steps {
sh '''
kdt scan \
-p ${JOB_NAME} \
-t checkmarx \
-b ${GIT_BRANCH} \
--threshold-crit 0 \
--threshold-high 5
'''
}
}
```
### 复杂工作流示例
#### 1. 完整的 DevSecOps Pipeline
```
# 从本地工具导入 scan results
kdt scan -p MyProject -t fortify -f results.fpr -b develop \
--threshold-crit 0 --threshold-high 0
# 检查 release criteria
kdt release -p MyProject -b develop --sast --sca --dast
```
#### 2. 容器安全工作流
```
# 扫描 container image
kdt scan -p MyProject -t trivy \
--image myapp:${VERSION} \
-b main \
--threshold-crit 0
# 导入 SBOM
kdt sbom import -f sbom.json -p MyProject -b main --sbom-type container
```
#### 3. Pull Request 工作流
```
# 触发 PR scan
kdt scan -p MyProject -t semgrep \
-b feature/new-feature \
-M main \
--pr-number ${PR_NUMBER} \
--pr-decoration-scanner-types all
```
#### 4. 多环境设置
```
# Development
kdt scan -p MyProject -t semgrep -b develop --env develop
# Staging
kdt scan -p MyProject -t sonarqube -b staging --env staging \
--threshold-high 10
# Production
kdt scan -p MyProject -t checkmarx -b main --env production \
--threshold-crit 0 --threshold-high 0 \
--release-timeout 10
```
#### 5. 用于高级配置的自定义参数
```
# 使用自定义规则的 Semgrep
kdt scan -p MyProject -t semgrep -b main \
--params=ruleset_type:2 \
--params=ruleset_options.ruleset:/custom/rules/ \
--params=ruleset_options.config:auto
# 使用自定义 registry 的 Container scan
kdt scan -p MyProject -t trivy \
--image registry.example.com/myapp:latest \
--params=registry.username:user \
--params=registry.password:pass
```
## Exit Codes
KDT 使用以下 exit codes:
| Code | 含义 |
|------|---------|
| `0` | 成功 |
| `1` | 一般错误 |
| `2` | 警告 |
| `100` | 未授权 |
| `-1` (255) | 否定响应(例如,项目不可用) |
## 支持的扫描器
KDT 支持在您的 Invicti ASPM 实例中启用的所有扫描器。查看可用的扫描器:
```
kdt list scanners
```
## 故障排除
### 启用详细日志记录
```
kdt -v scan -p MyProject -t semgrep -b main
```
### 测试连接
```
kdt ping
kdt ping -a # With authentication
```
### 验证配置
```
# 检查 host 和 token 是否已设置
echo $INVICTI_ASPM_HOST
echo $INVICTI_ASPM_TOKEN
# 或使用测试命令
kdt list projects
```
## 贡献
欢迎对 KDT 进行贡献!以下是您可以为项目做出贡献的方法:
### 报告问题
在 [GitHub repository](https://github.com/kondukto-io/kdt/issues) 中创建一个 issue,包含:
- 对问题的清晰描述
- 复现步骤
- 预期与实际行为对比
- KDT 版本 (`kdt version`)
### Pull Requests
1. Fork 该仓库
2. 遵循 [Git Flow](https://nvie.com/posts/a-successful-git-branching-model/) 创建一个 feature/bugfix 分支:
- 功能:`feature/example-feature`
- 修复:`bugfix/example-bugfix`
3. 编写符合习惯的 Go 代码
4. 为导出的函数编写文档
5. 编写详细的 PR 描述
6. 确保测试通过
### 开发设置
```
git clone https://github.com/kondukto-io/kdt.git
cd kdt
go mod download
go build -o kdt
./kdt --help
```
## 许可证
详情请参见 [LICENSE](LICENSE) 文件。
## 支持
- 文档:[https://docs.kondukto.io](https://docs.kondukto.io)
- 问题:[GitHub Issues](https://github.com/kondukto-io/kdt/issues)
- 网站:[https://kondukto.io](https://kondukto.io)
标签:ASPM, DevSecOps, EVTX分析, Go, GPT, Ruby工具, 上游代理, 日志审计, 漏洞管理
