Skip to content

Latest commit

 

History

History
162 lines (120 loc) · 9.09 KB

File metadata and controls

162 lines (120 loc) · 9.09 KB

Introduction

The CreateOTAUpdate operation is used by the AWS IoT console, the AWS CLI and the AWS SDKs to create AWS IoT Over the Air (OTA) updates.

At the time of writing, the CreateOTAUpdate operation does not support the following advanced job configuration features:

The purpose of this repository is to demonstrate an alternate method of creating an OTA update that can utilize these advanced job configuration features.

CreateOTAUpdate Deconstructed

AWS IoT OTA update is a feature built on top of AWS IoT Jobs. An OTA update is a job, but with a pre-defined job document. The CreateOTAUpdate API operation is an integrated operation that bundles several API operations into a single call. Depending on the parameters you pass, CreateOTAUpdate performs the following steps:

  1. If the user does NOT use custom signing, CreateOTAUpdate calls StartingSigningJob and DescribeSigningJob to sign a firmware binary file (or files) and places the signed result into an S3 bucket.
  2. If the user has NOT already created a stream, CreateOTAUpdate calls CreateStream to create an MQTT file stream for the firmware binary file in S3.
  3. Assembles an appropriate job document based on earlier steps.
  4. Uses CreateJob to create an AWS IoT Job.

You can use the knowledge of how CreateOTAUpdate is composed, to create your own jobs that are equivalent to an OTA update. This gives you access to all of the advanced job configurations that are exposed by the CreateJob operation. This repository provides an example of precisely that.

Requirements

The example in this repository is a Python script. Package dependencies can be resolved as follows:

pip3 install -r requirements.txt

Please consider to use a virtual environment.

Boto3 is included in the package dependencies and therefore your machine requires appropriate credentials.

Usage

The create_ota_update.py script creates an IoT job that is the equivalent of an OTA update. The usage is shown below.

@ubuntu:~/git/create-ota-update-deconstructed$ python create_ota_update.py -h
usage: create_ota_update.py [-h] binary bucket signingProfile otaRole thingGroup jobId

Create and execute AWS IoT OTA update directly using jobs

positional arguments:
  binary          Name of the binary file (object key) in the S3 bucket
  bucket          Name of the bucket
  signingProfile  Name of the signing profile
  otaRole         Name of the IAM role that grants IoT access to S3, IoT jobs and code signing
  thingGroup      Name of the target Thing group
  jobId           ID of the job to be created ('AFR_OTA-' will be prepended)

optional arguments:
  -h, --help      show this help message and exit

Equivalent CreateOTAUpdate

The steps implemented in create_ota_update.py are the equivalent of a CreateOTAUpdate call constructed as follows (but with retries and scheduling added):

    response = iot.create_ota_update(
        otaUpdateId = 'MyJobId',
        targets = ['arn:aws:iot:us-east-1:012345678901:thinggroup/MyThingGroupName'],
        files = [
            {
                'fileLocation': {
                    's3Location': {
                        'bucket': 'MyBucketName',
                        'key': 'MyBinaryFileName',
                        'version': '<version>'
                    }
                },
                'codeSigning': {
                    'startSigningJobParameter': {
                        'signingProfileName': 'MySigningProfileName'
                    }
                }
            }
        ],
        awsJobTimeoutConfig = {
            'inProgressTimeoutInMinutes': 10
        },
        protocols = ['MQTT'],
        roleArn = 'arn:aws:iam::012345678901:role/MyIoTOTARoleName'
    )

The following scenario is demonstrated:

  1. MQTT as the file transfer protocol.
  2. An unsigned binary file in S3 (rather than a pre-existing stream or a previously signed file).
  3. Signing performed using a signing profile (rather than a certificate or custom signing).
  4. Each device having 10 minutes to complete a job execution before it times out.
  5. Number of retries set to 3.
  6. A scheduled job that starts one hour in the future and ends an hour later.

The example can of course be adjusted to cater for different options and to use additional advanced job configuration such as recurring maintenance windows and software catalog package versions.

Deviations

The resultant jobs and artifacts deviate from CreateOTAUpdate only in the fact that no OTAUpdate resource is created. Thus the ListOTAUpdates, GetOTAUpdate and DeleteOTAUpdate operations cannot be used to manage the resultant job.

Signed Object

The signing job creates a signed object in S3 which is just a JSON document of the following structure:

{
    "rawPayloadSize":366816,
    "signature":"MEUCIQCuwPQBzaKu9Rp4v4BwGa7T4h3JK71KwDJ3LZoSvYdCsQIgclDeaFE+5NeJL3cydMiuKM909bprNXfCZcneIuiSZrk=",
    "signatureAlgorithm":"SHA256withECDSA",
    "payload":"U0ZVTQEAAQDgkAUAAAAAAOCQBQA+0Ac4CWNDyJ0zb+koNKotI2yKdpcEQX6MT3ozwlfdAD7QBzgJY0PInTNv6Sg0qi0jbIp2lwRBfoxPejPCV90AAAAAAAAAAAAAAAAAAAAAAAAAAAAA...."
}

All fields of course depend on the file being signed and the signing algorithm used.

Note that CreateOTAUpdate overwrites the signed object with a copy of the raw binary file object. Thus the object has two versions; the newer version is the raw binary, the older version is the above JSON file (with base64 encoded firmware). The stream is created from the raw binary (the newer version of the object).

Job Document

The resulting job document has a structure similar to:

{
  "afr_ota": {
    "protocols": [
      "MQTT"
    ],
    "streamname": "AFR_OTA-6e01bdb2-5057-4606-8966-b1bf8028416f",
    "files": [
      {
        "filepath": null,
        "filesize": 366816,
        "fileid": 0,
        "certfile": "foobar",
        "update_data_url": null,
        "auth_scheme": null,
        "sig-sha256-ecdsa": "MEUCIQCuwPQBzaKu9Rp4v4BwGa7T4h3JK71KwDJ3LZoSvYdCsQIgclDeaFE+5NeJL3cydMiuKM909bprNXfCZcneIuiSZrk="
      }
    ]
  }
}

The signature (sig-sha256-ecdsa in this case) and filesize values are taken from the signed object JSON. Note that the key of the signature depends on the signing algorithms used.

The auth_scheme and update_data_url are null when the protocol is MQTT.

The filepath value is device specific and not used on most devices.

The certfile value should match the certname value that was used when creating the signing profile.

Security

See CONTRIBUTING for more information.

License

This library is licensed under the MIT-0 License. See the LICENSE file.