到達可能性解析のセットアップ#
到達可能性解析は、お客様の CI でスクリプト vuls-reach-light.sh を実行して行います。
スクリプトは到達可能性解析プログラム vuls-reach をダウンロードし、指定した LockFile ごとにソースコードを解析して、結果を FutureVuls にアップロードします。
本機能の概要と注意事項は「到達可能性解析(ベータ版)」を参照してください。
前提条件#
FutureVuls 側の準備#
- CSIRT プランのオーガニゼーションであること。CSIRT プラン以外では、解析結果のアップロードが拒否されます
- アップロードに使うグループトークンの API 権限が「読み込み、更新」または「読み込み、更新、グループ設定」であること(「FutureVuls APIのトークン作成」)。API 権限が「読み込み」のトークン、グループセットトークン、オーガニゼーショントークンは使えません
- 解析する Go アプリケーションが、FutureVuls のサーバにアプリケーションとして登録済みであること。アプリケーションは、スキャン、LockFile の登録、SBOM のインポートのいずれかで登録します
- オーガニゼーションで IP アドレスの制限(「アクセス可能なIPアドレスを登録」)を設定している場合は、CI の送信元 IP アドレスが許可されていること。解析結果のアップロードは FutureVuls API を使うため、スキャン結果のアップロードと異なり、IP アドレスの制限の対象です
到達可能性解析は、アプリケーションを新しく登録しません。 先にスキャンなどでアプリケーションを登録し、その ID(applicationId)をスクリプトに指定します。
CI の実行環境#
| 項目 | 要件 |
|---|---|
| OS / CPU | Linux の x86_64 または aarch64 |
| コマンド | bash、curl、tar、Go toolchain(go コマンドが PATH にあること)jq と file は任意 |
| ソースコード | 解析する Go モジュールのソースコードが checkout されていることgo.sum に必要なエントリがすべて記録されていること(go mod tidy などで更新します)。不足していると解析が失敗します依存モジュールを取得できること(非公開のモジュールを使う場合は、 go build と同様の設定が必要です) |
| ネットワーク | installer.vuls.biz(スクリプトと vuls-reach のダウンロード)、rest.vuls.biz(解析結果のアップロード)、vuln.go.dev(Go 脆弱性データベース)に接続できることモジュールキャッシュにない依存モジュールや Go toolchain をダウンロードするため、Go の設定( GOPROXY、GOSUMDB)に従った接続先に接続できること。既定の設定では、Go のモジュールプロキシ(proxy.golang.org)と、プロキシから取得できないモジュールのリポジトリ(GitHub など)です |
手順1. サーバ UUID と applicationId を確認する#
スクリプトには、解析結果を登録するアプリケーションの ID(applicationId)と、そのアプリケーションが属するサーバのサーバ UUID を指定します。
サーバ UUID の確認方法は「UUIDの取得方法」を参照してください。
applicationId は、次のどちらかの方法で確認します。
- FutureVuls API の
GET /v1/lockfilesで取得するfilterServerIDに対象サーバのサーバ ID を指定して実行します(「serverIDの取得方法」)filterPathに LockFile のパス(登録名)を指定すると、そのアプリケーションだけが返ります。登録名との完全一致で、先頭の/の有無も区別します- レスポンスの
lockfilesのうち、解析したいアプリケーションの要素のidが applicationId です。pathはアプリケーションの登録名です - スキャンや LockFile の登録で登録したアプリケーションでは、
pathが解析したいgo.modまたはgo.sumのパスと一致する要素を選びます - SBOM のアプリケーションでは、
pathが<名前> | <SBOM の UUID>の形式です。解析したい Go アプリケーション(バイナリなど)の要素を選びます。その ID と、ソースコードの Go モジュールのgo.modまたはgo.sumのパスを組にして指定します - 見つからない場合は
filterPathを外して一覧から探します。既定では 20 件ずつ返されます。limit(最大 1000)とpageで取得する範囲を指定できます
- FutureVuls の画面で確認する
- サーバタブで対象のサーバを選択し、「アプリケーション」タブから解析したいアプリケーションを選択します
- 3 ペイン目の上部に表示されるタイトル(例:
applicationLibrary #123456)の、#に続く数字が applicationId です
curl -s -G -H 'accept: application/json' -H 'Authorization: <API トークン>' \
--data-urlencode 'filterServerID=<サーバ ID>' \
--data-urlencode 'filterPath=<LockFile のパス>' \
'https://rest.vuls.biz/v1/lockfiles'
手順2. 環境変数を設定する#
スクリプトは次の環境変数を読み込みます。
| 環境変数 | 説明 | 必須 |
|---|---|---|
VULS_SAAS_TOKEN |
API 権限が「読み込み、更新」以上のグループトークン | ✅ |
VULS_SERVER_UUID |
対象アプリケーションが属するサーバのサーバ UUID | ✅ |
VULS_REACH_TARGETS |
解析対象の一覧。<applicationId>:<LockFile のパス> を , または改行で区切って並べる例: 123456:services/api/go.mod,123457:tools/cli/go.mod |
✅ |
VULS_SAAS_PROXY |
プロキシサーバ(例:http://proxy.example.com:8080)。スクリプトはこの値を http_proxy と https_proxy に設定するため、vuls-reach と Go コマンドの通信もプロキシを経由しますスクリプト自体のダウンロード(手順3の curl)には適用されません。CI 側のプロキシ設定(https_proxy など)を使ってください |
トークンの管理
VULS_SAAS_TOKEN を使うと、指定したグループに対して FutureVuls API の更新操作ができます。
CI の暗号化されたストア(GitHub Actions の Secrets など)で保持し、CI のログやリポジトリに平文で残さないでください。
VULS_REACH_TARGETS の書き方#
- LockFile のパスは、スクリプトを実行するディレクトリ(通常は CI で checkout したリポジトリのルート)からの相対パスで書き、アプリケーションの登録名と一致させます(後述)。絶対パスは、同じ絶対パスで登録されたアプリケーション(例:エージェントのスキャンで登録された
/opt/app/go.mod)にだけ使えます - LockFile のファイル名は
go.modまたはgo.sumにしてください。スクリプトは LockFile があるディレクトリを解析します - Go モジュールごとに 1つの要素を書きます。同じ applicationId を 2 回以上書くことはできません
- LockFile のパスにはカンマ(
,)を含められません
LockFile のパスは、アプリケーションの登録内容と一致させる必要があります。
- SBOM 以外で登録したアプリケーションでは、LockFile のパスが登録名(
GET /v1/lockfilesのpath)と一致する必要があります。先頭の/や./の有無は区別しません - サーバ上の絶対パス(例:
/opt/app/go.mod)で登録されたアプリケーションでは、スクリプトを実行するディレクトリからの相対パスopt/app/go.mod(先頭の/を除いたパス)か、CI のホスト上の絶対パス/opt/app/go.modに LockFile を置き、そのパスを指定してください - SBOM のアプリケーションでは、最初にアップロードしたときの LockFile のパスが記録されます。以降は同じパスを指定してください
- SBOM のアプリケーションのうち
Go application(GET /v1/lockfilesのpathはGo application | <SBOM の UUID>)は、解析の対象にできません。パスが不明な Go のパッケージをまとめたアプリケーションで、複数のプログラムの依存ライブラリが混ざっている可能性があるためです
スクリプトは、解析を始める前に applicationId と LockFile の組をログに出力します。 組み合わせの取り違えは FutureVuls 側で検出できない場合があるため、初回の実行時にログで確認してください。
手順3. CI にスクリプトを組み込む#
スクリプトをダウンロードしてから実行します。
curl -fsSL -o vuls-reach-light.sh https://installer.vuls.biz/vuls-reach-light.sh
bash vuls-reach-light.sh scan
curl の出力を bash にパイプで渡さないでください
curl ... | bash の形で実行すると、ダウンロードに失敗したときに bash が空の入力を受け取り、終了コード 0 で終了します。
この場合、解析もアップロードも行われないまま CI が成功扱いになります。
GitHub Actions の例#
依存ライブラリのスキャン(「CI/CDパイプラインに組み込む」)の後に、同じパイプラインで到達可能性を解析する例です。
name: FutureVuls library scan and reachability analysis
on:
push:
branches:
- main
permissions:
contents: read
jobs:
futurevuls:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: go.mod
- name: Scan libraries
env:
VULS_SAAS_GROUPID: ${{ secrets.VULS_SAAS_GROUPID }}
VULS_SAAS_TOKEN: ${{ secrets.VULS_SCAN_TOKEN }}
TARGET_LIBRARY: ${{ github.workspace }}
VULS_SAAS_UUID: ${{ secrets.VULS_SERVER_UUID }}
run: |
curl -fsSL -o vuls-trivy-light.sh https://installer.vuls.biz/vuls-trivy-light.sh
bash vuls-trivy-light.sh inst
- name: Wait for the scan result to be imported
# 待機時間は、一般的な取り込み時間を目安にした値です。環境に合わせて調整してください
run: sleep 180
- name: Reachability analysis
env:
VULS_SAAS_TOKEN: ${{ secrets.VULS_REACH_TOKEN }}
VULS_SERVER_UUID: ${{ secrets.VULS_SERVER_UUID }}
VULS_REACH_TARGETS: "123456:go.mod"
run: |
curl -fsSL -o vuls-reach-light.sh https://installer.vuls.biz/vuls-reach-light.sh
bash vuls-reach-light.sh scan
VULS_SCAN_TOKENにはスキャン権限のあるグループトークンを、VULS_REACH_TOKENには API 権限が「読み込み、更新」以上のグループトークンを設定します。両方の権限を持つトークンであれば、同じトークンを使えますVULS_REACH_TARGETSの123456は、手順1で確認した applicationId に置き換えてください- 初回は、スキャンでアプリケーションが登録された後に applicationId を確認し、
VULS_REACH_TARGETSを設定してください - スキャン結果は、スキャンのステップが終わった後に FutureVuls 側で非同期に取り込まれます。このため、到達可能性解析の前に少し待機してください。待機が短いと、アップロードが失敗することがあります(
レポートの行がこのアプリケーションの検知済みパッケージと 1 件も一致しません。…など)。混雑時は取り込みに時間がかかることがあります。その場合は到達可能性解析を再実行してください。失敗した場合も、次回の実行で回復します
実行結果の確認#
解析結果のアップロードに成功すると、CI のログに次のメッセージが出力されます。
Task list, CSV exports, and the task list API can take several minutes to reflect the result (task detail is updated immediately)
タスク詳細には、アップロードの直後に反映されます。 タスク一覧、CSV レポート、FutureVuls API のタスク一覧には、反映まで時間がかかります。 結果の見方は「結果の見方」を参照してください。
運用上の注意#
- スクリプトは、実行のたびに最新の
vuls-reachをダウンロードします。vuls-reachのバージョンは指定できません - 到達可能性解析は、スキャンの後に、スキャン結果が取り込まれるまで少し待ってから実行してください。依存ライブラリのバージョンを上げた直後は、新しいバージョンがスキャンで検知されるまでアップロードが失敗することがあります。失敗した場合も前回の解析結果は残り、次回の実行で回復します
- 同じサーバのスキャン結果の取り込みや、Amazon Inspector 連携の定期スキャン(1日1回)と同時に実行すると、アップロードが一時的に失敗することがあります。CI の実行時刻は、これらと重ならないように設定してください
- 次の場合は、アプリケーションが削除されるか新しい ID で登録し直され、それまでの解析結果も削除されます。新しい applicationId を確認して、
VULS_REACH_TARGETSを更新してください- アプリケーションの削除と再登録
- SBOM の削除と再登録
- リポジトリ内での LockFile の移動、またはファイル名の変更(スキャンで登録されたアプリケーションの場合)
- スキャンで登録されたアプリケーションの名前を、画面または FutureVuls API で変更した。次のスキャンで元の名前のアプリケーションが新しい ID で登録され、名前を変更したアプリケーションは削除されます
- SBOM の更新や Amazon Inspector SBOM のインポートで、アプリケーションが SBOM に含まれなくなった。Amazon Inspector SBOM のインポートでは、同じ ECR リポジトリの別のイメージ(別のタグなど)が取り込まれた場合も含みます
- SBOM のアプリケーションは、到達可能性解析の結果を最初にアップロードしたときの LockFile のパスに固定されます。リポジトリ内で LockFile を移動しても ID は変わりませんが、新しいパスではアップロードが失敗します(
lockfile の指定がアプリケーションと一致しません。…)。SBOM の更新ではパスを変更できません。「SBOM の LockFile を移動した場合」を参照してください - LockFile の登録で登録したアプリケーションなど、LockFile の内容が FutureVuls に登録されているアプリケーションは、名前を変更しても ID と解析結果は変わりません。リポジトリ内で LockFile を移動したときは、アプリケーションの名前を新しいパスに変更してください。名前を変更したら、
VULS_REACH_TARGETSの LockFile のパスを新しい名前に合わせてください
SBOM の LockFile を移動した場合#
まず、CI 上で LockFile と解析対象のソースコードを、最初の解析時と同じパスで参照できるように配置してください。
VULS_REACH_TARGETS には、最初のアップロード時の LockFile パスと既存の applicationId を指定し、解析を再実行してください。
新しいパスに変更する必要がある場合、手動でインポートしたアプリケーション SBOM は、削除して登録し直すことができます。
削除すると、その SBOM に含まれるアプリケーションと解析結果も削除されます。
再登録後は、新しい applicationId と新しい LockFile パスを VULS_REACH_TARGETS に設定してください。
サーバ SBOM や自動生成された SBOM は、SBOM 単体では削除できません。 元のパスでの解析を続けられない場合は、サポートへお問い合わせください。
終了コードと再試行#
スクリプトは、VULS_REACH_TARGETS の対象を先頭から 1つずつ解析し、アップロードします。
1つの対象が失敗しても、残りの対象の処理は続けます。
最後に対象ごとの結果をログに出力し、次の終了コードで終了します。
| 終了コード | 意味 |
|---|---|
| 0 | すべての対象のアップロードに成功した |
| 1 | 失敗した対象が 1つ以上ある、または準備の段階(環境変数の確認、vuls-reach のダウンロードなど)で失敗した |
| 2 | 引数が scan でない |
解析またはアップロードに失敗しても、FutureVuls に登録済みの解析結果は変更されません。
次の場合、スクリプトは同じ解析結果を数秒の間隔を空けて自動で再送します。 再送は最大 2 回(合計 3 回)です。
- 一時的なエラー(「サーバの到達可能性データが更新中です。しばらく待ってから再実行してください」など)が返された
- HTTP 502、503、504 が返された(メンテナンス中など)
- 応答がなかった(接続できなかった場合など)。ただし、1 回の送信が 300 秒を超えて打ち切られた場合は再送しません
3 回とも失敗した場合、その対象は失敗になります。 時間を置いて CI を再実行してください。 その他のエラーは再送しません。
トラブルシューティング#
アップロードに失敗すると、CI のログに FutureVuls からのエラーメッセージが出力されます。
| メッセージ | 原因 | 対処 |
|---|---|---|
許可されていない動作です |
トークンに更新の権限がない(API 権限が「読み込み」のグループトークン、グループセットトークン、オーガニゼーショントークン) | API 権限が「読み込み、更新」以上のグループトークンを指定してください |
| HTTP 401 | トークンが無効、トークンに API 権限がない、または CI の送信元 IP アドレスがオーガニゼーションの IP アドレスの制限で許可されていない | トークンの状態と API 権限を確認してください。IP アドレスの制限を設定している場合は、CI の送信元 IP アドレスを許可してください(「アクセス可能なIPアドレスを登録」) |
サーバが見つかりません |
VULS_SERVER_UUID のサーバが、トークンのグループにない |
サーバ UUID とトークンのグループを確認してください |
applicationId に一致するアプリケーションがありません。先に通常スキャンを実行し、GET /v1/lockfiles またはコンソールで id を確認してください |
applicationId のアプリケーションが、指定したサーバにない(ID の誤り、アプリケーションの削除など) | 手順1で applicationId を確認し直してください |
lockfile の指定がアプリケーションと一致しません。VULS_REACH_TARGETS の applicationId と lockfile パスの対応を確認してください |
LockFile のパスがアプリケーションの登録名と一致しない、SBOM のアプリケーションで最初にアップロードしたときのパスと異なる、SBOM の Go application を指定した、など |
VULS_REACH_TARGETS の applicationId と LockFile のパスの組を確認してください。Go application は解析の対象にできません(「VULS_REACH_TARGETS の書き方」) |
レポートの行がこのアプリケーションの検知済みパッケージと 1 件も一致しません。applicationId の指定と、スキャンによるパッケージ検知が最新かを確認してください |
applicationId が別のアプリケーションを指している、または依存ライブラリの更新がまだスキャンで検知されていない | applicationId を確認してください。依存ライブラリを更新した場合は、スキャンの結果が反映された後に再実行してください |
CSIRT オプションが有効でないため、アクセスすることができません。 |
オーガニゼーションが CSIRT プランを契約していない | 本機能は CSIRT プランを契約しているオーガニゼーションでご利用いただけます |
レポートのサイズが上限(30 MB)を超えています |
1つのアプリケーションの解析結果のレポートが 30 MB を超えている | CI のログのメッセージを添えて、サポートへお問い合わせください |
より新しい実行のレポートが既に登録されています(runStartedAt が古い) |
同じアプリケーションについて、後から開始した CI の実行のレポートが先に登録された(CI の並列実行など) | 対処は不要です。新しい実行の結果が表示されています |
| 上記以外のメッセージ | ー | 時間を置いて再実行してください。続く場合は、CI のログのメッセージを添えてサポートへお問い合わせください |