jqでJSON形式のSPDXファイルを解析しSBOMデータからライセンス情報を抽出する方法


## はじめに

今回は、`jq`コマンドを使ってJSON形式のSPDXファイルを解析する方法を検討する。

SBOM（Software Bill of Materials）を管理する際、JSON形式のSPDXファイルから必要な情報を効率的に抽出することは非常に重要だ。前回の記事では`bom`コマンドを使ってSPDX形式のSBOMファイルを作成したが、`bom document query`コマンドには現時点で不具合や機能不足が見られる。そこで、`jq`コマンドを用いて作成したSPDXファイルを解析する。

https://qiita.com/rairaii/items/ee8be92ec8f2907ca2b7


## jq コマンド

`jq`は、JSON形式のデータを操作するためのコマンドラインツールである。JSONデータのフィルタリング、抽出、変換、編集などを簡単に行うことができ、データ解析やスクリプト内でのデータ操作に役立つ。特に、複雑なJSON構造を持つSPDXファイルのようなデータを扱う際に、必要な情報を迅速に抽出できるのが強みだ。

## JSON形式のSPDXファイルの解析

ここからは、前回作成した`bom_spdx.json`ファイルを用いて、`jq`コマンドによる具体的な解析方法を見ていく。

### トップレベルのオブジェクトのプロパティ

SPDXファイル内にどのようなキー（プロパティ）が存在するか確認するために、トップレベルのキーをリスト化する。

```bash
jq 'keys' bom_spdx.json  
```
```json
[
  "SPDXID",
  "creationInfo",
  "dataLicense",
  "documentDescribes",
  "documentNamespace",
  "files",
  "name",
  "packages",
  "relationships",
  "spdxVersion"
]
```

このコマンドにより、SPDXファイルに含まれる主な情報が何かを把握することができる。次にこれらのキーに基づいて詳細な解析を行う。


### ファイル一覧を取得する

プロジェクト内に含まれるファイル名を取得するには、次のコマンドを使用する。

```bash
jq '.files[] | .fileName ' bom_spdx.json
```
```console
"docs/assets/scss/_size.scss"
"pkg/spdx/imageanalyzer_distroless.go"
"docs/assets/scss/_variables_project.scss"
...
```

このコマンドで、SPDXファイル内のすべてのファイルをリスト化できる。

### ファイルとライセンスの組みの一覧を取得する

```bash
jq -r '.files[] | "\(.fileName) , \(.licenseConcluded)"' bom_spdx.json | sort -d
```
```console
.bom-config.yaml , Apache-2.0
cloudbuild.yaml , Apache-2.0
cmd/bom/cmd/document.go , Apache-2.0
...
```

### トップレベルディレクトリとライセンス

トップレベルディレクトリに存在するファイルやディレクトリのライセンスの組み合わせを表示する。ディレクトリ内部に複数のライセンスが存在する場合、複数行にわたってライセンス情報が表示する。

```bash
 jq -r '.files 
    | map("\(.fileName | split("/")[0]), \(.licenseConcluded)") 
    | sort 
    | unique[]' bom_spdx.json
```
```console
.bom-config.yaml, Apache-2.0
.github, Apache-2.0
.gitignore, Apache-2.0
.golangci.yml, Apache-2.0
.goreleaser.yml, Apache-2.0
.ko.yaml, Apache-2.0
CONTRIBUTING.md, Apache-2.0
LICENSE, Apache-2.0
OWNERS, Apache-2.0
OWNERS_ALIASES, Apache-2.0
README.md, Apache-2.0
RELEASE.md, Apache-2.0
SECURITY_CONTACTS, Apache-2.0
cloudbuild.yaml, Apache-2.0
cmd, Apache-2.0
code-of-conduct.md, Apache-2.0
dependencies.yaml, Apache-2.0
docs, Apache-2.0
go.mod, Apache-2.0
go.sum, Apache-2.0
logo, Apache-2.0
mage.go, Apache-2.0
magefile.go, Apache-2.0
pkg, Apache-2.0
scripts, Apache-2.0
```


### パッケージ一覧を取得する

次に、SPDXファイルに記述されているソフトウェアパッケージの一覧を取得する。

```bash
jq '.packages[] | .name' bom_spdx.json
```
```console
"github.com/sirupsen/logrus"
"github.com/in-toto/in-toto-golang"
"github.com/docker/cli"
...
```

ここでは、どのパッケージがプロジェクトに含まれているかを確認することができる。


### パッケージのライセンス一覧を取得する

次に、使用されているソフトウェアのライセンス情報をまとめて表示する。ライセンス情報をソートして出現回数と共に表示する。

```bash
jq -r '.packages[] | .licenseConcluded' bom_spdx.json | sort | uniq -c
```
```console
     13 Apache-2.0
      2 BSD-2-Clause
     18 BSD-3-Clause
      1 CC-BY-SA-4.0
      1 ISC
     16 MIT
      4 null
```

ライセンスが不明なパッケージ（null）が4つあることが確認できる。これをもとに、ライセンス未確認の依存パッケージを特定し、調査を進めることができる。


### パッケージとライセンスの組みの一覧を取得する

パッケージ名とそのライセンスをペアで表示するには、以下のコマンドを使用する。

```bash
jq -r '.packages[] |  "\(.name), \(.licenseConcluded)"' bom_spdx.json
```
```console
github.com/sirupsen/logrus, MIT
github.com/in-toto/in-toto-golang, null
github.com/docker/cli, null
...
```

これで、各パッケージとそのライセンスがどのように結びついているかを簡単に確認できる。

### ライセンス不明なパッケージ一覧を取得する

ライセンスがnullとなっているパッケージだけをリストアップしたい場合、以下のコマンドを使用する。

```bash
jq -r '.packages[] | select(.licenseConcluded == null) | "\(.name), \(.licenseConcluded)"' bom_spdx.json
```
```console
github.com/in-toto/in-toto-golang, null
github.com/docker/cli, null
github.com/spf13/cobra, null
github.com/opencontainers/image-spec, null
```

このコマンドで、ライセンス不明のパッケージをリストアップし、ライセンスの調査が必要なパッケージをすばやく特定できる。