popey/sbom-vm
GitHub: popey/sbom-vm
该工具通过在宿主机上只读挂载虚拟机磁盘镜像的方式,在不启动虚拟机的前提下调用 Syft 生成 SBOM,有效避免了虚拟机内部扫描时的内存溢出问题。
Stars: 19 | Forks: 4
# sbom-vm
从虚拟机磁盘镜像生成软件物料清单 (SBOM),无需启动虚拟机。
在当前状态下,此脚本利用常见的 Linux 实用工具(gdisk、qemu-nbd 等)以只读方式将分区呈现给宿主机,以便在宿主机上运行的 [Syft](https://github.com/anchore/syft) 能够读取文件并生成 SBOM。
## 功能
* 通过 qemu-nbd 只读挂载虚拟机磁盘镜像
* 支持多种虚拟机磁盘格式 (qcow2, vmdk)
* 自动检测并挂载常见的文件系统:
* Windows (NTFS)
* Linux (ext4, ZFS, BTRFS)
* macOS (HFS+, APFS)
* BSD (ZFS)
* 使用 Syft 进行安全、非破坏性的 SBOM 生成
## 背景
[Syft](https://github.com/anchore/syft) 是一款通用的 SBOM 生成器,专为从容器、目录和代码库创建 SBOM 而优化。
有些用户会扫描整个文件系统。当存在大量文件时,这可能会非常消耗计算资源,并且可能会生成非常大的 SBOM 文档。在一些反馈的情况中,在虚拟机内部运行 Syft 会导致其耗尽所有可用内存,并被内核的 OOM (Out Of Memory, 内存溢出) 杀手终止,从而导致 SBOM 创建失败。
Will Murphy 在 [Anchore Community Discourse](https://anchore.com/discourse) 上汇总了社区里的一些讨论,主题为“[改进整机扫描](https://anchorecommunity.discourse.group/t/improvements-to-scanning-whole-machine/301?u=popey)”。
## 项目目标
本项目的目标是对从运行中的虚拟机外部、直接通过磁盘镜像构建 SBOM 进行原型验证。从中获得的经验教训可用于改进或扩展 Syft,或者为 Syft 用于检查容器的库 [stereoscope](https://github.com/anchore/stereoscope) 添加新功能。
一个额外的好处是,在向 Syft 和/或 Stereoscope 贡献的代码完全集成此功能之前,可以满足目前需要扫描虚拟机磁盘镜像的 Syft 用户的需求。
## 项目范围
以下是我对用于从虚拟机磁盘镜像生成 SBOM 的 MVP (Minimum Viable Product, 最小可行性产品) 的设想。
### MVP
* 检查常见的磁盘镜像格式 (raw, ami, qcow2, vmdk)
* 挂载常见的分区类型 (ntfs, hfsplus, apfs, ext4, vfat, zfs)
* 使用适当的选项启动 Syft 以生成 SBOM
### 不在范围内
* 加密的磁盘镜像或分区
## 使用 sbom-vm
注意:到目前为止,这仅在我的 Ubuntu 24.04 工作站上进行了测试。
## 前置条件
需要以下软件包:
* [Syft](https://github.com/anchore/syft) - 用于生成 SBOM
* qemu-utils - 用于挂载磁盘镜像
* gzip - 用于解压 zip 格式的 ami
* gdisk - 用于处理 GPT 分区
* fdisk - 用于分区分析
* parted - 用于获取详细的分区信息
* util-linux - 用于 mount/umount 命令
* ntfs-3g - 用于支持 Windows NTFS 文件系统
* hfsprogs - 用于支持 MacOS HFS+ 文件系统
* apfs-dkms & apfsprogs - 用于支持 MacOS APFS 文件系统
* zfsutils-linux - 用于支持 ZFS 文件系统
在 Ubuntu 24.04 上,可以通过以下命令安装它们:
```
$ snap install syft
$ sudo apt install qemu-utils gdisk fdisk parted util-linux ntfs-3g hfsprogs apfs-dkms apfsprogs zfsutils-linux
```
## 安装
* 克隆此代码库,或者直接获取其中的单个 python 脚本
## 运行
* 运行该 python 脚本,并将磁盘镜像作为唯一参数传入
## 示例输出
### 使用 ext4 的 Ubuntu 24.04 qcow2 镜像
```
$ sudo sbom-vm.py test_images/ubuntu_22.04.qcow2
2025-02-01 18:45:59,394 - INFO - Loading NBD kernel module
2025-02-01 18:46:00,405 - INFO - Detecting format of /home/popey/sbom-vm/test_images/ubuntu_22.04.qcow2
2025-02-01 18:46:00,409 - INFO - qemu-img detected format: qcow2
2025-02-01 18:46:00,409 - INFO - Connecting image /home/popey/sbom-vm/test_images/ubuntu_22.04.qcow2 to NBD device
2025-02-01 18:46:01,426 - INFO - Analyzing partitions
2025-02-01 18:46:01,438 - INFO - Found EFI system partition /dev/nbd0p1
2025-02-01 18:46:01,438 - INFO - Found usable partition /dev/nbd0p2 of type ext4
2025-02-01 18:46:01,438 - INFO - Found filesystem partition(s): /dev/nbd0p1 (fat32), /dev/nbd0p2 (ext4)
2025-02-01 18:46:01,438 - INFO - Selected partition /dev/nbd0p2 (priority: 3, size: 547MB)
2025-02-01 18:46:01,442 - INFO - Mounting ext4 filesystem
2025-02-01 18:46:01,450 - INFO - Generating SBOM for mounted filesystem at /mnt/image_analysis
2025-02-01 18:46:01,451 - INFO - Filesystem type: ext4
2025-02-01 18:46:03,679 - INFO - SBOM generated: 20250201_184601_sbom_ubuntu_22.04_nbd0p2_ext4.json
2025-02-01 18:46:03,679 - INFO - Starting cleanup
2025-02-01 18:46:03,684 - INFO - Unmounting /mnt/image_analysis
2025-02-01 18:46:03,714 - INFO - Disconnecting NBD device
2025-02-01 18:46:03,717 - INFO - Removing NBD kernel module
2025-02-01 18:46:03,719 - INFO - Removing temporary directory: /tmp/sbomvm_ch80d0zx
```
### 使用 ZFS 的 Ubuntu 24.04 qcow2 镜像
```
$ sudo sbom-vm.py test_images/ubuntu_22.04_zfs.qcow2
2025-02-02 15:27:12,157 - INFO - Loading NBD kernel module
2025-02-02 15:27:13,159 - INFO - Detecting format of /home/alan/Temp/sbom-vm/test_images/ubuntu_22.04_zfs.qcow2
2025-02-02 15:27:13,163 - INFO - qemu-img detected format: qcow2
2025-02-02 15:27:13,163 - INFO - Connecting image /home/alan/Temp/sbom-vm/test_images/ubuntu_22.04_zfs.qcow2 to NBD device
2025-02-02 15:27:14,184 - INFO - Analyzing partitions
2025-02-02 15:27:14,195 - INFO - Found usable partition /dev/nbd0p1 of type zfs_member (via blkid)
2025-02-02 15:27:14,195 - INFO - Found filesystem partition(s): /dev/nbd0p1 (zfs_member)
2025-02-02 15:27:14,195 - INFO - Selected partition /dev/nbd0p1 (priority: 1, size: 1072MB)
2025-02-02 15:27:14,196 - INFO - Mounting zfs_member filesystem
2025-02-02 15:27:14,196 - INFO - Attempting to import ZFS pool from /dev/nbd0p1
2025-02-02 15:27:14,205 - INFO - Found ZFS pool: sbomtmp
2025-02-02 15:27:14,226 - INFO - Generating SBOM for mounted filesystem at /mnt/image_analysis
2025-02-02 15:27:14,226 - INFO - Filesystem type: zfs_member
2025-02-02 15:27:17,462 - INFO - SBOM generated: 20250202_152714_sbom_ubuntu_22.04_zfs_nbd0p1_zfs_member.json
2025-02-02 15:27:17,462 - INFO - Starting cleanup
2025-02-02 15:27:17,465 - INFO - Exporting ZFS pool sbomtmp
2025-02-02 15:27:17,479 - INFO - Disconnecting NBD device
2025-02-02 15:27:17,483 - INFO - Removing NBD kernel module
2025-02-02 15:27:17,485 - INFO - Removing temporary directory: /tmp/sbomvm_41rnscs4
```
## 测试镜像
如果你手头没有任何磁盘镜像,可以使用 `generate-test-images.py` 脚本,它会基于 docker 的容器内容创建一些测试用的虚拟机磁盘镜像。该脚本支持创建包含各种文件系统(包括 ext4 和 ZFS)的测试镜像。
```
$ sudo ./generate-test-images.py
2025-02-02 15:23:13,365 - INFO - Creating output directory at /home/alan/Temp/sbom-vm/test_images
2025-02-02 15:23:13,365 - INFO - Generating zfs test image from ubuntu:22.04
2025-02-02 15:23:13,366 - INFO - Creating 1024MB raw disk image at /home/alan/Temp/sbom-vm/test_images/disk_2jucd3yv.raw
2025-02-02 15:23:13,375 - INFO - Creating partition table for zfs on /home/alan/Temp/sbom-vm/test_images/disk_2jucd3yv.raw
2025-02-02 15:23:14,950 - INFO - Setting up loop device for /home/alan/Temp/sbom-vm/test_images/disk_2jucd3yv.raw
2025-02-02 15:23:16,983 - INFO - Creating zfs filesystem
2025-02-02 15:23:17,042 - INFO - Mounting root partition to /tmp/tmpsfp6mhg0/mnt
2025-02-02 15:23:17,043 - INFO - Populating root filesystem from container ubuntu:22.04
2025-02-02 15:23:17,355 - INFO - Pulling container ubuntu:22.04
2025-02-02 15:23:18,286 - INFO - Creating temporary container
2025-02-02 15:23:18,364 - INFO - Exporting container filesystem
2025-02-02 15:23:19,000 - INFO - Extracting rootfs
2025-02-02 15:23:19,344 - INFO - Cleaning up temporary container
2025-02-02 15:23:19,370 - INFO - Cleaning up ZFS pool sbomtmp
2025-02-02 15:23:19,479 - INFO - Detaching loop device /dev/loop154
2025-02-02 15:23:20,485 - INFO - Converting /home/alan/Temp/sbom-vm/test_images/disk_2jucd3yv.raw to qcow2 format
2025-02-02 15:23:20,564 - INFO - Successfully generated zfs test image: /home/alan/Temp/sbom-vm/test_images/ubuntu_22.04_zfs.qcow2
```
通过一个简单的循环来为每个生成的镜像生成 SBOM 是最简单的方法:
```
for f in $(ls -1 $PWD/test_images/*.qcow2); do echo $f ; sudo $PWD/sbom-vm.py $f; done
```
## 贡献
欢迎贡献代码!请随时提交 Pull Request。对于重大更改,请先开启一个 issue 讨论您希望更改的内容。
标签:SBOM, Syft, 生成式AI安全, 硬件无关, 虚拟机, 请求拦截, 跨平台文件系统, 逆向工具, 镜像解析