セキュリティ メタデータにアクセスしてパッケージを検証する

このページでは、assuredoss-metadata Cloud Storage バケットからセキュリティ メタデータにアクセスする方法について説明します。セキュリティ メタデータの説明については、セキュリティ メタデータ フィールドをご覧ください。

このページの内容は、Assured OSS のプレミアム ティアにのみ適用されます。無料ティアについては、Assured OSS の無料ティアで署名を検証するをご覧ください。

始める前に

認証を設定します

レガシーコードから

gcloud コマンドと curl コマンドのいずれかを使用して、メタデータをダウンロードできます。次の情報を使用して、両方の URL を作成します。

  • Language: javapython、または javascript。値は小文字にする必要があります。
  • Package_ID: Java の場合は groupId:artifactId、Python の場合は packageName、JavaScript の場合は @org-name/package-name@username/package-name、または package-name のいずれかです。値は小文字にする必要があります。
  • Version: パッケージのバージョン。

URL は次の形式にする必要があります。

gcloud

gs://assuredoss-metadata/language/package_id/version/metadata.json

URL は小文字にする必要があります。

Python の URL の例: gs://assuredoss-metadata/python/blessed/1.20.0/metadata.json

Java の URL の例: gs://assuredoss-metadata/java/org.apache.logging.log4j:log4j-core/2.17.1/metadata.json

JavaScript の URL の例: gs://assuredoss-metadata/javascript/@stoplight/spectral-core/0.0.0/metadata.json

curl

https://storage.googleapis.com/assuredoss-metadata/language/package_id/version/metadata.json

URL は小文字にする必要があります。

Python の URL の例: https://storage.googleapis.com/assuredoss-metadata/python/blessed/1.20.0/metadata.json

Java の URL の例: https://storage.googleapis.com/assuredoss-metadata/java/org.apache.logging.log4j:log4j-core/2.17.1/metadata.json

JavaScript の URL の例: https://storage.googleapis.com/assuredoss-metadata/javascript/@stoplight/spectral-core/0.0.0/metadata.json

  1. メタデータをダウンロードします。

gcloud

gcloud storage cp "gs://assuredoss-metadata/language/package_id/version/metadata.json" outputFolderLocation

curl

curl -H "Authorization: Bearer $(gcloud auth print-access-token)" -L https://storage.googleapis.com/assuredoss-metadata/language/package_id/version/metadata.json -o metadata.json

これで署名を検証できるようになりました。選択肢は 2 つです。

ダウンロードしたパッケージの署名を、aoss-verifier ツールを使用して検証する

aoss-verifier ツールを使用してパッケージのメタデータを確認します。

このツールを使用する前に、Go をインストールしてください。

  1. aoss-verifier ツールをインストールします。

  2. $(go env GOPATH)/bin をエクスポートします。

  3. aoss-verifier verify-metadata コマンドを実行します。

    aoss-verifier verify-metadata \
       --metadata_type TYPE \
       --language LANGUAGE \
       --package_id PACKAGE_ID \
       --version VERSION \
       [--disable_certificate_verification] \
       [--temp_downloads_path TEMP_DOWNLOADS_DIR_PATH] \
       [--disable_deletes]
    

    次のように置き換えます。

    • TYPE: 使用できる値は premiuminfo です。
    • LANGUAGE: パッケージの言語。値は小文字にする必要があります。
    • PACKAGE_ID: Java の場合、形式は groupId:artifactId です。Python の場合、形式は packageName です。値は小文字にする必要があります。
    • VERSION: パッケージのバージョン

    --disable_certificate_verification はオプションのフラグです。使用されている場合、証明書チェーンを介してリーフ証明書とルート証明書の照合をスキップします。

    --temp_downloads_path は、ファイルをダウンロードするパスを設定するオプションのフラグです(TEMP_DOWNLOADS_DIR_PATH を置き換えます)。フラグが設定されていない場合、ファイルを tmp_downloads フォルダにダウンロードします。

    --disable_deletes は、ダウンロードしたファイルを保持するオプションのフラグです。デフォルトでは、ツールはダウンロードしたすべてのファイルをクリーンアップします。

詳細については、README をご覧ください。

ダウンロードしたパッケージの署名を手動で検証する

アーティファクト署名を検証できるのは、Assured OSS によって安全にビルドされたバイナリに対してに限られます。プロキシ経由で Assured OSS から提供されるバイナリは検証できません。

署名を手動で検証するには、さまざまなツールを使用できます。以下の手順では、gcloud CLI、OpenSSL(バージョン 3.0.1 以降)、jq(1.7.1 以降)を使用して、Linux の署名を検証します。

  1. メタデータ ファイルをダウンロードしますCloud Storage を使用したメタデータへのアクセスの説明にあるように、メタデータ ファイルには、buildInfo フィールド内に SBOM フィールドが含まれています。SBOM には、署名を表すアノテーションとともにビルドされたアーティファクト(たとえば、JAR や EGG ファイル)が含まれます。このアーティファクトから SPDX ID を特定できます。

    たとえば、アーティファクト名が artifact_name の場合、spdx_idSPDXRef-Package-artifact_name です。gradio-3.30.0-py3-none-any.whl という名前のパッケージを検証する場合、spdx_idSPDXRef-Package-gradio-3.30.0-py3-none-any.whl です。

  2. メタデータ ファイルから SHA-256 ダイジェストを抽出します。

    cat METADATA_FILENAME | jq -rj '.buildInfo' | jq -rj '.sbom' | jq -rj '.packages' | jq '.[] | select(.SPDXID=="SPDX_ID")' | jq -rj '.annotations[0].comment' | jq -rj '.digest[0].digest' | cut -d ' ' -f1 > expectedDigest.txt
    

    次のように置き換えます。

    • METADATA_FILENAME: セキュリティ メタデータ ファイルの名前。

    • SPDX_ID: SPDX の識別子。

  3. アーティファクト ダイジェストを計算します。

    sha256sum ARTIFACT_FILE | cut -d ' ' -f1 > actualDigest.txt
    

    ARTIFACT_FILE は、アーティファクト ファイルの名前に置き換えます。

  4. 両者の差異を確認します。

    diff actualDigest.txt expectedDigest.txt
    

    差異がない場合、出力はありません。

  5. フィールドのダイジェストを .bin ファイルに抽出します。

    cat METADATA_FILENAME | jq -rj '.buildInfo' | jq -rj '.sbom' | jq -rj '.packages' | jq '.[] | select(.SPDXID=="SPDX_ID")' | jq -rj '.annotations[0].comment' | jq -rj '.digest[0].digest' | cut -d ':' -f2 | xxd -r -p > digest.bin
    
  6. ダイジェストの署名を .sig ファイルに抽出します。

    cat METADATA_FILENAME | jq -rj '.buildInfo' | jq -rj '.sbom' | jq -rj '.packages' | jq '.[] | select(.SPDXID=="SPDX_ID")' | jq -rj '.annotations[0].comment' | jq -rj '.signature[0].signature' | xxd -r -p > sig.sig
    
  7. 公開証明書を .pem ファイルに抽出します。

    cat METADATA_FILENAME | jq -rj '.buildInfo' | jq -rj '.sbom' | jq -rj '.packages' | jq '.[] | select(.SPDXID=="SPDX_ID")' | jq -rj '.annotations[0].comment' | jq -rj '.certInfo.cert' | openssl x509 -pubkey -noout  > pubKey.pem
    
  8. 証明書を使用してダイジェストの署名を検証します。

    openssl pkeyutl -in digest.bin -inkey pubKey.pem -pubin -verify -sigfile sig.sig
    

    成功した場合、このコマンドは Signature Verified Successfully を返します。これで、証明書を検証できるようになりました。

  9. 公開証明書チェーンを .pem ファイルに抽出します。

    cat METADATA_FILENAME | jq -rj '.buildInfo' | jq -rj '.sbom' | jq -rj '.packages' | jq '.[] | select(.SPDXID=="SPDX_ID")' | jq -rj '.annotations[0].comment' | jq -rj '.certInfo.certChain' | openssl x509 -pubkey -noout  > pubKeyChain.pem
    
  10. ルート証明書(次のコマンドの ca.crt)をダウンロードします。

    curl -o ca.crt https://privateca-content-6333d504-0000-2df7-afd6-30fd38154590.storage.googleapis.com/a2c725a592f1d586f1f8/ca.crt
    
  11. 証明書チェーンとルート証明書を使用して証明書を検証します。

    openssl verify -verbose -CAfile ca.crt -untrusted pubKeyChain.pem pubKey.pem
    

    成功した場合、このコマンドは pubKey.pem: OK を返します。

セキュリティ メタデータ フィールドの署名を検証する

セキュリティ メタデータ ファイルの次のフィールドの署名を個別に検証できます。

  • buildInfo
  • vexInfo
  • healthInfo(存在する場合)

フィールド内のデータは SHA-256 を使用してハッシュ化され、その後、ハッシュは ECDSAP256_DER アルゴリズムを使用して署名されます。証明書と証明書チェーンはメタデータ内で提供されるため、署名を検証できます。次のルート証明書を使用して証明書チェーンを検証します。

https://privateca-content-6333d504-0000-2df7-afd6-30fd38154590.storage.googleapis.com/a2c725a592f1d586f1f8/ca.crt

手動で署名を検証することも、Assured OSS 検証ツールを使用して署名を検証することもできます。

次の手順では、metadata.json ファイルの buildInfo フィールドの署名を手動で検証する方法について説明します。同様の手順を使用して、vexInfo フィールドまたは healthInfo フィールドの署名を検証できます。

署名はさまざまなツールを使用して検証できます。次の例では、gcloud CLI、OpenSSL(バージョン 3.0.1 以降)、jq(1.7.1 以降)を使用して、Linux システムの署名を検証します。

  1. フィールドの SHA-256 ダイジェストを生成します。

    cat metadata.json | jq -rj '.buildInfo' | sha256sum | cut -d ' ' -f1 > actualDigest.txt
    
  2. metadata.json ファイルにあるフィールドのダイジェストを抽出します。

    cat metadata.json | jq -rj '.buildInfoSignature.digest[0].digest' | cut -d ':' -f2 > expectedDigest.txt
    
  3. 2 つのダイジェストに差異がないか確認します。

    diff actualDigest.txt expectedDigest.txt
    

    差異がなければ、出力はありません。これが理想的なケースです。これで署名を検証できます。

  4. フィールドのダイジェストを .bin ファイルに抽出します。

    cat metadata.json | jq -rj '.buildInfoSignature.digest[0].digest' | cut -d ':' -f2 | xxd -r -p > digest.bin
    
  5. ダイジェストの署名を .sig ファイルに抽出します。

    cat metadata.json | jq -rj '.buildInfoSignature.signature[0].signature' | xxd -r -p > sig.sig
    
  6. 公開証明書を .pem ファイルに抽出します。

    cat metadata.json | jq -rj '.buildInfoSignature.certInfo.cert' | openssl x509 -pubkey -noout  > pubKey.pem
    
  7. 証明書を使用してダイジェストの署名を検証します。

    openssl pkeyutl -in digest.bin -inkey pubKey.pem -pubin -verify -sigfile sig.sig
    

    検証が成功すると、このコマンドは Signature Verified Successfully を返します。これで、証明書を検証できるようになりました。

  8. 公開証明書を .pem ファイルに抽出します。

    cat metadata.json | jq -rj '.buildInfoSignature.certInfo.cert' | openssl x509 -pubkey -noout  > pubKey.pem
    
  9. 公開証明書チェーンを .pem ファイルに抽出します。

    cat metadata.json | jq -rj '.buildInfoSignature.certInfo.certChain' | openssl x509 -pubkey -noout  > pubKeyChain.pem
    
  10. ルート証明書(次のコマンドの ca.crt)をダウンロードします。

    curl -o ca.crt https://privateca-content-6333d504-0000-2df7-afd6-30fd38154590.storage.googleapis.com/a2c725a592f1d586f1f8/ca.crt
    
  11. 証明書チェーンとルート証明書を使用して証明書を検証します。

    openssl verify -verbose -CAfile ca.crt -untrusted pubKeyChain.pem pubKey.pem
    

    成功した場合、コマンドは pubKey.pem: OK を返します。