ページの本文へ

Hitachi

日立ソリューションズ ソフトウェア部品管理ソリューション

OSS管理ブログ

SPDX-LiteでSBOMを作ってみよう

SPDX-LiteでSBOMを作ってみよう

毎々お世話になっております、株式会社 日立ソリューションズの明石と申します。本日はSPDX-LiteでSBOMを作成する手順についてご紹介したいと思います。

免責事項

当記事の内容については、できる限り正確な情報を提供するように努めておりますが、正確性や安全性を保証するものではなく、筆者独自の解釈も含むことをご了承ください。 掲載しているリンク先についても確認などは行っていますが、遷移先で提供される情報、サービスなどについては一切の責任を負いません。

また、掲載内容の活用は読者自身の自由と主体性の元に行うものとし、万が一損害が発生したとしても一切の責任を負いかねます。ご了承ください。

SPDX-Liteとは?

まず、SPDXというのはSPDX WorkGroupが提供しているSBOMフォーマットのことです。このフォーマットにはソフトウェアパッケージの来歴、ライセンス、セキュリティ、およびその他の関連情報を記述することができます。これは組織やコミュニティが共通の形式を使用することで情報交換時の冗長な作業を減らし、それによってコンプライアンスやセキュリティ、信頼性を合理化かつ改善する目的で定義、提供されています。

そしてSPDX-Liteは、このSPDXから最低限の必須情報のみを記述するだけで成立するよう定義された、SPDXのサブセットになります。SPDXは記述しなければならない情報が多く、手動で入力するには少し難しいフォーマットになっています。そこで、今回は手作業で作成することを念頭において定義されたSPDX-LiteでSBOMを作成してみよう、というのが本記事の主旨になります。

なお、本記事はあくまでこの形式に従ったSBOMを作成することが目的なので、SPDX Specificationそのものや個々の属性の意味、値の妥当性についての解説は最低限に留めます。

詳しく知りたい方は別記事で解説しておりますので、こちら「OSS管理ブログ SPDX Documentを理解する」をご覧ください。

目標

SPDX-Lite形式に則ったソフトウェアパッケージのSBOM、SPDX Documentを作成します。SPDXおよびSPDX-Lite形式として成立しているかどうかを確かめるには、公式から提供されているspdx-toolsで読み込むことができるかどうかで判断できます(方法は後述します。)

仮定

以下のようなソフトウェアパッケージ「example_1.0」を管理している状態を仮定します。

example_1.0
├── original_component
├── oss_component1
└── oss_component2

今回はこちらの情報を元にSBOMを作成していきます。

今回は例として上記のように単純な構造を持つプロジェクトを対象としていますが、SPDX-Liteでは基本的に「ソフトウェアパッケージの情報」、「ソフトウェアパッケージが依存している、または同梱されているパッケージの情報」が分かっていれば構造は特に気にする必要はありません。

(余談ですが、SPDX-LiteではなくSPDXでSPDX Documentを作成する場合は、ファイルやスニペット単位での情報や関係性を追加する必要が出てくるので、ソフトウェアパッケージ内の構造を正確に把握、記入していく必要があったりします。)

作成

SPDX Documentは一つのソフトウェアパッケージに対応します。したがって、今回作成するのはソフトウェアパッケージ「example_1.0」に対応する1つのSPDX Documentファイルです。SPDXはそのファイル形式として、Tag:valueRDFjsonXMLYAMLをサポートしています(文字コードはUTF-8が指定されています)。今回はTag:Value形式で記述していきます。

基本的な記述は↓のように書きます。

## ←これはコメント扱い
(属性): (値)
## 例
SPDXVersion: SPDX-2.0

それでは早速作成していきましょう。

SPDX Documentはいくつかのセクションで構成されており、各セクションはいくつかのインスタンスで構成されています。セクションは複数の属性をもっており、インスタンスごとにその値を記入することでデータを作成していきます。RDBで例えると、セクションがテーブルで、一つのインスタンスがレコード、各セクションが持つ属性に対して各インスタンスが値をもつと考えれば分かりやすいと思います。

SPDX-Liteで要求されているセクションは以下の3つです。

  • SPDX Document Creation Information

  • Package Information

  • Other Licensing Information Detected

これらの情報を上から順に記入していけばSPDX Documentが完成します。

(順番が異なるとフォーマットから外れてしまうので、間違えないようにしてください。最後の方に完成形を例示しています。)

SPDX Document Creation Information

作成するSPDX Documentについての情報を記入します。このセクションは1つのSPDX Documentにつき1つのインタンスとなっています。

  • SPDX Version、Data License、SPDX-Identifier

    これらは固定値を入力することになっているので、それを記入します。属性の意味としてはそれぞれ「SPDX Specificationのバージョン」、「このSPDX文書に適用されるライセンス」、「文書内でこのDocument Informationを一意に識別する識別子」となっています。

    SPDXVersion: SPDX-2.0
    DataLicense: CC0-1.0
    SPDXID: SPDXRef-DOCUMENT
  • Document Name

    このSPDX-Lite文書に対応するソフトウェアパッケージの名称です。基本的にはソフトウェアパッケージ名(≒フォルダ、ディレクトリ名)とバージョンを連結した形でよいと思います。

    DocumentName: example_1.0
  • SPDX Document Namespace

    この文書が定義する名前空間で、URIを記入します。RFC-3986にしたがってさえいれば自由に記述して構いませんが、SPDX Specificationではベストプラクティスとして以下が提示されています。

    • http://[CreatorWebsite]/[pathToSpdx]/[DocumentName]-[UUID]

      • [CreatorWebsite]...文書作成者によってホストされているウェブサイト
      • [pathToSpdx]...ウェブサイト上でのパス
      • [DocumentName]...このセクションのDocument Nameの値
      • [UUID]...universally unique identifier。v4かv5が利用可能。

      作成者がウェブサイトをホストしていない場合はデフォルト値としてspdx.org/spdxdocsを利用してよいとされているので、今回はこれにならって記入します。

      DocumentNamespace: http://spdx.org/spdxdocs/example_1.0-69527cee-596f-4ca4-9ecd-8c02fb12a175
  • Creator

    この文書の作者の情報です。こちらに記入規則があるので、それにしたがって記入します。基本は作成者の名前を「Person: ○○(××@exmaple.com)」という形で入力します(メールアドレス部分は任意です)。 ここの属性は複数入力できます。組織として作成した場合は「Organization: ○○ ()」を追加してもよいですし、何かしらのツールから自動生成した場合は「Tool: ○○」と入力します。せっかくなので、今回は組織としても作成したことにして記入してみます。

    Creator: Person: Nanashi no gonbe ()
    Creator: Organization: ExampleCorp ()
  • Created

    この文書を作成した時間です。こちらにフォーマットが規定されているので、ならって記入します。

    Created: 2021-10-31T14:00:00Z 

このセクションをまとめると以下のような状態になります。

## Document Info
SPDXVersion: SPDX-2.0
DataLicense: CC0-1.0
SPDXID: SPDXRef-DOCUMENT
DocumentName: example_1.0
DocumentNamespace: http://spdx.org/spdxdocs/example_1.0-69527cee-596f-4ca4-9ecd-8c02fb12a175
Creator: Person: Nanashi no gonbe ()
Creator: Organization: ExampleCorp ()
Created: 2021-10-31T14:00:00Z

Package Information

ここにはプロダクトに含まれるパッケージ(コンポーネント)の情報を入力します。含まれるパッケージの数だけPackage Informationが必要なので、今回は3つ分記入します。

※属性ごとに3つ分すべてを記載していますが、実際にはインスタンスごとに属性をまとめる必要があるので注意してください(最後にまとめて記載しているのが正しい形です)。

  • Package Name

    パッケージの名前です。一般名称でよいと思います。

    ### original_component
    PackageName: original_component
    ### oss_component1
    PackageName: oss_component1
    ### oss_component2
    PackageName: oss_component2
  • Package SPDX Identifier

    パッケージをSPDX文書内で一意に識別する識別子を「SPDXRef-○○」という形で記入します。文書内の名前空間で一意性があればよいので「SPDXRef-1」のような形でもまったく問題ありませんが、可能なら分かりやすい識別子が良いので今回はパッケージ名と近い形にします。

    ### original_component
    SPDXID: SPDXRef-original_component
    ### oss_component1
    SPDXID: SPDXRef-oss_component1
    ### oss_component2
    SPDXID: SPDXRef-oss_component2
  • Package Version

    このソフトウェアパッケージのバージョンを記入します。任意属性なので、分からない、ない場合は記入しなくても問題ありません。

    ### original_component
    PackageVersion: 1.0
    ### oss_component1
    PackageVersion: 1.0
    ### oss_component2
    PackageVersion: 2.0
  • Package File Name

    このソフトウェアパッケージのファイル名を記入します。Package Informationはパッケージ全体の情報を指すので、最上位のフォルダ、ディレクトリ名を記入しましょう。

    ### original_component
    PackageFileName: original_component
    ### oss_component1
    PackageFileName: oss_component1
    ### oss_component2
    PackageFileName: oss_component2
  • Package Download Location

    このソフトウェアパッケージの入手先を記入します。外部から入手した場合はそのURLを記入しますが、自社の所有するソフトウェアパッケージだったり、自前の実装だったりする場合はURLが存在しないかもしれません。この属性は必須なので、そういった場「NOASSERTION」と記入します。

    ### original_component
    PackageDownloadLocation: NOASSERTION
    ### oss_component1
    PackageDownloadLocation: http://oss_component1/download/v1.0
    ### oss_component2
    PackageDownloadLocation: http://oss_component2/download/v2.0
  • Files Analyzed

    SPDX-Liteにおいては、ここはfalseが規定されています。この属性の意味はパッケージを機械的に解析したか?という意味なので、今回のような手入力の場合は必然的にfalseになります。ここが一つでもtrueになっているPackage InformationがあるとSPDX-LiteではなくSPDXになってしまうので、必ずfalseを記入してください。

    ### original_component
    FilesAnalyzed: false
    ### oss_component1
    FilesAnalyzed: false
    ### oss_component2
    FilesAnalyzed: false
  • Package Home page

    このソフトウェアパッケージを提供しているWebサイトのURLを記入します。任意属性なので、ない場合は記入しなくても構いません。

    ### original_component
    ### なし
    ### oss_component1
    PackageHomePage: http://oss_component1/
    ### oss_component2
    ### なし
  • Concluded License、Declared License

    ここの説明は少し難しいので2つまとめて行います。まず、SPDXにおけるライセンス情報の扱いについて、SPDX License Listという存在を知る必要があります。このSPDX License ListというのはSPDXプロジェクトが取りまとめているOSSに適用されることの多いライセンスの情報リストです。SPDX Specではこのリストの存在を前提としており、ここに記載のあるライセンスについては細かい情報をいちいち記入しなくてよいということになっています。しかし、ここに記載がなければ参照する情報がないので、最後のOther Licensing Information Detectedに追加の情報を記入する必要があるという決まりになっています。それでは前提が分かったうえでこの属性について解説します。

    Concluded Licenseには"結果的に含まれていた、適用されていると判断された"ライセンス情報を、Declared Licenseには"パッケージへの適用が宣言された"ライセンス情報を記入します。前者はこのソフトウェアパッケージに対して最終的に適用されるライセンス、後者は宣言がなされているライセンスになります。基本的には両方同じライセンスが適用されるはずですが、ソフトウェアパッケージの作者がパッケージを構成するソフトウェアのライセンスの中に、意図しないライセンスが適用されていたものが含まれていた場合にここが変わってきます。何かしらのツールによって宣言されているライセンスが混入および適用されていることが認められた場合、そのライセンス名をConcluded Licenseに記入しなければなりません。(SPDX-Lite以外でSBOMを作成する場合でも、この調査はしっかりやっておくことを強く推奨します。)

    記入の手順としては、まずこちらに該当するライセンスがないか確認しましょう。該当するライセンスがあれば、それに対応するSPDX License Identifierをここに記入します。有名なライセンスはほとんどあると思いますが、ない場合は後述する「Other Licensing Information Detected」にて追加の記入が必要になります。その場合、SPDX Identifierの代わりにこの文書内で一意に識別する識別子を「LicenseRef-○○」という形で記入します。文書内の名前空間で一意性があればよいので、「LicenseRef-1」のような形でもまったく問題ありません。今回はoriginal_componentに「Haisho License」という、リストにないライセンスが適用されていたということにして情報を記述していきます。

    なお、この属性にはパッケージに適用されるライセンスが複数ある場合も、一つの文字列として記入します。説明が大変なので今回は触れずに先へ進みますが、もし気になる方はこちらをご覧ください。

    ### original_component
    PackageLicenseConcluded: LicenseRef-Haisho
    PackageLicenseDeclared: LicenseRef-Haisho
    ### oss_component1
    PackageLicenseConcluded: MIT
    PackageLicenseDeclared: MIT
    ### oss_component2
    PackageLicenseConcluded: LGPL-2.0-only
    PackageLicenseDeclared: LGPL-2.0-only
  • Comments on License

    このソフトウェアパッケージのライセンスについてのコメントを記入します。 任意属性なので、記入しなくてもよいのですが、今回の例にはSPDX License Listになかった「Haisho License」が適用されている自社パッケージが含まれているので、それについてコメントを記入しておきます。

    ### original_component
    PackageLicenseComments: Haisho Licenseは自社が配布しているossに適用されるセンス。
    ### oss_component1
    ### なし
    ### oss_component2
    ### なし
  • Copyright Text

    このソフトウェアパッケージのコピーライトをそのまま記入します。必須属性なので、存在しない場合はNONE、探しても見つからなかった場合はNOASSERTIONを記入します。

    ### original_component
    CopyrightText:Copyright 2020-2021 ExmapleCorp
    ### oss_component1
    CopyrightText:Copyright 2008-2010 oss suplier
    ### oss_component2
    CopyrightText: NOASSERTION
  • Package Comment

    このパッケージに対するコメントを記入します。任意属性なので特になければ記入しなくても構いませんが、今回は「original_component」が自前で作成しているソフトウェアパッケージなので、その旨は記入しておきましょう。

    ### original_component
    PackageComment: exampleCorp製のパッケージ。
    ### oss_component1
    ### なし
    ### oss_component2
    ### なし

このセクションの最終形は以下のような形になります。

## Package Info
### original_component
PackageName: original_component
SPDXID: SPDXRef-original_component
PackageVersion: 1.0
PackageFileName: original_component
PackageDownloadLocation: NOASSERTION
FilesAnalyzed: false
PackageLicenseConcluded: LicenseRef-Haisho
PackageLicenseDeclared: LicenseRef-Haisho
CopyrightText:Copyright 2020-2021 ExmapleCorp
PackageLicenseComments: Haisho Licenseは自社が配布しているossに適用されるライセス。
PackageComment: exampleCorp製のパッケージ。
### oss_component1
PackageName: oss_component1
SPDXID: SPDXRef-oss_component1
PackageVersion: 1.0
PackageFileName: oss_component1
PackageDownloadLocation: http://oss_component1/download/v1.0
FilesAnalyzed: false
PackageLicenseConcluded: MIT
PackageLicenseDeclared: MIT
PackageHomePage: http://oss_component1/
CopyrightText:Copyright 2008-2010 oss suplier
### oss_component2
PackageName: oss_component2
SPDXID: SPDXRef-oss_component2
PackageVersion: 2.0
PackageFileName: oss_component2
PackageDownloadLocation: http://oss_component2/download/v2.0
FilesAnalyzed: false
PackageLicenseConcluded: LGPL-2.0-only
PackageLicenseDeclared: LGPL-2.0-only
CopyrightText: NOASSERTION

Other Licensing Information Detected

ここにはSPDX License Listに記載のないライセンスについての情報を記入します。今回はoriginal_componentに「Haisho License」という記載のないライセンスが適用されていたので、これについての情報を記入していきます。

  • License Name

    ライセンスの名前を記入します。

    ## original_component
    LicenseName: Haisho License
  • License ID

    Package InformationのConcluded License、Declared Licenseで記入したIDを記入します。ここが一致していないと後でファイルの成立性を確かめる際に警告が出るので、間違えないようにしましょう。

    ## original_component
    LicenseID: LicenseRef-Haisho
  • Extracted Text

    このライセンスのテキストです。コピペで構いません。

    ## original_component
    ExtractedText: これは○○社が提供するOSSに適用されるライセンスです。このライセンスが適用されたOSSの使用者は、以降に宣言される項目すべてを"拝承"したとみなします。
  • Extracted Comment

    このライセンスに対するコメントです。任意なので特になければ記入しなくても構いません。

    ## original_component
    LicenseComment: This is the Haisho License.

    これらを記入すると以下のような状態になります。

    ## License Information
    LicenseID: LicenseRef-Haisho
    ExtractedText: これは○○社が提供するOSSに適用されるライセンスです。このライセンスが適用されたOSSを使用した場合、使用者は以下の項目すべてを"拝承"したとみなします。
    LicenseName: Haisho License
    LicenseComment: This is the Haisho License

お疲れさまでした、これにてSPDX-Liteフォーマットに則ったSBOMの完成です。整理した最終的な完成形はこちらになります。

## Document Info
SPDXVersion: SPDX-2.0
DataLicense: CC0-1.0
SPDXID: SPDXRef-DOCUMENT
DocumentName: example_1.0
DocumentNamespace: http://spdx.org/spdxdocs/example_10-69527cee-596f-4ca4-9ecd-8c02fb12a175
Creator: Person: Nanashi no gonbe ()
Creator: Organization: ExampleCorp ()
Created: 2021-10-31T14:00:00Z

## Package Info
### original_component
PackageName: original_component
SPDXID: SPDXRef-original_component
PackageVersion: 1.0
PackageFileName: original_component
PackageDownloadLocation: NOASSERTION
FilesAnalyzed: false
PackageLicenseConcluded: LicenseRef-Haisho
PackageLicenseDeclared: LicenseRef-Haisho
PackageCopyrightText: Copyright 2020-2021 ExmapleCorp
PackageLicenseComments: Haisho Licenseは自社が配布しているossに適用されるライセンス。
PackageComment: exampleCorp製のパッケージ。
### oss_component1
PackageName: oss_component1
SPDXID: SPDXRef-oss_component1
PackageVersion: 1.0
PackageFileName: oss_component1
PackageDownloadLocation: http://oss_component1/download/v1.0
FilesAnalyzed: false
PackageLicenseConcluded: MIT
PackageLicenseDeclared: MIT
PackageHomePage: http://oss_component1/
PackageCopyrightText: Copyright 2008-2010 oss suplier
### oss_component2
PackageName: oss_component2
SPDXID: SPDXRef-oss_component2
PackageVersion: 2.0
PackageFileName: oss_component2
PackageDownloadLocation: http://oss_component2/download/v2.0
FilesAnalyzed: false
PackageLicenseConcluded: LGPL-2.0-only
PackageLicenseDeclared: LGPL-2.0-only
PackageCopyrightText: NOASSERTION

## Other Licensing Info
LicenseID: LicenseRef-Haisho
ExtractedText: これは○○社が提供するOSSに適用されるライセンスです。このライセンスが適用されたOSSを使用した場合、使用者は以下の項目すべてを"拝承"したとみなします。
LicenseName: Haisho License
LicenseComment: This is the Haisho License

互換性の確認

それではSPDX-Lite形式として成立しているか確認をしてみましょう。確認には、前述したとおりspdx-toolsを使用します。インストールには公式のリポジトリとmavenを使用します。

$ git clone https://github.com/spdx/tools
$ cd tools
$ mvn clean install

以降は上記にしたがってローカル環境にspdx-toolsをインストールし、jarファイルをビルドした状態だと仮定して話を進めます。jarファイル名はビルド後作成されたものを指定してください。

jarファイルを指定して実行すると以下のような画面が表示されます。

$ java -jar spdx-tools-2.2.6-SNAPSHOT-jar-with-dependencies.jar
Usage: java -jar spdx-tools-jar-with-dependencies.jar function parameter
function                 parameter                         example
-------------------------------------------------------------------------------------------------------------------
TagToSpreadsheet         inputFile outputFile              Examples/SPDXTagExample.tag TagToSpreadsheet.xls
TagToRDF                 inputFile outputFile [format]     Examples/SPDXTagExample.tag TagToRDF.rdf
RdfToTag                 inputFile outputFile              TestFilesSPDXRdfExample.rdf  RdfToTag.tag
RdfToHtml                inputFile outputFile              TestFilesSPDXRdfExample.rdf  RdfToHtml.html
RdfToSpreadsheet         inputFile outputFile              TestFilesSPDXRdfExample.rdf RdfToSpreadsheet.xls
SpreadsheetToRDF         inputFile outputFile              ExamplesSPDXSpreadsheetExample.xls SpreadsheetToRDF.rdf
SpreadsheetToTag         inputFile outputFile              ExamplesSPDXSpreadsheetExample.xls SpreadsheetToTag.tag
SPDXViewer               inputFile                         TestFilesSPDXRdfExample.rdf
Verify                   inputFile                         TestFilesSPDXRdfExample.rdf
CompareMultipleSpdxDocs  output.xls doc1 doc2 ... docN
CompareSpdxDocs          doc1 doc2 [output]
GenerateVerificationCode sourceDirectory
Version
MatchingStandardLicenses licenseTextFile

確認にはこの中のVerifyコマンドを使用します。

引数に先ほど作成したファイルを渡してjarファイルを実行します。

java -jar spdx-tools-2.2.6-SNAPSHOT-jar-with-dependencies.jar Verify example_1.0.spdx

実行後、以下の文字列が表示されたら成功です。

This SPDX Document is valid.

SPDXに互換性のあるspdxファイルはspdx-toolsで以下のコマンドによりRDF、xlsに変換することもできます。何もかもエクセルで所望する上長、同僚にも対応が可能となっています。

// tag:value → RDF
$ java -jar spdx-tools-2.2.6-SNAPSHOT-jar-with-dependencies.jar TagToRDF example_1.0.spdx example_1.0.rdf
// tag:value → xls
$ java -jar spdx-tools-2.2.6-SNAPSHOT-jar-with-dependenciesjar TagToSpreadsheet example_1.0.spdx example_1.0.xls

終わりに

いかがだったでしょうか?今回はSPDX-Lite形式を用いたSBOMを作成してみました。大規模なプロダクトになってくるとどうしても依存先が増えてしまい、手入力では追いつかなくなる可能性があるので、機械的なスキャンで情報を収集することが必要になってきますが、小規模であればこちらのSPDX-Liteで簡単にSBOMを作成することができます。所有するプロダクト、ライセンス管理の一歩として作成してみてはいかがでしょうか?

最後までお読みいただきありがとうございました!

参考

オープンソース管理ソリューション
タグ一覧
新着記事