Skip to content

Advanced PKI hierarchy to issue Device certificates and client certificates

This example shows how to create an advanced setup with root and subordinate CAs for two uses cases:

  • Initial Device certificates
  • Client certificates for authetication purposes. ( In this example these are used to request the device certificates using mTLS)

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 products
  • Issuing client certificates
  • Issuing Initial Device certificates using mTLS

NOTE: If mTLS target environment is LAAVAT Platform maximum chain length is four

PKI hierarchy

The following PKI structure will be created:

graph TD
    A[Root CA<br>• Validity: 200 years<br>] --> B[Device Family Sub CA<br>• Validity: 100 years<br>]
    B --> D[Device CA<br>• Validity: 100 years<br>]
    D --> E[End-Entity certificates for devices<br>• Validity: 100 years<br>]
    A --> C[Client Family CA<br>• Validity: 100 years<br>]
    C --> F[Client CA<br>• Validity: 20 years<br>]
    F --> G[End-Entity certificates for clients<br>• Validity: 2 years<br>]

The PKI structure is created with 5 products. See below.

graph TD
    A[Product for ROOTCA] --> B[Product for Device Family Sub CA]
    A --> C[Product for Client Sub CA]
    B --> D[Product for issuing End-Entity certificates for devices]
    C --> F[Product for issuing End-Entity client certificates]

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

In this example a 5 Certificate Authorities are created and multiple profiles are needed. Please note that CloudHSM enforces strict compliance with NIST FIPS 140-2 or FIPS 140-3 standards. Therefore the signature algorithm strength cannot be lower that the key size. In this case the ROOT is using EC P384 key so it must sign the issued certificates with ECDSAWithSHA384.

ROOT CA

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1/ profile add \
    -F device-cert-root-ec-profile.yaml \
    -N "Initial Device Certificate Product Family RootCA EC Profile" -T ROOT
{
    "id": "4a63eff1-29ae-43fa-baba-c319575291db",
    "profile_name": "Initial Device Certificate Product Family RootCA EC Profile",
    "profile_type": 3,
    "profile_yaml": "IyBDb25maWcgZmlsZSBmb3IgdGhlIFN1YkNBIHByb2ZpbGUuIERvIG5vdCB1c2UgVEFCUwotLS0KTmFtZTogUk9PVCBQcm9maWxlCiMgRGlzdGluZ3Vpc2hlZCBuYW1lIG9mIHRoZSBDQQpETjoKICAjIE9yZ2FuaXphdGlvbjogCiAgT3JnYW5pemF0aW9uOiBMYWF2YXQKICAjIE9yZ2FuaXphdGlvbmFsVW5pdDogUiZECiAgIyBDb3VudHJ5OiBGSQogIENvdW50cnk6IEZJCiAgIyBQcm92aW5jZToKICAjIExvY2FsaXR5OgogICMgU3RyZWV0QWRkcmVzczoKICAjIFBvc3RhbENvZGU6CiAgIyBTZXJpYWxOdW1iZXIKICAjIENvbW1vbk5hbWU6IElNWDYKIyBFbmRFbnRpdHkgaXMgMSwgU3ViIENBIHByb2ZpbGUgMiAsIFJvb3QgcHJvZmlsZSAzClByb2ZpbGVUeXBlOiAzCiMgU2lnbmF0dXJlQWxnb3JpdGhtcwojICBTSEExV2l0aFJTQSA9IDMKIyAgU0hBMjU2V2l0aFJTQSA9IDQKIyAgU0hBMzg0V2l0aFJTQSA9IDUKIyAgU0hBNTEyV2l0aFJTQSA9IDYKIyAgRFNBV2l0aFNIQTEgPSA3CiMgIERTQVdpdGhTSEEyNTYgPSA4CiMgIEVDRFNBV2l0aFNIQTEgPSA5CiMgIEVDRFNBV2l0aFNIQTI1NiA9IDEwCiMgIEVDRFNBV2l0aFNIQTM4NCA9IDExCiMgIEVDRFNBV2l0aFNIQTUxMiA9IDEyCiMgIFNIQTI1NldpdGhSU0FQU1MgPSAxMwojICBTSEEzODRXaXRoUlNBUFNTID0gMTQKIyAgU0hBNTEyV2l0aFJTQVBTUyA9IDE1ClNpZ25hdHVyZUFsZ29yaXRobTogMTEKIyBLZXlBbGdvcml0aG1zCiMgICBSU0FBbGdvcml0aG0gPSAxCiMgICBFQ0RTQUFsZ29yaXRobSA9IDIKS2V5QWxnb3JpdGhtOiAyCiMgVmFsaWRpdHkgb2YgdGhlIGNlcnRpZmljYXRlIGluIGR1cmF0aW9uIChtYXggMjkwIHllYXJzKSBvciB3aXRoIGFic29sdXRlIGRhdGUgaW4gUkZDMzMzOSBlLmcuIDk5OTktMTItMzFUMjM6NTk6NTlaLgojIEV4YW1wbGUgaW4gYWJzb2x1dGUgZGF0ZSAiOTk5OS0xMi0zMVQyMzo1OTo1OVoiLgojIEV4YW1wbGUgaW4gZHVyYXRpb24gIjFoMTBtMTBzIi4gT25seSBoLCBtIGFuZC9vciBzIGFyZSBhY2NlcHRlZC4KVmFsaWRpdHlQZXJpb2Q6ICIxNzUyMDAwaCIKQmFzaWNDb25zdHJhaW50czoKICBCYXNpY0NvbnN0cmFpbnRzVmFsaWQ6IHRydWUKICBJc0NBOiB0cnVlCiAgTWF4UGF0aExlbjogMwogICMgTWF4UGF0aExlblplcm8gaW5kaWNhdGVzIHRoYXQgQmFzaWNDb25zdHJhaW50c1ZhbGlkPT10cnVlCiAgIyBhbmQgTWF4UGF0aExlbj09MCBzaG91bGQgYmUgaW50ZXJwcmV0ZWQgYXMgYW4gYWN0dWFsCiAgIyBtYXhpbXVtIHBhdGggbGVuZ3RoIG9mIHplcm8uIE90aGVyd2lzZSwgdGhhdCBjb21iaW5hdGlvbiBpcwogICMgaW50ZXJwcmV0ZWQgYXMgTWF4UGF0aExlbiBub3QgYmVpbmcgc2V0LgogICMgTWF4UGF0aExlblplcm86IHRydWUKQWRkU0tJOiB0cnVlCkFkZEFLSTogdHJ1ZQojIEtleVVzYWdlcwojICBLZXlVc2FnZURpZ2l0YWxTaWduYXR1cmUgPSAxCiMgIEtleVVzYWdlQ29udGVudENvbW1pdG1lbnQgPSAyCiMgIEtleVVzYWdlS2V5RW5jaXBoZXJtZW50ID0gNAojICBLZXlVc2FnZURhdGFFbmNpcGhlcm1lbnQgPSA4CiMgIEtleVVzYWdlS2V5QWdyZWVtZW50ID0gMTYKIyAgS2V5VXNhZ2VDZXJ0U2lnbiA9IDMyIAojICBLZXlVc2FnZUNSTFNpZ24gPSA2NAojICBLZXlVc2FnZUVuY2lwaGVyT25seSA9IDEyOAojICBLZXlVc2FnZURlY2lwaGVyT25seSA9IDI1NgpLZXlVc2FnZToKICAtIDEKICAtIDMyCiAgLSA2NApFeHRlbmRlZEtleVVzYWdlOgogICMgRXh0ZW5kZWRLZXlVc2FnZXMKICAjICBFeHRLZXlVc2FnZUFueSA9IDAKICAjICBFeHRLZXlVc2FnZVNlcnZlckF1dGggPSAxCiAgIyAgRXh0S2V5VXNhZ2VDbGllbnRBdXRoID0gMgogICMgIEV4dEtleVVzYWdlQ29kZVNpZ25pbmcgPSAzCiAgIyAgRXh0S2V5VXNhZ2VFbWFpbFByb3RlY3Rpb24gPSA0CiAgIyAgRXh0S2V5VXNhZ2VJUFNFQ0VuZFN5c3RlbSA9IDUKICAjICBFeHRLZXlVc2FnZUlQU0VDVHVubmVsID0gNgogICMgIEV4dEtleVVzYWdlSVBTRUNVc2VyID0gNwogICMgIEV4dEtleVVzYWdlVGltZVN0YW1waW5nID0gOAogICMgIEV4dEtleVVzYWdlT0NTUFNpZ25pbmcgPSA5CiAgIyAgRXh0S2V5VXNhZ2VNaWNyb3NvZnRTZXJ2ZXJHYXRlZENyeXB0byA9IDEwCiAgIyAgRXh0S2V5VXNhZ2VOZXRzY2FwZVNlcnZlckdhdGVkQ3J5cHRvID0gMTEKICAjICBFeHRLZXlVc2FnZU1pY3Jvc29mdENvbW1lcmNpYWxDb2RlU2lnbmluZyA9IDEyCiAgIyAgRXh0S2V5VXNhZ2VNaWNyb3NvZnRLZXJuZWxDb2RlU2lnbmluZyA9IDEzCiMgRXh0cmFFeHRlbnNpb25zOiB0cnVlCiMgU0FOVXNhZ2U6IHRydWUKIyBDUkxEaXN0cmlidXRpb25Qb2ludHMuIExpc3Qgb2YgVVJJIHN0cmluZ3MuCiNDUkxEaXN0cmlidXRpb25Qb2ludHM6CiMgIC0gaHR0cDovL2NybC5sYWF2YXQuY29tL3Byb2R1Y3RzLTAvcm9vdC5jcmwKCiMgUG9saWN5SWRlbnRpZmllcnMuIExpc3Qgb2YgQVNOMSBwb2xpY3kgT0lEUwojUG9saWN5SWRlbnRpZmllcnM6CiMgIC0gMS4xMC4xMjMuNDMyLjQuNQojICAtIDIuMTAuMTIzLjQzMi40LjY1CgojIEVuZm9yY2VVbmlxdWVETiBlbmFibGVzIHRoZSBjaGVja2luZyBpZiBhIGNlcnRpZmljYXRlIGhhcyBiZWVuIGlzc3VlZCB3aXRoIHRoZSBzYW1lIHN1YmplY3QgRE4gZnJvbSB0aGUgQ0EKIyBWYWx1ZXMgdHJ1ZSBvciBmYWxzZQojRW5mb3JjZVVuaXF1ZUROOiB0cnVlCg=="
}
Profile added. Profile ID: 4a63eff1-29ae-43fa-baba-c319575291db

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1/ profile add \
    -F device-cert-subca-ecdsa-p384-SHA384-profile.yaml \
    -N "Initial Device Certificate Product Family SubCA Profile EC for root issuer" \
    -T SUB
{
    "id": "bff08e23-9eaf-427c-a776-1dacbd546311",
    "profile_name": "Initial Device Certificate Product Family SubCA Profile EC for root issuer",
    "profile_type": 2,
    "profile_yaml": "IyBDb25maWcgZmlsZSBmb3IgdGhlIFN1YkNBIHByb2ZpbGUuIERvIG5vdCB1c2UgVEFCUwotLS0KTmFtZTogRmFtaWx5IFN1YkNBIFByb2ZpbGUgd2l0aCBFQ0RTQVdpdGhTSEEzODQKIyBEaXN0aW5ndWlzaGVkIG5hbWUgb2YgdGhlIENBCkROOgogICMgT3JnYW5pemF0aW9uOiAKICBPcmdhbml6YXRpb246IExhYXZhdAogICMgT3JnYW5pemF0aW9uYWxVbml0OiBSJkQKICAjIENvdW50cnk6IEZJCiAgQ291bnRyeTogRkkKICAjIFByb3ZpbmNlOgogICMgTG9jYWxpdHk6CiAgIyBTdHJlZXRBZGRyZXNzOgogICMgUG9zdGFsQ29kZToKICAjIFNlcmlhbE51bWJlcgogICMgQ29tbW9uTmFtZTogSU1YNgojIEVuZEVudGl0eSBpcyAxLCBTdWIgQ0EgcHJvZmlsZSAyICwgUm9vdCBwcm9maWxlIDMKUHJvZmlsZVR5cGU6IDIKIyBTaWduYXR1cmVBbGdvcml0aG1zCiMgIFNIQTFXaXRoUlNBID0gMwojICBTSEEyNTZXaXRoUlNBID0gNAojICBTSEEzODRXaXRoUlNBID0gNQojICBTSEE1MTJXaXRoUlNBID0gNgojICBEU0FXaXRoU0hBMSA9IDcKIyAgRFNBV2l0aFNIQTI1NiA9IDgKIyAgRUNEU0FXaXRoU0hBMSA9IDkKIyAgRUNEU0FXaXRoU0hBMjU2ID0gMTAKIyAgRUNEU0FXaXRoU0hBMzg0ID0gMTEKIyAgRUNEU0FXaXRoU0hBNTEyID0gMTIKIyAgU0hBMjU2V2l0aFJTQVBTUyA9IDEzCiMgIFNIQTM4NFdpdGhSU0FQU1MgPSAxNAojICBTSEE1MTJXaXRoUlNBUFNTID0gMTUKU2lnbmF0dXJlQWxnb3JpdGhtOiAxMQojIEtleUFsZ29yaXRobXMKIyAgIFJTQUFsZ29yaXRobSA9IDEKIyAgIEVDRFNBQWxnb3JpdGhtID0gMgpLZXlBbGdvcml0aG06IDIKIyBWYWxpZGl0eSBvZiB0aGUgY2VydGlmaWNhdGUgaW4gZHVyYXRpb24gKG1heCAyOTAgeWVhcnMpIG9yIHdpdGggYWJzb2x1dGUgZGF0ZSBpbiBSRkMzMzM5IGUuZy4gOTk5OS0xMi0zMVQyMzo1OTo1OVouCiMgRXhhbXBsZSBpbiBhYnNvbHV0ZSBkYXRlICI5OTk5LTEyLTMxVDIzOjU5OjU5WiIuCiMgRXhhbXBsZSBpbiBkdXJhdGlvbiAiMWgxMG0xMHMiLiBPbmx5IGgsIG0gYW5kL29yIHMgYXJlIGFjY2VwdGVkLgpWYWxpZGl0eVBlcmlvZDogIjg3NjAwMGgiCkJhc2ljQ29uc3RyYWludHM6CiAgQmFzaWNDb25zdHJhaW50c1ZhbGlkOiB0cnVlCiAgSXNDQTogdHJ1ZQogIE1heFBhdGhMZW46IDAKICAjIE1heFBhdGhMZW5aZXJvIGluZGljYXRlcyB0aGF0IEJhc2ljQ29uc3RyYWludHNWYWxpZD09dHJ1ZQogICMgYW5kIE1heFBhdGhMZW49PTAgc2hvdWxkIGJlIGludGVycHJldGVkIGFzIGFuIGFjdHVhbAogICMgbWF4aW11bSBwYXRoIGxlbmd0aCBvZiB6ZXJvLiBPdGhlcndpc2UsIHRoYXQgY29tYmluYXRpb24gaXMKICAjIGludGVycHJldGVkIGFzIE1heFBhdGhMZW4gbm90IGJlaW5nIHNldC4KICBNYXhQYXRoTGVuWmVybzogdHJ1ZQpBZGRTS0k6IHRydWUKQWRkQUtJOiB0cnVlCiMgS2V5VXNhZ2VzCiMgIEtleVVzYWdlRGlnaXRhbFNpZ25hdHVyZSA9IDEKIyAgS2V5VXNhZ2VDb250ZW50Q29tbWl0bWVudCA9IDIKIyAgS2V5VXNhZ2VLZXlFbmNpcGhlcm1lbnQgPSA0CiMgIEtleVVzYWdlRGF0YUVuY2lwaGVybWVudCA9IDgKIyAgS2V5VXNhZ2VLZXlBZ3JlZW1lbnQgPSAxNgojICBLZXlVc2FnZUNlcnRTaWduID0gMzIgCiMgIEtleVVzYWdlQ1JMU2lnbiA9IDY0CiMgIEtleVVzYWdlRW5jaXBoZXJPbmx5ID0gMTI4CiMgIEtleVVzYWdlRGVjaXBoZXJPbmx5ID0gMjU2CktleVVzYWdlOgogIC0gMQogIC0gMzIKICAtIDY0CkV4dGVuZGVkS2V5VXNhZ2U6CiAgIyBFeHRlbmRlZEtleVVzYWdlcwogICMgIEV4dEtleVVzYWdlQW55ID0gMAogICMgIEV4dEtleVVzYWdlU2VydmVyQXV0aCA9IDEKICAjICBFeHRLZXlVc2FnZUNsaWVudEF1dGggPSAyCiAgIyAgRXh0S2V5VXNhZ2VDb2RlU2lnbmluZyA9IDMKICAjICBFeHRLZXlVc2FnZUVtYWlsUHJvdGVjdGlvbiA9IDQKICAjICBFeHRLZXlVc2FnZUlQU0VDRW5kU3lzdGVtID0gNQogICMgIEV4dEtleVVzYWdlSVBTRUNUdW5uZWwgPSA2CiAgIyAgRXh0S2V5VXNhZ2VJUFNFQ1VzZXIgPSA3CiAgIyAgRXh0S2V5VXNhZ2VUaW1lU3RhbXBpbmcgPSA4CiAgIyAgRXh0S2V5VXNhZ2VPQ1NQU2lnbmluZyA9IDkKICAjICBFeHRLZXlVc2FnZU1pY3Jvc29mdFNlcnZlckdhdGVkQ3J5cHRvID0gMTAKICAjICBFeHRLZXlVc2FnZU5ldHNjYXBlU2VydmVyR2F0ZWRDcnlwdG8gPSAxMQogICMgIEV4dEtleVVzYWdlTWljcm9zb2Z0Q29tbWVyY2lhbENvZGVTaWduaW5nID0gMTIKICAjICBFeHRLZXlVc2FnZU1pY3Jvc29mdEtlcm5lbENvZGVTaWduaW5nID0gMTMKIyBFeHRyYUV4dGVuc2lvbnM6IHRydWUKIyBTQU5Vc2FnZTogdHJ1ZQojIENSTERpc3RyaWJ1dGlvblBvaW50cy4gTGlzdCBvZiBVUkkgc3RyaW5ncy4KI0NSTERpc3RyaWJ1dGlvblBvaW50czoKIyAgLSBodHRwOi8vY3JsLmxhYXZhdC5jb20vcHJvZHVjdHMtMC9yb290LmNybAoKIyBQb2xpY3lJZGVudGlmaWVycy4gTGlzdCBvZiBBU04xIHBvbGljeSBPSURTCiNQb2xpY3lJZGVudGlmaWVyczoKIyAgLSAxLjEwLjEyMy40MzIuNC41CiMgIC0gMi4xMC4xMjMuNDMyLjQuNjUKCiMgRW5mb3JjZVVuaXF1ZUROIGVuYWJsZXMgdGhlIGNoZWNraW5nIGlmIGEgY2VydGlmaWNhdGUgaGFzIGJlZW4gaXNzdWVkIHdpdGggdGhlIHNhbWUgc3ViamVjdCBETiBmcm9tIHRoZSBDQQojIFZhbHVlcyB0cnVlIG9yIGZhbHNlCiNFbmZvcmNlVW5pcXVlRE46IHRydWUK"
}
Profile added. Profile ID: bff08e23-9eaf-427c-a776-1dacbd546311

SUB CA and End-Entity profiles

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1/ profile add \
    -F device-cert-subca-ecdsa-p256-SHA256-profile.yaml \
    -N "Initial Device Certificate Product Family SubCA Profile EC" -T SUB
{
    "id": "3adb4838-10d8-4ad5-b2b2-a711ef4a28db",
    "profile_name": "Initial Device Certificate Product Family SubCA Profile EC",
    "profile_type": 2,
    "profile_yaml": "IyBDb25maWcgZmlsZSBmb3IgdGhlIFN1YkNBIHByb2ZpbGUuIERvIG5vdCB1c2UgVEFCUwotLS0KTmFtZTogRmFtaWx5IFN1YkNBIFByb2ZpbGUKIyBEaXN0aW5ndWlzaGVkIG5hbWUgb2YgdGhlIENBCkROOgogICMgT3JnYW5pemF0aW9uOiAKICBPcmdhbml6YXRpb246IExhYXZhdAogICMgT3JnYW5pemF0aW9uYWxVbml0OiBSJkQKICAjIENvdW50cnk6IEZJCiAgQ291bnRyeTogRkkKICAjIFByb3ZpbmNlOgogICMgTG9jYWxpdHk6CiAgIyBTdHJlZXRBZGRyZXNzOgogICMgUG9zdGFsQ29kZToKICAjIFNlcmlhbE51bWJlcgogICMgQ29tbW9uTmFtZTogSU1YNgojIEVuZEVudGl0eSBpcyAxLCBTdWIgQ0EgcHJvZmlsZSAyICwgUm9vdCBwcm9maWxlIDMKUHJvZmlsZVR5cGU6IDIKIyBTaWduYXR1cmVBbGdvcml0aG1zCiMgIFNIQTFXaXRoUlNBID0gMwojICBTSEEyNTZXaXRoUlNBID0gNAojICBTSEEzODRXaXRoUlNBID0gNQojICBTSEE1MTJXaXRoUlNBID0gNgojICBEU0FXaXRoU0hBMSA9IDcKIyAgRFNBV2l0aFNIQTI1NiA9IDgKIyAgRUNEU0FXaXRoU0hBMSA9IDkKIyAgRUNEU0FXaXRoU0hBMjU2ID0gMTAKIyAgRUNEU0FXaXRoU0hBMzg0ID0gMTEKIyAgRUNEU0FXaXRoU0hBNTEyID0gMTIKIyAgU0hBMjU2V2l0aFJTQVBTUyA9IDEzCiMgIFNIQTM4NFdpdGhSU0FQU1MgPSAxNAojICBTSEE1MTJXaXRoUlNBUFNTID0gMTUKU2lnbmF0dXJlQWxnb3JpdGhtOiAxMAojIEtleUFsZ29yaXRobXMKIyAgIFJTQUFsZ29yaXRobSA9IDEKIyAgIEVDRFNBQWxnb3JpdGhtID0gMgpLZXlBbGdvcml0aG06IDIKIyBWYWxpZGl0eSBvZiB0aGUgY2VydGlmaWNhdGUgaW4gZHVyYXRpb24gKG1heCAyOTAgeWVhcnMpIG9yIHdpdGggYWJzb2x1dGUgZGF0ZSBpbiBSRkMzMzM5IGUuZy4gOTk5OS0xMi0zMVQyMzo1OTo1OVouCiMgRXhhbXBsZSBpbiBhYnNvbHV0ZSBkYXRlICI5OTk5LTEyLTMxVDIzOjU5OjU5WiIuCiMgRXhhbXBsZSBpbiBkdXJhdGlvbiAiMWgxMG0xMHMiLiBPbmx5IGgsIG0gYW5kL29yIHMgYXJlIGFjY2VwdGVkLgpWYWxpZGl0eVBlcmlvZDogIjg3NjAwMGgiCkJhc2ljQ29uc3RyYWludHM6CiAgQmFzaWNDb25zdHJhaW50c1ZhbGlkOiB0cnVlCiAgSXNDQTogdHJ1ZQogIE1heFBhdGhMZW46IDAKICAjIE1heFBhdGhMZW5aZXJvIGluZGljYXRlcyB0aGF0IEJhc2ljQ29uc3RyYWludHNWYWxpZD09dHJ1ZQogICMgYW5kIE1heFBhdGhMZW49PTAgc2hvdWxkIGJlIGludGVycHJldGVkIGFzIGFuIGFjdHVhbAogICMgbWF4aW11bSBwYXRoIGxlbmd0aCBvZiB6ZXJvLiBPdGhlcndpc2UsIHRoYXQgY29tYmluYXRpb24gaXMKICAjIGludGVycHJldGVkIGFzIE1heFBhdGhMZW4gbm90IGJlaW5nIHNldC4KICBNYXhQYXRoTGVuWmVybzogdHJ1ZQpBZGRTS0k6IHRydWUKQWRkQUtJOiB0cnVlCiMgS2V5VXNhZ2VzCiMgIEtleVVzYWdlRGlnaXRhbFNpZ25hdHVyZSA9IDEKIyAgS2V5VXNhZ2VDb250ZW50Q29tbWl0bWVudCA9IDIKIyAgS2V5VXNhZ2VLZXlFbmNpcGhlcm1lbnQgPSA0CiMgIEtleVVzYWdlRGF0YUVuY2lwaGVybWVudCA9IDgKIyAgS2V5VXNhZ2VLZXlBZ3JlZW1lbnQgPSAxNgojICBLZXlVc2FnZUNlcnRTaWduID0gMzIgCiMgIEtleVVzYWdlQ1JMU2lnbiA9IDY0CiMgIEtleVVzYWdlRW5jaXBoZXJPbmx5ID0gMTI4CiMgIEtleVVzYWdlRGVjaXBoZXJPbmx5ID0gMjU2CktleVVzYWdlOgogIC0gMQogIC0gMzIKICAtIDY0CkV4dGVuZGVkS2V5VXNhZ2U6CiAgIyBFeHRlbmRlZEtleVVzYWdlcwogICMgIEV4dEtleVVzYWdlQW55ID0gMAogICMgIEV4dEtleVVzYWdlU2VydmVyQXV0aCA9IDEKICAjICBFeHRLZXlVc2FnZUNsaWVudEF1dGggPSAyCiAgIyAgRXh0S2V5VXNhZ2VDb2RlU2lnbmluZyA9IDMKICAjICBFeHRLZXlVc2FnZUVtYWlsUHJvdGVjdGlvbiA9IDQKICAjICBFeHRLZXlVc2FnZUlQU0VDRW5kU3lzdGVtID0gNQogICMgIEV4dEtleVVzYWdlSVBTRUNUdW5uZWwgPSA2CiAgIyAgRXh0S2V5VXNhZ2VJUFNFQ1VzZXIgPSA3CiAgIyAgRXh0S2V5VXNhZ2VUaW1lU3RhbXBpbmcgPSA4CiAgIyAgRXh0S2V5VXNhZ2VPQ1NQU2lnbmluZyA9IDkKICAjICBFeHRLZXlVc2FnZU1pY3Jvc29mdFNlcnZlckdhdGVkQ3J5cHRvID0gMTAKICAjICBFeHRLZXlVc2FnZU5ldHNjYXBlU2VydmVyR2F0ZWRDcnlwdG8gPSAxMQogICMgIEV4dEtleVVzYWdlTWljcm9zb2Z0Q29tbWVyY2lhbENvZGVTaWduaW5nID0gMTIKICAjICBFeHRLZXlVc2FnZU1pY3Jvc29mdEtlcm5lbENvZGVTaWduaW5nID0gMTMKIyBFeHRyYUV4dGVuc2lvbnM6IHRydWUKIyBTQU5Vc2FnZTogdHJ1ZQojIENSTERpc3RyaWJ1dGlvblBvaW50cy4gTGlzdCBvZiBVUkkgc3RyaW5ncy4KI0NSTERpc3RyaWJ1dGlvblBvaW50czoKIyAgLSBodHRwOi8vY3JsLmxhYXZhdC5jb20vcHJvZHVjdHMtMC9yb290LmNybAoKIyBQb2xpY3lJZGVudGlmaWVycy4gTGlzdCBvZiBBU04xIHBvbGljeSBPSURTCiNQb2xpY3lJZGVudGlmaWVyczoKIyAgLSAxLjEwLjEyMy40MzIuNC41CiMgIC0gMi4xMC4xMjMuNDMyLjQuNjUKCiMgRW5mb3JjZVVuaXF1ZUROIGVuYWJsZXMgdGhlIGNoZWNraW5nIGlmIGEgY2VydGlmaWNhdGUgaGFzIGJlZW4gaXNzdWVkIHdpdGggdGhlIHNhbWUgc3ViamVjdCBETiBmcm9tIHRoZSBDQQojIFZhbHVlcyB0cnVlIG9yIGZhbHNlCiNFbmZvcmNlVW5pcXVlRE46IHRydWUK"
}

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1/ profile add \
    -F device-cert-endentity-ecdsa-p256-SHA256-profile.yaml \
    -N "Initial Device Certificate EndEntity Profile EC" -T END
{
    "id": "4d48c275-445a-4e95-9cdb-064688010dc1",
    "profile_name": "Initial Device Certificate EndEntity Profile EC",
    "profile_type": 1,
    "profile_yaml": "IyBDb25maWcgZmlsZSBmb3IgdGhlIEVuZCBlbnRpdHkgcHJvZmlsZS4gRG8gbm90IHVzZSBUQUJTCi0tLQpOYW1lOiBFbmRFbnRpdHkgUHJvZmlsZQpETjoKICAjT3JnYW5pemF0aW9uOiBUZXN0IENvbXAKICBPcmdhbml6YXRpb246IExhYXZhdAogICNPcmdhbml6YXRpb25hbFVuaXQ6IFImRAogICNDb3VudHJ5OiBGSQogIENvdW50cnk6IEZJCiAgI1Byb3ZpbmNlOgogICMtIFNvbWV0aGluZwogICMgTG9jYWxpdHk6CiAgIyBTdHJlZXRBZGRyZXNzOgogICMgUG9zdGFsQ29kZToKICAjIFNlcmlhbE51bWJlcgogICMgQ29tbW9uTmFtZTogCiMgRW5kRW50aXR5IGlzIDEsIFN1YiBDQSBwcm9maWxlIDIgLCBSb290IHByb2ZpbGUgMwpQcm9maWxlVHlwZTogMQojIFNpZ25hdHVyZUFsZ29yaXRobXMKIyAgU0hBMVdpdGhSU0EgPSAzCiMgIFNIQTI1NldpdGhSU0EgPSA0CiMgIFNIQTM4NFdpdGhSU0EgPSA1CiMgIFNIQTUxMldpdGhSU0EgPSA2CiMgIERTQVdpdGhTSEExID0gNwojICBEU0FXaXRoU0hBMjU2ID0gOAojICBFQ0RTQVdpdGhTSEExID0gOQojICBFQ0RTQVdpdGhTSEEyNTYgPSAxMAojICBFQ0RTQVdpdGhTSEEzODQgPSAxMQojICBFQ0RTQVdpdGhTSEE1MTIgPSAxMgojICBTSEEyNTZXaXRoUlNBUFNTID0gMTMKIyAgU0hBMzg0V2l0aFJTQVBTUyA9IDE0CiMgIFNIQTUxMldpdGhSU0FQU1MgPSAxNQpTaWduYXR1cmVBbGdvcml0aG06IDEwCiMgS2V5QWxnb3JpdGhtcwojICAgUlNBQWxnb3JpdGhtID0gMQojICAgRUNEU0FBbGdvcml0aG0gPSAyCktleUFsZ29yaXRobTogMgojIFZhbGlkaXR5IG9mIHRoZSBjZXJ0aWZpY2F0ZSBpbiBkdXJhdGlvbiAobWF4IDI5MCB5ZWFycykgb3Igd2l0aCBhYnNvbHV0ZSBkYXRlIGluIFJGQzMzMzkgZS5nLiA5OTk5LTEyLTMxVDIzOjU5OjU5Wi4KIyBFeGFtcGxlIGluIGFic29sdXRlIGRhdGUgIjk5OTktMTItMzFUMjM6NTk6NTlaIi4KIyBFeGFtcGxlIGluIGR1cmF0aW9uICIxaDEwbTEwcyIuIE9ubHkgaCwgbSBhbmQvb3IgcyBhcmUgYWNjZXB0ZWQuClZhbGlkaXR5UGVyaW9kOiAiODc2MDAwaCIKQmFzaWNDb25zdHJhaW50czoKICBVc2U6IHRydWUKICBJc0NBOiBmYWxzZQpBZGRTS0k6IHRydWUKQWRkQUtJOiB0cnVlCiMgS2V5VXNhZ2VzCiMgIEtleVVzYWdlRGlnaXRhbFNpZ25hdHVyZSA9IDEKIyAgS2V5VXNhZ2VDb250ZW50Q29tbWl0bWVudCA9IDIKIyAgS2V5VXNhZ2VLZXlFbmNpcGhlcm1lbnQgPSA0CiMgIEtleVVzYWdlRGF0YUVuY2lwaGVybWVudCA9IDgKIyAgS2V5VXNhZ2VLZXlBZ3JlZW1lbnQgPSAxNgojICBLZXlVc2FnZUNlcnRTaWduID0gMzIgCiMgIEtleVVzYWdlQ1JMU2lnbiA9IDY0CiMgIEtleVVzYWdlRW5jaXBoZXJPbmx5ID0gMTI4CiMgIEtleVVzYWdlRGVjaXBoZXJPbmx5ID0gMjU2CktleVVzYWdlOgogIC0gMQogIC0gMTYKRXh0ZW5kZWRLZXlVc2FnZToKICAjIEV4dGVuZGVkS2V5VXNhZ2VzCiAgIyAgRXh0S2V5VXNhZ2VBbnkgPSAwCiAgIyAgRXh0S2V5VXNhZ2VTZXJ2ZXJBdXRoID0gMQogICMgIEV4dEtleVVzYWdlQ2xpZW50QXV0aCA9IDIKICAjICBFeHRLZXlVc2FnZUNvZGVTaWduaW5nID0gMwogICMgIEV4dEtleVVzYWdlRW1haWxQcm90ZWN0aW9uID0gNAogICMgIEV4dEtleVVzYWdlSVBTRUNFbmRTeXN0ZW0gPSA1CiAgIyAgRXh0S2V5VXNhZ2VJUFNFQ1R1bm5lbCA9IDYKICAjICBFeHRLZXlVc2FnZUlQU0VDVXNlciA9IDcKICAjICBFeHRLZXlVc2FnZVRpbWVTdGFtcGluZyA9IDgKICAjICBFeHRLZXlVc2FnZU9DU1BTaWduaW5nID0gOQogICMgIEV4dEtleVVzYWdlTWljcm9zb2Z0U2VydmVyR2F0ZWRDcnlwdG8gPSAxMAogICMgIEV4dEtleVVzYWdlTmV0c2NhcGVTZXJ2ZXJHYXRlZENyeXB0byA9IDExCiAgIyAgRXh0S2V5VXNhZ2VNaWNyb3NvZnRDb21tZXJjaWFsQ29kZVNpZ25pbmcgPSAxMgogICMgIEV4dEtleVVzYWdlTWljcm9zb2Z0S2VybmVsQ29kZVNpZ25pbmcgPSAxMwogIC0gMQogIC0gMgpFeHRyYUV4dGVuc2lvbnM6IHRydWUKU0FOVXNhZ2U6IHRydWUKIyBDUkxEaXN0cmlidXRpb25Qb2ludHMuIExpc3Qgb2YgVVJJIHN0cmluZ3MuCkNSTERpc3RyaWJ1dGlvblBvaW50czoKICAtIGh0dHA6Ly9jcmwubGFhdmF0LmNvbS9lMzdmMDQ1Yy5jcmwKIyBQb2xpY3lJZGVudGlmaWVycy4gTGlzdCBvZiBBU04xIHBvbGljeSBPSURTCiMgRW5mb3JjZVVuaXF1ZUROIGVuYWJsZXMgdGhlIGNoZWNraW5nIGlmIGEgY2VydGlmaWNhdGUgaGFzIGJlZW4gaXNzdWVkIHdpdGggdGhlIHNhbWUgc3ViamVjdCBETiBmcm9tIHRoZSBDQQojIFZhbHVlcyB0cnVlIG9yIGZhbHNlCiMgRW5mb3JjZVVuaXF1ZUROOiB0cnVlCg=="
}

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1/ profile add \
    -F client-cert-subca-ecdsa-p256-SHA256-profile.yaml \
    -N "Client Certificate Product Family SubCA Profile EC" -T SUB
{
    "id": "73011594-d7b7-428c-b38c-f3ba9213de81",
    "profile_name": "Client Certificate Product Family SubCA Profile EC",
    "profile_type": 2,
    "profile_yaml": "IyBDb25maWcgZmlsZSBmb3IgdGhlIFN1YkNBIHByb2ZpbGUuIERvIG5vdCB1c2UgVEFCUwotLS0KTmFtZTogQ2xpZW50IENlcnRpZmljYXRlIFByb2R1Y3QgRmFtaWx5IFN1YkNBIFByb2ZpbGUKIyBEaXN0aW5ndWlzaGVkIG5hbWUgb2YgdGhlIENBCkROOgogICMgT3JnYW5pemF0aW9uOiAKICBPcmdhbml6YXRpb246IExhYXZhdAogICMgT3JnYW5pemF0aW9uYWxVbml0OiBSJkQKICAjIENvdW50cnk6IEZJCiAgQ291bnRyeTogRkkKICAjIFByb3ZpbmNlOgogICMgTG9jYWxpdHk6CiAgIyBTdHJlZXRBZGRyZXNzOgogICMgUG9zdGFsQ29kZToKICAjIFNlcmlhbE51bWJlcgogICMgQ29tbW9uTmFtZTogSU1YNgojIEVuZEVudGl0eSBpcyAxLCBTdWIgQ0EgcHJvZmlsZSAyICwgUm9vdCBwcm9maWxlIDMKUHJvZmlsZVR5cGU6IDIKIyBTaWduYXR1cmVBbGdvcml0aG1zCiMgIFNIQTFXaXRoUlNBID0gMwojICBTSEEyNTZXaXRoUlNBID0gNAojICBTSEEzODRXaXRoUlNBID0gNQojICBTSEE1MTJXaXRoUlNBID0gNgojICBEU0FXaXRoU0hBMSA9IDcKIyAgRFNBV2l0aFNIQTI1NiA9IDgKIyAgRUNEU0FXaXRoU0hBMSA9IDkKIyAgRUNEU0FXaXRoU0hBMjU2ID0gMTAKIyAgRUNEU0FXaXRoU0hBMzg0ID0gMTEKIyAgRUNEU0FXaXRoU0hBNTEyID0gMTIKIyAgU0hBMjU2V2l0aFJTQVBTUyA9IDEzCiMgIFNIQTM4NFdpdGhSU0FQU1MgPSAxNAojICBTSEE1MTJXaXRoUlNBUFNTID0gMTUKU2lnbmF0dXJlQWxnb3JpdGhtOiAxMAojIEtleUFsZ29yaXRobXMKIyAgIFJTQUFsZ29yaXRobSA9IDEKIyAgIEVDRFNBQWxnb3JpdGhtID0gMgpLZXlBbGdvcml0aG06IDIKIyBWYWxpZGl0eSBvZiB0aGUgY2VydGlmaWNhdGUgaW4gZHVyYXRpb24gKG1heCAyOTAgeWVhcnMpIG9yIHdpdGggYWJzb2x1dGUgZGF0ZSBpbiBSRkMzMzM5IGUuZy4gOTk5OS0xMi0zMVQyMzo1OTo1OVouCiMgRXhhbXBsZSBpbiBhYnNvbHV0ZSBkYXRlICI5OTk5LTEyLTMxVDIzOjU5OjU5WiIuCiMgRXhhbXBsZSBpbiBkdXJhdGlvbiAiMWgxMG0xMHMiLiBPbmx5IGgsIG0gYW5kL29yIHMgYXJlIGFjY2VwdGVkLgpWYWxpZGl0eVBlcmlvZDogIjE3NTIwMGgiCkJhc2ljQ29uc3RyYWludHM6CiAgQmFzaWNDb25zdHJhaW50c1ZhbGlkOiB0cnVlCiAgSXNDQTogdHJ1ZQogIE1heFBhdGhMZW46IDAKICAjIE1heFBhdGhMZW5aZXJvIGluZGljYXRlcyB0aGF0IEJhc2ljQ29uc3RyYWludHNWYWxpZD09dHJ1ZQogICMgYW5kIE1heFBhdGhMZW49PTAgc2hvdWxkIGJlIGludGVycHJldGVkIGFzIGFuIGFjdHVhbAogICMgbWF4aW11bSBwYXRoIGxlbmd0aCBvZiB6ZXJvLiBPdGhlcndpc2UsIHRoYXQgY29tYmluYXRpb24gaXMKICAjIGludGVycHJldGVkIGFzIE1heFBhdGhMZW4gbm90IGJlaW5nIHNldC4KICBNYXhQYXRoTGVuWmVybzogdHJ1ZQpBZGRTS0k6IHRydWUKQWRkQUtJOiB0cnVlCiMgS2V5VXNhZ2VzCiMgIEtleVVzYWdlRGlnaXRhbFNpZ25hdHVyZSA9IDEKIyAgS2V5VXNhZ2VDb250ZW50Q29tbWl0bWVudCA9IDIKIyAgS2V5VXNhZ2VLZXlFbmNpcGhlcm1lbnQgPSA0CiMgIEtleVVzYWdlRGF0YUVuY2lwaGVybWVudCA9IDgKIyAgS2V5VXNhZ2VLZXlBZ3JlZW1lbnQgPSAxNgojICBLZXlVc2FnZUNlcnRTaWduID0gMzIgCiMgIEtleVVzYWdlQ1JMU2lnbiA9IDY0CiMgIEtleVVzYWdlRW5jaXBoZXJPbmx5ID0gMTI4CiMgIEtleVVzYWdlRGVjaXBoZXJPbmx5ID0gMjU2CktleVVzYWdlOgogIC0gMQogIC0gMzIKICAtIDY0CkV4dGVuZGVkS2V5VXNhZ2U6CiAgIyBFeHRlbmRlZEtleVVzYWdlcwogICMgIEV4dEtleVVzYWdlQW55ID0gMAogICMgIEV4dEtleVVzYWdlU2VydmVyQXV0aCA9IDEKICAjICBFeHRLZXlVc2FnZUNsaWVudEF1dGggPSAyCiAgIyAgRXh0S2V5VXNhZ2VDb2RlU2lnbmluZyA9IDMKICAjICBFeHRLZXlVc2FnZUVtYWlsUHJvdGVjdGlvbiA9IDQKICAjICBFeHRLZXlVc2FnZUlQU0VDRW5kU3lzdGVtID0gNQogICMgIEV4dEtleVVzYWdlSVBTRUNUdW5uZWwgPSA2CiAgIyAgRXh0S2V5VXNhZ2VJUFNFQ1VzZXIgPSA3CiAgIyAgRXh0S2V5VXNhZ2VUaW1lU3RhbXBpbmcgPSA4CiAgIyAgRXh0S2V5VXNhZ2VPQ1NQU2lnbmluZyA9IDkKICAjICBFeHRLZXlVc2FnZU1pY3Jvc29mdFNlcnZlckdhdGVkQ3J5cHRvID0gMTAKICAjICBFeHRLZXlVc2FnZU5ldHNjYXBlU2VydmVyR2F0ZWRDcnlwdG8gPSAxMQogICMgIEV4dEtleVVzYWdlTWljcm9zb2Z0Q29tbWVyY2lhbENvZGVTaWduaW5nID0gMTIKICAjICBFeHRLZXlVc2FnZU1pY3Jvc29mdEtlcm5lbENvZGVTaWduaW5nID0gMTMKIyBFeHRyYUV4dGVuc2lvbnM6IHRydWUKIyBTQU5Vc2FnZTogdHJ1ZQojIENSTERpc3RyaWJ1dGlvblBvaW50cy4gTGlzdCBvZiBVUkkgc3RyaW5ncy4KI0NSTERpc3RyaWJ1dGlvblBvaW50czoKIyAgLSBodHRwOi8vY3JsLmxhYXZhdC5jb20vcHJvZHVjdHMtMC9yb290LmNybAoKIyBQb2xpY3lJZGVudGlmaWVycy4gTGlzdCBvZiBBU04xIHBvbGljeSBPSURTCiNQb2xpY3lJZGVudGlmaWVyczoKIyAgLSAxLjEwLjEyMy40MzIuNC41CiMgIC0gMi4xMC4xMjMuNDMyLjQuNjUKCiMgRW5mb3JjZVVuaXF1ZUROIGVuYWJsZXMgdGhlIGNoZWNraW5nIGlmIGEgY2VydGlmaWNhdGUgaGFzIGJlZW4gaXNzdWVkIHdpdGggdGhlIHNhbWUgc3ViamVjdCBETiBmcm9tIHRoZSBDQQojIFZhbHVlcyB0cnVlIG9yIGZhbHNlCiNFbmZvcmNlVW5pcXVlRE46IHRydWUK"
}
Profile added. Profile ID: 73011594-d7b7-428c-b38c-f3ba9213de81

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1/ profile add \
    -F client-cert-endentity-ecdsa-p256-SHA256-profile.yaml \
    -N "Client Certificate EndEntity Profile EC" -T END
{
    "id": "292017ef-1987-48f4-a0ca-915991ecf780",
    "profile_name": "Client Certificate EndEntity Profile EC",
    "profile_type": 1,
    "profile_yaml": "IyBDb25maWcgZmlsZSBmb3IgdGhlIEVuZCBlbnRpdHkgcHJvZmlsZS4gRG8gbm90IHVzZSBUQUJTCi0tLQpOYW1lOiBDbGllbnQgQ2VydGlmaWNhdGUgRW5kRW50aXR5IFByb2ZpbGUKRE46CiAgI09yZ2FuaXphdGlvbjogVGVzdCBDb21wCiAgT3JnYW5pemF0aW9uOiBMYWF2YXQKICAjT3JnYW5pemF0aW9uYWxVbml0OiBSJkQKICAjQ291bnRyeTogRkkKICBDb3VudHJ5OiBGSQogICNQcm92aW5jZToKICAjLSBTb21ldGhpbmcKICAjIExvY2FsaXR5OgogICMgU3RyZWV0QWRkcmVzczoKICAjIFBvc3RhbENvZGU6CiAgIyBTZXJpYWxOdW1iZXIKICAjIENvbW1vbk5hbWU6IAojIEVuZEVudGl0eSBpcyAxLCBTdWIgQ0EgcHJvZmlsZSAyICwgUm9vdCBwcm9maWxlIDMKUHJvZmlsZVR5cGU6IDEKIyBTaWduYXR1cmVBbGdvcml0aG1zCiMgIFNIQTFXaXRoUlNBID0gMwojICBTSEEyNTZXaXRoUlNBID0gNAojICBTSEEzODRXaXRoUlNBID0gNQojICBTSEE1MTJXaXRoUlNBID0gNgojICBEU0FXaXRoU0hBMSA9IDcKIyAgRFNBV2l0aFNIQTI1NiA9IDgKIyAgRUNEU0FXaXRoU0hBMSA9IDkKIyAgRUNEU0FXaXRoU0hBMjU2ID0gMTAKIyAgRUNEU0FXaXRoU0hBMzg0ID0gMTEKIyAgRUNEU0FXaXRoU0hBNTEyID0gMTIKIyAgU0hBMjU2V2l0aFJTQVBTUyA9IDEzCiMgIFNIQTM4NFdpdGhSU0FQU1MgPSAxNAojICBTSEE1MTJXaXRoUlNBUFNTID0gMTUKU2lnbmF0dXJlQWxnb3JpdGhtOiAxMAojIEtleUFsZ29yaXRobXMKIyAgIFJTQUFsZ29yaXRobSA9IDEKIyAgIEVDRFNBQWxnb3JpdGhtID0gMgpLZXlBbGdvcml0aG06IDIKIyBWYWxpZGl0eSBvZiB0aGUgY2VydGlmaWNhdGUgaW4gZHVyYXRpb24gKG1heCAyOTAgeWVhcnMpIG9yIHdpdGggYWJzb2x1dGUgZGF0ZSBpbiBSRkMzMzM5IGUuZy4gOTk5OS0xMi0zMVQyMzo1OTo1OVouCiMgRXhhbXBsZSBpbiBhYnNvbHV0ZSBkYXRlICI5OTk5LTEyLTMxVDIzOjU5OjU5WiIuCiMgRXhhbXBsZSBpbiBkdXJhdGlvbiAiMWgxMG0xMHMiLiBPbmx5IGgsIG0gYW5kL29yIHMgYXJlIGFjY2VwdGVkLgpWYWxpZGl0eVBlcmlvZDogIjE3NTIwaCIKQmFzaWNDb25zdHJhaW50czoKICBVc2U6IHRydWUKICBJc0NBOiBmYWxzZQpBZGRTS0k6IHRydWUKQWRkQUtJOiB0cnVlCiMgS2V5VXNhZ2VzCiMgIEtleVVzYWdlRGlnaXRhbFNpZ25hdHVyZSA9IDEKIyAgS2V5VXNhZ2VDb250ZW50Q29tbWl0bWVudCA9IDIKIyAgS2V5VXNhZ2VLZXlFbmNpcGhlcm1lbnQgPSA0CiMgIEtleVVzYWdlRGF0YUVuY2lwaGVybWVudCA9IDgKIyAgS2V5VXNhZ2VLZXlBZ3JlZW1lbnQgPSAxNgojICBLZXlVc2FnZUNlcnRTaWduID0gMzIgCiMgIEtleVVzYWdlQ1JMU2lnbiA9IDY0CiMgIEtleVVzYWdlRW5jaXBoZXJPbmx5ID0gMTI4CiMgIEtleVVzYWdlRGVjaXBoZXJPbmx5ID0gMjU2CktleVVzYWdlOgogIC0gMQogIC0gMTYKRXh0ZW5kZWRLZXlVc2FnZToKICAjIEV4dGVuZGVkS2V5VXNhZ2VzCiAgIyAgRXh0S2V5VXNhZ2VBbnkgPSAwCiAgIyAgRXh0S2V5VXNhZ2VTZXJ2ZXJBdXRoID0gMQogICMgIEV4dEtleVVzYWdlQ2xpZW50QXV0aCA9IDIKICAjICBFeHRLZXlVc2FnZUNvZGVTaWduaW5nID0gMwogICMgIEV4dEtleVVzYWdlRW1haWxQcm90ZWN0aW9uID0gNAogICMgIEV4dEtleVVzYWdlSVBTRUNFbmRTeXN0ZW0gPSA1CiAgIyAgRXh0S2V5VXNhZ2VJUFNFQ1R1bm5lbCA9IDYKICAjICBFeHRLZXlVc2FnZUlQU0VDVXNlciA9IDcKICAjICBFeHRLZXlVc2FnZVRpbWVTdGFtcGluZyA9IDgKICAjICBFeHRLZXlVc2FnZU9DU1BTaWduaW5nID0gOQogICMgIEV4dEtleVVzYWdlTWljcm9zb2Z0U2VydmVyR2F0ZWRDcnlwdG8gPSAxMAogICMgIEV4dEtleVVzYWdlTmV0c2NhcGVTZXJ2ZXJHYXRlZENyeXB0byA9IDExCiAgIyAgRXh0S2V5VXNhZ2VNaWNyb3NvZnRDb21tZXJjaWFsQ29kZVNpZ25pbmcgPSAxMgogICMgIEV4dEtleVVzYWdlTWljcm9zb2Z0S2VybmVsQ29kZVNpZ25pbmcgPSAxMwogIC0gMQogIC0gMgpFeHRyYUV4dGVuc2lvbnM6IHRydWUKU0FOVXNhZ2U6IHRydWUKIyBDUkxEaXN0cmlidXRpb25Qb2ludHMuIExpc3Qgb2YgVVJJIHN0cmluZ3MuCkNSTERpc3RyaWJ1dGlvblBvaW50czoKICAtIGh0dHA6Ly9jcmwubGFhdmF0LmNvbS9lMzdmMDQ1Yy5jcmwKIyBQb2xpY3lJZGVudGlmaWVycy4gTGlzdCBvZiBBU04xIHBvbGljeSBPSURTCiMgUG9saWN5SWRlbnRpZmllcnM6CiMgICAtIDEuMTAuMTIzLjQzMi40LjUKIyAgIC0gMi4xMC4xMjMuNDMyLjQuNjUKIyBFbmZvcmNlVW5pcXVlRE4gZW5hYmxlcyB0aGUgY2hlY2tpbmcgaWYgYSBjZXJ0aWZpY2F0ZSBoYXMgYmVlbiBpc3N1ZWQgd2l0aCB0aGUgc2FtZSBzdWJqZWN0IEROIGZyb20gdGhlIENBCiMgVmFsdWVzIHRydWUgb3IgZmFsc2UKIyBFbmZvcmNlVW5pcXVlRE46IHRydWUK"
}
Profile added. Profile ID: 292017ef-1987-48f4-a0ca-915991ecf780

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1/ profile getall
{
    "count": 6,
    "items": [
        {
            "id": "292017ef-1987-48f4-a0ca-915991ecf780",
            "profile_name": "Client Certificate EndEntity Profile EC",
            "profile_type": 1
        },
        {
            "id": "73011594-d7b7-428c-b38c-f3ba9213de81",
            "profile_name": "Client Certificate Product Family SubCA Profile EC",
            "profile_type": 2
        },
        {
            "id": "4d48c275-445a-4e95-9cdb-064688010dc1",
            "profile_name": "Initial Device Certificate EndEntity Profile EC",
            "profile_type": 1
        },
        {
            "id": "4a63eff1-29ae-43fa-baba-c319575291db",
            "profile_name": "Initial Device Certificate Product Family RootCA EC Profile",
            "profile_type": 3
        },
        {
            "id": "3adb4838-10d8-4ad5-b2b2-a711ef4a28db",
            "profile_name": "Initial Device Certificate Product Family SubCA Profile EC",
            "profile_type": 2
        },
        {
            "id": "bff08e23-9eaf-427c-a776-1dacbd546311",
            "profile_name": "Initial Device Certificate Product Family SubCA Profile EC for root issuer",
            "profile_type": 2
        }
    ],
    "next": "/cas/profiles/?page=1",
    "pages": 1,
    "prev": "/cas/profiles/?page=1"
}

Create products

Product for ROOT CA

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

  • ROOTPROFILEID=4a63eff1-29ae-43fa-baba-c319575291db
  • SUBPROFILEID=bff08e23-9eaf-427c-a776-1dacbd546311

In this product there is one operation.

$WRITERGROUP is 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-ecdsa-dev-ca-root.template
Product:
{
    "ca_info": [
        {
            "cert_override_payload": null,
            "certificate_type": "ROOT",
            "cn": "Root CA 2025",
            "crl_distribution_points": [
                "http://crl.company.com/e37f045c.crl"
            ],
            "crl_expiry": "24h",
            "crl_issue_interval": "12h",
            "csr": null,
            "description": "ROOT CA to issue SUB CA certificates",
            "external_request_id": null,
            "external_root": false,
            "id": null,
            "issuer_ca_id": null,
            "key_override_id": null,
            "key_type": "ECDSAP384",
            "leafs": [],
            "originating_id": null,
            "policy_identifiers": [],
            "product_id": null,
            "profile_id": "4a63eff1-29ae-43fa-baba-c319575291db",
            "state": null,
            "use_case": "DeviceCA"
        }
    ],
    "description": "Root CA for customer",
    "enabled": true,
    "external_request_id": null,
    "id": null,
    "name": "Product for ROOT 2025",
    "product_config_items": null,
    "product_operations": [
        {
            "approval_rule": {
                "allowed_groups": [
                    "b716abb1-2e3b-47a9-bca5-a3669faa50a6"
                ],
                "approval_groups": [],
                "blanket_groups": [],
                "description": "desc",
                "name": "This is rule"
            },
            "ca_use_case": null,
            "description": "Issuer of Subordinate CAs in ROOT CA",
            "id": null,
            "name": "Issue Subordinate CA",
            "operation_type": "IssueDeviceCertificate",
            "profile_id": "bff08e23-9eaf-427c-a776-1dacbd546311",
            "token": null
        }
    ],
    "product_type": "Production",
    "rnd_keys": [],
    "state": null
}
Is product ok(Y/N): y
{
    "ca_info": [],
    "description": "Root CA for customer",
    "enabled": null,
    "external_request_id": null,
    "id": "1193ecc1-8182-487c-86e4-91857527c1e5",
    "name": "Product for ROOT 2025",
    "product_config_items": null,
    "product_operations": [],
    "product_type": null,
    "rnd_keys": [],
    "state": 2
}
Product Add request sent. Request ID: 1193ecc1-8182-487c-86e4-91857527c1e5 state: ApprovalRequired

Approve product

The product was approved using the GUI.

  • productID = 1193ecc1-8182-487c-86e4-91857527c1e5

Create product for Device Family Sub CA

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

  • SUBPROFILEID=3adb4838-10d8-4ad5-b2b2-a711ef4a28db
  • ENDPROFILEID=3adb4838-10d8-4ad5-b2b2-a711ef4a28db

In this product there is one operation.

$WRITERGROUP is 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-ecdsa-dev-ca-ext1.template
Product:
{
    "ca_info": [
        {
            "cert_override_payload": null,
            "certificate_type": "SUBCA",
            "cn": "Device CA Product for Device Family Sub CA",
            "crl_distribution_points": [
                "http://crl.company.com/e37f045c.crl"
            ],
            "crl_expiry": "24h",
            "crl_issue_interval": "12h",
            "csr": null,
            "description": "Ca used for Product for Device Family Sub CA",
            "external_request_id": null,
            "external_root": true,
            "id": null,
            "issuer_ca_id": null,
            "key_override_id": null,
            "key_type": "ECDSAP256",
            "leafs": [],
            "originating_id": null,
            "policy_identifiers": [],
            "product_id": null,
            "profile_id": "3adb4838-10d8-4ad5-b2b2-a711ef4a28db",
            "state": null,
            "use_case": "DeviceCA"
        }
    ],
    "description": "Product testing hierarchy",
    "enabled": false,
    "external_request_id": null,
    "id": null,
    "name": "Product for Device Family Sub CA",
    "product_config_items": null,
    "product_operations": [
        {
            "approval_rule": {
                "allowed_groups": [
                    "b716abb1-2e3b-47a9-bca5-a3669faa50a6"
                ],
                "approval_groups": [],
                "blanket_groups": [],
                "description": "desc",
                "name": "This is rule"
            },
            "ca_use_case": null,
            "description": "Device certificates for Product for Device Family Sub CA",
            "id": null,
            "name": "Issue device certificates",
            "operation_type": "IssueDeviceCertificate",
            "profile_id": "3adb4838-10d8-4ad5-b2b2-a711ef4a28db",
            "token": null
        }
    ],
    "product_type": "RnD",
    "rnd_keys": [],
    "state": null
}
Is product ok(Y/N): y
{
    "ca_info": [],
    "description": "Product testing hierarchy",
    "enabled": null,
    "external_request_id": null,
    "id": "156a10af-325a-4f35-ba96-1e3d28bbe550",
    "name": "Product for Device Family Sub CA",
    "product_config_items": null,
    "product_operations": [],
    "product_type": null,
    "rnd_keys": [],
    "state": 2
}
Product Add request sent. Request ID: 156a10af-325a-4f35-ba96-1e3d28bbe550 state: ApprovalRequired

Approve product "Product for Device Family Sub CA"

The product was approved using the GUI.

  • productID = 156a10af-325a-4f35-ba96-1e3d28bbe550

Issue certificate for the SUB CA from ROOT

We need to get the CA ID from the created product. That datastructure contains the CSR. In this example jq tool is used to extract the id.

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1 product get \
    -I 156a10af-325a-4f35-ba96-1e3d28bbe550 | jq -r .ca_info[0].id
daba7613-a99d-4f32-8039-2c4d6792a08d

Get the CSR to a file named daba7613-a99d-4f32-8039-2c4d6792a08d.csr

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1 ca getcsr \
    --caid daba7613-a99d-4f32-8039-2c4d6792a08d \
    -O /tmp/daba7613-a99d-4f32-8039-2c4d6792a08d.csr
Payload written to file: /tmp/daba7613-a99d-4f32-8039-2c4d6792a08d.csr

The CSR is sent to the ROOT CA product. In this case product with id=1193ecc1-8182-487c-86e4-91857527c1e5

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1 production add \
    -P 1193ecc1-8182-487c-86e4-91857527c1e5 \
    -C /tmp/daba7613-a99d-4f32-8039-2c4d6792a08d.csr 
{
    "certificate": null,
    "chain": [],
    "error_status": null,
    "id": "78335f77-c392-4776-96f6-d9080c30c0f3",
    "state": 1,
    "subject": "CN=Device CA Product for Device Family Sub CA,O=Laavat,C=FI"
}
Certificate signing request sent. Request ID: 78335f77-c392-4776-96f6-d9080c30c0f3 state: Created

The created certificate is requested and stored to a file

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1 production get \
    -I 78335f77-c392-4776-96f6-d9080c30c0f3 \
    -O subca1
{
    "certificate": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNSRENDQWNxZ0F3SUJBZ0lSQUlvWXd0VnZYZDc0c3o0SExRUkYwc3d3Q2dZSUtvWkl6ajBFQXdNd05URUwKTUFrR0ExVUVCaE1DUmtreER6QU5CZ05WQkFvVEJreGhZWFpoZERFVk1CTUdBMVVFQXhNTVVtOXZkQ0JEUVNBeQpNREkxTUNBWERUSTFNRFl4TnpBNU16a3hObG9ZRHpJeE1qVXdOVEkwTURrek9URTJXakJUTVFzd0NRWURWUVFHCkV3SkdTVEVQTUEwR0ExVUVDaE1HVEdGaGRtRjBNVE13TVFZRFZRUURFeXBFWlhacFkyVWdRMEVnVUhKdlpIVmoKZENCbWIzSWdSR1YyYVdObElFWmhiV2xzZVNCVGRXSWdRMEV3V1RBVEJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQgpCd05DQUFUMEFMTXp4Q1pXMHVzZjRXWlQ2RU1yTHZ5Q3VHb2c3RXA1SkhadDVreG4xYjRtd0Frd1NFL1pPVmtHCm1TOEVRL1BKdk55WTQ1SUNjV1BKOVQ1cEtXSmtvNEdhTUlHWE1BNEdBMVVkRHdFQi93UUVBd0lCaGpBUEJnTlYKSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCVEZkUFArdEJzakZJZXREdFNGYWtuZjk0KytzakFmQmdOVgpIU01FR0RBV2dCVGMrWk83YWRaTFFyTjBFd0pkcGVjVExIeEl4ekEwQmdOVkhSOEVMVEFyTUNtZ0o2QWxoaU5vCmRIUndPaTh2WTNKc0xtTnZiWEJoYm5rdVkyOXRMMlV6TjJZd05EVmpMbU55YkRBS0JnZ3Foa2pPUFFRREF3Tm8KQURCbEFqQUhxd2hrMUlGKzNDNjk3bnlaTG1VZ2xqeWR6S1NNMnFYWkVqSjJEaU42VkdoVmc1cFp2NkxpQWl1awp4T3RKaXpVQ01RQ2h5SmRHdnpQeU8yeGNGcWZjZ2JmcTJxN3J1NkJ2UnJSMmUzbnBwNkkxaDUyeGVJK3JjcU1rCk9DZWIwLzhCVXMwPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==",
    "chain": [
        "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNEekNDQVpTZ0F3SUJBZ0lSQUxva3I5K0UyUkZGTHNoQ0NLNjN0Snd3Q2dZSUtvWkl6ajBFQXdNd05URUwKTUFrR0ExVUVCaE1DUmtreER6QU5CZ05WQkFvVEJreGhZWFpoZERFVk1CTUdBMVVFQXhNTVVtOXZkQ0JEUVNBeQpNREkxTUNBWERUSTFNRFl4TnpBNU1UazBNMW9ZRHpJeU1qVXdORE13TURreE9UUXpXakExTVFzd0NRWURWUVFHCkV3SkdTVEVQTUEwR0ExVUVDaE1HVEdGaGRtRjBNUlV3RXdZRFZRUURFd3hTYjI5MElFTkJJREl3TWpVd2RqQVEKQmdjcWhrak9QUUlCQmdVcmdRUUFJZ05pQUFRZ21nRFFqMlg2YWVXNVBZNk1xdVN6NDNqWnFmTWpzWFFLQnNGRAp5d1hLamtWMURSZkdxWGVJdWJOYzRWRGVXaHBhRk5QZXAvRGttS2s3REs1cnN4bUYramxOdnVEOWJjSEVVODNTCmZLakZXTFROVlFUWFZPY0NPaDU2VXpDWXBJdWpaakJrTUE0R0ExVWREd0VCL3dRRUF3SUJoakFTQmdOVkhSTUIKQWY4RUNEQUdBUUgvQWdFRE1CMEdBMVVkRGdRV0JCVGMrWk83YWRaTFFyTjBFd0pkcGVjVExIeEl4ekFmQmdOVgpIU01FR0RBV2dCVGMrWk83YWRaTFFyTjBFd0pkcGVjVExIeEl4ekFLQmdncWhrak9QUVFEQXdOcEFEQm1BakVBCnpML3lzZldjaDlYT3JpUmVQVGYwN2dYemJHUTJ5Y1pWSzc3NWM1SUMwRFNyVktpYjRXTFFuOG5PZkZ6YUlBRzMKQWpFQTBndEYyUjREZkx4Z1l2YWFRZlpUdmZTYWw1bWpsRS82OEx2a01PeGZHUHNNdXFHampsZnVQNnBSQm9neQpWZXRHCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
    ],
    "error_status": null,
    "id": "78335f77-c392-4776-96f6-d9080c30c0f3",
    "state": 16,
    "subject": "CN=Device CA Product for Device Family Sub CA,O=Laavat,C=FI"
}
Certificate signing request. Request ID: 78335f77-c392-4776-96f6-d9080c30c0f3 state: Ready
certificate written to: subca1.crt
certificate chain written to: subca1.chain

The chain is uploaded to the SUB CA product. After this the CA is ready.

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1 ca patch \
    --caid daba7613-a99d-4f32-8039-2c4d6792a08d \
    -F subca1.chain 
None
Chain upload

Create product for issuing the device certificates

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

  • SUBPROFILEID=3adb4838-10d8-4ad5-b2b2-a711ef4a28db
  • ENDPROFILEID=4d48c275-445a-4e95-9cdb-064688010dc1

In this product there is one operation.

$WRITERGROUP is 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-ecdsa-dev-ca-ext-sub1.template
Product:
{
    "ca_info": [
        {
            "cert_override_payload": null,
            "certificate_type": "SUBCA",
            "cn": "SUB CA for Device CA",
            "crl_distribution_points": [
                "http://crl.company.com/e37f045c.crl"
            ],
            "crl_expiry": "24h",
            "crl_issue_interval": "12h",
            "csr": null,
            "description": "Ca used for SUBCA1 for Device CA",
            "external_request_id": null,
            "external_root": true,
            "id": null,
            "issuer_ca_id": null,
            "key_override_id": null,
            "key_type": "ECDSAP256",
            "leafs": [],
            "originating_id": null,
            "policy_identifiers": [],
            "product_id": null,
            "profile_id": "3adb4838-10d8-4ad5-b2b2-a711ef4a28db",
            "state": null,
            "use_case": "DeviceCA"
        }
    ],
    "description": "SUB CA for customer",
    "enabled": true,
    "external_request_id": null,
    "id": null,
    "name": "Device CA",
    "product_config_items": null,
    "product_operations": [
        {
            "approval_rule": {
                "allowed_groups": [
                    "b716abb1-2e3b-47a9-bca5-a3669faa50a6"
                ],
                "approval_groups": [],
                "blanket_groups": [],
                "description": "desc",
                "name": "This is rule"
            },
            "ca_use_case": null,
            "description": "Device certificates for Device CA",
            "id": null,
            "name": "Issue Device certificates",
            "operation_type": "IssueDeviceCertificate",
            "profile_id": "4d48c275-445a-4e95-9cdb-064688010dc1",
            "token": null
        }
    ],
    "product_type": "Production",
    "rnd_keys": [],
    "state": null
}
Is product ok(Y/N): y
{
    "ca_info": [],
    "description": "SUB CA for customer",
    "enabled": null,
    "external_request_id": null,
    "id": "842b2c8e-543f-414b-a1a6-89347db38348",
    "name": "Device CA",
    "product_config_items": null,
    "product_operations": [],
    "product_type": null,
    "rnd_keys": [],
    "state": 2
}
Product Add request sent. Request ID: 842b2c8e-543f-414b-a1a6-89347db38348 state: ApprovalRequired

Approve product "Device CA"

The product was approved using the GUI.

  • productID = 842b2c8e-543f-414b-a1a6-89347db38348

Issue certificate for the Device CA from Sub CA

We need to get the CA ID from the created product. That datastructure contains the CSR. In this example jq tool is used to extract the id.

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1 product get \
    -I 842b2c8e-543f-414b-a1a6-89347db38348 | jq -r .ca_info[0].id
1b24a868-0b49-4225-a2d5-8a7ced78e439

Get the CSR to a file named 1b24a868-0b49-4225-a2d5-8a7ced78e439.csr

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1 ca getcsr \
    --caid 1b24a868-0b49-4225-a2d5-8a7ced78e439 \
    -O /tmp/1b24a868-0b49-4225-a2d5-8a7ced78e439.csr
Payload written to file: /tmp/1b24a868-0b49-4225-a2d5-8a7ced78e439.csr    

The CSR is sent to the SUB CA product. In this case product with id=156a10af-325a-4f35-ba96-1e3d28bbe550

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1 production add \
    -P 156a10af-325a-4f35-ba96-1e3d28bbe550 \
    -C /tmp/1b24a868-0b49-4225-a2d5-8a7ced78e439.csr 
{
    "certificate": null,
    "chain": [],
    "error_status": null,
    "id": "f287159f-e826-433c-9c97-fbdeab0949b2",
    "state": 1,
    "subject": "CN=SUB CA for Device CA,O=Laavat,C=FI"
}
Certificate signing request sent. Request ID: f287159f-e826-433c-9c97-fbdeab0949b2 state: Created

The created certificate is requested and stored to a file

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1 production get \
    -I f287159f-e826-433c-9c97-fbdeab0949b2 \
    -O deviceca
{
    "certificate": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNMRENDQWRHZ0F3SUJBZ0lRRUdmalhWaWMxRFRxeHQxMmdpc2I1REFLQmdncWhrak9QUVFEQWpCVE1Rc3cKQ1FZRFZRUUdFd0pHU1RFUE1BMEdBMVVFQ2hNR1RHRmhkbUYwTVRNd01RWURWUVFERXlwRVpYWnBZMlVnUTBFZwpVSEp2WkhWamRDQm1iM0lnUkdWMmFXTmxJRVpoYldsc2VTQlRkV0lnUTBFd0lCY05NalV3TmpFM01UQXdNakE0CldoZ1BNakV5TlRBMU1qUXdPVE01TVRaYU1EMHhDekFKQmdOVkJBWVRBa1pKTVE4d0RRWURWUVFLRXdaTVlXRjIKWVhReEhUQWJCZ05WQkFNVEZGTlZRaUJEUVNCbWIzSWdSR1YyYVdObElFTkJNRmt3RXdZSEtvWkl6ajBDQVFZSQpLb1pJemowREFRY0RRZ0FFZk1sNVpWSlFIN2xHYklOaDEvbkJITWdGNU5OUytSYW0zSXBVT3MrTXdkOVNhMmw3CkdRT09sQVhiVVpHNE1BNjE5dE1EY3lLalRidUZHeThMYjJHVFM2T0JtakNCbHpBT0JnTlZIUThCQWY4RUJBTUMKQVlZd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVXhldGl1OGRWaVFES3czMXBrZUJSZEd1RApZOTh3SHdZRFZSMGpCQmd3Rm9BVXhYVHovclFiSXhTSHJRN1VoV3BKMy9lUHZySXdOQVlEVlIwZkJDMHdLekFwCm9DZWdKWVlqYUhSMGNEb3ZMMk55YkM1amIyMXdZVzU1TG1OdmJTOWxNemRtTURRMVl5NWpjbXd3Q2dZSUtvWkkKemowRUF3SURTUUF3UmdJaEFPek5oY2JPSHdNYmFGOHlhaEw5QkpXSjhYazNtWnIrNHBHUWhLdlJnT01LQWlFQQp3SE9RcVhQa21mQ2JPa1VXc2VhREZKOHJkOE9oeU8yVUxLUU1qaEU0ZmJNPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==",
    "chain": [
        "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNSRENDQWNxZ0F3SUJBZ0lSQUlvWXd0VnZYZDc0c3o0SExRUkYwc3d3Q2dZSUtvWkl6ajBFQXdNd05URUwKTUFrR0ExVUVCaE1DUmtreER6QU5CZ05WQkFvVEJreGhZWFpoZERFVk1CTUdBMVVFQXhNTVVtOXZkQ0JEUVNBeQpNREkxTUNBWERUSTFNRFl4TnpBNU16a3hObG9ZRHpJeE1qVXdOVEkwTURrek9URTJXakJUTVFzd0NRWURWUVFHCkV3SkdTVEVQTUEwR0ExVUVDaE1HVEdGaGRtRjBNVE13TVFZRFZRUURFeXBFWlhacFkyVWdRMEVnVUhKdlpIVmoKZENCbWIzSWdSR1YyYVdObElFWmhiV2xzZVNCVGRXSWdRMEV3V1RBVEJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQgpCd05DQUFUMEFMTXp4Q1pXMHVzZjRXWlQ2RU1yTHZ5Q3VHb2c3RXA1SkhadDVreG4xYjRtd0Frd1NFL1pPVmtHCm1TOEVRL1BKdk55WTQ1SUNjV1BKOVQ1cEtXSmtvNEdhTUlHWE1BNEdBMVVkRHdFQi93UUVBd0lCaGpBUEJnTlYKSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCVEZkUFArdEJzakZJZXREdFNGYWtuZjk0KytzakFmQmdOVgpIU01FR0RBV2dCVGMrWk83YWRaTFFyTjBFd0pkcGVjVExIeEl4ekEwQmdOVkhSOEVMVEFyTUNtZ0o2QWxoaU5vCmRIUndPaTh2WTNKc0xtTnZiWEJoYm5rdVkyOXRMMlV6TjJZd05EVmpMbU55YkRBS0JnZ3Foa2pPUFFRREF3Tm8KQURCbEFqQUhxd2hrMUlGKzNDNjk3bnlaTG1VZ2xqeWR6S1NNMnFYWkVqSjJEaU42VkdoVmc1cFp2NkxpQWl1awp4T3RKaXpVQ01RQ2h5SmRHdnpQeU8yeGNGcWZjZ2JmcTJxN3J1NkJ2UnJSMmUzbnBwNkkxaDUyeGVJK3JjcU1rCk9DZWIwLzhCVXMwPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==",
        "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNEekNDQVpTZ0F3SUJBZ0lSQUxva3I5K0UyUkZGTHNoQ0NLNjN0Snd3Q2dZSUtvWkl6ajBFQXdNd05URUwKTUFrR0ExVUVCaE1DUmtreER6QU5CZ05WQkFvVEJreGhZWFpoZERFVk1CTUdBMVVFQXhNTVVtOXZkQ0JEUVNBeQpNREkxTUNBWERUSTFNRFl4TnpBNU1UazBNMW9ZRHpJeU1qVXdORE13TURreE9UUXpXakExTVFzd0NRWURWUVFHCkV3SkdTVEVQTUEwR0ExVUVDaE1HVEdGaGRtRjBNUlV3RXdZRFZRUURFd3hTYjI5MElFTkJJREl3TWpVd2RqQVEKQmdjcWhrak9QUUlCQmdVcmdRUUFJZ05pQUFRZ21nRFFqMlg2YWVXNVBZNk1xdVN6NDNqWnFmTWpzWFFLQnNGRAp5d1hLamtWMURSZkdxWGVJdWJOYzRWRGVXaHBhRk5QZXAvRGttS2s3REs1cnN4bUYramxOdnVEOWJjSEVVODNTCmZLakZXTFROVlFUWFZPY0NPaDU2VXpDWXBJdWpaakJrTUE0R0ExVWREd0VCL3dRRUF3SUJoakFTQmdOVkhSTUIKQWY4RUNEQUdBUUgvQWdFRE1CMEdBMVVkRGdRV0JCVGMrWk83YWRaTFFyTjBFd0pkcGVjVExIeEl4ekFmQmdOVgpIU01FR0RBV2dCVGMrWk83YWRaTFFyTjBFd0pkcGVjVExIeEl4ekFLQmdncWhrak9QUVFEQXdOcEFEQm1BakVBCnpML3lzZldjaDlYT3JpUmVQVGYwN2dYemJHUTJ5Y1pWSzc3NWM1SUMwRFNyVktpYjRXTFFuOG5PZkZ6YUlBRzMKQWpFQTBndEYyUjREZkx4Z1l2YWFRZlpUdmZTYWw1bWpsRS82OEx2a01PeGZHUHNNdXFHampsZnVQNnBSQm9neQpWZXRHCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
    ],
    "error_status": null,
    "id": "f287159f-e826-433c-9c97-fbdeab0949b2",
    "state": 16,
    "subject": "CN=SUB CA for Device CA,O=Laavat,C=FI"
}
Certificate signing request. Request ID: f287159f-e826-433c-9c97-fbdeab0949b2 state: Ready
certificate written to: deviceca.crt
certificate chain written to: deviceca.chain

The chain is uploaded to the SUB CA product. After this the CA is ready.

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1 ca patch \
    --caid 1b24a868-0b49-4225-a2d5-8a7ced78e439  \
    -F deviceca.chain 
None
Chain upload

Create product for Client Family Sub CA

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

  • SUBPROFILEID=73011594-d7b7-428c-b38c-f3ba9213de81
  • ENDPROFILEID=73011594-d7b7-428c-b38c-f3ba9213de81

In this product there is one operation.

$WRITERGROUP is 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-ecdsa-dev-ca-ext2.template 
Product:
{
    "ca_info": [
        {
            "cert_override_payload": null,
            "certificate_type": "SUBCA",
            "cn": "Client CA for Sub CA",
            "crl_distribution_points": [
                "http://crl.company.com/e37f045xxx.crl"
            ],
            "crl_expiry": "24h",
            "crl_issue_interval": "12h",
            "csr": null,
            "description": "Ca used for client authentication for Product for Client Sub CA",
            "external_request_id": null,
            "external_root": true,
            "id": null,
            "issuer_ca_id": null,
            "key_override_id": null,
            "key_type": "ECDSAP256",
            "leafs": [],
            "originating_id": null,
            "policy_identifiers": [],
            "product_id": null,
            "profile_id": "73011594-d7b7-428c-b38c-f3ba9213de81",
            "state": null,
            "use_case": "DeviceCA"
        }
    ],
    "description": "Client certs for authentication",
    "enabled": true,
    "external_request_id": null,
    "id": null,
    "name": "Product for Client Sub CA",
    "product_config_items": null,
    "product_operations": [
        {
            "approval_rule": {
                "allowed_groups": [
                    "b716abb1-2e3b-47a9-bca5-a3669faa50a6"
                ],
                "approval_groups": [],
                "blanket_groups": [],
                "description": "desc",
                "name": "This is rule"
            },
            "ca_use_case": null,
            "description": "Client certificates for Product for Client Sub CA",
            "id": null,
            "name": "Issue client certificates",
            "operation_type": "IssueDeviceCertificate",
            "profile_id": "73011594-d7b7-428c-b38c-f3ba9213de81",
            "token": null
        }
    ],
    "product_type": "Production",
    "rnd_keys": [],
    "state": null
}
Is product ok(Y/N): y
{
    "ca_info": [],
    "description": "Client certs for authentication",
    "enabled": null,
    "external_request_id": null,
    "id": "7f1429b1-8a20-4630-b782-e58a20075f82",
    "name": "Product for Client Sub CA",
    "product_config_items": null,
    "product_operations": [],
    "product_type": null,
    "rnd_keys": [],
    "state": 2
}
Product Add request sent. Request ID: 7f1429b1-8a20-4630-b782-e58a20075f82 state: ApprovalRequired

Approve product "Product for Client Sub CA"

The product was approved using the GUI.

  • productID = 7f1429b1-8a20-4630-b782-e58a20075f82

Issue certificate for the product "Product for Client Sub CA" from ROOT

We need to get the CA ID from the created product. That datastructure contains the CSR. In this example jq tool is used to extract the id.

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1 product get \
    -I 7f1429b1-8a20-4630-b782-e58a20075f82 | jq -r .ca_info[0].id
f0582789-9e53-49f5-b61e-f185cb18e405

Get the CSR to a file named f0582789-9e53-49f5-b61e-f185cb18e405.csr

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1 ca getcsr \
    --caid f0582789-9e53-49f5-b61e-f185cb18e405 \
    -O /tmp/f0582789-9e53-49f5-b61e-f185cb18e405.csr
Payload written to file: /tmp/f0582789-9e53-49f5-b61e-f185cb18e405.csr

The CSR is sent to the ROOT CA product. In this case product with id=1193ecc1-8182-487c-86e4-91857527c1e5

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1 production add \
    -P 1193ecc1-8182-487c-86e4-91857527c1e5 \
    -C /tmp/f0582789-9e53-49f5-b61e-f185cb18e405.csr 
{
    "certificate": null,
    "chain": [],
    "error_status": null,
    "id": "b688b2f5-0650-451a-b6df-6dfb2d565d49",
    "state": 1,
    "subject": "CN=Client CA for Sub CA,O=Laavat,C=FI"
}
Certificate signing request sent. Request ID: b688b2f5-0650-451a-b6df-6dfb2d565d49 state: Created

The created certificate is requested and stored to a file

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1 production get \
    -I b688b2f5-0650-451a-b6df-6dfb2d565d49 \
    -O subca2
{
    "certificate": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNMakNDQWJTZ0F3SUJBZ0lSQUw1ejdIcmZ4R1YwcmcxZm5qUzM3WTR3Q2dZSUtvWkl6ajBFQXdNd05URUwKTUFrR0ExVUVCaE1DUmtreER6QU5CZ05WQkFvVEJreGhZWFpoZERFVk1CTUdBMVVFQXhNTVVtOXZkQ0JEUVNBeQpNREkxTUNBWERUSTFNRFl4TnpFd01qUXlNMW9ZRHpJeE1qVXdOVEkwTVRBeU5ESXpXakE5TVFzd0NRWURWUVFHCkV3SkdTVEVQTUEwR0ExVUVDaE1HVEdGaGRtRjBNUjB3R3dZRFZRUURFeFJEYkdsbGJuUWdRMEVnWm05eUlGTjEKWWlCRFFUQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJIMWZRYzRBR3E5SlBwRjZieWg1c254bQpHTTNXQ0w5dkM3R3dDM1ZCcHd1NUZoTjM4NmlqSmpiSU4wQ3V0ZlJIY2t2dTNldHQralg5ZWFYVkRWUHJGS0tqCmdab3dnWmN3RGdZRFZSMFBBUUgvQkFRREFnR0dNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdIUVlEVlIwT0JCWUUKRkpTaDZZZ2Y0THJJZURMVERFUzlHUEE1TjM2S01COEdBMVVkSXdRWU1CYUFGTno1azd0cDFrdENzM1FUQWwybAo1eE1zZkVqSE1EUUdBMVVkSHdRdE1Dc3dLYUFub0NXR0kyaDBkSEE2THk5amNtd3VZMjl0Y0dGdWVTNWpiMjB2ClpUTTNaakEwTldNdVkzSnNNQW9HQ0NxR1NNNDlCQU1EQTJnQU1HVUNNQmErNHZGQkQvQ0FJNWlOR2NxVFJ2YW4KTVNPYXc1YlNRRm40UmNqUERsRHlHVkJaMXZRcjNXbW1hZ1VlTHcrVU1BSXhBTDBtbkVwZDZ6QWlBWVJ3K1M3OAp3dmdzMzlKY2Y3V1A3VEdBMExKQXVMbUVTdW9NK3pVYmJwQnBLSlA1MlZyN0FnPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=",
    "chain": [
        "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNEekNDQVpTZ0F3SUJBZ0lSQUxva3I5K0UyUkZGTHNoQ0NLNjN0Snd3Q2dZSUtvWkl6ajBFQXdNd05URUwKTUFrR0ExVUVCaE1DUmtreER6QU5CZ05WQkFvVEJreGhZWFpoZERFVk1CTUdBMVVFQXhNTVVtOXZkQ0JEUVNBeQpNREkxTUNBWERUSTFNRFl4TnpBNU1UazBNMW9ZRHpJeU1qVXdORE13TURreE9UUXpXakExTVFzd0NRWURWUVFHCkV3SkdTVEVQTUEwR0ExVUVDaE1HVEdGaGRtRjBNUlV3RXdZRFZRUURFd3hTYjI5MElFTkJJREl3TWpVd2RqQVEKQmdjcWhrak9QUUlCQmdVcmdRUUFJZ05pQUFRZ21nRFFqMlg2YWVXNVBZNk1xdVN6NDNqWnFmTWpzWFFLQnNGRAp5d1hLamtWMURSZkdxWGVJdWJOYzRWRGVXaHBhRk5QZXAvRGttS2s3REs1cnN4bUYramxOdnVEOWJjSEVVODNTCmZLakZXTFROVlFUWFZPY0NPaDU2VXpDWXBJdWpaakJrTUE0R0ExVWREd0VCL3dRRUF3SUJoakFTQmdOVkhSTUIKQWY4RUNEQUdBUUgvQWdFRE1CMEdBMVVkRGdRV0JCVGMrWk83YWRaTFFyTjBFd0pkcGVjVExIeEl4ekFmQmdOVgpIU01FR0RBV2dCVGMrWk83YWRaTFFyTjBFd0pkcGVjVExIeEl4ekFLQmdncWhrak9QUVFEQXdOcEFEQm1BakVBCnpML3lzZldjaDlYT3JpUmVQVGYwN2dYemJHUTJ5Y1pWSzc3NWM1SUMwRFNyVktpYjRXTFFuOG5PZkZ6YUlBRzMKQWpFQTBndEYyUjREZkx4Z1l2YWFRZlpUdmZTYWw1bWpsRS82OEx2a01PeGZHUHNNdXFHampsZnVQNnBSQm9neQpWZXRHCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
    ],
    "error_status": null,
    "id": "b688b2f5-0650-451a-b6df-6dfb2d565d49",
    "state": 16,
    "subject": "CN=Client CA for Sub CA,O=Laavat,C=FI"
}
Certificate signing request. Request ID: b688b2f5-0650-451a-b6df-6dfb2d565d49 state: Ready
certificate written to: subca2.crt
certificate chain written to: subca2.chain

The chain is uploaded to the SUB CA product. After this the CA is ready.

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1 ca patch \
    --caid f0582789-9e53-49f5-b61e-f185cb18e405 \
    -F subca2.chain 
None
Chain upload

Create product for issuing the client certificates

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

  • SUBPROFILEID=73011594-d7b7-428c-b38c-f3ba9213de81
  • ENDPROFILEID=292017ef-1987-48f4-a0ca-915991ecf780

In this product there is one operation.

$WRITERGROUP is 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-ecdsa-dev-ca-ext-sub2.template
Product:
{
    "ca_info": [
        {
            "cert_override_payload": null,
            "certificate_type": "SUBCA",
            "cn": "Client CA",
            "crl_distribution_points": [
                "http://crl.company.com/e37f045c.crl"
            ],
            "crl_expiry": "24h",
            "crl_issue_interval": "12h",
            "csr": null,
            "description": "Ca used for SUBCA2 for Product for issuing End-Entity client certificates",
            "external_request_id": null,
            "external_root": true,
            "id": null,
            "issuer_ca_id": null,
            "key_override_id": null,
            "key_type": "ECDSAP256",
            "leafs": [],
            "originating_id": null,
            "policy_identifiers": [],
            "product_id": null,
            "profile_id": "73011594-d7b7-428c-b38c-f3ba9213de81",
            "state": null,
            "use_case": "DeviceCA"
        }
    ],
    "description": "SUB CA for customer",
    "enabled": true,
    "external_request_id": null,
    "id": null,
    "name": "Product for issuing End-Entity client certificates",
    "product_config_items": null,
    "product_operations": [
        {
            "approval_rule": {
                "allowed_groups": [
                    "b716abb1-2e3b-47a9-bca5-a3669faa50a6"
                ],
                "approval_groups": [],
                "blanket_groups": [],
                "description": "desc",
                "name": "This is rule"
            },
            "ca_use_case": null,
            "description": "Client certificates for Product for issuing End-Entity client certificates",
            "id": null,
            "name": "Issue client certificates",
            "operation_type": "IssueDeviceCertificate",
            "profile_id": "292017ef-1987-48f4-a0ca-915991ecf780",
            "token": null
        }
    ],
    "product_type": "Production",
    "rnd_keys": [],
    "state": null
}
Is product ok(Y/N): y
{
    "ca_info": [],
    "description": "SUB CA for customer",
    "enabled": null,
    "external_request_id": null,
    "id": "680bc232-092e-474b-a27a-67767cf2cdad",
    "name": "Product for issuing End-Entity client certificates",
    "product_config_items": null,
    "product_operations": [],
    "product_type": null,
    "rnd_keys": [],
    "state": 2
}
Product Add request sent. Request ID: 680bc232-092e-474b-a27a-67767cf2cdad state: ApprovalRequired

Approve product "Product for issuing End-Entity client certificates"

The product was approved using the GUI.

  • productID = 680bc232-092e-474b-a27a-67767cf2cdad

Issue certificate for product "Product for issuing End-Entity client certificates" from Sub CA

We need to get the CA ID from the created product. That datastructure contains the CSR. In this example jq tool is used to extract the id.

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1 product get \
    -I 680bc232-092e-474b-a27a-67767cf2cdad | jq -r .ca_info[0].id
bc4c6917-1b2a-4f21-bbe0-2e4f12e0b6da

Get the CSR to a file named bc4c6917-1b2a-4f21-bbe0-2e4f12e0b6da.csr

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1 ca getcsr \
    --caid bc4c6917-1b2a-4f21-bbe0-2e4f12e0b6da \
    -O /tmp/bc4c6917-1b2a-4f21-bbe0-2e4f12e0b6da.csr
Payload written to file: /tmp/bc4c6917-1b2a-4f21-bbe0-2e4f12e0b6da.csr    

The CSR is sent to the SUB CA product. In this case product with id=7f1429b1-8a20-4630-b782-e58a20075f82

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1 production add \
    -P 7f1429b1-8a20-4630-b782-e58a20075f82 \
    -C /tmp/bc4c6917-1b2a-4f21-bbe0-2e4f12e0b6da.csr 
{
    "certificate": null,
    "chain": [],
    "error_status": null,
    "id": "02482c85-9423-4abc-b4d0-54cbc2ee9d76",
    "state": 1,
    "subject": "CN=Client CA,O=Laavat,C=FI"
}
Certificate signing request sent. Request ID: 02482c85-9423-4abc-b4d0-54cbc2ee9d76 state: Created

The created certificate is requested and stored to a file

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1 production get \
    -I 02482c85-9423-4abc-b4d0-54cbc2ee9d76 \
    -O clientca
{
    "certificate": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNDakNDQWJHZ0F3SUJBZ0lSQVBHZlVqYUt1VmdHRmJqSmY3eDgxY293Q2dZSUtvWkl6ajBFQXdJd1BURUwKTUFrR0ExVUVCaE1DUmtreER6QU5CZ05WQkFvVEJreGhZWFpoZERFZE1Cc0dBMVVFQXhNVVEyeHBaVzUwSUVOQgpJR1p2Y2lCVGRXSWdRMEV3SGhjTk1qVXdOakUzTVRBek1qUXlXaGNOTkRVd05qRXlNVEF6TWpReVdqQXlNUXN3CkNRWURWUVFHRXdKR1NURVBNQTBHQTFVRUNoTUdUR0ZoZG1GME1SSXdFQVlEVlFRREV3bERiR2xsYm5RZ1EwRXcKV1RBVEJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQVJSUENKQlB6L3VIN2tRbVp4VE1NQnRaczFMWTFIMApSclRHRkJNWjdHSGtGVWt2bWk0cE13Ujl0cHhVS3p0eTREdEZycXhkTFE1U2tETTJoM2hDU2wwRG80R2NNSUdaCk1BNEdBMVVkRHdFQi93UUVBd0lCaGpBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJUR09hUFAKSWs4U1VJdVhYa0dYeFhBdzA3b3ErREFmQmdOVkhTTUVHREFXZ0JTVW9lbUlIK0M2eUhneTB3eEV2Ump3T1RkKwppakEyQmdOVkhSOEVMekF0TUN1Z0thQW5oaVZvZEhSd09pOHZZM0pzTG1OdmJYQmhibmt1WTI5dEwyVXpOMll3Ck5EVjRlSGd1WTNKc01Bb0dDQ3FHU000OUJBTUNBMGNBTUVRQ0lCR0F6cmowc2hTTVRnZDZ1TTdVMGtaOVEyOEcKMUZkQVBXUjFHb0lUdEwrY0FpQmJqUUdnNHZlR2ZEYzVJa0drbTlNNE1LS25nYi9nRFZRcVhYV3NZV3lDemc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==",
    "chain": [
        "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNMakNDQWJTZ0F3SUJBZ0lSQUw1ejdIcmZ4R1YwcmcxZm5qUzM3WTR3Q2dZSUtvWkl6ajBFQXdNd05URUwKTUFrR0ExVUVCaE1DUmtreER6QU5CZ05WQkFvVEJreGhZWFpoZERFVk1CTUdBMVVFQXhNTVVtOXZkQ0JEUVNBeQpNREkxTUNBWERUSTFNRFl4TnpFd01qUXlNMW9ZRHpJeE1qVXdOVEkwTVRBeU5ESXpXakE5TVFzd0NRWURWUVFHCkV3SkdTVEVQTUEwR0ExVUVDaE1HVEdGaGRtRjBNUjB3R3dZRFZRUURFeFJEYkdsbGJuUWdRMEVnWm05eUlGTjEKWWlCRFFUQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJIMWZRYzRBR3E5SlBwRjZieWg1c254bQpHTTNXQ0w5dkM3R3dDM1ZCcHd1NUZoTjM4NmlqSmpiSU4wQ3V0ZlJIY2t2dTNldHQralg5ZWFYVkRWUHJGS0tqCmdab3dnWmN3RGdZRFZSMFBBUUgvQkFRREFnR0dNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdIUVlEVlIwT0JCWUUKRkpTaDZZZ2Y0THJJZURMVERFUzlHUEE1TjM2S01COEdBMVVkSXdRWU1CYUFGTno1azd0cDFrdENzM1FUQWwybAo1eE1zZkVqSE1EUUdBMVVkSHdRdE1Dc3dLYUFub0NXR0kyaDBkSEE2THk5amNtd3VZMjl0Y0dGdWVTNWpiMjB2ClpUTTNaakEwTldNdVkzSnNNQW9HQ0NxR1NNNDlCQU1EQTJnQU1HVUNNQmErNHZGQkQvQ0FJNWlOR2NxVFJ2YW4KTVNPYXc1YlNRRm40UmNqUERsRHlHVkJaMXZRcjNXbW1hZ1VlTHcrVU1BSXhBTDBtbkVwZDZ6QWlBWVJ3K1M3OAp3dmdzMzlKY2Y3V1A3VEdBMExKQXVMbUVTdW9NK3pVYmJwQnBLSlA1MlZyN0FnPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=",
        "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNEekNDQVpTZ0F3SUJBZ0lSQUxva3I5K0UyUkZGTHNoQ0NLNjN0Snd3Q2dZSUtvWkl6ajBFQXdNd05URUwKTUFrR0ExVUVCaE1DUmtreER6QU5CZ05WQkFvVEJreGhZWFpoZERFVk1CTUdBMVVFQXhNTVVtOXZkQ0JEUVNBeQpNREkxTUNBWERUSTFNRFl4TnpBNU1UazBNMW9ZRHpJeU1qVXdORE13TURreE9UUXpXakExTVFzd0NRWURWUVFHCkV3SkdTVEVQTUEwR0ExVUVDaE1HVEdGaGRtRjBNUlV3RXdZRFZRUURFd3hTYjI5MElFTkJJREl3TWpVd2RqQVEKQmdjcWhrak9QUUlCQmdVcmdRUUFJZ05pQUFRZ21nRFFqMlg2YWVXNVBZNk1xdVN6NDNqWnFmTWpzWFFLQnNGRAp5d1hLamtWMURSZkdxWGVJdWJOYzRWRGVXaHBhRk5QZXAvRGttS2s3REs1cnN4bUYramxOdnVEOWJjSEVVODNTCmZLakZXTFROVlFUWFZPY0NPaDU2VXpDWXBJdWpaakJrTUE0R0ExVWREd0VCL3dRRUF3SUJoakFTQmdOVkhSTUIKQWY4RUNEQUdBUUgvQWdFRE1CMEdBMVVkRGdRV0JCVGMrWk83YWRaTFFyTjBFd0pkcGVjVExIeEl4ekFmQmdOVgpIU01FR0RBV2dCVGMrWk83YWRaTFFyTjBFd0pkcGVjVExIeEl4ekFLQmdncWhrak9QUVFEQXdOcEFEQm1BakVBCnpML3lzZldjaDlYT3JpUmVQVGYwN2dYemJHUTJ5Y1pWSzc3NWM1SUMwRFNyVktpYjRXTFFuOG5PZkZ6YUlBRzMKQWpFQTBndEYyUjREZkx4Z1l2YWFRZlpUdmZTYWw1bWpsRS82OEx2a01PeGZHUHNNdXFHampsZnVQNnBSQm9neQpWZXRHCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
    ],
    "error_status": null,
    "id": "02482c85-9423-4abc-b4d0-54cbc2ee9d76",
    "state": 16,
    "subject": "CN=Client CA,O=Laavat,C=FI"
}
Certificate signing request. Request ID: 02482c85-9423-4abc-b4d0-54cbc2ee9d76 state: Ready
certificate written to: clientca.crt
certificate chain written to: clientca.chain

The chain is uploaded to the SUB CA product. After this the CA is ready.

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1 ca patch \
    --caid bc4c6917-1b2a-4f21-bbe0-2e4f12e0b6da \
    -F clientca.chain 
None
Chain upload

Issuing Client certificates

Create CSR

In real life scenario the user creates the key and the corresponding CSR.

(venv) $ openssl ecparam \
                             -name prime256v1 \
                             -genkey -noout \
                             -conv_form uncompressed \
                             -out client.key
(venv) $ openssl req \
                             -new -nodes \
                             -key client.key \
                             -outform DER \
                             -subj "/C=FI/O=Customer/CN=user-123" \
                             2>/dev/null > /tmp/csr.bin

Send the CSR for issuance

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1/ production add \
    -P 680bc232-092e-474b-a27a-67767cf2cdad \
    -C /tmp/csr.bin 
{
    "certificate": null,
    "chain": [],
    "error_status": null,
    "id": "7066508a-7238-4db8-bcb3-e896da4dcda1",
    "state": 1,
    "subject": "CN=device-123,O=Customer,C=FI"
}
Certificate signing request sent. Request ID: 7066508a-7238-4db8-bcb3-e896da4dcda1 state: Created

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1/ production get \
    -I 7066508a-7238-4db8-bcb3-e896da4dcda1 \
    -O client
{
    "certificate": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNERENDQWJPZ0F3SUJBZ0lSQVB4VVFnWXJOTXJMMU1EamRRODVGUzB3Q2dZSUtvWkl6ajBFQXdJd01qRUwKTUFrR0ExVUVCaE1DUmtreER6QU5CZ05WQkFvVEJreGhZWFpoZERFU01CQUdBMVVFQXhNSlEyeHBaVzUwSUVOQgpNQjRYRFRJMU1EWXhOekV3TXpnME9Wb1hEVEkzTURZeE56RXdNemcwT1Zvd016RUxNQWtHQTFVRUJoTUNSa2t4CkR6QU5CZ05WQkFvVEJreGhZWFpoZERFVE1CRUdBMVVFQXhNS1pHVjJhV05sTFRFeU16QlpNQk1HQnlxR1NNNDkKQWdFR0NDcUdTTTQ5QXdFSEEwSUFCTlVUU202OXFrWnpnSTBOaHVRbkcrYnZFYnlONmhtMGNVZ1MzZTIyRThtZApuOXl1MnRWQTUyaUlOcFJkUlViWkIzbFE0RjJkdGZEVUpJRW5ydFIwL2IramdhZ3dnYVV3RGdZRFZSMFBBUUgvCkJBUURBZ09JTUIwR0ExVWRKUVFXTUJRR0NDc0dBUVVGQndNQkJnZ3JCZ0VGQlFjREFqQWRCZ05WSFE0RUZnUVUKQS9WVm5NbU8vejl0NkxWU3d6dEdCeGp6TEx3d0h3WURWUjBqQkJnd0ZvQVV4am1qenlKUEVsQ0xsMTVCbDhWdwpNTk82S3Znd05BWURWUjBmQkMwd0t6QXBvQ2VnSllZamFIUjBjRG92TDJOeWJDNWpiMjF3WVc1NUxtTnZiUzlsCk16ZG1NRFExWXk1amNtd3dDZ1lJS29aSXpqMEVBd0lEUndBd1JBSWdYL0VSUElRMXFXNSs1NWcyWk4zNmVOL0UKRVZSWE1kS0Z1bktOVW9JeGZPOENJSGQ4bXdGd3p1bEdYRzNZYkN5OHByUk9yTnB1TTFXTlA2VXQzNkhaeHdURAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==",
    "chain": [
        "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNDakNDQWJHZ0F3SUJBZ0lSQVBHZlVqYUt1VmdHRmJqSmY3eDgxY293Q2dZSUtvWkl6ajBFQXdJd1BURUwKTUFrR0ExVUVCaE1DUmtreER6QU5CZ05WQkFvVEJreGhZWFpoZERFZE1Cc0dBMVVFQXhNVVEyeHBaVzUwSUVOQgpJR1p2Y2lCVGRXSWdRMEV3SGhjTk1qVXdOakUzTVRBek1qUXlXaGNOTkRVd05qRXlNVEF6TWpReVdqQXlNUXN3CkNRWURWUVFHRXdKR1NURVBNQTBHQTFVRUNoTUdUR0ZoZG1GME1SSXdFQVlEVlFRREV3bERiR2xsYm5RZ1EwRXcKV1RBVEJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQVJSUENKQlB6L3VIN2tRbVp4VE1NQnRaczFMWTFIMApSclRHRkJNWjdHSGtGVWt2bWk0cE13Ujl0cHhVS3p0eTREdEZycXhkTFE1U2tETTJoM2hDU2wwRG80R2NNSUdaCk1BNEdBMVVkRHdFQi93UUVBd0lCaGpBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJUR09hUFAKSWs4U1VJdVhYa0dYeFhBdzA3b3ErREFmQmdOVkhTTUVHREFXZ0JTVW9lbUlIK0M2eUhneTB3eEV2Ump3T1RkKwppakEyQmdOVkhSOEVMekF0TUN1Z0thQW5oaVZvZEhSd09pOHZZM0pzTG1OdmJYQmhibmt1WTI5dEwyVXpOMll3Ck5EVjRlSGd1WTNKc01Bb0dDQ3FHU000OUJBTUNBMGNBTUVRQ0lCR0F6cmowc2hTTVRnZDZ1TTdVMGtaOVEyOEcKMUZkQVBXUjFHb0lUdEwrY0FpQmJqUUdnNHZlR2ZEYzVJa0drbTlNNE1LS25nYi9nRFZRcVhYV3NZV3lDemc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==",
        "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNMakNDQWJTZ0F3SUJBZ0lSQUw1ejdIcmZ4R1YwcmcxZm5qUzM3WTR3Q2dZSUtvWkl6ajBFQXdNd05URUwKTUFrR0ExVUVCaE1DUmtreER6QU5CZ05WQkFvVEJreGhZWFpoZERFVk1CTUdBMVVFQXhNTVVtOXZkQ0JEUVNBeQpNREkxTUNBWERUSTFNRFl4TnpFd01qUXlNMW9ZRHpJeE1qVXdOVEkwTVRBeU5ESXpXakE5TVFzd0NRWURWUVFHCkV3SkdTVEVQTUEwR0ExVUVDaE1HVEdGaGRtRjBNUjB3R3dZRFZRUURFeFJEYkdsbGJuUWdRMEVnWm05eUlGTjEKWWlCRFFUQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJIMWZRYzRBR3E5SlBwRjZieWg1c254bQpHTTNXQ0w5dkM3R3dDM1ZCcHd1NUZoTjM4NmlqSmpiSU4wQ3V0ZlJIY2t2dTNldHQralg5ZWFYVkRWUHJGS0tqCmdab3dnWmN3RGdZRFZSMFBBUUgvQkFRREFnR0dNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdIUVlEVlIwT0JCWUUKRkpTaDZZZ2Y0THJJZURMVERFUzlHUEE1TjM2S01COEdBMVVkSXdRWU1CYUFGTno1azd0cDFrdENzM1FUQWwybAo1eE1zZkVqSE1EUUdBMVVkSHdRdE1Dc3dLYUFub0NXR0kyaDBkSEE2THk5amNtd3VZMjl0Y0dGdWVTNWpiMjB2ClpUTTNaakEwTldNdVkzSnNNQW9HQ0NxR1NNNDlCQU1EQTJnQU1HVUNNQmErNHZGQkQvQ0FJNWlOR2NxVFJ2YW4KTVNPYXc1YlNRRm40UmNqUERsRHlHVkJaMXZRcjNXbW1hZ1VlTHcrVU1BSXhBTDBtbkVwZDZ6QWlBWVJ3K1M3OAp3dmdzMzlKY2Y3V1A3VEdBMExKQXVMbUVTdW9NK3pVYmJwQnBLSlA1MlZyN0FnPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=",
        "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNEekNDQVpTZ0F3SUJBZ0lSQUxva3I5K0UyUkZGTHNoQ0NLNjN0Snd3Q2dZSUtvWkl6ajBFQXdNd05URUwKTUFrR0ExVUVCaE1DUmtreER6QU5CZ05WQkFvVEJreGhZWFpoZERFVk1CTUdBMVVFQXhNTVVtOXZkQ0JEUVNBeQpNREkxTUNBWERUSTFNRFl4TnpBNU1UazBNMW9ZRHpJeU1qVXdORE13TURreE9UUXpXakExTVFzd0NRWURWUVFHCkV3SkdTVEVQTUEwR0ExVUVDaE1HVEdGaGRtRjBNUlV3RXdZRFZRUURFd3hTYjI5MElFTkJJREl3TWpVd2RqQVEKQmdjcWhrak9QUUlCQmdVcmdRUUFJZ05pQUFRZ21nRFFqMlg2YWVXNVBZNk1xdVN6NDNqWnFmTWpzWFFLQnNGRAp5d1hLamtWMURSZkdxWGVJdWJOYzRWRGVXaHBhRk5QZXAvRGttS2s3REs1cnN4bUYramxOdnVEOWJjSEVVODNTCmZLakZXTFROVlFUWFZPY0NPaDU2VXpDWXBJdWpaakJrTUE0R0ExVWREd0VCL3dRRUF3SUJoakFTQmdOVkhSTUIKQWY4RUNEQUdBUUgvQWdFRE1CMEdBMVVkRGdRV0JCVGMrWk83YWRaTFFyTjBFd0pkcGVjVExIeEl4ekFmQmdOVgpIU01FR0RBV2dCVGMrWk83YWRaTFFyTjBFd0pkcGVjVExIeEl4ekFLQmdncWhrak9QUVFEQXdOcEFEQm1BakVBCnpML3lzZldjaDlYT3JpUmVQVGYwN2dYemJHUTJ5Y1pWSzc3NWM1SUMwRFNyVktpYjRXTFFuOG5PZkZ6YUlBRzMKQWpFQTBndEYyUjREZkx4Z1l2YWFRZlpUdmZTYWw1bWpsRS82OEx2a01PeGZHUHNNdXFHampsZnVQNnBSQm9neQpWZXRHCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
    ],
    "error_status": null,
    "id": "7066508a-7238-4db8-bcb3-e896da4dcda1",
    "state": 16,
    "subject": "CN=device-123,O=Customer,C=FI"
}
Certificate signing request. Request ID: 7066508a-7238-4db8-bcb3-e896da4dcda1 state: Ready
certificate written to: client.crt
certificate chain written to: client.chain

Configure the trustpoint

Send the Client CA chain to Laavat so that the service can be configured accordingly.

Request a secure transfer link from the LAAVAT Secure Transfer

Add a client for accessing the MTLS endpoints

In order to access a specific product with mTLS it needs to be configured.

In this example the CA certificate for Client certificates used. Type "IssueDeviceCertificateCA" gives access to all certificates issued under the CA in client.crt

(venv) $ ./signing-tool.py -c -t $TOKEN \
    -a https://app.laavat.io/<CustomerName>/api/v1/ \
    client add \
    -N "ClientSUB1" \
    -D "Access device certs" \
    -C clientca.crt \
    -T IssueDeviceCertificateCA \
    -p 842b2c8e-543f-414b-a1a6-89347db38348
{
    "client_type": "IssueDeviceCertificateCA",
    "description": "Access device certs",
    "id": "1c150751-33b4-429b-9845-c9e9598a29c5",
    "id_product": "842b2c8e-543f-414b-a1a6-89347db38348",
    "name": "ClientSUB1",
    "state": 2
}
Client Add request sent. Request ID: 1c150751-33b4-429b-9845-c9e9598a29c5 state: ApprovalRequired

Approve the client request

The client request was approved using the GUI.

Issuing Device certificates using mTLS

Create CSR for device certificates

In real life scenario the device creates the key and the corresponding CSR.

(venv) $ openssl ecparam \
                             -name prime256v1 \
                             -genkey -noout \
                             -conv_form uncompressed \
                             -out device.key
(venv) $ openssl req \
                             -new -nodes \
                             -key device.key \
                             -outform DER \
                             -subj "/C=FI/O=Customer/CN=device-123" \
                             2>/dev/null | base64 -w 0 > /tmp/csr.b64

Create certificate from CSR

Use the csr.b64 file contents as the value for the "csr" field. Certificate is requested from product with id=842b2c8e-543f-414b-a1a6-89347db38348

curl -sS --cert client.crt --key client.key \
-XPOST https://mtls.app.laavat.io/<CustomerName>/api/v1/certificaterequests \
-H 'Content-Type: application/json' \
-d '{ "csr": "MIHxMIGXAgEAMDUxCzAJBgNVBAYTAkZJMREwDwYDVQQKDAhDdXN0b21lcjETMBEGA1UEAwwKZGV2aWNlLTEyMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNUTSm69qkZzgI0NhuQnG+bvEbyN6hm0cUgS3e22E8mdn9yu2tVA52iINpRdRUbZB3lQ4F2dtfDUJIEnrtR0/b+gADAKBggqhkjOPQQDAgNJADBGAiEA7NOQ7xMqtNM7U6vnBqISSVlDMQ4O/wy1OxCYQf3NlfACIQDFTxPofaU+2k06N3jB2HNqt3cPV8rxWw/7FGJFbqTMjw==", "productId": "842b2c8e-543f-414b-a1a6-89347db38348"}'
{"chain":[],"id":"929aaf03-e60a-4b87-a579-66bc0f2964d5","state":1,"CN=device-123,O=Customer,C=FI"}

The certificate request is 929aaf03-e60a-4b87-a579-66bc0f2964d5

curl -sS -XGET --cert client.crt \
--key /tmp/ec.key \
https://mtls.app.laavat.io/<CustomerName>/api/v1/certificaterequests/929aaf03-e60a-4b87-a579-66bc0f2964d5 \
-H 'Content-Type: application/json' | jq -r
{
  "certificate": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNHVENDQWNDZ0F3SUJBZ0lSQU1VRGxiUWF3WVYxb3FjbGx6ak8vbDB3Q2dZSUtvWkl6ajBFQXdJd1BURUwKTUFrR0ExVUVCaE1DUmtreER6QU5CZ05WQkFvVEJreGhZWFpoZERFZE1Cc0dBMVVFQXhNVVUxVkNJRU5CSUdadgpjaUJFWlhacFkyVWdRMEV3SUJjTk1qVXdOakUzTVRFek1EQXdXaGdQTWpFeU5UQTFNalF3T1RNNU1UWmFNRE14CkN6QUpCZ05WQkFZVEFrWkpNUTh3RFFZRFZRUUtFd1pNWVdGMllYUXhFekFSQmdOVkJBTVRDbVJsZG1salpTMHgKTWpNd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFUVkUwcHV2YXBHYzRDTkRZYmtKeHZtN3hHOApqZW9adEhGSUV0M3R0aFBKblovY3J0clZRT2RvaURhVVhVVkcyUWQ1VU9CZG5iWHcxQ1NCSjY3VWRQMi9vNEdvCk1JR2xNQTRHQTFVZER3RUIvd1FFQXdJRGlEQWRCZ05WSFNVRUZqQVVCZ2dyQmdFRkJRY0RBUVlJS3dZQkJRVUgKQXdJd0hRWURWUjBPQkJZRUZBUDFWWnpKanY4L2JlaTFVc003UmdjWTh5eThNQjhHQTFVZEl3UVlNQmFBRk1YcgpZcnZIVllrQXlzTjlhWkhnVVhScmcyUGZNRFFHQTFVZEh3UXRNQ3N3S2FBbm9DV0dJMmgwZEhBNkx5OWpjbXd1ClkyOXRjR0Z1ZVM1amIyMHZaVE0zWmpBME5XTXVZM0pzTUFvR0NDcUdTTTQ5QkFNQ0EwY0FNRVFDSUcvQWtXeGUKaWxLU1M4UFZCUExNWG5VNDlwVVNCVGptUFY2anhId1ZBRUJRQWlBU3BxalFDSjZvQzYwYnc2K3NFc0ZzOXJwQgo5TXYyUWE0cTlMRXVpc2ozaGc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==",
  "chain": [
    "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNMRENDQWRHZ0F3SUJBZ0lRRUdmalhWaWMxRFRxeHQxMmdpc2I1REFLQmdncWhrak9QUVFEQWpCVE1Rc3cKQ1FZRFZRUUdFd0pHU1RFUE1BMEdBMVVFQ2hNR1RHRmhkbUYwTVRNd01RWURWUVFERXlwRVpYWnBZMlVnUTBFZwpVSEp2WkhWamRDQm1iM0lnUkdWMmFXTmxJRVpoYldsc2VTQlRkV0lnUTBFd0lCY05NalV3TmpFM01UQXdNakE0CldoZ1BNakV5TlRBMU1qUXdPVE01TVRaYU1EMHhDekFKQmdOVkJBWVRBa1pKTVE4d0RRWURWUVFLRXdaTVlXRjIKWVhReEhUQWJCZ05WQkFNVEZGTlZRaUJEUVNCbWIzSWdSR1YyYVdObElFTkJNRmt3RXdZSEtvWkl6ajBDQVFZSQpLb1pJemowREFRY0RRZ0FFZk1sNVpWSlFIN2xHYklOaDEvbkJITWdGNU5OUytSYW0zSXBVT3MrTXdkOVNhMmw3CkdRT09sQVhiVVpHNE1BNjE5dE1EY3lLalRidUZHeThMYjJHVFM2T0JtakNCbHpBT0JnTlZIUThCQWY4RUJBTUMKQVlZd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVXhldGl1OGRWaVFES3czMXBrZUJSZEd1RApZOTh3SHdZRFZSMGpCQmd3Rm9BVXhYVHovclFiSXhTSHJRN1VoV3BKMy9lUHZySXdOQVlEVlIwZkJDMHdLekFwCm9DZWdKWVlqYUhSMGNEb3ZMMk55YkM1amIyMXdZVzU1TG1OdmJTOWxNemRtTURRMVl5NWpjbXd3Q2dZSUtvWkkKemowRUF3SURTUUF3UmdJaEFPek5oY2JPSHdNYmFGOHlhaEw5QkpXSjhYazNtWnIrNHBHUWhLdlJnT01LQWlFQQp3SE9RcVhQa21mQ2JPa1VXc2VhREZKOHJkOE9oeU8yVUxLUU1qaEU0ZmJNPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==",
    "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNSRENDQWNxZ0F3SUJBZ0lSQUlvWXd0VnZYZDc0c3o0SExRUkYwc3d3Q2dZSUtvWkl6ajBFQXdNd05URUwKTUFrR0ExVUVCaE1DUmtreER6QU5CZ05WQkFvVEJreGhZWFpoZERFVk1CTUdBMVVFQXhNTVVtOXZkQ0JEUVNBeQpNREkxTUNBWERUSTFNRFl4TnpBNU16a3hObG9ZRHpJeE1qVXdOVEkwTURrek9URTJXakJUTVFzd0NRWURWUVFHCkV3SkdTVEVQTUEwR0ExVUVDaE1HVEdGaGRtRjBNVE13TVFZRFZRUURFeXBFWlhacFkyVWdRMEVnVUhKdlpIVmoKZENCbWIzSWdSR1YyYVdObElFWmhiV2xzZVNCVGRXSWdRMEV3V1RBVEJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQgpCd05DQUFUMEFMTXp4Q1pXMHVzZjRXWlQ2RU1yTHZ5Q3VHb2c3RXA1SkhadDVreG4xYjRtd0Frd1NFL1pPVmtHCm1TOEVRL1BKdk55WTQ1SUNjV1BKOVQ1cEtXSmtvNEdhTUlHWE1BNEdBMVVkRHdFQi93UUVBd0lCaGpBUEJnTlYKSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCVEZkUFArdEJzakZJZXREdFNGYWtuZjk0KytzakFmQmdOVgpIU01FR0RBV2dCVGMrWk83YWRaTFFyTjBFd0pkcGVjVExIeEl4ekEwQmdOVkhSOEVMVEFyTUNtZ0o2QWxoaU5vCmRIUndPaTh2WTNKc0xtTnZiWEJoYm5rdVkyOXRMMlV6TjJZd05EVmpMbU55YkRBS0JnZ3Foa2pPUFFRREF3Tm8KQURCbEFqQUhxd2hrMUlGKzNDNjk3bnlaTG1VZ2xqeWR6S1NNMnFYWkVqSjJEaU42VkdoVmc1cFp2NkxpQWl1awp4T3RKaXpVQ01RQ2h5SmRHdnpQeU8yeGNGcWZjZ2JmcTJxN3J1NkJ2UnJSMmUzbnBwNkkxaDUyeGVJK3JjcU1rCk9DZWIwLzhCVXMwPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==",
    "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNEekNDQVpTZ0F3SUJBZ0lSQUxva3I5K0UyUkZGTHNoQ0NLNjN0Snd3Q2dZSUtvWkl6ajBFQXdNd05URUwKTUFrR0ExVUVCaE1DUmtreER6QU5CZ05WQkFvVEJreGhZWFpoZERFVk1CTUdBMVVFQXhNTVVtOXZkQ0JEUVNBeQpNREkxTUNBWERUSTFNRFl4TnpBNU1UazBNMW9ZRHpJeU1qVXdORE13TURreE9UUXpXakExTVFzd0NRWURWUVFHCkV3SkdTVEVQTUEwR0ExVUVDaE1HVEdGaGRtRjBNUlV3RXdZRFZRUURFd3hTYjI5MElFTkJJREl3TWpVd2RqQVEKQmdjcWhrak9QUUlCQmdVcmdRUUFJZ05pQUFRZ21nRFFqMlg2YWVXNVBZNk1xdVN6NDNqWnFmTWpzWFFLQnNGRAp5d1hLamtWMURSZkdxWGVJdWJOYzRWRGVXaHBhRk5QZXAvRGttS2s3REs1cnN4bUYramxOdnVEOWJjSEVVODNTCmZLakZXTFROVlFUWFZPY0NPaDU2VXpDWXBJdWpaakJrTUE0R0ExVWREd0VCL3dRRUF3SUJoakFTQmdOVkhSTUIKQWY4RUNEQUdBUUgvQWdFRE1CMEdBMVVkRGdRV0JCVGMrWk83YWRaTFFyTjBFd0pkcGVjVExIeEl4ekFmQmdOVgpIU01FR0RBV2dCVGMrWk83YWRaTFFyTjBFd0pkcGVjVExIeEl4ekFLQmdncWhrak9QUVFEQXdOcEFEQm1BakVBCnpML3lzZldjaDlYT3JpUmVQVGYwN2dYemJHUTJ5Y1pWSzc3NWM1SUMwRFNyVktpYjRXTFFuOG5PZkZ6YUlBRzMKQWpFQTBndEYyUjREZkx4Z1l2YWFRZlpUdmZTYWw1bWpsRS82OEx2a01PeGZHUHNNdXFHampsZnVQNnBSQm9neQpWZXRHCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
  ],
  "id": "953b256b-58f6-4e16-8533-9547f9119f86",
  "state": 16,
  "subject": "CN=device-123,O=Customer,C=FI"
}