SBOMツール紹介 ~SCANOSS編 ~ ③PythonのSDK「scanoss.py」

はじめに

こんにちは!SBOMツールを調査中のなーがです。前回に引き続きSCANOSSについてみていきます。今回はPythonのSDK「scanoss.py」を使ってみたのでインストール方法や機能について書きます。SBOMについてよく分からないという方は、まずこちらの記事を読んでみてください。

インストール

Pythonの仮想環境を作成し、 Python Scannerをインストールします。

https://www.softwaretransparency.org/download

コマンドオプション

コマンドオプションは以下の通りです。scanだけでなく、依存関係を含めたスキャンやフォーマット変換が用意されています。

Fingerprinting生成(オプション)

スキャンコマンドの実行中に自動的に行われます。ここで生成されたFingerprintがサーバーに送信されます。

fingerprint.wfp

file=6e588ad70d32289ba8473f7e24716b8f,476,/express-app/views/index.ejs
5=a0e44c67
6=50cf271f,688f9bfe
10=3a8d7c3a
12=dac0aa3f
14=c6b5efb0
16=7af50e1f
file=31c693a880e86ce5a534fb03d151b4f4,2391,/express-app/index.js
5=40daea7b,ccb8356e
9=5800d9dc
10=b9ccb2d2,0db59e12
12=d59964a0
14=f636b37b
17=1db7ed12
19=d73a22b6,a8f419e7
20=8197b0b1,6b8f68ef
22=f1421678
24=fdd6d858
26=78f246d7,1fc66e08
28=72bd1285
32=f24bbde2,ac04acee
...

最初のフィールドはスキャンするファイルの MD5 を含む文字列になっています。この例では下記になります。

6e588ad70d32289ba8473f7e24716b8f

次にファイルサイズ、

476

最後にファイル名が表示されています。

/express-app/views/index.ejs

その下は行番号とソースコードの抽象化を表すフィンガープリントによって作成された行のリストになります。

5=a0e44c67
6=50cf271f,688f9bfe
10=3a8d7c3a
12=dac0aa3f
14=c6b5efb0
16=7af50e1f

このように、フィンガープリントからソースコードを再構築することはほとんど不可能であることがわかります。

スキャン実行

下記のコマンドを実行します。スキャン中はプログレスバーが表示されます。スキャンにかかる時間はプロジェクトのファイル数が多くなるにつれて長くなります。

scanoss-py scan -o scan-output.json スキャン対象のフォルダをパスで指定

フォーマットを指定しない場合は、下記のようにJSON形式で出力されます。出力内容としては、一致したコンポーネント名、バージョン、パール、ライセンス、著作権などの情報が含まれます。

{
  "ag-api//function_app.py": [
    {
      "id": "none",
      "server": {
        "kb_version": {
          "daily": "24.09.26",
          "monthly": "24.08"
        },
        "version": "5.4.8"
      }
    }
  ],
  "xpress-app//index.js": [
    {
      "id": "none",
      "server": {
        "kb_version": {
          "daily": "24.09.26",
          "monthly": "24.08"
        },
        "version": "5.4.8"
      }
    }
  ],
  "xpress-app//node_modules//@azure-rest//core-client//dist//browser//apiVersionPolicy.d.ts": [
    {
      "component": "@azure-rest/core-client",
      "file": "package/dist/browser/apiVersionPolicy.d.ts",
      "file_hash": "6026cf8d3f84e321eaa68250d98048be",
      "file_url": "<https://api.osskb.org/file_contents/6026cf8d3f84e321eaa68250d98048be>",
      "id": "file",
      "latest": "2.2.1-alpha.20240802.1",
      "licenses": [
...

フォーマット指定

オプション --format (または -f)を付けることで、下記の3パターンで出力できます。

  • RAW:plain(デフォルト)
  • SPDXLite:spdxlite
  • CycloneDX:cyclonedx
  • CSV: csv

以下はフォーマットとして CycloneDX を指定してスキャンを実行しています。

依存関係のスキャン

pip install scancode-toolkit

コンポーネント検索

APIキーを指定して、GitHubから vue を含むコンポーネントを検索してみます。 vue として登録されているコンポーネントがPURL(Package URL)、URLとともに出力されました。

APIキーは、こちらからトライアルキーをリクエストする必要があります。

Dockerイメージによる実行

Dockerイメージをpullします。

docker pull ghcr.io/scanoss/scanoss-py:latest

PythonのCLIはDockerイメージから公開されており、以下の方法で実行できます。

現在のフォルダをスキャンするには下記のように指定します。

docker run -it -v "$(pwd)":"/scanoss" ghcr.io/scanoss/scanoss-py scan .

また、 -oオプションで結果をファイルに出力することもできます。

docker run -it -v "$(pwd)":"/scanoss" ghcr.io/scanoss/scanoss-py scan -o results.json .

さらに、依存関係のスキャンをサポートするために、このコンテナには scancode-toolkit が含まれています。 依存関係をスキャンするには以下を実行します。

docker run -it -v "$(pwd)":"/scanoss" ghcr.io/scanoss/scanoss-py scan -D .

GitHub Actions

scanoss.pyをGitHub Actionsで実行してみます。

スキャン対象のリポジトリにワークフローを作成し、生成されたSBOMを確認します。

「Actions」から「set up a workflow yourself」をクリックします。

ファイル名(今回はscan.yml)、下記のワークフローを記載して「Commit changes…」をクリックします。ここではSCANOSSのdockerイメージからscanoss.pyを実行します。

name: SCANOSS CI Scan
on: 
  push: 
    branches: [ "master" ] 
  pull_request: 
    branches: [ "master" ]
jobs:
  build:
    runs-on: ubuntu-latest
    steps: 
      - uses: actions/checkout@v3
      - name: Scan 
        run: docker run -v "$(pwd)":"/scanoss" ghcr.io/scanoss/scanoss-py scan --output output.json .
      - uses: actions/upload-artifact@v3 
        with: 
          name: output.json
          path: output.json

今回は masterブランチに追加せず、新しいブランチを作成したいので、「Create a new branch for this commit and start a pull request」を選択して「Propose changes」をクリックします。

(master(main)ブランチに直接追加したい場合は「Commit directly to the master(main) branch」を選択します)

「Create pull request」をクリックします。

Pull Requestが発行されるとGitHub Actionsが実行されるので、実行結果を確認します。「Actions」からワークフロー(今回は Create scanoss.yml)をクリックします。

Actionsの実行結果が表示されます。

ダウンロードボタンをクリックすると、出力結果の output.json をダウンロードできます。

ダウンロードされたZipファイルを解凍し、 output.json を確認すると、下記のようなスキャン結果が出力されていることが分かります。

{
  "express-app/index.js": [
    {
      "id": "none",
      "server": {
        "kb_version": {
          "daily": "24.09.27",
          "monthly": "24.08"
        },
        "version": "5.4.8"
      }
    }
  ],
  "express-app/public/js/app.js": [
    {
      "component": "juanzi",
      "file": "package/index.js",
      "file_hash": "4c0e7d3ec9dd03fd7830e56642ab77ff",
      "file_url": "<https://api.osskb.org/file_contents/4c0e7d3ec9dd03fd7830e56642ab77ff>",
      "id": "file",
      "latest": "1.0.0",
      "licenses": [
        {
          "checklist_url": "<https://www.osadl.org/fileadmin/checklists/unreflicenses/ISC.txt>",
          "copyleft": "no",
          "name": "ISC",
          "osadl_updated": "2024-09-20T09:32:00+0000",
          "patent_hints": "no",
          "source": "component_declared",
          "url": "<https://spdx.org/licenses/ISC.html>"
        }
      ],
      "lines": "all",
      "matched": "100%",
      "oss_lines": "all",
      "purl": [
        "pkg:npm/juanzi"
      ],
      "release_date": "2019-11-18",
...

さいごに

今回はPythonのSDK「scanoss.py」を使ってみたのでインストール方法や機能について書きました。今後も業務で学習した内容をブログとして投稿しようと思います。

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

0人がこの投稿は役に立ったと言っています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です