How to provision for multitenancy
This how-to shows how to securely provision multiple simulated symmetric key devices to a group of IoT Hubs using an allocation policy. Allocation policies that are defined by the provisioning service support a variety of allocation scenarios. Two common scenarios are:
Geolocation / GeoLatency: As a device moves between locations, network latency is improved by having the device provisioned to the IoT hub that's closest to each location. In this scenario, a group of IoT hubs, which span across regions, are selected for enrollments. The Lowest latency allocation policy is selected for these enrollments. This policy causes the Device Provisioning Service to evaluate device latency and determine the closet IoT hub out of the group of IoT hubs.
Multi-tenancy: Devices used within an IoT solution may need to be assigned to a specific IoT hub or group of IoT hubs. The solution may require all devices for a particular tenant to communicate with a specific group of IoT hubs. In some cases, a tenant may own IoT hubs and require devices to be assigned to their IoT hubs.
It's common to combine these two scenarios. For example, a multitenant IoT solution commonly assigns tenant devices using a group of IoT hubs that are scattered across different regions. These tenant devices can be assigned to the IoT hub in the group that has the lowest latency based on geographic location.
This article uses a simulated device sample from the Azure IoT C SDK to demonstrate how to provision devices in a multitenant scenario across regions. You will perform the following steps in this article:
- Use the Azure CLI to create two regional IoT hubs (West US 2 and East US)
- Create a multitenant enrollment
- Use the Azure CLI to create two regional Linux VMs to act as devices in the same regions (West US 2 and East US)
- Set up the development environment for the Azure IoT C SDK on both Linux VMs
- Simulate the devices to see that they are provisioned for the same tenant in the closest region.
Important
Some regions may, from time to time, enforce restrictions on the creation of Virtual Machines. At the time of writing this guide, the westus2 and eastus regions permitted the creation of VMs. If you're unable to create in either one of those regions, you can try a different region. To learn more about choosing Azure geographical regions when creating VMs, see Regions for virtual machines in Azure
Prerequisites
If you don't have an Azure subscription, create a free account before you begin.
Complete the steps in Set up IoT Hub Device Provisioning Service with the Azure portal.
Use the Bash environment in Azure Cloud Shell. For more information, see Azure Cloud Shell Quickstart - Bash.
If you prefer to run CLI reference commands locally, install the Azure CLI. If you are running on Windows or macOS, consider running Azure CLI in a Docker container. For more information, see How to run the Azure CLI in a Docker container.
If you're using a local installation, sign in to the Azure CLI by using the az login command. To finish the authentication process, follow the steps displayed in your terminal. For additional sign-in options, see Sign in with the Azure CLI.
When you're prompted, install Azure CLI extensions on first use. For more information about extensions, see Use extensions with the Azure CLI.
Run az version to find the version and dependent libraries that are installed. To upgrade to the latest version, run az upgrade.
Create two regional IoT hubs
In this section, you'll create an Azure resource group, and two new regional IoT hub resources for a tenant. One IoT hub will be for the West US 2 region and the other will be for the East US region.
Important
It's recommended that you use the same resource group for all resources created in this article. This will make clean up easier after you are finished.
In the Azure Cloud Shell, create a resource group with the following az group create command:
az group create --name contoso-us-resource-group --location eastusCreate an IoT hub in the eastus location, and add it to the resource group you created with the following az iot hub create command(replace
{unique-hub-name}with your own unique name):az iot hub create --name {unique-hub-name} --resource-group contoso-us-resource-group --location eastus --sku S1This command may take a few minutes to complete.
Now, create an IoT hub in the westus2 location, and add it to the resource group you created with the following az iot hub create command(replace
{unique-hub-name}with your own unique name):az iot hub create --name {unique-hub-name} --resource-group contoso-us-resource-group --location westus2 --sku S1This command may take a few minutes to complete.
Create the multitenant enrollment
In this section, you'll create a new enrollment group for the tenant devices.
For simplicity, this article uses Symmetric key attestation with the enrollment. For a more secure solution, consider using X.509 certificate attestation with a chain of trust.
In the Azure portal, select your Device Provisioning Service.
In the Settings menu, select Manage enrollments.
Select + Add enrollment group.
On the Add Enrollment Group page, enter the following information:
Group name: Enter contoso-us-devices. The enrollment group name is a case-insensitive string (up to 128 characters long) of alphanumeric characters plus the special characters:
'-','.','_',':'. The last character must be alphanumeric or dash ('-').Attestation Type: Select Symmetric Key.
Auto Generate Keys: This checkbox should already be checked.
Select how you want to assign devices to hubs: Select Lowest latency.
Select Link a new IoT Hub
On the Add link to IoT hub page, enter the following information:
Subscription: If you have multiple subscriptions, choose the subscription where you created the regional IoT hubs.
IoT hub: Select the IoT hub that you created for the eastus location.
Access Policy: Select iothubowner.
Select Save.
Repeat Steps 5 through 7 for the second IoT hub that you created for the westgus location.
Select the two IoT Hubs you created in the Select the IoT hubs this group can be assigned to drop down.
Select Save
Select contoso-us-devices in the enrollment groups list.
Copy the Primary Key. This key will be used later to generate unique device keys for both simulated devices.
Create regional Linux VMs
In this section, you'll create two regional Linux virtual machines (VMs). These VMs will run a device simulation sample from each region to demonstrate device provisioning for tenant devices from both regions.
To make clean-up easier, these VMs will be added to the same resource group that contains the IoT hubs that were created, contoso-us-resource-group. However, the VMs will run in separate regions (West US 2 and East US).
In the Azure Cloud Shell, run the following command to create an East US region VM after making the following parameter changes in the command:
--name: Enter a unique name for your East US regional device VM.
--admin-username: Use your own admin user name.
--admin-password: Use your own admin password.
az vm create \ --resource-group contoso-us-resource-group \ --name ContosoSimDeviceEast \ --location eastus \ --image Canonical:UbuntuServer:18.04-LTS:18.04.201809110 \ --admin-username contosoadmin \ --admin-password myContosoPassword2018 \ --authentication-type password --public-ip-sku StandardThis command will take a few minutes to complete.
Once the command has completed, copy the publicIpAddress value for your East US region VM.
In the Azure Cloud Shell, run the command to create a West US 2 region VM after making the following parameter changes in the command:
--name: Enter a unique name for your West US 2 regional device VM.
--admin-username: Use your own admin user name.
--admin-password: Use your own admin password.
az vm create \ --resource-group contoso-us-resource-group \ --name ContosoSimDeviceWest2 \ --location westus2 \ --image Canonical:UbuntuServer:18.04-LTS:18.04.201809110 \ --admin-username contosoadmin \ --admin-password myContosoPassword2018 \ --authentication-type password --public-ip-sku StandardThis command will take a few minutes to complete.
Once the command has completed, copy the publicIpAddress value for your West US 2 region VM.
Open two command-line shells.
Connect to one of the regional VMs in each shell using SSH.
Pass your admin username and the public IP address that you copied as parameters to SSH. Enter the admin password when prompted.
ssh contosoadmin@1.2.3.4 contosoadmin@ContosoSimDeviceEast:~$ssh contosoadmin@5.6.7.8 contosoadmin@ContosoSimDeviceWest:~$
Prepare the Azure IoT C SDK development environment
In this section, you'll clone the Azure IoT C SDK on each VM. The SDK contains a sample that simulates a tenant's device provisioning from each region.
For each VM:
Install CMake, g++, gcc, and Git using the following commands:
sudo apt-get update sudo apt-get install cmake build-essential libssl-dev libcurl4-openssl-dev uuid-dev git-allFind and copy the tag name for the latest release of the SDK.
Clone the Azure IoT C SDK on both VMs. Use the tag you found in the previous step as the value for the
-bparameter:git clone -b <release-tag> https://github.com/Azure/azure-iot-sdk-c.git cd azure-iot-sdk-c git submodule update --initYou should expect this operation to take several minutes to complete.
Create a new cmake folder inside the repository and change to that folder.
mkdir ~/azure-iot-sdk-c/cmake cd ~/azure-iot-sdk-c/cmakeRun the following command, which builds a version of the SDK specific to your development client platform:
cmake -Dhsm_type_symm_key:BOOL=ON -Duse_prov_client:BOOL=ON ..Once the build succeeds, the last few output lines will look similar to the following output:
-- IoT Client SDK Version = 1.7.0 -- Provisioning SDK Version = 1.7.0 -- Looking for include file stdint.h -- Looking for include file stdint.h - found -- Looking for include file stdbool.h -- Looking for include file stdbool.h - found -- target architecture: x86_64 -- Performing Test CXX_FLAG_CXX11 -- Performing Test CXX_FLAG_CXX11 - Success -- Found OpenSSL: /usr/lib/x86_64-linux-gnu/libcrypto.so (found version "1.1.1") -- Found CURL: /usr/lib/x86_64-linux-gnu/libcurl.so (found version "7.58.0") -- Found CURL: /usr/lib/x86_64-linux-gnu/libcurl.so -- target architecture: x86_64 -- iothub architecture: x86_64 -- Configuring done -- Generating done -- Build files have been written to: /home/contosoadmin/azure-iot-sdk-c/azure-iot-sdk-c
Derive unique device keys
When using symmetric key attestation with group enrollments, you don't use the enrollment group keys directly. Instead, you derive a unique key from the enrollment group key for each device. For more information, see Group Enrollments with symmetric keys.
In this part of the tutorial, you'll generate a device key from the you group master key to compute an HMAC-SHA256 of the unique registration ID for the device. The result will then be converted into Base64 format.
Important
Don't include your group master key in your device code.
For both eastus and westus 2 devices:
Generate your unique key using openssl. You'll use the following Bash shell script (replace
{primary-key}with the enrollment group's Primary Key that you copied earlier and replace{contoso-simdevice}with your own unique registration ID for each device. The registration ID is a case-insensitive string (up to 128 characters long) of alphanumeric characters plus the special characters:'-','.','_',':'. The last character must be alphanumeric or dash ('-').KEY={primary-key} REG_ID={contoso-simdevice} keybytes=$(echo $KEY | base64 --decode | xxd -p -u -c 1000) echo -n $REG_ID | openssl sha256 -mac HMAC -macopt hexkey:$keybytes -binary | base64The script will output something like the following key:
p3w2DQr9WqEGBLUSlFi1jPQ7UWQL4siAGy75HFTFbf8=Now each tenant device has their own derived device key and unique registration ID to perform symmetric key attestation with the enrollment group during the provisioning process.
Simulate the devices from each region
In this section, you'll update a provisioning sample in the Azure IoT C SDK for both of the regional VMs.
The sample code simulates a device boot sequence that sends the provisioning request to your Device Provisioning Service instance. The boot sequence causes the device to be recognized and assigned to the IoT hub that is closest based on latency.
In the Azure portal, select the Overview tab for your Device Provisioning Service and note down the ID Scope value.
On both VMS, open ~/azure-iot-sdk-c/provisioning_client/samples/prov_dev_client_sample/prov_dev_client_sample.c for editing.
vi ~/azure-iot-sdk-c/provisioning_client/samples/prov_dev_client_sample/prov_dev_client_sample.cOn both VMs, find the
id_scopeconstant, and replace the value with your ID Scope value that you copied earlier.static const char* id_scope = "0ne00002193";On both VMs, find the definition for the
main()function in the same file. Make sure thehsm_typevariable is set toSECURE_DEVICE_TYPE_SYMMETRIC_KEYas shown below to match the enrollment group attestation method.Save your changes to the files on both VMs.
SECURE_DEVICE_TYPE hsm_type; //hsm_type = SECURE_DEVICE_TYPE_TPM; //hsm_type = SECURE_DEVICE_TYPE_X509; hsm_type = SECURE_DEVICE_TYPE_SYMMETRIC_KEY;On both VMs, find the call to
prov_dev_set_symmetric_key_info()in prov_dev_client_sample.c which is commented out.// Set the symmetric key if using they auth type //prov_dev_set_symmetric_key_info("<symm_registration_id>", "<symmetric_Key>");Uncomment the function calls, and replace the placeholder values (including the angle brackets) with the unique registration IDs and derived device keys for each device that you derived in the previous section. The keys shown below are for example purposes only. Use the keys you generated earlier.
East US:
// Set the symmetric key if using they auth type prov_dev_set_symmetric_key_info("contoso-simdevice-east", "p3w2DQr9WqEGBLUSlFi1jPQ7UWQL4siAGy75HFTFbf8=");West US:
// Set the symmetric key if using they auth type prov_dev_set_symmetric_key_info("contoso-simdevice-west", "J5n4NY2GiBYy7Mp4lDDa5CbEe6zDU/c62rhjCuFWxnc=");On both VMs, save the file.
On both VMs, navigate to the sample folder shown below, and build the sample.
cd ~/azure-iot-sdk-c/cmake/provisioning_client/samples/prov_dev_client_sample/ cmake --build . --target prov_dev_client_sample --config DebugOnce the build succeeds, run prov_dev_client_sample.exe on both VMs to simulate a tenant device from each region. Notice that each device is allocated to the tenant IoT hub closest to the simulated device's regions.
Run the simulation:
~/azure-iot-sdk-c/cmake/provisioning_client/samples/prov_dev_client_sample/prov_dev_client_sampleExample output from the East US VM:
contosoadmin@ContosoSimDeviceEast:~/azure-iot-sdk-c/cmake/provisioning_client/samples/prov_dev_client_sample$ ./prov_dev_client_sample Provisioning API Version: 1.2.9 Registering Device Provisioning Status: PROV_DEVICE_REG_STATUS_CONNECTED Provisioning Status: PROV_DEVICE_REG_STATUS_ASSIGNING Provisioning Status: PROV_DEVICE_REG_STATUS_ASSIGNING Registration Information received from service: contoso-east-hub.azure-devices.net, deviceId: contoso-simdevice-east Press enter key to exit:Example output from the West US VM:
contosoadmin@ContosoSimDeviceWest:~/azure-iot-sdk-c/cmake/provisioning_client/samples/prov_dev_client_sample$ ./prov_dev_client_sample Provisioning API Version: 1.2.9 Registering Device Provisioning Status: PROV_DEVICE_REG_STATUS_CONNECTED Provisioning Status: PROV_DEVICE_REG_STATUS_ASSIGNING Provisioning Status: PROV_DEVICE_REG_STATUS_ASSIGNING Registration Information received from service: contoso-west-hub.azure-devices.net, deviceId: contoso-simdevice-west Press enter key to exit:
Clean up resources
If you plan to continue working with resources created in this article, you can leave them. Otherwise, use the following steps to delete all resources created by this article to avoid unnecessary charges.
The steps here assume that you created all resources in this article as instructed in the same resource group named contoso-us-resource-group.
Important
Deleting a resource group is irreversible. The resource group and all the resources contained in it are permanently deleted. Make sure that you do not accidentally delete the wrong resource group or resources. If you created the IoT Hub inside an existing resource group that contains resources you want to keep, only delete the IoT Hub resource itself instead of deleting the resource group.
To delete the resource group by name:
Sign in to the Azure portal.
Select Resource groups.
In the Filter by name... textbox, type the name of the resource group containing your resources, contoso-us-resource-group.
To the right of your resource group in the result list, click ... then Delete resource group.
You'll be asked to confirm the deletion of the resource group. Type the name of your resource group again to confirm, and then select Delete. After a few moments, the resource group and all of its contained resources are deleted.
Next steps
- To learn more about reprovisioning, see:
- To learn more about deprovisioning, see
Povratne informacije
Pošalјite i prikažite povratne informacije za
