お疲れ様です。すぺきよです。
昨今、OSS(Open Source Software)界隈で話題になっているSBOM(Software Bill Of Materials:ソフトウェア部品表)ですが、この2023年の夏になり、日本国内でも話題を聞くことが増えてきました。
2023年7月に経済産業省が「ソフトウェア管理に向けたSBOM(Software Bill of Materials)の導入に関する手引」を公開したこともあり、今後、よりSBOM界隈の動きが活発化してくることが予想されます。
ということで、試しにSBOMの抽出をやってみることにしました。
今回はPHPのパッケージマネージャーであるcomposerを使ってパッケージ管理をしている場合のSBOMの出力手順についてまとめます。
SBOMとは
そもそもSBOM(Software Bill Of Materials:ソフトウェア部品表)とはなんなのかを軽く説明します。
詳しく説明すると非常に長くなり、私如きの理解で説明しても良いのか不安なため、簡単に概要のみを説明します。
SBOMとは、つまるところ日本語訳にある通り「ソフトウェア部品表」です。・・・といわれても、それで分かれば苦労はしませんよね。
昨今、開発されている多くのソフトウェアは多かれ少なかれ、様々なライブラリや、OSSで公開されているパッケージなどを利用して、開発されていると思います。
ものすごく簡単に言えば、SBOMとは開発したソフトウェアが動作するために利用しているライブラリやパッケージの一覧のことです。Webアプリであれば、WebサーバーであるApacheやNginx、データベースなどのミドルウェアもこの一覧に含まれるべきでしょう。
「SBOMなんてなくても、もう利用しているパッケージやミドルウェアの一覧表は作って管理しているよ」という方もいらっしゃるかもしれません。
しかし、SBOMは使っているミドルウェアやライブラリを単純に並べたものではありません。
なぜならば、利用しているミドルウェアやライブラリ、パッケージはそれぞれ別のライブラリやパッケージを利用し、依存しているためです。
SBOMでは、これらミドルウェアやライブラリ、パッケージが利用、依存しているライブラリやパッケージについても記載することが求められます。
SBOMというとOSSのライブラリやパッケージのみとのイメージを持たれるかもしれませんが、プロプライエタリソフトウェアのようなソースコードが公開されていないライブラリやパッケージについても記載しても問題ありません。
SBOMが叫ばれるようになった背景
なぜSBOMが叫ばれるようになったのか、それは記憶に新しい「Log4Shell」という脆弱性が関係しています。
この「Log4shell」という脆弱性は、Javaのパッケージである「Apache Log4j」(以下Log4j)という、ログを出力するためのパッケージあった脆弱性で、条件が揃うと任意のコードをシステム内で実行されてしまうという恐ろしい脆弱性です。
この脆弱性の怖いところは、直接システムがLog4jのパッケージを参照していなくても、別の目的で利用しているパッケージがLog4jを利用していることがあるという点です。
そう、表面だけの直接利用しているパッケージのみを管理したとしても、本当に影響がないかは判断できないということです。
そこで、依存関係まで一覧で管理するSBOMの出番ということですね。
そのほかにも2020年に発生した「SolarWinds事件」も背景にあるそうですが、こちらはあまり詳しくないので割愛します。
SBOMはどうやって作る?
SBOMは人の手でも作ることができます。・・・が、パッケージが参照しているパッケージが参照しているパッケージの・・・と人の手で作るには限界があります。複雑なシステムとなれば現実的ではありません。
そこで出てくるのがパッケージマネージャーです。RedHatで言えば「dnf」や「yum」、PHPで言えば「composer」、Pythonで言えば「pip」、NodeJSで言えば「npm」、Rustで言えば「cargo」などなどですね。
パッケージマネージャーは、依存関係のあるパッケージを自動的にインストールしてくれる機能を持っています。すなわち、パッケージの依存関係を知っているということで、SBOMを機械的に作成するにはうってつけ、というわけですね。
筆者が試した時の環境
私が試した時の環境を以下に示します。
OS | Rockey Linux 9.2 |
PHP | 8.0.27(当時最新は8.2.10) |
Composer | 2.6.2 |
今回出力するフォーマット
SBOMのフォーマットとしては「SPDX(Software Package Data Exchange)」「CycloneDX」「SWID タグ(Software Identification タグ)」の3つが主流です。
今回はこのうち、OWASPが制定している「CycloneDX」のフォーマットのJSON形式で出力を行います。
テスト用プロジェクトの準備
すでに既存のプロジェクトがあり、そちらで試してもいいのであればこのブロックはスキップしていただいて構いません。
また、PHPとComposerのインストール手順はここではすでにインストール済みである前提とします。
今回のテストプロジェクトは「~/cowsay/php/composer」というディレクトリを作り、その中に「cowsayphp」というパッケージをインストールして、SBOMを作成してみます。
ディレクトリを作成して移動
以下のコマンドを実行して、ディレクトリを作成して移動しましょう。
> mkdir -p ~/cowsay/php/composer
> cd ~/cowsay/php/composer
cowsayパッケージをインストール
cowsayphpパッケージをインストールします。
> composer require alrik11es/cowsayphp
インストールが完了したら、lsコマンドでディレクトリの状況を見てみましょう。きっと以下のようにcomposer.jsonが含まれていると思います
> ls
composer.json composer.lock vendor
以上で準備は完了です。
実際の出力手順
CycloneDX PHP Composer Pluginをインストール
次のコマンドで、「CycloneDX PHP Composer Plugin」をグローバルにインストールします。
> composer global require cyclonedx/cyclonedx-php-composer
CycloneDX PHP Composer Pluginの最新版は執筆時点で4.2.0で、PHPの最低要件は8.1以上でした。
今回の環境であるPHP8.0.27ではうまく動作しないかと心配しましたが、インストールされている環境にあったバージョンがインストールされるようで、今回の環境の場合、CycloneDX PHP Composer Pluginは3.11.0がインストールされました。
SBOMを出力
最後に次のコマンドでSBOMを出力するだけです。思った以上に簡単ですね。
> cd ~/cowsay/php/composer
> composer CycloneDX:make-sbom --output-file=sbom.json --output-format=JSON
処理が完了すると「Write output to: sbom.json」というメッセージとともに、プロジェクトのディレクトリに「sbom.json」ファイルが作成され、この中にSBOMの情報が含まれています。
> ls ~/cowsay/php/composer
composer.json composer.lock sbom.json vendor
今回は「–output-file」オプションに「sbom.json」を与えているため、出力されるファイルは「sbom.json」となっています。
また、「–output-format」オプションに「JSON」を指定しているため、出力フォーマットはJSONとなっています。ここが未指定だと、デフォルトではxmlが選択されるようです。
まとめ
今回はphp composerでSBOMの出力をやってみました。
CycloneDX SBOM Standardのプロジェクトでは、pythonやnode-moduleなどなど、いろんなパッケージ向けのSBOM出力ツールを開発されているようです。