APC 技術ブログ

株式会社エーピーコミュニケーションズの技術ブログです。

株式会社 エーピーコミュニケーションズの技術ブログです。

SBOMをGUACで可視化してみよう

はじめに

こんにちは、ACS事業部の谷合です。

先日Githubから、SBOMのエクスポート機能が提供されたとのアナウンスがありました。

github.blog

ちなみにSBOMとは、Software Bill of Materialsの略語であり、ソフトウェアのコンポーネント、
ライブラリ、ツール、およびプロセスを部品とみなし、それらを可視化 した一覧表です。
2021年末に発覚した「Log4j」の脆弱性などをきっかけにソフトウェアサプライチェーン における
脆弱性に注目が集まったことで、ソフトウェアの依存関係を可視化する取り組み として注目されています。
また、現在米国では大統領令にて、政府機関が調達するソフトウエアにSBOM提出が義務化されて
おり、KubeCon EU 2023でもSBOM関連のセッションは多数あるようなので、注目度の高さが窺い
知れます。

話を戻しましょう。Githubからエクスポートしたら、jsonファイルでダウンロードされるのですが
生の状態だと何がどのように依存しているのかが非常に分かりづらいです。

{
    "SPDXID": "SPDXRef-DOCUMENT",
    "spdxVersion": "SPDX-2.3",
    "creationInfo": {
        "created": "2023-04-11T01:31:59Z",
        "creators": [
            "Tool: GitHub.com-Dependency-Graph"
        ]
    },
    "name": "com.github.jnytnai0613/ssa-nginx-controller",
    "dataLicense": "CC0-1.0",
    "documentDescribes": [
        "com.github.jnytnai0613/ssa-nginx-controller"
    ],
    "documentNamespace": "https://github.com/jnytnai0613/ssa-nginx-controller/dependency_graph/sbom-84f35ddd423c238d",
    "packages": [
        {
            "SPDXID": "SPDXRef-go-cloud.google.com/go-0.81.0",
            "name": "go:cloud.google.com/go",
            "versionInfo": "0.81.0",
            "downloadLocation": "NOASSERTION",
            "filesAnalyzed": false,
            "licenseConcluded": "NOASSERTION",
            "licenseDeclared": "NOASSERTION",
            "supplier": "NOASSERTION",
            "externalRefs": [
                {
                    "referenceCategory": "PACKAGE-MANAGER",
                    "referenceLocator": "pkg:golang/cloud.google.com/go@0.81.0",
                    "referenceType": "purl"
                }
            ]
        },
        {
            "SPDXID": "SPDXRef-go-cloud.google.com/go-0.97.0",
            "name": "go:cloud.google.com/go",
            "versionInfo": "0.97.0",
            "downloadLocation": "NOASSERTION",
            "filesAnalyzed": false,
            "licenseConcluded": "NOASSERTION",
            "licenseDeclared": "NOASSERTION",
            "supplier": "NOASSERTION",
            "externalRefs": [
                {
                    "referenceCategory": "PACKAGE-MANAGER",
                    "referenceLocator": "pkg:golang/cloud.google.com/go@0.97.0",
                    "referenceType": "purl"
                }
            ]
        },
:

そこで、今回はGUAC(Graph for Understanding Artifact Composition)という グラフでSBOMを管理することができるOSSツールで可視化してみました。

github.com

アーキテクチャは以下のようになっており、GUACはSBOMやSLSAなどのデータを取り込み、
GraphQL言語でクエリを実行して可視化を行います。
この時、コンポーネント、ライブラリ、ツール、およびプロセスなどの部品を同士を繋ぎ、
それらの関係性をグラフ(Neo4j)として管理します。これにより部品同士の複雑な依存関係や
脆弱性情報関係を、つぶさに確認することができるようになります。

https://user-images.githubusercontent.com/3060102/182689908-477f4770-1142-4c18-8fa9-16d93dcf84b4.png

今回は僭越ながら私のGithubリポジトリからSBOMをエクスポートして検証してみました。

github.com

SBOMのエクスポート

まず、Insightsタブ → Dependency Graph → Export SBOMボタンを押下し、SBOMを
ローカルにダウンロードします。この操作により上記Github記事にあるように、
機械可読なJSONファイルがSPDX形式で作成されます。

SBOMのExport

GUAC起動

次にGUACのSETUP.mdファイルの手順に則り、インストールしていきます。
なお、このSETUP.mdファイルではguacsec/guac-dataというサンプルデータを利用していますが、 今回はGithubからエクスポートしたSBOMを利用します。

まず、以下のツールをインストールします。
1つ注意点ですが、GUACは現在go1.19で書かれていますのでgo1.18を使用している場合、1.19が必要である旨のエラーが発生するようでした。

[Requirements](https://github.com/guacsec/guac/blob/v0.0.1/SETUP.md#requirements)
1. make
2. npm (some makefile tasks use npx)
3. docker
4. golang 1.18+
5. protoc/protoc-gen-go/protoc-gen-go-grpc

次に以下の手順で、GUACをダウンロードし、起動準備をします。

# Export the variable(s).
$ export GUACSEC_HOME="$(go env GOPATH)/src/github.com/guacsec"

# Create the folders.
$ mkdir -p ${GUACSEC_HOME}
$ cd ${GUACSEC_HOME}

# Clone the Guacsec repositories.
$ git clone https://github.com/guacsec/guac.git

# Set guac to v0.0.1 release
$ cd guac
$ git checkout tags/v0.0.1 -b v0.0.1-branch

その後、Neo4jをセットアップし、GUACを起動します。 起動には少々時間が掛かりますが、"Started"と表示されるまで待ってください。
また、dockerコマンドは起動しっぱなしにし、この後の手順は別ターミナルで実行ください。

$ docker run --rm \
∙   -p7474:7474 \
∙   -p7687:7687 \
∙   -e NEO4J_AUTH=neo4j/s3cr3t \
∙   -e NEO4J_apoc_export_file_enabled=true \
∙   -e NEO4J_apoc_import_file_enabled=true \
∙   -e NEO4J_apoc_import_file_use__neo4j__config=true \
∙   -e NEO4JLABS_PLUGINS=\[\"apoc\"\] \
∙   neo4j:4.4.9-community

Changed password for user 'neo4j'. IMPORTANT: this change will only take effect if performed before the database is started for the first time.
Fetching versions.json for Plugin 'apoc' from https://neo4j-contrib.github.io/neo4j-apoc-procedures/versions.json
Installing Plugin 'apoc' from https://github.com/neo4j-contrib/neo4j-apoc-procedures/releases/download/4.4.0.9/apoc-4.4.0.9-all.jar to /var/lib/neo4j/plugins/apoc.jar
Applying default values for plugin apoc to neo4j.conf
2023-04-10 13:43:13.422+0000 INFO  Starting...
2023-04-10 13:43:17.631+0000 INFO  This instance is ServerId{e5a03ab4} (e5a03ab4-8041-4c25-9657-5ddf2f9dfe4b)
2023-04-10 13:43:22.228+0000 INFO  ======== Neo4j 4.4.9 ========
2023-04-10 13:44:09.970+0000 INFO  Initializing system graph model for component 'security-users' with version -1 and status UNINITIALIZED
2023-04-10 13:44:10.159+0000 INFO  Setting up initial user from `auth.ini` file: neo4j
2023-04-10 13:44:10.162+0000 INFO  Creating new user 'neo4j' (passwordChangeRequired=false, suspended=false)
2023-04-10 13:44:10.191+0000 INFO  Setting version for 'security-users' to 3
2023-04-10 13:44:10.205+0000 INFO  After initialization of system graph model component 'security-users' have version 3 and status CURRENT
2023-04-10 13:44:10.219+0000 INFO  Performing postInitialization step for component 'security-users' with version 3 and status CURRENT
2023-04-10 13:44:26.343+0000 INFO  Called db.clearQueryCaches(): Query caches successfully cleared of 1 queries.
2023-04-10 13:44:28.334+0000 INFO  Bolt enabled on 0.0.0.0:7687.
2023-04-10 13:44:37.974+0000 INFO  Remote interface available at http://localhost:7474/
2023-04-10 13:44:38.046+0000 INFO  id: 30E70AE85D1058D26EE778EEA662C9D1665375655BBFF4FAE896C2FC5AFEC775
2023-04-10 13:44:38.047+0000 INFO  name: system
2023-04-10 13:44:38.049+0000 INFO  creationDate: 2023-04-10T13:43:26.017Z
2023-04-10 13:44:38.050+0000 INFO  Started.

最後にExample 3: OSV Certifierに記載のコマンドを修正し、 SBOMをインポートします。

$ cd ${GUACSEC_HOME}
$ bin/guacone files --gdbuser neo4j --gdbpass s3cr3t <エクスポートしたSBOMのjsonファイルパス>

{"level":"info","ts":1681134379.9089239,"caller":"cmd/root.go:94","msg":"Using config file: /Users/taniaijunya/go/src/github.com/guacsec/guac/guac.yaml"}
{"level":"info","ts":1681134385.730068,"caller":"parser/parser.go:122","msg":"parsing document tree with root type: SPDX"}
{"level":"info","ts":1681134398.7071948,"caller":"cmd/files.go:156","msg":"[13.047723086s] completed doc {Collector:FileCollector Source:file:////Users/taniaijunya/Downloads/ssa-nginx-controller_jnytnai0613_e97ac968411a713a51782d186e1372d0e0da86bd.json}"}
{"level":"info","ts":1681134398.707372,"caller":"cmd/files.go:163","msg":"collector ended gracefully"}
{"level":"info","ts":1681134398.707681,"caller":"cmd/files.go:176","msg":"completed ingesting 1 documents"}

余談ですが、GUACでは以下のフォーマットがサポートされています。
なお、GithubのSBOMはSPDXです。
- CycloneDX
- Dead Simple Signing Envelope
- In-toto ITE6
- OpenSSF Scorecard
- SLSA
- SPDX

ここまできたら、http://localhost:7474/でGUACにアクセスします。 ユーザ名とパスワードは neo4j/s3cr3t です。

グラフ確認

早速以下をGraphQLコマンドを打って結果を表示してみます。
こちら、先頭25件を表示するコマンドです。

neo4j$ MATCH (n) RETURN n LIMIT 25;

上記の画面は、コマンド結果を表示させた上で、どれかの部品をクリックした画面となります。
クリックした部品のグレーの下のボタンを押下することで、大量の依存情報が表示されます。

GUACでは上記のグラフが主な機能ですが、以下のように部品をテキストとしても確認することができます。

おわりに

SBOMは簡単に出力および確認できるようになりましたが、いざ管理しようとすると、読み取りづらく、 可視化が必要不可欠となります。GUACを用いることでそれが簡単にでき、管理が容易になります。 また、米国でのSBOM提出義務化を受け、日本でもSBOMの義務化が検討されています。今のうちに、 SBOMの管理に取り掛かり、対応できるようになりましょう!

なお、GUACはGithubのSBOMだけでなく、SLSA(Supply-chain Levels for Software Artifacts)も インポート可能となっています。SLSAもKubeCon EU 2023で発表が多数あり、注目度の高いものとなっています。 是非こちらもご確認ください!

security.googleblog.com

私達ACS事業部はAzure・AKSを活用した内製化のご支援をしております。ご相談等ありましたらぜひご連絡ください。 www.ap-com.co.jp また、一緒に働いていただける仲間も募集中です! 切磋琢磨しながらスキルを向上できる、エンジニアには良い環境だと思います。ご興味を持っていただけたら嬉しく思います。 www.ap-com.co.jp