This is a quick tutorial with the steps to create, get, query, and delete a bulk of individual enrollments in the Microsoft Azure IoT Hub Device Provisioning Service using the ProvisioningServiceClient on the java SDK.
All the artifacts that you need to execute this sample are ready to be built and executed on this sample.
Provisioning service client - documentation Provisioning service client - source code
Note that the samples for Windows and Linux use Maven.
-
Clone the java SDK repo (https://github.com/Azure/azure-iot-sdk-java.git).
-
Compile the SDK. This step is only necessary if you don't want to use a precompiled Maven package.
- Change to the root azure-iot-sdk-java directory.
- Run
mvn install
. It will download all needed packages, compile and test the SDK. - At the end of this step, you will have the
com.microsoft.azure.sdk.iot.provisioning.service
on your machine.
-
Navigate to the sample root
azure-iot-sdk-java/provisioning/provisioning-samples/service-bulkoperation-sample
. -
Edit the
/src/main/java/samples/com/microsoft/azure/sdk/iot/ServiceBulkOperationSample.java
to add your provisioning service information.-
Replace the
[Provisioning Connection String]
by the Provisioning Connection String that you copied from the portal./* * Details of the Provisioning. */ private static final String PROVISIONING_CONNECTION_STRING = "[Provisioning Connection String]";
-
For TPM attestation:
- For each device that you have, you must copy the registrationId and the endorsementKey. If you don't have a physical device with TPM, you can use the tpm-simulator. For this sample, you probably want to run it in, at least, two different machines.
- Fill the
DEVICE_MAP
with the pairs registrationId and endorsementKey that you copied from the hardware or emulator. If you need more that two, just add moreput
lines.private static final Map<String, String> DEVICE_MAP = new HashMap<String, String>() { { put("RegistrationId1","TPMEndorsementKey1"); put("RegistrationId2","TPMEndorsementKey2"); } };
-
For X509 attestation:
-
For each device that you have, you must copy the registrationId and the client certificate. If you don't have a physical device with X509, you can use the provisioning X509 cert generator. Answer
Y
to provide your common name, the Client Cert commonName is your registrationId. For this sample, you probably want to generate, at least, two certificates. -
Fill the
DEVICE_MAP
with the pairs registrationId and clientCertificate that you copied from the hardware or emulator. Be careful to do not change your certificate, adding or removing characters like spaces, tabs or new lines (\n
). If you need more that two, just add moreput
lines.private static final Map<String, String> DEVICE_MAP = new HashMap<String, String>() { { put("RegistrationId1","ClientCertificate1"); put("RegistrationId2","ClientCertificate2"); } };
-
Replace the Attestation mechanism in the sample, line #46, to work with X509 client certificate instead of TPM.
Replace:
Attestation attestation = new TpmAttestation(device.getValue());
By:
Attestation attestation = X509Attestation.createFromClientCertificates(device.getValue());
-
-
-
In a command line, navigate to the directory
azure-iot-sdk-java/provisioning/provisioning-samples/service-bulkoperation-sample
where thepom.xml
file for this test lives, and build your sample:{sample root}/>mvn install -DskipTests
-
Navigate to the folder containing the executable JAR file for the sample and run the sample as follows:
The executable JAR file for create an IndividualEnrollment can be found at:
{sample root}/target/service-bulkoperation-sample-{version}-with-deps.jar
Navigate to the
target
directory that containing the jar. Run the sample using the following command:java -jar ./service-bulkoperation-sample-{version}-with-deps.jar
If you prefer to create and populate your own java app, this section will guide you step by step.
- If you don't want to use the precompiled Service SDK, follow the steps 1 and 2 above to produce it locally on your machine.
- On your development machine, create a empty folder called
provisioning-getstarted
. That will be the base directory for all provisioning samples that you want to create. - Navigate to the
provisioning-getstarted
folder, create a Maven project calledservice-bulkoperation-sample
, using the following command at your command prompt. Note this is a single, long command:
mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=service-bulkoperation-sample -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
- At your command prompt, navigate to the
service-bulkoperation-sample
folder. - Using a text editor, open the
pom.xml
file in theservice-bulkoperation-sample
folder and add the following dependency to the dependencies node. This dependency enables you to use the provisioning-service-client package in your app to communicate with your Device Provisioning Service:<dependencies> <dependency> <groupId>com.microsoft.azure.sdk.iot.provisioning</groupId> <artifactId>provisioning-service-client</artifactId> <version>0.0.1</version> </dependency> </dependencies>
- Add the following build node after the dependencies node. This configuration (1) instructs Maven to use
java 1.8 to build the app, (2) create a manifest to point the main entrance of your sample to the App class
in the App.java, and (3) create a full contained jar, including dependencies:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>2.6</version> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <mainClass>com.mycompany.app.App</mainClass> </manifest> </archive> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.3</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <artifactId>maven-shade-plugin</artifactId> <version>2.4</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.RSA</exclude> </excludes> </filter> </filters> <shadedArtifactAttached>true</shadedArtifactAttached> <shadedClassifierName>with-deps</shadedClassifierName> </configuration> </execution> </executions> </plugin> </plugins> </build>
- Save and close the
pom.xml
file. - At this point you can build and run your new App to make sure that everything is working as expected.
- In a command line, navigate to the sample folder (where the
pom.xml
file lives) and build it:
{sample root}/>mvn install
- Navigate to the directory
service-bulkoperation-sample\target
containing the.jar
file. - Run the sample using the following command:
java -jar ./service-bulkoperation-sample-1.0-SNAPSHOT-with-deps.jar
- As a result, it should print
Hello world!
in the screen.
- In a command line, navigate to the sample folder (where the
- Now, you are ready to write the provisioning code to create the bulk of individualEnrollments. Using a text editor, open the
service-bulkoperation-sample\src\main\java\com\mycompany\app\App.java
file. - Add the following import statements at the beginning of the file, after the
package com.mycompany.app;
:import com.microsoft.azure.sdk.iot.provisioning.service.ProvisioningServiceClient; import com.microsoft.azure.sdk.iot.provisioning.service.Query; import com.microsoft.azure.sdk.iot.provisioning.service.configs.*; import com.microsoft.azure.sdk.iot.provisioning.service.exceptions.ProvisioningServiceClientException; import java.util.LinkedList; import java.util.List; import java.util.UUID;
- Copy the connection string for your Device Provisioning Service from the portal, you will need it for the next step.
- Access the Azure portal.
- Navigate to your Device Provisioning Service.
- Click on
Shared access policies
. - Select the desired
POLICY
. It should be the one that you haveEnrollmentWrite
permission. - Copy the
Primary key connection string
.
- Add the following class-level variables to the App class. Replace the
{Provisioning Connection String}
with your provisioning connection string, and fill the DEVICE_MAP with your own list of devices:/* * Details of the Provisioning. */ private static final String PROVISIONING_CONNECTION_STRING = "{Provisioning Connection String}"; private static final int QUERY_PAGE_SIZE = 3;
- For TPM attestation:
- For each device that you have, you must copy the registrationId and the endorsementKey. If you don't have a physical device with TPM, you can use the tpm-simulator. For this sample, you probably want to run it in, at least, two different machines.
- Add the follow class-level variable to the App, and fill the
DEVICE_MAP
with the pairs registrationId and endorsementKey that you copied from the hardware or emulator. If you need more that two, just add moreput
lines.private static final Map<String, String> DEVICE_MAP = new HashMap<String, String>() { { put("RegistrationId1","TPMEndorsementKey1"); put("RegistrationId2","TPMEndorsementKey2"); } };
- For X509 attestation:
- For each device that you have, you must copy the registrationId and the client certificate. If you don't have
a physical device with X509, you can use the provisioning X509 cert generator.
Answer
Y
to provide your common name, the Client Cert commonName is your registrationId. For this sample, you probably want to generate, at least, two certificates. - Add the follow class-level variable to the App, and fill the
DEVICE_MAP
with the pairs registrationId and clientCertificate that you copied from the hardware or emulator. If you need more that two, just add moreput
lines.private static final Map<String, String> DEVICE_MAP = new HashMap<String, String>() { { put("RegistrationId1","ClientCertificate1"); put("RegistrationId2","ClientCertificate2"); } };
- For each device that you have, you must copy the registrationId and the client certificate. If you don't have
a physical device with X509, you can use the provisioning X509 cert generator.
Answer
- Update your
main
method signature to include the followingthrows
clause:public static void main(String[] args) throws ProvisioningServiceClientException
- Create a new instance of the ProvisioningServiceClient
replacing the
System.out.println( "Hello World!" );
by:System.out.println("Beginning my sample for the Provisioning Service Client!"); // ********************************** Create a Provisioning Service Client ************************************ ProvisioningServiceClient provisioningServiceClient = ProvisioningServiceClient.createFromConnectionString(PROVISIONING_CONNECTION_STRING);
- After that, you can create a new bulk of IndividualEnrollment.
- Every individualEnrollment needs a unique name, called RegistrationId, and an Attestation that can be TpmAttestation or X509Attestation.
- Once you defined the set of RegistrationId and the Attestation mechanism, you can create the list of Enrollment
configuration.
// ******************************** Create a new bulk of IndividualEnrollment ********************************* System.out.println("\nCreate a new set of individualEnrollments..."); List<IndividualEnrollment> individualEnrollments = new LinkedList<>(); for(Map.Entry<String, String> device:DEVICE_MAP.entrySet()) { Attestation attestation = new TpmAttestation(device.getValue()); String registrationId = device.getKey(); System.out.println(" Add " + registrationId); IndividualEnrollment individualEnrollment = new IndividualEnrollment( registrationId, attestation); individualEnrollments.add(individualEnrollment); }
- For X509, replace the Attestation mechanism in the preview loop, to work with X509 client certificate
instead of TPM.
Replace:By:Attestation attestation = new TpmAttestation(device.getValue());
Attestation attestation = X509Attestation.createFromClientCertificates(device.getValue());
- Now, call the runBulkOperation
on the ProvisioningServiceClient to create a new IndividualEnrollment.
// ********************************* Create a new set of individualEnrollment ********************************* System.out.println("\nRun the bulk operation to create the individualEnrollments..."); BulkOperationResult bulkOperationResult = provisioningServiceClient.runBulkOperation( BulkOperationMode.CREATE, individualEnrollments); System.out.println("Result of the Create bulk individualEnrollment..."); System.out.println(bulkOperationResult);
- Save and close the
app.java
file. - Build and run the App as you did in the item 8.
- The App should print something like:
Beginning my sample for the Provisioning Service Client! Create a new set of individualEnrollments... Add RegistrationId1 Add RegistrationId2 Run the bulk operation to create the individualEnrollments... Result of the Create bulk individualEnrollment... { "isSuccessful": true, "errors": [] }
- Check in the Azure Portal if your set of individual enrollments was created with success.
- Check the created individualEnrollments information in your App. You can consult using 2 ProvisioningServiceClient APIs,
get
andquery
.- Use the getIndividualEnrollment
to get an specific individualEnrollment using the registrationId. Add the following code and check the result.
// ************************************ Get info of individualEnrollments ************************************* for (IndividualEnrollment individualEnrollment: individualEnrollments) { String registrationId = individualEnrollment.getRegistrationId(); System.out.println("\nGet the individualEnrollment information for " + registrationId + "..."); IndividualEnrollment getResult = provisioningServiceClient.getIndividualEnrollment(registrationId); System.out.println(getResult); }
- Use the createIndividualEnrollmentQuery
to create a query for the individual enrollments in the provisioning service. The QuerySpecificationBuilder
will help you to create a correct QuerySpecification.
For this sample, we will query all
"*"
individualEnrollments is the provisioning service.// ************************************ Query info of individualEnrollments *********************************** System.out.println("\nCreate a query for individualEnrollments..."); QuerySpecification querySpecification = new QuerySpecificationBuilder("*", QuerySpecificationBuilder.FromType.ENROLLMENTS) .createSqlQuery(); Query query = provisioningServiceClient.createIndividualEnrollmentQuery(querySpecification, QUERY_PAGE_SIZE); while(query.hasNext()) { System.out.println("\nQuery the next individualEnrollments..."); QueryResult queryResult = query.next(); System.out.println(queryResult); }
- Use the getIndividualEnrollment
to get an specific individualEnrollment using the registrationId. Add the following code and check the result.
- Delete the bulk of individualEnrollments from the provisioning service. You can delete a bulk of individualEnrollments
adding the following code that invokes the API runBulkOperation:
// ********************************** Delete bulk of individualEnrollments ************************************ System.out.println("\nDelete the set of individualEnrollments..."); bulkOperationResult = provisioningServiceClient.runBulkOperation(BulkOperationMode.DELETE, individualEnrollments); System.out.println(bulkOperationResult);
- Save and close the
app.java
file. - Build and run the App as you did in the item 8. Check the results on your console. Note that you will not see any new individualEnrollment in the Azure Portal, because we are deleting it in the item 19.