Quickstart: Enroll individual device to IoT Hub Device Provisioning Service using TPM attestation

This article shows you how to programmatically create an individual enrollment for a TPM device in the Azure IoT Hub Device Provisioning Service by using the Microsoft Azure IoT SDK and a sample application. You can optionally enroll a simulated TPM device to the provisioning service by using this individual enrollment entry.

Although these steps work on both Windows and Linux computers, this article uses a Windows development computer.

Prerequisites

If you don't have an Azure subscription, create a free account before you begin.

  • Install Visual Studio 2019.

  • Install .NET Core 3.1 SDK or later or later on your Windows-based machine. You can use the following command to check your version.

    dotnet --info
    
  • (Optional) If you want to enroll a simulated device at the end of this quickstart, follow the procedure in Create and provision a simulated TPM device up to the step where you get an endorsement key for the device. Save the endorsement key, registration ID, and, optionally, the device ID.

  • Download and install Python 2.x or 3.x. Make sure to use the 32-bit or 64-bit installation as required by your setup. When prompted during the installation, make sure to add Python to your platform-specific environment variables.

  • Install Pip, if not included with your distribution of Python.

Important

This article only applies to the deprecated V1 Python SDK. Device and service clients for the IoT Hub Device Provisioning Service are not yet available in V2. The team is currently hard at work to bring V2 to feature parity.

  • Install the Java SE Development Kit 8. This quickstart installs the Java Service SDK below. It works on both Windows and Linux. This quickstart uses Windows.

  • Install Maven 3.

  • Install Git and make sure the the path is added to the environment variable PATH.

Note

Don't follow the steps to create an individual enrollment by using the Azure portal.

Prepare the development environment

Copy symmetric and TPM enrollment keys

This quickstart demonstrates both symmetric key and TPM enrollments. You'll need to either create your own or use the provided test keys:

For simulated symmetric key device enrollments, you need a primary and secondary key for your device. If you don't have a valid symmetric key, you can use the following test keys for this example:

Primary Symmetric key

UmorGiEVPNIQuaWGXXbe8v9gWayS7XtOZmNMo6DEaEXP65GvhuK3OeRf8RVZ9BymBCHxNg3oRTey0pUHUwwYKQ==

Secondary Symmetric key

Zx8/eE7PUBmnouB1qlNQxI7fcQ2HbJX+y96F1uCVQvDj88jFL+q6L9YWLLi4jqTmkRPOulHlSbSv2uFgj4vKtw==

Prepare the development environment

Set up environment variables

To set up environment variables:

  1. The PATH variable should include the full path to jdk1.8.x\bin directory. If this is your machine's first Java installation, then create a new environment variable named JAVA_HOME and point it to the full path to the jdk1.8.x directory. On Windows machine, this directory is found in the C:\Program Files\Java\ folder, and you can create or edit environment variables by searching for Edit the system environment variables on the Control panel of your Windows machine.

    You can check if Java is successfully set up on your machine by running the following command on your command window:

    java -version
    
  2. Edit environment variable PATH to point to the apache-maven-3.x.x\bin folder inside the folder where Maven was extracted. You may confirm that Maven is successfully installed by running this command on your command window:

    mvn --version
    
  3. Make sure git is installed on your machine and is added to the environment variable PATH.

Clone Git repository for Azure IoT Java SDK

To clone the Azure IoT Java SDK:

  1. Open a command prompt.

  2. Clone the GitHub repo for device enrollment code sample using the Java Service SDK:

    git clone https://github.com/Azure/azure-iot-sdk-java.git --recursive
    

Get the connection string for your provisioning service

For the sample in this quickstart, you'll need to copy the connection string for your provisioning service.

  1. Sign in to the Azure portal.

  2. On the left-hand menu or on the portal page, select All resources.

  3. Select your Device Provisioning Service.

  4. In the Settings menu, select Shared access policies.

  5. Select the access policy that you want to use.

  6. In the Access Policy panel, copy and save the primary key connection string.

    Get provisioning service connection string from the portal.

Create the individual enrollment sample

This section shows you how to create a .NET Core console app that adds an individual enrollment for a TPM device to your provisioning service. With some modification, you can also follow these steps to create a Windows IoT Core console app to add the individual enrollment. To learn more about developing with IoT Core, see Windows IoT Core developer documentation.

  1. Open Visual Studio, and select Create a new project.

  2. In the Create a new project panel, select *Console Application.

  3. Select Next.

  4. For Project name, type CreateEnrollmentGroup.

  5. SelectNext. Keep the default Target framework.

  6. Select Create.

  7. After the solution opens, in the Solution Explorer pane, right-click the CreateEnrollmentGroup project, and then select Manage NuGet Packages.

  8. In NuGet Package Manager, select Browse.

  9. Type in and select Microsoft.Azure.Devices.Provisioning.Service.

  10. Select Install.

    NuGet Package Manager window

    This step downloads, installs, and adds a reference to the Azure IoT Provisioning Service Client SDK NuGet package and its dependencies.

  11. Add the following using statements after the other using statements at the top of Program.cs:

    using System.Threading.Tasks;
    using Microsoft.Azure.Devices.Provisioning.Service;
    
  12. Add the following fields to the Program class, and make the listed changes.

    private static string ProvisioningConnectionString = "{ProvisioningServiceConnectionString}";
    private const string RegistrationId = "sample-registrationid-csharp";
    private const string TpmEndorsementKey =
        "AToAAQALAAMAsgAgg3GXZ0SEs/gakMyNRqXXJP1S124GUgtk8qHaGzMUaaoABgCAAEMAEAgAAAAAAAEAxsj2gUS" +
        "cTk1UjuioeTlfGYZrrimExB+bScH75adUMRIi2UOMxG1kw4y+9RW/IVoMl4e620VxZad0ARX2gUqVjYO7KPVt3d" +
        "yKhZS3dkcvfBisBhP1XH9B33VqHG9SHnbnQXdBUaCgKAfxome8UmBKfe+naTsE5fkvjb/do3/dD6l4sGBwFCnKR" +
        "dln4XpM03zLpoHFao8zOwt8l/uP3qUIxmCYv9A7m69Ms+5/pCkTu/rK4mRDsfhZ0QLfbzVI6zQFOKF/rwsfBtFe" +
        "WlWtcuJMKlXdD8TXWElTzgh7JS4qhFzreL0c1mI0GCj+Aws0usZh7dLIVPnlgZcBhgy1SSDQMQ==";
    
    // Optional parameters
    private const string OptionalDeviceId = "myCSharpDevice";
    private const ProvisioningStatus OptionalProvisioningStatus = ProvisioningStatus.Enabled;
    
  13. Replace the ProvisioningServiceConnectionString placeholder value with the connection string of the provisioning service that you copied in the previous section.

  14. If you're using this quickstart together with the Create and provision a simulated TPM device quickstart to provision a simulated device, replace the endorsement key and registration ID with the values that you noted in that quickstart. You can replace the device ID with the value suggested in that quickstart, use your own value, or use the default value in this sample.

  15. Add the following method to the Program class. This code creates individual enrollment entry and then calls the CreateOrUpdateIndividualEnrollmentAsync method on the ProvisioningServiceClient to add the individual enrollment to the provisioning service.

    public static async Task RunSample()
    {
        Console.WriteLine("Starting sample...");
    
        using (ProvisioningServiceClient provisioningServiceClient =
                ProvisioningServiceClient.CreateFromConnectionString(ProvisioningConnectionString))
        {
            #region Create a new individualEnrollment config
            Console.WriteLine("\nCreating a new individualEnrollment...");
            Attestation attestation = new TpmAttestation(TpmEndorsementKey);
            IndividualEnrollment individualEnrollment =
                    new IndividualEnrollment(
                            RegistrationId,
                            attestation);
    
            // The following parameters are optional. Remove them if you don't need them.
            individualEnrollment.DeviceId = OptionalDeviceId;
            individualEnrollment.ProvisioningStatus = OptionalProvisioningStatus;
            #endregion
    
            #region Create the individualEnrollment
            Console.WriteLine("\nAdding new individualEnrollment...");
            IndividualEnrollment individualEnrollmentResult =
                await provisioningServiceClient.CreateOrUpdateIndividualEnrollmentAsync(individualEnrollment).ConfigureAwait(false);
            Console.WriteLine("\nIndividualEnrollment created with success.");
            Console.WriteLine(individualEnrollmentResult);
            #endregion
    
        }
    }
    
  16. Finally, replace the Main method with the following lines:

    static async Task Main(string[] args)
    {
        await RunSample();
        Console.WriteLine("\nHit <Enter> to exit ...");
        Console.ReadLine();
    }
    
  17. Build the solution.

  1. From a command window in your working folder, run:

    npm install azure-iot-provisioning-service
    
  2. Using a text editor, create a create_individual_enrollment.js file in your working folder. Add the following code to the file:

    'use strict';
    
    var provisioningServiceClient = require('azure-iot-provisioning-service').ProvisioningServiceClient;
    
    var serviceClient = provisioningServiceClient.fromConnectionString(process.argv[2]);
    var endorsementKey = process.argv[3];
    
    var enrollment = {
      registrationId: 'first',
      attestation: {
        type: 'tpm',
        tpm: {
          endorsementKey: endorsementKey
        }
      }
    };
    
    serviceClient.createOrUpdateIndividualEnrollment(enrollment, function(err, enrollmentResponse) {
      if (err) {
        console.log('error creating the individual enrollment: ' + err);
      } else {
        console.log("enrollment record returned: " + JSON.stringify(enrollmentResponse, null, 2));
      }
    });
    
  3. Save the file.

  1. Using a text editor, create a new Enrollment.py file.

  2. Add the following import statements and variables at the start of the Enrollment.py file(replace {dpsConnectionString} with the connection string you copied earlier, the certificate placeholder with the certificate created in Copy symmetric and TPM enrollment keys, and {registrationid} with a unique registrationid that consists only of lower-case alphanumerics and hyphens):

    from provisioningserviceclient import ProvisioningServiceClient
    from provisioningserviceclient.models import IndividualEnrollment, AttestationMechanism
    from provisioningserviceclient.protocol.models import SymmetricKeyAttestation
    
    CONNECTION_STRING = "Enter your DPS connection string"
    PRIMARY_KEY = "Add a valid key"
    SECONDARY_KEY = "Add a valid key"
    REGISTRATION_ID = "Enter a registration ID"
    
  3. Add the following Python code to implement the creation of the individual enrollment:

    def main():
        print ( "Starting individual enrollment..." )
    
        psc = ProvisioningServiceClient.create_from_connection_string(CONNECTION_STRING)
    
        symAtt = SymmetricKeyAttestation(primary_key=PRIMARY_KEY, secondary_key=SECONDARY_KEY)
        att = AttestationMechanism(type="symmetricKey", symmetric_key=symAtt)
        ie = IndividualEnrollment.create(REGISTRATION_ID, att)
    
        ie = psc.create_or_update(ie)
    
        print ( "Individual enrollment successful." )
    
    if __name__ == '__main__':
        main()
    
  4. Save and close the Enrollment.py file.

  1. In the downloaded source code, navigate to the sample folder azure-iot-sdk-java/provisioning/provisioning-samples/service-enrollment-sample. Open the file /src/main/java/samples/com/microsoft/azure/sdk/iot/ServiceEnrollmentSample.java.

  2. Replace [Provisioning Connection String] with the connection string that you copied in Get the connection string for your provisioning service.

    private static final String PROVISIONING_CONNECTION_STRING = "[Provisioning Connection String]";
    
    1. Add the TPM device details:
      1. Get the Registration ID and the TPM endorsement key for a TPM device simulation, by following the steps leading to the section Simulate TPM device.

      2. Use the Registration ID and the Endorsement Key from the output of the preceding step, to replace the [RegistrationId] and [TPM Endorsement Key] in the sample code file ServiceEnrollmentSample.java:

        private static final String REGISTRATION_ID = "[RegistrationId]";
        private static final String TPM_ENDORSEMENT_KEY = "[TPM Endorsement Key]";
        
  3. To configure your provisioning service from within the sample code, proceed to the next step. If you do not want to configure it, make sure to comment out or delete the following statements in the ServiceEnrollmentSample.java file:

    / / The following parameters are optional. Remove it if you don't need.
    individualEnrollment.setDeviceId(DEVICE_ID);
    individualEnrollment.setIotHubHostName(IOTHUB_HOST_NAME);
    individualEnrollment.setProvisioningStatus(PROVISIONING_STATUS);
    
  4. This step shows you how to configure your provisioning service in the sample code.

    1. Go to the Azure portal.

    2. On the left-hand menu or on the portal page, select All resources.

    3. Select your Device Provisioning Service.

    4. In the Overview panel, copy the hostname of the Service endpoint. In the source code sample, replace [Host name] with the copied hostname.

    private static final String IOTHUB_HOST_NAME = "[Host name].azure-devices.net";
    
  5. Study the sample code. It creates, updates, queries, and deletes an individual TPM device enrollment. To verify successful enrollment in portal, temporarily comment out the following lines of code at the end of the ServiceEnrollmentSample.java file:

    // *********************************** Delete info of individualEnrollment ************************************
    System.out.println("\nDelete the individualEnrollment...");
    provisioningServiceClient.deleteIndividualEnrollment(REGISTRATION_ID);
    
  6. Save the file ServiceEnrollmentSample.java.

Run the individual enrollment sample

  1. Run the sample in Visual Studio to create the enrollment. A command window will appear, and will display confirmation messages.

  2. Upon successful creation, the command window displays the properties of the new enrollment.

To run the sample, you'll need the connection string for your provisioning service that you copied in the previous section, as well as the endorsement key for device. If you've followed the Create and provision a simulated device quickstart to create a simulated TPM device, use the key created for that device. Otherwise, to create a sample individual enrollment, you can use the following endorsement key supplied with the Node.js Service SDK:

AToAAQALAAMAsgAgg3GXZ0SEs/gakMyNRqXXJP1S124GUgtk8qHaGzMUaaoABgCAAEMAEAgAAAAAAAEAxsj2gUScTk1UjuioeTlfGYZrrimExB+bScH75adUMRIi2UOMxG1kw4y+9RW/IVoMl4e620VxZad0ARX2gUqVjYO7KPVt3dyKhZS3dkcvfBisBhP1XH9B33VqHG9SHnbnQXdBUaCgKAfxome8UmBKfe+naTsE5fkvjb/do3/dD6l4sGBwFCnKRdln4XpM03zLpoHFao8zOwt8l/uP3qUIxmCYv9A7m69Ms+5/pCkTu/rK4mRDsfhZ0QLfbzVI6zQFOKF/rwsfBtFeWlWtcuJMKlXdD8TXWElTzgh7JS4qhFzreL0c1mI0GCj+Aws0usZh7dLIVPnlgZcBhgy1SSDQMQ==
  1. To create an individual enrollment for your TPM device, run the following command (include the quotes around the command arguments):

    node create_individual_enrollment.js "<the connection string for your provisioning service>" "<endorsement key>"
    
  2. Upon successful creation, the command window displays the properties of the new enrollment.

  1. Open a command prompt, and run the following script.

    python Enrollment.py
    
  2. Upon successful creation, the command window displays the properties of the new enrollment.

  1. Open a command window in Administrator mode, and go to the folder azure-iot-sdk-java/provisioning/provisioning-samples/service-enrollment-group-sample.

  2. In the command prompt, use this command:

    mvn install -DskipTests
    

    This command downloads the Maven package com.microsoft.azure.sdk.iot.provisioning.service to your machine. This package includes the binaries for the Java service SDK, that the sample code needs to build. If you ran the X.509 certificate generator tool in the preceding section, this package will be already downloaded on your machine.

  3. In the command prompt, run the script:

    cd target
    java -jar ./service-enrollment-group-sample-{version}-with-deps.jar
    
  4. Upon successful creation, the command window displays the properties of the new enrollment.

To verify that the enrollment group has been created:

  1. In the Azure portal, select your Device Provisioning Service.

  2. In the Settings menu, select Manage enrollments.

  3. Select Individual Enrollments. You should see a new enrollment entry that corresponds to the registration ID that you used in the sample.

Verify enrollment for C# individual device in the portal.

Verify enrollment for Node.js individual device in the portal.

Verify enrollment for Python individual device in the portal.

Verify enrollment for Java individual device in the portal.

Clean up resources

If you plan to explore the Azure IoT Hub Device Provisioning Service tutorials, don't clean up the resources created in this quickstart. Otherwise, use the following steps to delete all resources created by this quickstart.

  1. Close the sample output window on your computer.

  2. From the left-hand menu in the Azure portal, select All resources.

  3. Select your Device Provisioning Service.

  4. In the Settings menu, select Manage enrollments.

  5. Select the Individual Enrollments tab.

  6. Select the check box next to the REGISTRATION ID of the device you enrolled in this quickstart.

  7. At the top of the page, select Delete.

  8. From your Device Provisioning Service in the Azure portal, select Certificates.

  9. Select the certificate you uploaded for this quickstart.

  10. At the top of Certificate Details, select Delete.

  11. If you followed the steps in Create and provision a simulated TPM device to create a simulated TPM device, do the following steps:

    1. Close the TPM simulator window and the sample output window for the simulated device.

    2. In the Azure portal, navigate to the IoT Hub where your device was provisioned.

    3. In the menu under Explorers, select IoT devices.

    4. Select the check box next to the DEVICE ID of the device you registered in this quickstart.

    5. At the top of the pane, select Delete.

Next steps

In this quickstart, you’ve programmatically created an individual enrollment entry for a TPM device. Optionally, you created a TPM simulated device on your computer and provisioned it to your IoT hub using the Azure IoT Hub Device Provisioning Service. To learn about device provisioning in depth, continue to the tutorial for the Device Provisioning Service setup in the Azure portal.