|
| 1 | +--- |
| 2 | +title: "Quickstart: Upload firmware images to Defender for IoT Firmware Analysis using Python" |
| 3 | +description: "Learn how to upload firmware images for analysis using Python." |
| 4 | +author: karengu0 |
| 5 | +ms.author: karenguo |
| 6 | +ms.topic: quickstart |
| 7 | +ms.date: 04/10/2024 |
| 8 | + |
| 9 | +--- |
| 10 | + |
| 11 | +# Quickstart: Upload firmware images to Defender for IoT Firmware Analysis using Python |
| 12 | + |
| 13 | +This article explains how to use a Python script to upload firmware images to Defender for IoT Firmware Analysis. |
| 14 | + |
| 15 | +[Defender for IoT Firmware Analysis](/azure/defender-for-iot/device-builders/overview-firmware-analysis) is a tool that analyzes firmware images and provides an understanding of security vulnerabilities in the firmware images. |
| 16 | + |
| 17 | +## Prerequisites |
| 18 | + |
| 19 | +This quickstart assumes a basic understanding of Defender for IoT Firmware Analysis. For more information, see [Firmware analysis for device builders](/azure/defender-for-iot/device-builders/overview-firmware-analysis). For a list of the file systems that are supported, see [Frequently asked Questions about Defender for IoT Firmware Analysis](../../../articles/defender-for-iot/device-builders/defender-iot-firmware-analysis-faq.md#what-types-of-firmware-images-does-defender-for-iot-firmware-analysis-support). |
| 20 | + |
| 21 | +### Prepare your environment |
| 22 | + |
| 23 | +* Python version 3.8+ is required to use this package. Run the command `python --version` to check your Python version. |
| 24 | +* Make note of your Azure subscription ID, the name of your Resource Group where you'd like to upload your images, your workspace name, and the name of the firmware image that you'd like to upload. |
| 25 | +* Ensure that your Azure account has the necessary permissions to upload firmware images to Defender for IoT Firmware Analysis for your Azure subscription. You must be an Owner, Contributor, Security Admin, or Firmware Analysis Admin at the Subscription or Resource Group level to upload firmware images. For more information, visit [Defender for IoT Firmware Analysis Roles, Scopes, and Capabilities](/azure/defender-for-iot/device-builders/defender-iot-firmware-analysis-rbac#defender-for-iot-firmware-analysis-roles-scopes-and-capabilities). |
| 26 | +* Ensure that your firmware image is stored in the same directory as the Python script. |
| 27 | +* Install the packages needed to run this script: |
| 28 | + ```python |
| 29 | + pip install azure-mgmt-iotfirmwaredefense |
| 30 | + pip install azure-identity |
| 31 | + ``` |
| 32 | +* Log in to your Azure account by running the command [`az login`](/cli/azure/reference-index?#az-login). |
| 33 | + |
| 34 | +## Run the following Python script |
| 35 | + |
| 36 | +Copy the following Python script into a `.py` file and save it to the same directory as your firmware image. Replace the `subscription_id` variable with your Azure subscription ID, `resource_group_name` with the name of your Resource Group where you'd like to upload your firmware image, and `firmware_file` with the name of your firmware image, which is saved in the same directory as the Python script. |
| 37 | + |
| 38 | +```python |
| 39 | +from azure.identity import AzureCliCredential |
| 40 | +from azure.mgmt.iotfirmwaredefense import * |
| 41 | +from azure.mgmt.iotfirmwaredefense.models import * |
| 42 | +from azure.core.exceptions import * |
| 43 | +from azure.storage.blob import BlobClient |
| 44 | +import uuid |
| 45 | +from time import sleep |
| 46 | +from halo import Halo |
| 47 | +from tabulate import tabulate |
| 48 | + |
| 49 | +subscription_id = "subscription-id" |
| 50 | +resource_group_name = "resource-group-name" |
| 51 | +workspace_name = "default" |
| 52 | +firmware_file = "firmware-image-name" |
| 53 | + |
| 54 | +def main(): |
| 55 | + firmware_id = str(uuid.uuid4()) |
| 56 | + fw_client = init_connections(firmware_id) |
| 57 | + upload_firmware(fw_client, firmware_id) |
| 58 | + get_results(fw_client, firmware_id) |
| 59 | + |
| 60 | +def init_connections(firmware_id): |
| 61 | + spinner = Halo(text=f"Creating client for firmware {firmware_id}") |
| 62 | + cli_credential = AzureCliCredential() |
| 63 | + client = IoTFirmwareDefenseMgmtClient(cli_credential, subscription_id, 'https://management.azure.com') |
| 64 | + spinner.succeed() |
| 65 | + return client |
| 66 | + |
| 67 | +def upload_firmware(fw_client, firmware_id): |
| 68 | + spinner = Halo(text="Uploading firmware to Azure...", spinner="dots") |
| 69 | + spinner.start() |
| 70 | + token = fw_client.workspaces.generate_upload_url(resource_group_name, workspace_name, {"firmware_id": firmware_id}) |
| 71 | + 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"}}) |
| 72 | + bl_client = BlobClient.from_blob_url(token.url) |
| 73 | + with open(file=firmware_file, mode="rb") as data: |
| 74 | + bl_client.upload_blob(data=data) |
| 75 | + spinner.succeed() |
| 76 | + |
| 77 | +def get_results(fw_client, firmware_id): |
| 78 | + fw = fw_client.firmwares.get(resource_group_name, workspace_name, firmware_id) |
| 79 | + |
| 80 | + spinner = Halo("Waiting for analysis to finish...", spinner="dots") |
| 81 | + spinner.start() |
| 82 | + while fw.properties.status != "Ready": |
| 83 | + sleep(5) |
| 84 | + fw = fw_client.firmwares.get(resource_group_name, workspace_name, firmware_id) |
| 85 | + spinner.succeed() |
| 86 | + |
| 87 | + print("-"*107) |
| 88 | + |
| 89 | + summary = fw_client.summaries.get(resource_group_name, workspace_name, firmware_id, summary_name=SummaryName.FIRMWARE) |
| 90 | + print_summary(summary.properties) |
| 91 | + print() |
| 92 | + |
| 93 | + components = fw_client.sbom_components.list_by_firmware(resource_group_name, workspace_name, firmware_id) |
| 94 | + if components is not None: |
| 95 | + print_components(components) |
| 96 | + else: |
| 97 | + print("No components found") |
| 98 | + |
| 99 | +def print_summary(summary): |
| 100 | + 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]] |
| 101 | + header = ["Extracted Size", "File Size", "Extracted Files", "Components", "Binaries", "Analysis Time", "File Systems"] |
| 102 | + print(tabulate(table, header)) |
| 103 | + |
| 104 | +def print_components(components): |
| 105 | + table = [] |
| 106 | + header = ["Component", "Version", "License", "Paths"] |
| 107 | + for com in components: |
| 108 | + table.append([com.properties.component_name, com.properties.version, com.properties.license, com.properties.file_paths]) |
| 109 | + print(tabulate(table, header, maxcolwidths=[None, None, None, 57])) |
| 110 | + |
| 111 | +if __name__ == "__main__": |
| 112 | + exit(main()) |
| 113 | +``` |
| 114 | + |
0 commit comments