Skip to content

RAUC usage example

This example shows how to create a product which enables RAUC signing. Also example signing operation is performed and the result is also verified.

This example uses the reference python client and the UI to perform different actions.

The example is divided to following stages:

  • How to get authentication token
  • Adding certificate profiles
  • Creating product
  • Signing RAUC bundles
  • Verifying RAUC bundle

Authentication

In order to use the reference python client a valid JWT token is needed. How to obtain one is explained in more detail in the authentication chapter. New token must be requested if the current token expires. ( roughly 1 hour of validity)

(venv) $ az login --allow-no-subscriptions --only-show-error
A web browser has been opened at https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize. Please continue the login in the web browser. If no web browser is available or if the web browser fails to open, use device code flow with `az login --use-device-code`.

[1]    N/A(tenant level account)  <redacted>  <redacted>

The default is marked with an *; the default tenant is '<redacted>' and subscription is 'N/A(tenant level account)' (<redacted>).

Select a subscription and tenant (Type a number or Enter for no changes): 1

Tenant: <redacted>
Subscription: N/A(tenant level account) (<redacted>)


(venv) $ az account get-access-token --resource api://<redacted>
{
  "accessToken": "<redacted>",
  "expiresOn": "2025-06-04 15:18:10.000000",
  "expires_on": 1749039490,
  "subscription": "<redacted>",
  "tenant": "<redacted>",
  "tokenType": "Bearer"
}
(venv) $ export TOKEN=<redacted>

Add profiles

RAUC signing is using a Certificate authority which is used as a trustpoint in the devices and a Code signing End-Entity issued under that CA to signing the RAUC bundles.

The example profiles were taken as base and modified for this example

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1/ profile add \
    -F rootca.yaml -N "Customer Root CA" -T ROOT
{
    "id": "321c7960-ec34-459d-bc5c-ee2399633922",
    "profile_name": "Customer Root C",
    "profile_type": 3,
    "profile_yaml": "IyBDb25maWcgZmlsZSBmb3IgdGhlIFJvb3QgcHJvZmlsZS4gRG8gbm90IHVzZSBUQUJTCi0tLQpOYW1lOiBHZW5lcmljIFJvb3QgQ0EKIyBEaXN0aW5ndWlzaGVkIG5hbWUgb2YgdGhlIENBCkROOgogICMgT3JnYW5pemF0aW9uOiAKICAjIE9yZ2FuaXphdGlvbmFsVW5pdDogCiAgQ291bnRyeTogRkkKICAjIFByb3ZpbmNlOgogICMgTG9jYWxpdHk6CiAgIyBTdHJlZXRBZGRyZXNzOgogICMgUG9zdGFsQ29kZToKICAjIFNlcmlhbE51bWJlcgogICMgQ29tbW9uTmFtZTogR2VuZXJpYyBSb290IENBCiMgRW5kRW50aXR5IGlzIDEsIFN1YiBDQSBwcm9maWxlIDIgLCBSb290IHByb2ZpbGUgMwpQcm9maWxlVHlwZTogMwojIFNpZ25hdHVyZUFsZ29yaXRobXMKIyAgU0hBMVdpdGhSU0EgPSAzCiMgIFNIQTI1NldpdGhSU0EgPSA0CiMgIFNIQTM4NFdpdGhSU0EgPSA1CiMgIFNIQTUxMldpdGhSU0EgPSA2CiMgIERTQVdpdGhTSEExID0gNwojICBEU0FXaXRoU0hBMjU2ID0gOAojICBFQ0RTQVdpdGhTSEExID0gOQojICBFQ0RTQVdpdGhTSEEyNTYgPSAxMAojICBFQ0RTQVdpdGhTSEEzODQgPSAxMQojICBFQ0RTQVdpdGhTSEE1MTIgPSAxMgojICBTSEEyNTZXaXRoUlNBUFNTID0gMTMKIyAgU0hBMzg0V2l0aFJTQVBTUyA9IDE0CiMgIFNIQTUxMldpdGhSU0FQU1MgPSAxNQpTaWduYXR1cmVBbGdvcml0aG06IDQKIyBLZXlBbGdvcml0aG1zCiMgICBSU0FBbGdvcml0aG0gPSAxCiMgICBFQ0RTQUFsZ29yaXRobSA9IDIKS2V5QWxnb3JpdGhtOiAxCiMgVmFsaWRpdHkgb2YgdGhlIGNlcnRpZmljYXRlIGluIGR1cmF0aW9uIChtYXggMjkwIHllYXJzKSBvciB3aXRoIGFic29sdXRlIGRhdGUgaW4gUkZDMzMzOSBlLmcuIDk5OTktMTItMzFUMjM6NTk6NTlaLgojIEV4YW1wbGUgaW4gYWJzb2x1dGUgZGF0ZSAiOTk5OS0xMi0zMVQyMzo1OTo1OVoiLgojIEV4YW1wbGUgaW4gZHVyYXRpb24gIjFoMTBtMTBzIi4gT25seSBoLCBtIGFuZC9vciBzIGFyZSBhY2NlcHRlZC4KVmFsaWRpdHlQZXJpb2Q6ICIxNzUyMDAwaCIgIyAyMDAgWWVhcnMKQmFzaWNDb25zdHJhaW50czoKICBCYXNpY0NvbnN0cmFpbnRzVmFsaWQ6IHRydWUKICBJc0NBOiB0cnVlCiAgTWF4UGF0aExlbjogMgogICMgTWF4UGF0aExlblplcm8gaW5kaWNhdGVzIHRoYXQgQmFzaWNDb25zdHJhaW50c1ZhbGlkPT10cnVlCiAgIyBhbmQgTWF4UGF0aExlbj09MCBzaG91bGQgYmUgaW50ZXJwcmV0ZWQgYXMgYW4gYWN0dWFsCiAgIyBtYXhpbXVtIHBhdGggbGVuZ3RoIG9mIHplcm8uIE90aGVyd2lzZSwgdGhhdCBjb21iaW5hdGlvbiBpcwogICMgaW50ZXJwcmV0ZWQgYXMgTWF4UGF0aExlbiBub3QgYmVpbmcgc2V0LgogIE1heFBhdGhMZW5aZXJvOiBmYWxzZQpBZGRTS0k6IHRydWUKQWRkQUtJOiB0cnVlCiMgS2V5VXNhZ2VzCiMgIEtleVVzYWdlRGlnaXRhbFNpZ25hdHVyZSA9IDEKIyAgS2V5VXNhZ2VDb250ZW50Q29tbWl0bWVudCA9IDIKIyAgS2V5VXNhZ2VLZXlFbmNpcGhlcm1lbnQgPSA0CiMgIEtleVVzYWdlRGF0YUVuY2lwaGVybWVudCA9IDgKIyAgS2V5VXNhZ2VLZXlBZ3JlZW1lbnQgPSAxNgojICBLZXlVc2FnZUNlcnRTaWduID0gMzIgCiMgIEtleVVzYWdlQ1JMU2lnbiA9IDY0CiMgIEtleVVzYWdlRW5jaXBoZXJPbmx5ID0gMTI4CiMgIEtleVVzYWdlRGVjaXBoZXJPbmx5ID0gMjU2CktleVVzYWdlOgogIC0gMQogIC0gMzIKICAtIDY0CkV4dGVuZGVkS2V5VXNhZ2U6CiAgIyBFeHRlbmRlZEtleVVzYWdlcwogICMgIEV4dEtleVVzYWdlQW55ID0gMAogICMgIEV4dEtleVVzYWdlU2VydmVyQXV0aCA9IDEKICAjICBFeHRLZXlVc2FnZUNsaWVudEF1dGggPSAyCiAgIyAgRXh0S2V5VXNhZ2VDb2RlU2lnbmluZyA9IDMKICAjICBFeHRLZXlVc2FnZUVtYWlsUHJvdGVjdGlvbiA9IDQKICAjICBFeHRLZXlVc2FnZUlQU0VDRW5kU3lzdGVtID0gNQogICMgIEV4dEtleVVzYWdlSVBTRUNUdW5uZWwgPSA2CiAgIyAgRXh0S2V5VXNhZ2VJUFNFQ1VzZXIgPSA3CiAgIyAgRXh0S2V5VXNhZ2VUaW1lU3RhbXBpbmcgPSA4CiAgIyAgRXh0S2V5VXNhZ2VPQ1NQU2lnbmluZyA9IDkKICAjICBFeHRLZXlVc2FnZU1pY3Jvc29mdFNlcnZlckdhdGVkQ3J5cHRvID0gMTAKICAjICBFeHRLZXlVc2FnZU5ldHNjYXBlU2VydmVyR2F0ZWRDcnlwdG8gPSAxMQogICMgIEV4dEtleVVzYWdlTWljcm9zb2Z0Q29tbWVyY2lhbENvZGVTaWduaW5nID0gMTIKICAjICBFeHRLZXlVc2FnZU1pY3Jvc29mdEtlcm5lbENvZGVTaWduaW5nID0gMTMKIyBFeHRyYUV4dGVuc2lvbnM6IHRydWUKIyBTQU5Vc2FnZTogdHJ1ZQojIENSTERpc3RyaWJ1dGlvblBvaW50cy4gTGlzdCBvZiBVUkkgc3RyaW5ncy4KI0NSTERpc3RyaWJ1dGlvblBvaW50czoKCiMgUG9saWN5SWRlbnRpZmllcnMuIExpc3Qgb2YgQVNOMSBwb2xpY3kgT0lEUwojUG9saWN5SWRlbnRpZmllcnM6CiMgIC0gMS4xMC4xMjMuNDMyLjQuNQojICAtIDIuMTAuMTIzLjQzMi40LjY1Cg=="
}
Profile added. Profile ID: 321c7960-ec34-459d-bc5c-ee2399633922

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1/ profile add \
    -F endentity.yaml -N "Customer signing cert" -T END
{
    "id": "f30679fb-00cb-4630-b550-1d026d4d63b6",
    "profile_name": "Customer signing cert",
    "profile_type": 1,
    "profile_yaml": "IyBDb25maWcgZmlsZSBmb3IgdGhlIEVuZC1FbnRpdHkgcHJvZmlsZS4gRG8gbm90IHVzZSBUQUJTCi0tLQpOYW1lOiBHZW5lcmljIGNvZGUgc2lnbmluZyBFbmRFbnRpdHkgUHJvZmlsZQpETjoKICBPcmdhbml6YXRpb246IFRlc3QgQ29tcAogICMgT3JnYW5pemF0aW9uYWxVbml0OiBSJkQKICBDb3VudHJ5OiBGSQogICMgUHJvdmluY2U6CiAgIy0gU29tZXRoaW5nCiAgIyBMb2NhbGl0eToKICAjIFN0cmVldEFkZHJlc3M6CiAgIyBQb3N0YWxDb2RlOgogICMgU2VyaWFsTnVtYmVyCiAgIyBDb21tb25OYW1lOiBJTUcKIyBFbmRFbnRpdHkgaXMgMSwgU3ViIENBIHByb2ZpbGUgMiAsIFJvb3QgcHJvZmlsZSAzClByb2ZpbGVUeXBlOiAxCiMgU2lnbmF0dXJlQWxnb3JpdGhtcwojICBTSEExV2l0aFJTQSA9IDMKIyAgU0hBMjU2V2l0aFJTQSA9IDQKIyAgU0hBMzg0V2l0aFJTQSA9IDUKIyAgU0hBNTEyV2l0aFJTQSA9IDYKIyAgRFNBV2l0aFNIQTEgPSA3CiMgIERTQVdpdGhTSEEyNTYgPSA4CiMgIEVDRFNBV2l0aFNIQTEgPSA5CiMgIEVDRFNBV2l0aFNIQTI1NiA9IDEwCiMgIEVDRFNBV2l0aFNIQTM4NCA9IDExCiMgIEVDRFNBV2l0aFNIQTUxMiA9IDEyCiMgIFNIQTI1NldpdGhSU0FQU1MgPSAxMwojICBTSEEzODRXaXRoUlNBUFNTID0gMTQKIyAgU0hBNTEyV2l0aFJTQVBTUyA9IDE1ClNpZ25hdHVyZUFsZ29yaXRobTogNAojIEtleUFsZ29yaXRobXMKIyAgIFJTQUFsZ29yaXRobSA9IDEKIyAgIEVDRFNBQWxnb3JpdGhtID0gMgpLZXlBbGdvcml0aG06IDEKIyBWYWxpZGl0eSBvZiB0aGUgY2VydGlmaWNhdGUgaW4gZHVyYXRpb24gKG1heCAyOTAgeWVhcnMpIG9yIHdpdGggYWJzb2x1dGUgZGF0ZSBpbiBSRkMzMzM5IGUuZy4gOTk5OS0xMi0zMVQyMzo1OTo1OVouCiMgRXhhbXBsZSBpbiBhYnNvbHV0ZSBkYXRlICI5OTk5LTEyLTMxVDIzOjU5OjU5WiIuCiMgRXhhbXBsZSBpbiBkdXJhdGlvbiAiMWgxMG0xMHMiLiBPbmx5IGgsIG0gYW5kL29yIHMgYXJlIGFjY2VwdGVkLgpWYWxpZGl0eVBlcmlvZDogIjE3NTIwMDBoIiAjIDIwMCBZZWFycwpCYXNpY0NvbnN0cmFpbnRzOgogIFVzZTogdHJ1ZQogIElzQ0E6IGZhbHNlCkFkZFNLSTogdHJ1ZQpBZGRBS0k6IHRydWUKIyBLZXlVc2FnZXMKIyAgS2V5VXNhZ2VEaWdpdGFsU2lnbmF0dXJlID0gMQojICBLZXlVc2FnZUNvbnRlbnRDb21taXRtZW50ID0gMgojICBLZXlVc2FnZUtleUVuY2lwaGVybWVudCA9IDQKIyAgS2V5VXNhZ2VEYXRhRW5jaXBoZXJtZW50ID0gOAojICBLZXlVc2FnZUtleUFncmVlbWVudCA9IDE2CiMgIEtleVVzYWdlQ2VydFNpZ24gPSAzMiAKIyAgS2V5VXNhZ2VDUkxTaWduID0gNjQKIyAgS2V5VXNhZ2VFbmNpcGhlck9ubHkgPSAxMjgKIyAgS2V5VXNhZ2VEZWNpcGhlck9ubHkgPSAyNTYKS2V5VXNhZ2U6CiAgLSAxCiAgLSAyCkV4dGVuZGVkS2V5VXNhZ2U6CiAgLSAzCiAgIyBFeHRlbmRlZEtleVVzYWdlcwogICMgIEV4dEtleVVzYWdlQW55ID0gMAogICMgIEV4dEtleVVzYWdlU2VydmVyQXV0aCA9IDEKICAjICBFeHRLZXlVc2FnZUNsaWVudEF1dGggPSAyCiAgIyAgRXh0S2V5VXNhZ2VDb2RlU2lnbmluZyA9IDMKICAjICBFeHRLZXlVc2FnZUVtYWlsUHJvdGVjdGlvbiA9IDQKICAjICBFeHRLZXlVc2FnZUlQU0VDRW5kU3lzdGVtID0gNQogICMgIEV4dEtleVVzYWdlSVBTRUNUdW5uZWwgPSA2CiAgIyAgRXh0S2V5VXNhZ2VJUFNFQ1VzZXIgPSA3CiAgIyAgRXh0S2V5VXNhZ2VUaW1lU3RhbXBpbmcgPSA4CiAgIyAgRXh0S2V5VXNhZ2VPQ1NQU2lnbmluZyA9IDkKICAjICBFeHRLZXlVc2FnZU1pY3Jvc29mdFNlcnZlckdhdGVkQ3J5cHRvID0gMTAKICAjICBFeHRLZXlVc2FnZU5ldHNjYXBlU2VydmVyR2F0ZWRDcnlwdG8gPSAxMQogICMgIEV4dEtleVVzYWdlTWljcm9zb2Z0Q29tbWVyY2lhbENvZGVTaWduaW5nID0gMTIKICAjICBFeHRLZXlVc2FnZU1pY3Jvc29mdEtlcm5lbENvZGVTaWduaW5nID0gMTMKRXh0cmFFeHRlbnNpb25zOiB0cnVlClNBTlVzYWdlOiB0cnVlCiMgQ1JMRGlzdHJpYnV0aW9uUG9pbnRzLiBMaXN0IG9mIFVSSSBzdHJpbmdzLgojQ1JMRGlzdHJpYnV0aW9uUG9pbnRzOgoKIyBQb2xpY3lJZGVudGlmaWVycy4gTGlzdCBvZiBBU04xIHBvbGljeSBPSURTCiNQb2xpY3lJZGVudGlmaWVyczoKIyAgLSAxLjEwLjEyMy40MzIuNC41CiMgIC0gMi4xMC4xMjMuNDMyLjQuNjUKCiMgRW5mb3JjZVVuaXF1ZUROIGVuYWJsZXMgdGhlIGNoZWNraW5nIGlmIGEgY2VydGlmaWNhdGUgaGFzIGJlZW4gaXNzdWVkIHdpdGggdGhlIHNhbWUgc3ViamVjdCBETiBmcm9tIHRoZSBDQQojIFZhbHVlcyB0cnVlIG9yIGZhbHNlCiNFbmZvcmNlVW5pcXVlRE46IHRydWUK"
}
Profile added. Profile ID: f30679fb-00cb-4630-b550-1d026d4d63b6

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1/ profile getall
{
    "count": 2,
    "items": [
        {
            "id": "321c7960-ec34-459d-bc5c-ee2399633922",
            "profile_name": "Customer Root CA",
            "profile_type": 3
        },
        {
            "id": "f30679fb-00cb-4630-b550-1d026d4d63b6",
            "profile_name": "Customer signing cert",
            "profile_type": 1
        }
    ],
    "next": "/cas/profiles/?page=1",
    "pages": 1,
    "prev": "/cas/profiles/?page=1"
}

Create product

Here is the used product template. The product template was updated with the profile ids obtained from the previous commands. The values $ROOTPROFILEID, $ENDSIGPROFILEID were changed with their corresponding profile id.

  • ROOTPROFILEID=321c7960-ec34-459d-bc5c-ee2399633922
  • ENDSIGPROFILEID=f30679fb-00cb-4630-b550-1d026d4d63b6

In the approval rule it was decided that entities in the $WRITERGROUP were able to make RAUC signing requests. And entities in the $APPROVERGROUP group would be able to approve those. Autoapproval was not used.

$WRITERGROUP and $APPROVERGROUP were replaced with the corresponding Group Object ID from Microsoft Entra.

The template was saved as product.json.

More information about rules can be found from approval rules.

Product was created using the python tool

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1/ product add -T product.json 
{
    "ca_info": [
        {
            "cert_override_payload": null,
            "certificate_type": "SUBCA",
            "cn": "CA for One Time Signing certs",
            "crl_distribution_points": null,
            "crl_expiry": null,
            "crl_issue_interval": null,
            "csr": null,
            "description": "One Time Signing RAUC code signing certs",
            "external_request_id": null,
            "external_root": null,
            "id": null,
            "issuer_ca_id": null,
            "key_override_id": null,
            "key_type": "RSA2048",
            "leafs": [],
            "originating_id": null,
            "policy_identifiers": null,
            "product_id": null,
            "profile_id": "321c7960-ec34-459d-bc5c-ee2399633922",
            "state": null,
            "use_case": "RaucCodeSigning"
        }
    ],
    "description": "Product for testing RAUC bundle One Time Signing",
    "enabled": true,
    "external_request_id": null,
    "id": null,
    "name": "RAUC onetime",
    "product_config_items": [],
    "product_operations": [
        {
            "approval_rule": {
                "allowed_groups": [
                    "b716abb1-2e3b-47a9-bca5-a3669faa50a6"
                ],
                "approval_groups": [
                    "f65a3ea9-60db-47a4-9ad8-c6915735ec5f"
                ],
                "blanket_groups": [],
                "description": "Rule used for testing for RAUC onetime",
                "name": "Test rule2"
            },
            "ca_use_case": null,
            "description": "RAUC code signing With end entity cert and key",
            "id": null,
            "name": "RAUC code signing cert and key",
            "operation_type": "RaucBundleSigningWithOneTimeKey",
            "profile_id": "f30679fb-00cb-4630-b550-1d026d4d63b6",
            "token": {
                "description": "One Time Signing key for issuing signing certificates",
                "extractable": null,
                "key_override_id": null,
                "key_type": "RSA2048",
                "name": "Token for One Time Signing certificates",
                "public_key": null
            }
        }
    ],
    "product_type": "Production",
    "rnd_keys": [],
    "state": null
}
Is product ok(Y/N): y
{
    "ca_info": [],
    "description": "Product for testing RAUC bundle One Time Signing",
    "enabled": null,
    "external_request_id": null,
    "id": "51ec9ce9-3956-4e12-bea3-e994ed6a2395",
    "name": "RAUC onetime",
    "product_config_items": null,
    "product_operations": [],
    "product_type": null,
    "rnd_keys": [],
    "state": 2
}
Product Add request sent. Request ID: 51ec9ce9-3956-4e12-bea3-e994ed6a2395 state: ApprovalRequired

Approve product

The product was approved using the GUI.

Then with the python tool the state was checked ( state is 16 for ready product) and the product ID and operation ID was obtained.

  • productID = 51ec9ce9-3956-4e12-bea3-e994ed6a2395
  • operation ID for RAUC signing = e007176c-6b29-4640-9f6e-7cee6abb6c0a
(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1/ product getall
{
    "count": 1,
    "items": [
        {
            "description": "Product for testing RAUC bundle One Time Signing",
            "id": "51ec9ce9-3956-4e12-bea3-e994ed6a2395",
            "name": "RAUC onetime",
            "state": 16
        }
    ],
    "next": "/products/?page=1",
    "pages": 1,
    "prev": "/products/?page=1"
}
(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1/ product \
    get -I 51ec9ce9-3956-4e12-bea3-e994ed6a2395
{
    "ca_info": [
        {
            "cert_override_payload": null,
            "certificate_type": "SUBCA",
            "cn": "CA for One Time Signing certs",
            "crl_distribution_points": null,
            "crl_expiry": null,
            "crl_issue_interval": null,
            "csr": null,
            "description": "One Time Signing RAUC code signing certs",
            "external_request_id": null,
            "external_root": null,
            "id": "fe6c6a91-a771-4cd4-a00e-363f10f77cc2",
            "issuer_ca_id": null,
            "key_override_id": null,
            "key_type": "RSA2048",
            "leafs": [],
            "originating_id": null,
            "policy_identifiers": null,
            "product_id": null,
            "profile_id": "321c7960-ec34-459d-bc5c-ee2399633922",
            "state": 16,
            "use_case": "RaucCodeSigning"
        }
    ],
    "description": "Product for testing RAUC bundle One Time Signing",
    "enabled": null,
    "external_request_id": "a68e9b4e-64d4-cde8-6abc-d88f45d03bb3",
    "id": "51ec9ce9-3956-4e12-bea3-e994ed6a2395",
    "name": "RAUC onetime",
    "product_config_items": [],
    "product_operations": [
        {
            "approval_rule": {
                "allowed_groups": [
                    "b716abb1-2e3b-47a9-bca5-a3669faa50a6"
                ],
                "approval_groups": [
                    "f65a3ea9-60db-47a4-9ad8-c6915735ec5f"
                ],
                "blanket_groups": [
                    ""
                ],
                "description": "Rule used for testing for RAUC onetime",
                "name": "Test rule2"
            },
            "ca_use_case": null,
            "description": "RAUC code signing With end entity cert and key",
            "id": "e007176c-6b29-4640-9f6e-7cee6abb6c0a",
            "name": "RAUC code signing cert and key",
            "operation_type": "RaucBundleSigningWithOneTimeKey",
            "profile_id": "f30679fb-00cb-4630-b550-1d026d4d63b6",
            "token": {
                "description": "One Time Signing key for issuing signing certificates",
                "extractable": null,
                "key_override_id": null,
                "key_type": "RSA2048",
                "name": "Token for One Time Signing certificates",
                "public_key": null
            }
        }
    ],
    "product_type": "Production",
    "rnd_keys": [],
    "state": 16
}

Getting the sensitive items

In manufacturing there are some sensitive items which are needed. Here a client is registered which can obtain e.g., certificates.

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1/ client add -N Manufacturing -D "Get sensitive information" \
     -K client.public -U "upn:<redacted>" -T ProductionPC -p 51ec9ce9-3956-4e12-bea3-e994ed6a2395
{
    "client_type": "ProductionPC",
    "description": "Get sensitive information",
    "id": "5235da30-6c2b-493c-bfec-937b70dc6742",
    "id_product": "51ec9ce9-3956-4e12-bea3-e994ed6a2395",
    "name": "Manufacturing",
    "state": 2
}
Client Add request sent. Request ID: 5235da30-6c2b-493c-bfec-937b70dc6742 state: ApprovalRequired

Approve the client from UI

Now the product sensitive items can be fetched.

(venv) $  ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1/ secrets get \
    -P 51ec9ce9-3956-4e12-bea3-e994ed6a2395 -C client.private -O /tmp/prod.json
SRKHASH written to: /tmp/prod.jsonSRKHASH
SRKTABLE written to: /tmp/prod.jsonSRKTABLE
KEKIV written to: /tmp/prod.jsonKEKIV
Full secret payload written to: /tmp/prod.json

The /tmp/prod.json contains all the items in one file. All the Certificates can be seen in that file.

More info can be found from client usage.

RAUC signing

See more information about RAUC packages.

The rauc-verity.tar.gz was used for signing. request.json was same as in documentation

$ tar -tvf rauc-verity.tar.gz 
drwxrwxr-x user/user   0 2025-03-27 14:34 data/
-rw-rw-r-- user/user 65536 2025-03-27 14:10 data/rootfs.img
-rw-rw-r-- user/user 32768 2025-03-27 14:10 data/appfs.img
-rw-rw-r-- user/user  8192 2025-03-27 14:10 data/space-dummy
-rw-rw-r-- user/user   144 2025-03-27 15:39 data/manifest.raucm
-rw-rw-r-- user/user    52 2025-03-27 14:15 request.json


(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1/ imagesigning add RaucBundleSigning \
    -P 51ec9ce9-3956-4e12-bea3-e994ed6a2395 \
    --operid e007176c-6b29-4640-9f6e-7cee6abb6c0a \
    -N TEST -D TEST -F rauc-verity.tar.gz
{
    "call_back_url": null,
    "description": "TEST",
    "id": "8a0bcafc-df97-48c9-a60a-b06e5f0b169d",
    "id_product": "51ec9ce9-3956-4e12-bea3-e994ed6a2395",
    "id_product_operation": "e007176c-6b29-4640-9f6e-7cee6abb6c0a",
    "name": "TEST",
    "payload": {
        "id": null,
        "metadata": [
            {
                "name": "first",
                "value": "val"
            }
        ],
        "modified_sha256": null,
        "name": "rauc-verity.tar.gz",
        "original_sha256": null,
        "s3_url": null,
        "service_provided_parameters": null
    },
    "state": 1
}
Request sent. Request ID: 8a0bcafc-df97-48c9-a60a-b06e5f0b169d, state: Created

The operation created ID "8a0bcafc-df97-48c9-a60a-b06e5f0b169d" which is then used when querying/downloading the signed content.

Approve signing request

Request was approved from the GUI.

Download signed content

After approval the request is processed and it can be queried. If the state is 16 then the signing is complete and the content is downloaded.

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1/ imagesigning get \
    -I 8a0bcafc-df97-48c9-a60a-b06e5f0b169d -O /tmp/test.bin --skipBase64
{
    "call_back_url": null,
    "description": "TEST",
    "id": "8a0bcafc-df97-48c9-a60a-b06e5f0b169d",
    "id_product": "51ec9ce9-3956-4e12-bea3-e994ed6a2395",
    "id_product_operation": "e007176c-6b29-4640-9f6e-7cee6abb6c0a",
    "name": "TEST",
    "payload": {
        "id": "750b4ae9-a324-487f-9109-8bbfe408ba3e",
        "metadata": [
            {
                "name": "first",
                "value": "val"
            }
        ],
        "modified_sha256": null,
        "name": "rauc-verity.tar.gz",
        "original_sha256": null,
        "s3_url": "<redacted>ss>",
        "service_provided_parameters": []
    },
    "state": 16
}
Downloading signed binary to: /tmp/test.bin
File Downloaded

Verify the bundle

In this example the trustpoint for the device is the CA certificate with CN "CA for issuing RAUC code signing certs". In this example the certificate was copied from the UI and the obtained PKCS7 content was stored to a file(input.pkcs7).

14:18:53 user$ cat input.pkcs7 | openssl pkcs7 -print_certs > certs.pem

See example response with validation

In production scenarios the trustpoint is downloaded securely using a registered client.