vdanen/syfter
GitHub: vdanen/syfter
syfter 是一个基于Syft的SBOM生成与管理工具,旨在提升软件供应链的可见性和安全性。
Stars: 1 | Forks: 0
# Syfter
[](https://www.bestpractices.dev/projects/11827)
[](https://scorecard.dev/viewer/?uri=github.com/vdanen/syfter)



使用 [Syft](https://github.com/anchore/syft) 的 SBOM 生成与管理工具。
**版本: 0.9.1.0**
## 概述
- **扫描**包含 RPM 包、容器镜像及其他制品的目录
- **丰富** SBOM 的产品特定元数据(带有发行版限定符的 CPE 和 PURL)
- **存储** SBOM 至可查询的数据库(SQLite 或 PostgreSQL)
- **查询**跨产品或系统的所有软件包和文件
- **导出**为面向客户的格式(SPDX, CycloneDX)
### 企业级能力
除了所有标准 syfter 功能外,此版本增加了面向生产的服务器功能:
| 功能 | 描述 |
|---------|-------------|
| **API 密钥认证** | 基于团队的密钥,支持管理员管理(`X-API-Key` 请求头) |
| **速率限制** | 基于令牌桶算法,按密钥限制(每分钟查询和上传次数) |
| **响应缓存** | 进程内缓存,数据修改时自动失效 |
| **RPM 依赖关系跟踪** | 大规模查询 Requires/Provides 关系 |
| **跨产品追踪** | `syfter trace` 跨仓库、基础镜像和分层容器追踪软件包 |
| **证明元数据** | Cosign SLSA 和 SPDX 证明索引 |
| **组件关系** | 产品到产品的组合映射 |
| **查询性能** | 针对数千万软件包优化的 PostgreSQL 查询模式 |
### 两种运行模式
Syfter 支持两种不同的模式:
### 两种部署选项
Syfter 可以在两种部署配置下运行:
| 模式 | 存储 | 适用场景 |
|------|---------|----------|
| **本地模式** | SQLite (`~/.syfter/syfter.db`) | 开发、单用户、小规模 |
| **服务器模式** | PostgreSQL + MinIO (S3) | 生产环境、多用户、大规模 |
- **本地模式**是默认模式 - 无需额外设置,安装即可运行
- **服务器模式**需要通过 `podman-compose` 运行 API 服务器
## 前置条件
- **Python 3.9+**
- **Syft** - 从 [GitHub releases](https://github.com/anchore/syft/releases)、Homebrew 安装,或运行以下命令:
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
- **Skopeo** - 可通过 dnf 或 Homebrew 安装,参见 [GitHub 安装说明](https://github.com/containers/skopeo/blob/main/install.md)
## 安装说明
### 使用 uv(推荐)
```
# 安装为独立 CLI 工具(隔离环境)
uv tool install syfter
# 或安装包含服务器组件
uv tool install "syfter[server]"
# 升级到最新版本
uv tool upgrade syfter
```
### 使用 pip
```
# 从 PyPI 安装
pip install syfter
# 安装包含服务器组件
pip install "syfter[server]"
```
### 从源代码安装
```
git clone https://github.com/vdanen/syfter.git
cd syfter
# 使用 uv
uv tool install .
# 或使用 pip
pip install -e .
# 安装所有组件(服务器 + 开发工具)
pip install -e ".[all]"
```
详细的构建和分发选项请参见 [docs/BUILDING.md](docs/BUILDING.md)。
## 部署选项
### 选项 1:本地模式(默认)
本地模式使用 SQLite,无需额外设置。安装即可开始使用:
```
# 扫描存储至 ~/.syfter/syfter.db
syfter scan /path/to/rpms -p myproduct -v 1.0
syfter products
syfter query -n "openssl%"
```
本地模式适用于:
- 开发和测试
- 单用户工作站
- 中小规模的扫描量(约 50 个产品以内)
### 选项 2:服务器模式(分布式)
服务器模式使用 PostgreSQL 作为数据库,使用 MinIO(兼容 S3)存储 SBOM。可扩展至支持数千个产品和多个并发用户。
#### 服务器模式的前置条件
- **Podman** 和 **podman-compose**(或 Docker/docker-compose)
# Fedora/RHEL
sudo dnf install podman podman-compose
# macOS
brew install podman podman-compose
#### 启动服务器
```
cd podman
# 创建包含密码的环境文件
cp env.example .env
# 编辑 .env 以设置安全密码:
# POSTGRES_PASSWORD=your_secure_password
# MINIO_ROOT_PASSWORD=your_secure_password
# 启动所有服务(PostgreSQL、MinIO、API)
podman-compose up -d
# 检查状态
podman-compose ps
# 查看日志
podman-compose logs -f syfter-api
```
服务将可通过以下地址访问:
- **API 服务器**: http://localhost:8000
- **MinIO 控制台**: http://localhost:9001(使用 MINIO_ROOT_USER/PASSWORD 登录)
- **PostgreSQL**: localhost:5432
#### 配置 CLI 以使用服务器模式
设置 `SYFTER_SERVER` 环境变量指向您的 API 服务器:
```
# 添加到你的 ~/.bashrc 或 ~/.zshrc
export SYFTER_SERVER=http://localhost:8000
# 或在每次命令中指定
syfter --server http://localhost:8000 products
# 认证服务器(设置团队 API 密钥)
export SYFTER_API_KEY=your-team-key
```
#### API 认证
当 `SYFTER_AUTH_ENABLED=true`(默认值)时,除 `/health` 外,所有 API 请求都需要 `X-API-Key` 请求头。
```
# 使用种子管理员密钥启动服务器
SYFTER_AUTH_ENABLED=true \
SYFTER_ADMIN_API_KEY=$(python3 -c "import secrets; print(secrets.token_hex(32))") \
SYFTER_DB_TYPE=postgresql \
SYFTER_PG_HOST=localhost \
SYFTER_PG_PASSWORD=changeme \
python -m uvicorn server.main:app --host 0.0.0.0 --port 8000
# 创建团队密钥
curl -X POST http://localhost:8000/api/v1/admin/keys/ \
-H "X-API-Key: $SYFTER_ADMIN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"team_name": "security"}'
export SYFTER_API_KEY=
export SYFTER_SERVER=http://localhost:8000
syfter products
```
如需在本地开发时禁用 API 密钥认证,可设置 `SYFTER_AUTH_ENABLED=false`。
#### 服务器模式命令
设置 `SYFTER_SERVER` 后,所有命令将自动使用服务器:
```
# 现在这些将连接到 API 服务器
syfter scan registry.redhat.io/ubi9:latest -p ubi -v 9.0
syfter products
syfter query -n "kernel%"
syfter export -p ubi -v 9.0 -f spdx-json -o ubi9.spdx.json
```
#### 强制使用本地模式
如果已设置 `SYFTER_SERVER` 但仍想使用本地 SQLite:
```
syfter --local products
```
#### 服务器架构
```
┌─────────────────────────────────────────────────────────────────┐
│ syfter CLI (client) │
│ SYFTER_SERVER=http://localhost:8000 │
└───────────────────────────────┬─────────────────────────────────┘
│ HTTP API
▼
┌─────────────────────────────────────────────────────────────────┐
│ Syfter API Server │
│ (FastAPI, syfter-api) │
└───────────────────────────────┬─────────────────────────────────┘
│ │
▼ ▼
┌─────────────────────┐ ┌─────────────────────┐
│ PostgreSQL │ │ MinIO (S3) │
│ (syfter-postgres) │ │ (syfter-minio) │
│ │ │ │
│ • Products │ │ • Original SBOMs │
│ • Packages │ │ • Modified SBOMs │
│ • Files │ │ (gzip compressed) │
│ • Systems │ │ │
└─────────────────────┘ └─────────────────────┘
```
#### 服务器管理
```
cd podman
# 停止所有服务
podman-compose down
# 停止并移除卷(删除所有数据)
podman-compose down -v
# 代码更改后重新构建
podman-compose build --no-cache api
podman-compose up -d api
# 查看 API 日志
podman-compose logs -f syfter-api
# 直接访问 PostgreSQL
podman-compose exec syfter-postgres psql -U syfter -d syfter
```
#### ARM 架构 Mac 用户
在 Apple Silicon Mac 上,可能需要指定平台:
```
# 选项 1:在 .env 中设置
echo "DOCKER_DEFAULT_PLATFORM=linux/arm64" >> .env
# 选项 2:设置环境变量
export DOCKER_DEFAULT_PLATFORM=linux/arm64
podman-compose up -d
```
## 快速开始
### 1. 扫描包含 RPM 包的目录
```
# 扫描 RHEL 10.0 软件包
syfter scan /path/to/rhel10/rpms -p rhel -v 10.0
# 带描述扫描
syfter scan /path/to/rpms -p rhel -v 10.0 --description "Red Hat Enterprise Linux 10.0"
```
### 2. 扫描容器镜像
```
syfter scan registry.redhat.io/rhel9:latest -p rhel -v 9.0
syfter scan docker:ubi9/ubi:latest -p ubi -v 9.0
```
#### 仓库认证
许多容器仓库(如 `registry.redhat.io`)需要认证。Syfter 使用您的本地容器凭据,因此扫描前请先登录:
```
# Red Hat Registry(需要 Red Hat 账户)
podman login registry.redhat.io
# Quay.io(用于私有仓库)
podman login quay.io
# 通用注册表
podman login myregistry.example.com
```
凭据存储在 `~/.config/containers/auth.json`(或 `$XDG_RUNTIME_DIR/containers/auth.json`)中,并由 `podman` 和 `skopeo` 自动使用。
**访问红帽仓库:**
1. 在 [access.redhat.com](https://access.redhat.com) 创建免费账户
2. 或使用来自 [红帽仓库服务账户](https://access.redhat.com/terms-based-registry/) 页面的服务账户令牌
```
# 使用服务账户(非交互式)
podman login registry.redhat.io \
--username "12345678|myserviceaccount" \
--password-stdin < token.txt
```
**验证认证:**
```
# 检查是否可以访问注册表
skopeo inspect --override-arch amd64 --override-os linux \
docker://registry.redhat.io/ubi9/ubi:latest | jq '.Name'
```
#### Linux 签名外观库配置
在 RHEL/Fedora 系统上,skopeo 被配置为通过 `/etc/containers/registries.d/registry.redhat.io.yaml` 从红帽的签名存储库获取镜像签名:
```
docker:
registry.redhat.io:
lookaside: https://registry.redhat.io/containers/sigstore
```
这会导致 skopeo 在拉取镜像时获取签名。当复制到 OCI 目录格式(syfter 内部使用)时,由于 OCI 目录无法存储签名,skopeo 会失败:
```
FATA[0002] Can not copy signatures to oci:/tmp/...: Pushing signatures for OCI images is not supported
```
Syfter 通过在复制镜像时使用 `--remove-signatures` 自动处理此问题。这只影响写入临时 OCI 目录的内容——不会禁用签名验证。如果您的 `policy.json` 需要签名验证,拉取时仍会进行验证;签名只是不会复制到本地目标。
**注意:** macOS 系统通常没有此仓库配置(通过 brew 安装的 skopeo 不包含它),因此此问题仅出现在 Linux 上。
#### 容器层追踪
扫描容器镜像时,Syfter 会**自动**确定每个软件包来自哪个基础镜像。这有助于在多阶段容器构建中识别漏洞修复位置。
```
# 扫描容器镜像 - 基础镜像扫描自动进行
syfter scan registry.redhat.io/rhel9/go-toolset:latest -p go-toolset -v 9.0
# 查询软件包 - 显示每个软件包的源镜像
syfter query -n "go%" -p go-toolset -v 9.0
```
输出显示每个软件包来自哪个镜像:
```
Name Version Product Source Image
────────────────────────────────────────────────────────────────────────────
bash 5.1.8-9.el9 go-toolset-9.0 ubi9/ubi
git 2.47.3-1.el9_6 go-toolset-9.0 ubi9/s2i-base
golang 1.25.3-1.el9_7 go-toolset-9.0 rhel9/go-toolset
```
**工作原理:**
1. 使用**层摘要比较**准确识别基础镜像链(例如 `ubi9/ubi` → `ubi9/s2i-core` → `ubi9/s2i-base` → `rhel9/go-toolset`)
2. 从标签中提取精确的镜像引用(例如 `registry.redhat.io/ubi9/ubi:9.7-1767674301`)
3. 扫描每个基础镜像以构建软件包列表
4. 比较软件包列表以确定哪个镜像引入了每个软件包
5. 在数据库中为每个软件包记录 `source_image`
`syfter layers` 命令显示完整的层链,包含:
- `layer_id`:容器层摘要(截断)
- `layer_index`:在层栈中的位置(0 = 基础层)
- `source_image`:引入此层的镜像
- `image_reference`:完整的镜像引用(仓库/名称:版本-发布号)
### 3. 查询软件包
```
# 查找所有产品中的内核软件包
syfter query -n "kernel%"
# 在特定产品中查找软件包
syfter query -n "openssl%" -p rhel -v 10.0
# 查找文件
syfter query -f "%/bin/bash"
```
### 4. 导出 SBOM
```
# 导出为 SPDX JSON
syfter export -p rhel -v 10.0 -f spdx-json -o rhel-10.spdx.json
# 导出为 CycloneDX
syfter export -p rhel -v 10.0 -f cyclonedx-json -o rhel-10.cdx.json
# 导出为所有格式
syfter export -p rhel -v 10.0 -f all -o ./sboms/
```
## 系统模式(基础设施扫描)
除了扫描产品,Syfter 还可以扫描基础设施中的主机,以跟踪各系统安装的软件包。
### 扫描本地主机
```
# 扫描本地主机并上传到服务器
syfter system-scan
# 添加标签进行分组
syfter system-scan --tag production
# 使用描述性标签扫描
syfter system-scan --tag "web-servers"
```
### 通过 SSH 扫描远程主机
```
# 扫描远程主机
syfter system-scan webserver01.example.com
# 使用 SSH 选项
syfter system-scan 192.168.1.100 -u admin -i ~/.ssh/server_key
# 带标签扫描
syfter system-scan dbserver.local --tag databases
```
**注意:** 远程扫描需要在远程主机上安装 `syft`。
### 列出系统
```
# 列出所有已扫描系统
syfter systems
# 按标签筛选
syfter systems --tag production
```
### 跨系统查询软件包
```
# 查找安装了 openssh 的系统
syfter system-query -n "openssh%"
# 在特定系统中搜索
syfter system-query -n "kernel%" --tag production
# 跨系统查找文件
syfter system-query -f "%/bin/bash"
```
### 列出系统的软件包/文件
```
# 列出系统上的所有软件包
syfter system-list -H webserver01 -t packages
# 列出所有文件
syfter system-list -H webserver01 -t files
```
## CLI 参考
### `syfter scan`
扫描目标并存储带有产品元数据的 SBOM。
```
Usage: syfter scan [OPTIONS] TARGET
Options:
-p, --product TEXT Product name (required)
-v, --version TEXT Product version (required)
--vendor TEXT Vendor name (default: "Red Hat")
--cpe-vendor TEXT CPE vendor string (default: "redhat")
--purl-namespace TEXT PURL namespace (default: "redhat")
--description TEXT Product description
-o, --output PATH Write modified SBOM to file
--original-output PATH Write original SBOM to file
--no-store Don't store in database
```
### `syfter search`(别名:`query`)
跨所有产品搜索软件包和文件。
```
Usage: syfter search [OPTIONS]
Options:
-n, --name TEXT Package name pattern (% = wildcard)
-f, --file TEXT File path pattern
-d, --digest TEXT File digest (exact match)
-p, --product TEXT Filter by product name
-v, --version TEXT Filter by product version
--limit INTEGER Maximum results (default: 50)
--json Output as JSON
--cross-product Trace package across the full product stack (server mode)
```
`query` 命令名已弃用但仍被接受。
### `syfter trace`
跨产品技术栈(RHEL 仓库、UBI 基础镜像、分层容器)追踪软件包。需要服务器模式。
```
Usage: syfter trace [OPTIONS] PACKAGE_NAME
Options:
--pkg-version TEXT Package version filter
--limit INTEGER Maximum results per category (default: 200)
--json Output as JSON
```
### `syfter deps`
查询 RPM 依赖关系(需要已索引依赖关系的服务器模式)。
```
Usage: syfter deps [OPTIONS] [DEPENDENCY_NAME]
Options:
--package TEXT Filter by package name
--type [requires|provides] Dependency type (default: requires)
-p, --product TEXT Filter by product name
-v, --version TEXT Filter by product version
--limit INTEGER Maximum results (default: 50)
--json Output as JSON
```
### `syfter relationships`
列出产品间的组件关系(服务器模式)。
```
Usage: syfter relationships [OPTIONS]
Options:
--limit INTEGER Maximum results (default: 50)
--json Output as JSON
```
### `syfter export`
将产品的 SBOM 导出为各种格式。
```
Usage: syfter export [OPTIONS]
Options:
-p, --product TEXT Product name (required)
-v, --version TEXT Product version (required)
-f, --format TEXT Output format: syft-json, spdx-json, spdx-tv,
cyclonedx-json, cyclonedx-xml, all
-o, --output PATH Output file or directory
```
### `syfter products`
列出数据库中的所有产品。
### `syfter scans`
列出所有扫描,可按产品筛选。
### `syfter stats`
显示数据库统计信息。
### `syfter check`
验证 syft 是否已安装并显示其版本。
### `syfter list`
列出产品版本的文件或软件包。
```
Usage: syfter list [OPTIONS]
Options:
-p, --product TEXT Product name (required)
-v, --version TEXT Product version (required)
-t, --type [files|packages] What to list (default: files)
--full Include architecture in package output
--layers Include source layer (container scans only)
```
使用 `--layers` 时,软件包输出格式为 `源镜像::软件包版本`:
```
syfter list -p go-toolset -v 1.25 -t packages --layers | grep zlib
ubi9/ubi::zlib-1.2.11-40.el9
ubi9/s2i-base::zlib-devel-1.2.11-40.el9
# 从特定基础镜像查找所有软件包
syfter list -p go-toolset -v 1.25 -t packages --layers | grep "^ubi9/ubi::"
# 统计每层软件包数量
syfter list -p go-toolset -v 1.25 -t packages --layers | cut -d: -f1 | sort | uniq -c
```
### `syfter layers`
显示产品的容器层链(仅容器扫描)。
```
Usage: syfter layers [OPTIONS]
Options:
-p, --product TEXT Product name (required)
-v, --version TEXT Product version (required)
--json Output as JSON
```
显示容器镜像的逐层分解,包括:
- 层索引和截断的摘要
- 源镜像名称(例如 `ubi9/ubi`, `rhel9/go-toolset`)
- 每层的版本和完整镜像引用
### `syfter system-scan`
扫描主机并存储用于基础设施跟踪的 SBOM。
```
Usage: syfter system-scan [OPTIONS] [TARGET]
Arguments:
TARGET Hostname or IP (default: localhost)
Options:
-t, --tag TEXT Tag for grouping/CMDB linking
-u, --user TEXT SSH user for remote hosts
-p, --port INTEGER SSH port (default: 22)
-i, --identity PATH SSH identity file
-o, --output PATH Write SBOM to file
--no-store Don't store (just output)
-q, --quiet Suppress progress output
--skip-files Skip file indexing
--include-debug Include debuginfo packages
```
### `syfter systems`
列出数据库中的所有系统。
```
Usage: syfter systems [OPTIONS]
Options:
--tag TEXT Filter by system tag
```
### `syfter system-query`
跨系统查询软件包和文件。
```
Usage: syfter system-query [OPTIONS]
Options:
-n, --name TEXT Package name pattern (% = wildcard)
-f, --file TEXT File path pattern
-d, --digest TEXT File digest (exact match)
-H, --hostname TEXT Filter by hostname
-t, --tag TEXT Filter by system tag
--limit INTEGER Maximum results (default: 50)
--json Output as JSON
```
### `syfter system-list`
列出特定系统的文件或软件包。
```
Usage: syfter system-list [OPTIONS]
Options:
-H, --hostname TEXT System hostname (required)
-t, --type [files|packages] What to list (default: files)
--full Include architecture in package output
```
## Shell 脚本包装器
为方便起见,`scripts/` 目录中提供了 shell 脚本:
```
# 简单扫描包装器
./scripts/scan-product.sh /path/to/rpms rhel 10.0
# 查询包装器
./scripts/query.sh package "kernel%"
./scripts/query.sh file "%/bin/bash"
# 导出包装器
./scripts/export-sbom.sh rhel 10.0 spdx-json rhel-10.spdx.json
# 从配置文件批量扫描
./scripts/batch-scan.sh products.conf
```
### 批量扫描配置
为批量扫描创建配置文件:
```
# products.conf
/path/to/rhel10 rhel 10.0 "RHEL 10.0"
/path/to/rhel9 rhel 9.4 "RHEL 9.4"
/path/to/ocp openshift 4.14 "OpenShift Container Platform 4.14"
registry.redhat.io/ubi9:latest ubi 9.0 "Universal Base Image 9"
```
然后运行:
```
./scripts/batch-scan.sh products.conf
```
## 工作原理
### SBOM 丰富
当您扫描目标时,Syfter 会:
1. 运行 Syft 生成 `syft-json` 格式的 SBOM
2. 修改每个软件包的元数据以包含:
- **CPE**:更新供应商信息(例如 `cpe:2.3:a:redhat:kernel:...`)
- **PURL**:添加发行版限定符(例如 `pkg:rpm/redhat/kernel@5.14?distro=rhel-10.0`)
- **元数据**:用于追溯的产品信息
### 存储
Syfter 将数据存储在两个位置:
**本地模式**(SQLite):
- 数据库:`~/.syfter/syfter.db`
- SBOM 作为压缩 BLOB 存储在数据库中
**服务器模式**(PostgreSQL + MinIO):
- 数据库:PostgreSQL 用于存储索引后的元数据(软件包、文件、产品)
- 对象存储:MinIO/S3 用于存储压缩的 SBOM 文件
两种模式都存储:
- **完整 SBOM 保留**:原始和修改后的 syft-json 均原样存储
- **索引的软件包**:用于快速查询的软件包元数据
- **索引的文件**:用于查找的文件路径和摘要
- **容器层**:用于容器扫描的层到镜像的映射
这种双重方法允许:
- 跨所有产品的快速查询(数据库)
- 用于导出的原始 SBOM 检索(对象存储)
### 导出格式
Syfter 使用 Syft 的原生转换功能生成:
| 格式 | 扩展名 | 描述 |
|--------|-----------|-------------|
| `syft-json` | `.syft.json` | Syft 原生格式(内部存储) |
| `spdx-json` | `.spdx.json` | SPDX 2.3 JSON |
| `spdx-tv` | `.spdx` | SPDX 标签-值 |
| `cyclonedx-json` | `.cdx.json` | CycloneDX 1.4 JSON |
| `cyclonedx-xml` | `.cdx.xml` | CycloneDX 1.4 XML |
## 环境变量
### 客户端变量
| 变量 | 描述 | 默认值 |
|----------|-------------|---------|
| `SYFTER_DB` | SQLite 数据库路径(本地模式) | `~/.syfter/syfter.db` |
| `SYFTER_SERVER` | API 服务器 URL(服务器模式) | 无(使用本地模式) |
### 服务器变量(用于 API 容器)
| 变量 | 描述 | 默认值 |
|----------|-------------|---------|
| `SYFTER_DB_TYPE` | 数据库类型(`sqlite` 或 `postgresql`) | `sqlite` |
| `SYFTER_PG_HOST` | PostgreSQL 主机 | `localhost` |
| `SYFTER_PG_PORT` | PostgreSQL 端口 | `5432` |
| `SYFTER_PG_DATABASE` | PostgreSQL 数据库名 | `syfter` |
| `SYFTER_PG_USER` | PostgreSQL 用户名 | `syfter` |
| `SYFTER_PG_PASSWORD` | PostgreSQL 密码 | (必需) |
| `SYFTER_STORAGE_TYPE` | 存储类型(`local` 或 `s3`) | `local` |
| `SYFTER_S3_ENDPOINT` | S3/MinIO 端点 URL | (s3 模式必需) |
| `SYFTER_S3_BUCKET` | S3 存储桶名称 | `syfter-sboms` |
| `SYFTER_S3_ACCESS_KEY` | S3 访问密钥 | (s3 模式必需) |
| `SYFTER_S3_SECRET_KEY` | S3 秘密密钥 | (s3 模式必需) |
| `SYFTER_API_KEY` | 客户端 API 密钥(服务器模式) | 无 |
| `SYFTER_AUTH_ENABLED` | 启用 API 密钥认证 | `true` |
| `SYFTER_ADMIN_API_KEY` | 用于初始管理员访问的种子密钥 | 无 |
| `SYFTER_AUTH_CACHE_TTL` | 认证验证缓存 TTL(秒) | `60` |
| `SYFTER_RATE_LIMIT_ENABLED` | 启用每密钥速率限制 | `true` |
| `SYFTER_RATE_LIMIT_QUERY` | 每密钥每分钟查询请求数 | `60` |
| `SYFTER_RATE_LIMIT_QUERY_BURST` | 查询突发允许量 | `20` |
| `SYFTER_RATE_LIMIT_UPLOAD` | 每密钥每分钟上传请求数 | `10` |
| `SYFTER_RATE_LIMIT_UPLOAD_BURST` | 上传突发允许量 | `5` |
| `SYFTER_CACHE_STATS_TTL` | 统计信息缓存 TTL(秒) | `300` |
| `SYFTER_CACHE_PRODUCTS_TTL` | 产品缓存 TTL(秒) | `300` |
## 数据库索引(大规模部署)
对于拥有超过 100 万个软件包的部署,以下 PostgreSQL 索引对于查询性能至关重要:
```
-- LIKE prefix queries + ORDER BY (the COLLATE "C" is essential)
CREATE INDEX idx_package_name_c ON packages (name COLLATE "C");
-- LIKE via text_pattern_ops (used by the index scan filter)
CREATE INDEX idx_package_name_pattern ON packages (name text_pattern_ops);
-- Foreign key lookups for product-scoped counts
CREATE INDEX idx_packages_product_id ON packages (product_id);
CREATE INDEX idx_scan_product ON scans (product_id);
-- Dependency queries (package-scoped + type filter)
CREATE INDEX idx_dep_package_type ON dependencies (package_id, dependency_type);
```
## 示例
### 工作流:生成客户 SBOM
```
# 1. 扫描所有产品
syfter scan /mnt/rhel10-rpms -p rhel -v 10.0
syfter scan /mnt/rhel9-rpms -p rhel -v 9.4
syfter scan registry.redhat.io/ubi9:latest -p ubi -v 9.0
# 2. 检查存储内容
syfter products
syfter stats
# 3. 跨所有产品查询
syfter query -n "openssl%"
# 4. 导出面向客户的 SBOMs
mkdir -p customer-sboms
syfter export -p rhel -v 10.0 -f all -o customer-sboms/
syfter export -p rhel -v 9.4 -f spdx-json -o customer-sboms/rhel-9.4.spdx.json
```
### 工作流:查找软件包位置
```
# 查找包含特定软件包的产品
syfter query -n "curl" --json | jq '.[] | {product: "\(.product_name)-\(.product_version)", version: .version}'
# 按路径模式查找文件
syfter query -f "%libssl%"
# 按摘要查找文件
syfter query -d "sha256:abc123..."
```
## 架构
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ syfter CLI │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │
│ │ Scanner │───>│ Manipulator │───>│ Storage │ │
│ │ (syft, ssh+syft) │ │ (CPE/PURL) │ │ (SQLite/PostgreSQL+S3) │ │
│ └───────────────────┘ └─────────────┘ └───────────┬─────────────┘ │
│ │ │ │
│ │ v │
│ ┌───────┴───────┐ ┌──────────┐ │
│ │ Scan Targets │ │ Exporter │ │
│ ├───────────────┤ │ (SPDX/ │ │
│ │ • Products │ │ CDX) │ │
│ │ - RPM dirs │ └──────────┘ │
│ │ - Containers│ │
│ │ - Archives │ │
│ │ • Systems │ │
│ │ - Localhost │ │
│ │ - SSH hosts │ │
│ └───────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
```
## 构建与分发
关于以下内容的说明,请参见 [docs/BUILDING.md](docs/BUILDING.md):
- 构建用于分发的 Python wheel 包
- 创建容器镜像
- 构建 RPM 包
- 离线安装包
## 部署
关于生产部署指南,请参见 [docs/DEPLOYMENT.md](docs/DEPLOYMENT.md),包括:
- 服务器架构
- PostgreSQL 设置
- MinIO/S3 配置
- systemd 服务文件
- 安全考虑
对于 OpenShift/Kubernetes 部署,API 容器镜像基于 `podman/Containerfile` 构建。典型的生产技术栈包括 Syfter API(通常带有用于浏览器 OIDC 的 oauth2-proxy sidecar)、PostgreSQL 和兼容 S3 的对象存储(MinIO 或通过 IRSA 使用 AWS S3)。
## 理解容器层
关于以下内容的详细信息,请参见 [docs/MULTI-STAGE-BUILDS.md](docs/MULTI-STAGE-BUILDS.md):
- Syfter 如何处理多阶段 Docker/Podman 构建
- 为什么构建阶段的层不会出现在最终镜像中
- 理解编译二进制文件中的 Go 模块检测
- 非包管理文件的文件搜索限制
## 开发
```
# 安装开发依赖项
pip install -e ".[all]"
# 运行测试
./scripts/run-tests.sh local # Local SQLite tests
./scripts/run-tests.sh coverage # With coverage report
./scripts/run-tests.sh server # Server tests (requires running server)
# 格式化代码
black syfter/
ruff check syfter/
```
## 致谢
[syfter](https://github.com/vdanen/syfter) 由 Vincent Danen 开发,红帽产品安全团队贡献。
## 许可证
Apache License 2.0
## AI 编码声明
完全透明地说,此代码几乎完全由 AI 编写。虽然
我能用 Python 编程,但我确实没有时间去做,因此
利用了 AI 来完成它。如果有问题(很可能有!),欢迎
提交 PR 修复。此项目背后的意图是
快速创建一个能解决围绕 SBOM 生产和使用
某些挑战的工具。它非常复杂,这就是为什么它
利用了 [Syft](https://github.com/anchore/syft)(何必重新发明轮子呢?)。
如果使用 AI 生成的代码让您感到不安或冒犯,可能还有其他工具可用。如果不是,这个工具可能正在解决
您面临的、对我来说也同样需要解决的挑战。
标签:API安全, Cosign, CycloneDX, DevSecOps, GPT, JSON输出, PostgreSQL, RPM扫描, SBOM生成工具, SLSA, SPDX, SQLite, Syft集成, 上游代理, 企业级部署, 供应链风险管理, 依赖关系跟踪, 元数据丰富, 安全合规, 安全最佳实践, 容器扫描, 导出格式, 开源安全工具, 数据库存储, 查询优化, 测试用例, 漏洞管理, 缓存机制, 网络代理, 请求拦截, 跌倒检测, 跨产品追溯, 跨产品追踪, 软件供应链安全, 软件物料清单, 远程方法调用, 逆向工具, 逆向工程平台