次の方法で共有


クイック スタート: Python を使用して、ファームウェア分析にファームウェア イメージをアップロードする

この記事では、Python スクリプトを使用してファームウェア分析にファームウェア イメージをアップロードする方法について説明します。

ファームウェア分析は、ファームウェア イメージを分析し、ファームウェア イメージのセキュリティの脆弱性を理解できるようにするツールです。

前提条件

このクイック スタートでは、ファームウェア分析に関する基本的な理解を前提としています。 詳細については、「デバイス ビルダーのファームウェア分析」を参照してください。 サポートされているファイル システムの一覧については、「ファームウェア分析についてよく寄せられる質問」を参照してください。

環境を準備する

  1. このパッケージを使用するには、Python バージョン 3.8 以降が必要です。 Python のバージョンを確認するには、コマンド python --version を実行します。
  2. Azure サブスクリプション ID、イメージをアップロードするリソース グループの名前、ワークスペース名、アップロードするファームウェア イメージの名前をメモします。
  3. お使いの Azure アカウントに、Azure サブスクリプションのファームウェア イメージをファームウェア分析にアップロードするために必要なアクセス許可があることを確認します。 ファームウェア イメージをアップロードするには、サブスクリプションまたはリソース グループのレベルで所有者、共同作成者、セキュリティ管理者、またはファームウェア分析管理者である必要があります。 詳しくは、ファームウェア分析のロール、スコープ、機能に関する記事を参照してください。
  4. ファームウェア イメージが Python スクリプトと同じディレクトリに保存されていることを確認します。
  5. このスクリプトを実行するために必要なパッケージをインストールします。
    pip install azure-mgmt-iotfirmwaredefense
    pip install azure-identity
    
  6. az login コマンドを実行して Azure アカウントにログインします。

次の Python スクリプトを実行します

次の Python スクリプトを .py ファイルにコピーし、ファームウェア イメージと同じディレクトリに保存します。 subscription_id 変数を Azure サブスクリプション ID に、resource_group_name をファームウェア イメージをアップロードするリソース グループの名前に、firmware_file を Python スクリプトと同じディレクトリに保存されているファームウェア イメージの名前に置き換えます。

from azure.identity import AzureCliCredential
from azure.mgmt.iotfirmwaredefense import *
from azure.mgmt.iotfirmwaredefense.models import *
from azure.core.exceptions import *
from azure.storage.blob import BlobClient
import uuid
from time import sleep
from halo import Halo
from tabulate import tabulate

subscription_id = "subscription-id"
resource_group_name = "resource-group-name"
workspace_name = "default"
firmware_file = "firmware-image-name"

def main():
    firmware_id = str(uuid.uuid4())
    fw_client = init_connections(firmware_id)
    upload_firmware(fw_client, firmware_id)
    get_results(fw_client, firmware_id)

def init_connections(firmware_id):
    spinner = Halo(text=f"Creating client for firmware {firmware_id}")
    cli_credential = AzureCliCredential()
    client = IoTFirmwareDefenseMgmtClient(cli_credential, subscription_id, 'https://management.azure.com')
    spinner.succeed()
    return client

def upload_firmware(fw_client, firmware_id):
    spinner = Halo(text="Uploading firmware to Azure...", spinner="dots")
    spinner.start()
    token = fw_client.workspaces.generate_upload_url(resource_group_name, workspace_name, {"firmware_id": firmware_id})
    fw_client.firmwares.create(resource_group_name, workspace_name, firmware_id, {"properties": {"file_name": firmware_file, "vendor": "Contoso Ltd.", "model": "Wifi Router", "version": "1.0.1", "status": "Pending"}})
    bl_client = BlobClient.from_blob_url(token.url)
    with open(file=firmware_file, mode="rb") as data:
        bl_client.upload_blob(data=data)
    spinner.succeed()

def get_results(fw_client, firmware_id):
    fw = fw_client.firmwares.get(resource_group_name, workspace_name, firmware_id)

    spinner = Halo("Waiting for analysis to finish...", spinner="dots")
    spinner.start()
    while fw.properties.status != "Ready":
        sleep(5)
        fw = fw_client.firmwares.get(resource_group_name, workspace_name, firmware_id)
    spinner.succeed()

    print("-"*107)

    summary = fw_client.summaries.get(resource_group_name, workspace_name, firmware_id, summary_name=SummaryName.FIRMWARE)
    print_summary(summary.properties)
    print()

    components = fw_client.sbom_components.list_by_firmware(resource_group_name, workspace_name, firmware_id)
    if components is not None:
        print_components(components)
    else:
        print("No components found")

def print_summary(summary):
    table = [[summary.extracted_size, summary.file_size, summary.extracted_file_count, summary.component_count, summary.binary_count, summary.analysis_time_seconds, summary.root_file_systems]]
    header = ["Extracted Size", "File Size", "Extracted Files", "Components", "Binaries", "Analysis Time", "File Systems"]
    print(tabulate(table, header))

def print_components(components):
    table = []
    header = ["Component", "Version", "License", "Paths"]
    for com in components:
        table.append([com.properties.component_name, com.properties.version, com.properties.license, com.properties.file_paths])
    print(tabulate(table, header, maxcolwidths=[None, None, None, 57]))

if __name__ == "__main__":
    exit(main())