SBOMを作ってみよう

::: note info
この記事は[NTTテクノクロス Advent Calendar 2023](https://qiita.com/advent-calendar/2023/ntt-tx)、シリーズ2の18日目の記事です。
:::

こんにちは！NTTテクノクロスの千歳です。
普段は、セキュリティに関する技術研究やリサーチ、開発業務に携わっています。


## はじめに
本記事では、SBOM（Software Bill Of Materials）に関して、概要および実際に作ってみる方法に触れていきたいと思います。


## SBOMとは？
SBOMは、例えとして、しばしば【ソフトウェアの食品成分表】と言われています。ソフトウェアや機器に含まれているソフトウェアコンポーネントにはどういったものが含まれているのか、バージョンやライセンスはどうなっているのか、などがまとめられたドキュメント（インベントリ）です。
SBOMの最小構成要素として、NTIA（National Telecommunications and Information Administration）が以下のように発表しています。
- サプライヤー名(Supplier Name)
- コンポーネント名(Component Name)
- コンポーネントのバージョン(Version of the Component)
- その他の一意な識別子(Other Unique Identifiers)
- 依存関係(Dependency Relationship)
- SBOMの作成者(Author of SBOM Data)
- タイムスタンプ(Timestamp)

昨今、ソフトウェアサプライチェーン攻撃も増加しており、Apache Log4jやSolarWinds社の製品が攻撃を受けて大きな話題にもなりましたが、ソフトウェアが利用するライブラリまで明示的に管理しているケースは少なく、影響を確認するのも一苦労でした。こういった課題に対して、近年話題になっているのがSBOMです。

## SBOM動向
2021年に米国で発令された[国家サイバーセキュリティに関する大統領令第14028号](https://www.whitehouse.gov/briefing-room/presidential-actions/2021/05/12/executive-order-on-improving-the-nations-cybersecurity/)をはじめとして、EUの[サイバーレジリエンス法](https://digital-strategy.ec.europa.eu/en/library/cyber-resilience-act?_ga=2.197160875.544060384.1702342337-1172754294.1702342336&_fsi=tGtouyat)などでSBOMの提供・活用が推奨もしくは義務化する流れが進んでいます。特に医療機器業界では、米国食品医薬品局（FDA）がSBOMを医療機器の市販前申請に含めるよう強く推奨しています。
日本でも、各所でSBOMに関する研究・検討が進められています。例えば、経産省では、[ソフトウェア管理に向けたSBOM（Software Bill of Materials）の導入に関する手引](https://www.meti.go.jp/press/2023/07/20230728004/20230728004.html)が公開されており、実証実験が進められていますし、総務省でも[通信機器に対するサプライチェーンリスク対策](https://www.soumu.go.jp/johotsusintokei/whitepaper/ja/r05/html/nd255230.html)としてSBOMの活用を検討しています。さらに、厚生労働省からは、[薬機法の医療機器の基本要件基準第12条第3項の改正](https://www.mhlw.go.jp/content/11120000/001167157.pdf)にて令和6年よりSBOMの提供が求められることとなっており、日本国内でもSBOMを作って利用する、あるいは提供するケースが増えていくことが予想されます。



## SBOMを作ってみよう！
それでは、実際にSBOMの作り方について、いくつかご紹介していきます。
SBOMの作り方として有償ツールで作る方法と、無償ツールで作る方法があります。本記事では、自由にお試ししやすい無償ツールを使ったSBOMの作り方について触れていきたいと思います。

### SBOM生成ツール
ソフトウェアを対象にSBOMを作る場合、ソフトウェアの開発言語に合わせてツールを選定する必要があります。
例えば、JavaであればMavenやGradleでも生成可否はツールによって変わります。今回は、以下4つのツールでSBOMを作ってみます。
| No. | ツール | 提供元 |
| --- | --- | --- |
| 1 | [syft](https://github.com/anchore/syft) | Anchore |
| 2 | [Trivy](https://github.com/aquasecurity/trivy) | Aqua Security |
| 3 | [SBOM Tool](https://github.com/microsoft/sbom-tool) | Microsoft |
| 4 | [GitHub SBOM Export](https://docs.github.com/ja/code-security/supply-chain-security/understanding-your-software-supply-chain/exporting-a-software-bill-of-materials-for-your-repository) | GitHub |


### SBOM作成
では、実際にSBOMを作ってみましょう。今回は、コンポーネント解析プラットフォームであるOWASPのDependency-Track（Java）を対象に、SBOMフォーマットの1種であるSPDX形式のSBOMを作成していきます。

- GitHubリポジトリからDependency-Trackのソースコードを取得します

```shell:事前準備
# get Software
$ git clone https://github.com/DependencyTrack/dependency-track.git
```

- Syft : バイナリをインストールし、依存関係ファイル（pom.xml）からSBOMを作成します

```shell:Syftのinstall/実行
# install syft
$ curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
# exec syft
$ syft file:./dependency-track/pom.xml -o spdx-json --file dependency-track_spdx.json
```

- Trivy : Docker Imageを利用し、依存関係ファイル（pom.xml）からSBOMを作成します

```shell:Trivyのinstall/実行
# install Trivy(container)
$ docker pull aquasec/trivy:0.48.0
# exec trivy
$ docker run -v ./dependency-track:/app:rw -v /var/run/docker.sock:/var/run/docker.sock -v $HOME/Library/Caches:/root/.cache/ aquasec/trivy:0.48.0 fs --format spdx-json --output /root/.cache/dependency-track_spdx.json /app/pom.xml
```
- SBOM Tool : バイナリをインストールし、ローカルプロジェクトからSBOMを作成します

```shell:SBOM Toolのinstall/実行
# install SBOM Tool
$ curl -Lo sbom-tool https://github.com/microsoft/sbom-tool/releases/latest/download/sbom-tool-linux-x64
$ chmod +x sbom-tool
# exec Sbom-tool
$ sbom-tool generate -b ./dependency-track -bc ./dependency-track -pn dependency-track -ps ntt-tx -pv 4.11.0-SNAPSHOT
```
- GitHub SBOM Export : GitHubにログインし、GUIからエクスポートします
    - Insights -> Dependency graph を選択し、"Export SBOM"をクリックします

![export_sbom2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624677/e055ee5a-ada4-316f-f655-6d268a4bc61c.jpeg)


実際に出力されたSBOM（抜粋）は以下の通りです。
※ 一部のツールでは整形されていないため、自前でフォーマットする必要があります
```json: Syft出力結果
{
    "name": "commons-compress",
    "SPDXID": "SPDXRef-Package-java-archive-commons-compress-c05bee49fdbbcc30",
    "versionInfo": "1.25.0",
    "supplier": "NOASSERTION",
    "downloadLocation": "NOASSERTION",
    "filesAnalyzed": false,
    "sourceInfo": "acquired package info from installed java archive: /pom.xml",
    "licenseConcluded": "NOASSERTION",
    "licenseDeclared": "NOASSERTION",
    "copyrightText": "NOASSERTION",
    "externalRefs": [
        {
            "referenceCategory": "SECURITY",
            "referenceType": "cpe23Type",
            "referenceLocator": "cpe:2.3:a:apache:commons-compress:1.25.0:*:*:*:*:*:*:*"
        },
        {
            "referenceCategory": "SECURITY",
            "referenceType": "cpe23Type",
            "referenceLocator": "cpe:2.3:a:apache:commons_compress:1.25.0:*:*:*:*:*:*:*"
        },
        {
            "referenceCategory": "SECURITY",
            "referenceType": "cpe23Type",
            "referenceLocator": "cpe:2.3:a:apache:commons:1.25.0:*:*:*:*:*:*:*"
        },
        {
            "referenceCategory": "PACKAGE-MANAGER",
            "referenceType": "purl",
            "referenceLocator": "pkg:maven/org.apache.commons/commons-compress@1.25.0"
        }
    ]
}
```

```json: Trivy出力結果
{
  "name": "org.apache.commons:commons-compress",
  "SPDXID": "SPDXRef-Package-747f95bec5d691f0",
  "versionInfo": "1.25.0",
  "supplier": "NOASSERTION",
  "downloadLocation": "NONE",
  "filesAnalyzed": false,
  "licenseConcluded": "Apache-2.0",
  "licenseDeclared": "Apache-2.0",
  "externalRefs": [
    {
      "referenceCategory": "PACKAGE-MANAGER",
      "referenceType": "purl",
      "referenceLocator": "pkg:maven/org.apache.commons/commons-compress@1.25.0"
    }
  ],
  "attributionTexts": [
    "PkgID: org.apache.commons:commons-compress:1.25.0"
  ],
  "primaryPackagePurpose": "LIBRARY"
}
```

```json: SBOM Tool出力結果
{
  "name": "org.apache.commons.commons-compress",
  "SPDXID": "SPDXRef-Package-748D8C5DFA50C9CB753835F9F1DFF6F0E089469C9FE617F31C0AA113F494E434",
  "downloadLocation": "NOASSERTION",
  "filesAnalyzed": false,
  "licenseConcluded": "NOASSERTION",
  "licenseDeclared": "NOASSERTION",
  "copyrightText": "NOASSERTION",
  "versionInfo": "1.25.0",
  "externalRefs": [
    {
      "referenceCategory": "PACKAGE-MANAGER",
      "referenceType": "purl",
      "referenceLocator": "pkg:maven/org.apache.commons/commons-compress@1.25.0"
    }
  ],
  "supplier": "NOASSERTION"
}
```

```json: GitHub SBOM Export出力結果
{
    "SPDXID": "SPDXRef-maven-org.apache.commons-commons-compress-1.25.0",
    "name": "maven:org.apache.commons:commons-compress",
    "versionInfo": "1.25.0",
    "downloadLocation": "NOASSERTION",
    "filesAnalyzed": false,
    "supplier": "NOASSERTION",
    "externalRefs": [
        {
            "referenceCategory": "PACKAGE-MANAGER",
            "referenceLocator": "pkg:maven/org.apache.commons/commons-compress@1.25.0",
            "referenceType": "purl"
        }
    ]
}
```

作成したSBOMを比較してみると、以下のような結果となりました。

| ツール名/version | 出力ファイルサイズ | 検出コンポーネント数 | 検出ライセンス数 | 備考/他ツールとの差異など |
| --- | --- | --- | --- | --- |
| syft/0.98.0 | 115KB | 51件 | 0件 | 脆弱性識別子であるCPEが1コンポーネントに複数個出力されている |
| Trivy/0.48 | 62KB | 72件 | 68件 | コンポーネントの主目的（primaryPackagePurpose）が出力されている |
| SBOM Tool/2.2.1 | 1,483KB | 307件 | 0件 | プロジェクトのファイル(XXX.java)やそのHASH値が出力されている |
| GitHub SBOM Export/- | 43KB | 78件 | 0件 | GitHubの設定(GitHub Actionなど)がコンポーネントとして検出されている |


検出されたコンポーネント数などもそれぞれのツールで異なっており、SBOM生成ツールによって特性が異なることが分かります。SBOMを実際に利用する際には、SBOMに期待する要件や要求に合わせて、ツールの選定および合意を得る必要があります。

### 他のSBOM作成方法について
主にソフトウェアを対象としたSBOMの作成方法について紹介しましたが、他にもSBOMを作成する方法は多数あります。
SBOMはContainer技術とも親和性が高く、例えば[Docker Scout](https://www.docker.com/ja-jp/products/docker-scout/)を利用してImageファイルからSBOMを作成する方法もあります。また、AWSでも[AWS Inspector](https://aws.amazon.com/jp/inspector/)の機能に[SBOM Export](https://docs.aws.amazon.com/ja_jp/inspector/latest/user/sbom-export.html)が追加されるなど、利用しているサービス側の一部機能に組み込まれるケースも増えていますので、環境やユースケースに合わせた選択が可能です。

## 最後に
今回はSBOMの作成に注力しましたが、SBOM作成のモチベーションには脆弱性管理やライセンス管理に利用することが考えられています。SBOMを管理するツールやSBOMをinputに各コンポーネントの脆弱性を取得するツールもOSSなどで提供されているため、興味のある方は色々なSBOMを作ってお試しされてはいかがでしょうか。

--- 

というわけで、SBOMの概要及び作り方について簡単に紹介させていただきました。
明日は、 [@Yuka Kawasaki](https://qiita.com/yu_kawachaki)氏によるAWS troubleshootingに関する記事となります。お楽しみに！