OTA Connect Developer Guide

Add custom metadata fields to Targets metadata

In some cases, you might find it useful to include extra metadata about your software inside the signed Uptane metadata that OTA Connect delivers to your device. Some reasons you might want to do this include:

  • to provide installation instructions or scripts for an image that can’t or shouldn’t be included in the image itself

  • to add extra tracking fields for internal compliance or auditing

To accommodate this use case, you can manually manage your Uptane metadata and add custom fields to your targets.json file.

For more information on additional use cases which will require customization of the Targets metadata, please refer to the section 'Custom metadata about images' in the Uptane standard.

Prerequisites

For this to be useful, you will need to write a custom handler for the metadata you add, so building your own update client using libaktualizr is required. (Consult the Doxygen API reference for how to access custom metadata in-client.)

You will also need to have rotated your signing keys offline. The following instructions assume you have already done this, and know where to find your targets.json.

Anatomy of targets.json metadata

Your targets.json file includes:

  • A signatures block, containing key IDs and signatures generated over the signed block

  • A signed block, containing some necessary Uptane fields

  • Inside the signed block, a targets block, listing all of your software images. Each software image block (identified by its name and version) contains three objects:

    • hashes, which contains the sha256 hash of the software image

    • length, which is the size of the software image in bytes

    • custom, which contains other metadata that aktualizr uses. An example of the custom field is shown below:

      "custom": {
        "name": "aegisub-font",
        "version": "1",
        "hardwareIds": [
          "kmk-docker-debian"
        ],
        "targetFormat": null,
        "uri": null,
        "createdAt": "2018-08-20T09:28:27Z",
        "updatedAt": "2018-08-20T09:28:27Z"
      }

The custom object is where you can add metadata of your choice. Do not modify any of the existing values. Our recommended best practice is to add a new field namespaced to your organization or some other unique identifier, and put any custom sub-keys under that field, as in the example below:

"custom": {
  "name": "aegisub-font",
  "version": "1",
  "hardwareIds": [
    "kmk-docker-debian"
  ],
  "targetFormat": null,
  "uri": null,
  "createdAt": "2018-08-20T09:28:27Z",
  "updatedAt": "2018-08-20T09:28:27Z",
  "acme_inc_metadata": {
    "application_install_handler": "com.dockerconfig.packager",
    "build_correlation_id": "2ce4ebaf-b3ca-411b-977f-cd6b98065d88"
  }
}

Once you add your custom metadata, of course, the signatures will no longer be valid. You will need to sign the modified metadata using garage-sign:

garage-sign targets sign --repo myimagerepo --key-name mytargets

You can then upload your customized targets.json to OTA Connect as normal:

garage-sign targets push --repo myimagerepo
You also might want to add custom metadata while bitbaking. You can do this, for example, by modifying the IMAGE_CMD_garagesign function in image_types_ostree.bbclass. A detailed guide on how to accomplish this is out of our scope, however. Refer to the Yocto Reference Manual for further details.