At the core of any Internet of Things (IoT) solution built with Microsoft Azure is the need to connect IoT devices to the cloud and send/retrieve event telemetry for those devices. When building an IoT solution using Azure IoT, the two primary services that you will use in almost every IoT solution are the Azure IoT Hub and Azure IoT Device Provisioning Service (DPS). Of course, you can easily create and manage these services from the Azure Portal, Azure CLi, and other tools, but you can also easily create and manage them using Terraform as well!
Let’s dig into how to do this!
Related: If you’re new to Terraform, or looking for a bit more information about it, then we recommend you check out our “Get Started with Terraform on Azure” article. This will give you a great jump start to both using Terraform for infrastructure automation, as well as some tips on using it with Microsoft Azure.
Create Azure IoT Hub
Azure IoT Hub is the highly scalable IoT messaging service to use for building IoT solutions in Microsoft Azure. This service provides a cloud-based message broker for connecting to, authenticating, and communicating with IoT devices. To get started with it, you need to create an instance of Azure IoT Hub within your Azure Subscription.
The Azure provider for Terraform exposes the azurerm_iothub
resource type for managing Azure IoT Hub resource instances. At minimum, there are only a few property configurations to set for creating an Azure IoT Hub instance within your Azure Subscription.
name
– The unique Name of the Azure IoT Hub resource instance in Azure.resource_group_name
– The name of the Azure Resource Group for which the IoT Hub resource will be organized within.location
– The Azure Region where the IoT Hub resource will be created.sku
– Asku
block that defines the SKU (pricing tier) and capacity units of the IoT Hub.
Naming Requirements: The name of the Azure IoT Hub resource must meet the following requirements:
- must be unique across all customers using Azure IoT Hub, as it’s used as part of the DNS name for the service endpoint.
- must be between 3 and 50 characters long
- can only be alphanumeric characters
Let’s take a look at some example Terraform using the azurerm
provider to create / manage an instance of Azure IoT Hub:
# Create an Azure IoT Hub
resource "azurerm_iothub" "b59iothub" {
name = "b59iothub"
# "azurerm_resource_group.b59" is an Azure Resource Group
# defined elsewhere in the Terraform project
resource_group_name = azurerm_resource_group.b59.name
location = azurerm_resource_group.b59.location
# Define the Pricing Tier (SKU & Capacity)
sku {
name = "S1"
capacity = 1
}
}
The sku
block is used to specify the pricing tier and capacity units for the Azure IoT Hub. The sku.name
defines the pricing tier, and the sku.capacity
defines the number of provisioned Azure IoT Hub Units.
The possible value options for setting the Azure IoT Hub pricing tier using the sku.name
property are as follows:
SKU Edition | Tier | Msgs/Day per IoT Hub Unit |
---|---|---|
Basic | B1 |
400,000 |
B2 |
6,000,000 | |
B3 |
300,000,000 | |
Free (Standard) | F1 |
8,000 |
Standard | S1 |
400,000 |
S2 |
6,000,000 | |
S3 |
300,000,000 |
Note: The Free (
F1
) pricing tier is a special type of Standard tier meant for DEV / TEST purposes, and is limited to only a single Free tier IoT Hub per Azure Subscription. The Free tier has a limit of 8,000 messages per day, and the ability to register up to 500 device identities. This device identity limit only applies to the Free tier.
Azure IoT Hub Units are the method used to scale the chosen SKU to handle a higher number of messages per day. At minimum, the sku.capacity
for Azure IoT Hub will need to be set to 1
unit. To handle higher scalability, a higher number of units for the chosen SKU can be configured
The Standard S1, S2, and Basic B1, B2 SKU’s have a limit of up to 200 IoT Hub Units. Also. the Standard S3 and Basic B3 have a limit of up to 10 IoT Hub Units. If you require to move above these limits, then you will need to contact Microsoft support for assistance.
Related: If you’re looking for more about Azure IoT services, architecture, and how everything fits together, then we recommend you check out our “Introduction to Azure IoT for Administrators” article. This will give you a great jump start on the “what” and “why” of Microsoft Azure IoT solutions.
Create Azure IoT Hub Device Provisioning Service (DPS)
The Azure IoT Hub Device Provisioning Service (DPS) provides a rich set of features for enabling zero-touch, just-in-time provisioning of devices with Azure IoT Hub. DPS can be used to provision millions of devices in a secure and scalable manner without requiring human intervention. Since DPS is a separate service, you will create Azure IoT Hub and DPS service instances as you build an Azure IoT solution.
The Azure provider for Terraform exposes the azurerm_iothub_dps
resource type for managing Azure IoT Hub Device Provisioning Service (DPS) resource instances. At minimum, there are only a few property configurations to set for creating a DPS instance within your Azure Subscription.
name
– The Name of the Azure IoT Hub DPS resource instance in Azure.resource_group_name
– The name of the Azure Resource Group for which the DPS resource will be organized within.location
– The Azure Region where the IoT Hub resource will be created.sku
– Asku
block that defines the SKU (pricing tier) and capacity units of the IoT Hub.
Naming Requirements: The name of the Azure IoT Hub Device Provisioning Service (DPS) resource must meet the following requirements:
- must be unique across all customers using Azure IoT Hub DPS, as it’s used as part of the DNS name for the service endpoint.
- must be between 3 and 64 characters long
- can only contain alphanumeric characters, or
-
- must not end with
-
Let’s take a look at some example Terraform using the azurerm
provider to create / manage an instance of Azure IoT Hub Device Provisioning Service (DPS):
# Create a Device Provisioning Service
resource "azurerm_iothub_dps" "b59dps" {
name = "b59dps"
resource_group_name = azurerm_resource_group.b59.name
location = azurerm_resource_group.b59.location
sku {
name = "S1"
capacity = 1
}
}
The sku
block is used to specify the pricing tier and capacity units for the Azure IoT Hub Device Provisioning Service. The sku.name
defines the pricing tier, and the sku.capacity
defines the number of provisioned Azure IoT Hub Device Provisioning Service Units.
Currently, the Standard S1
SKU is the only option for the DPS service.
SKU Edition | Tier |
---|---|
Standard | S1 |
Also, currently, the only value used for the sku.capacity
is 1
.
Configure Azure IoT Hub DPS Linked Hub
When implementing Azure IoT Hub Device Provisioning Service (DPS), it needs to be linked to Azure IoT Hub for the service to be able to provision millions of devices with the service. This is done by configuring the Linked Hub of the DPS instance to connect it with the Azure IoT Hub service where the devices will be provisioned using DPS.
Before the DPS service can be linked to an Azure IoT Hub, there needs to be a Shared Access Policy on the Azure IoT Hub. This Connection String from this policy will be used to configure DPS to connect to the Azure IoT Hub with. You can create a new policy just for this, or you can use the iothubowner
Shared Access Policy of the Azure IoT Hub that gets created by default when creating a new instance of the service.
To setup a reference for the existing iothubowner
Shared Access Policy on the Azure IoT Hub, the azurerm_iothub_shared_access_policy
resource type in Terraform can be used. A Terraform data
reference can be defined to create a reference tot he existing policy. Alternatively, a Terraform resource
could be used to create a new Shared Access Policy, if that is required for the IoT solution.
When defining a data
reference of the azurerm_iothub_shared_access_policy
resource type in Terraform, there are three properties that need to be set to target the desired, existing Shared Access Policy:
name
– The Name of the Azure IoT Hub Shared Access Policy.resource_group_name
– The name of the Azure Resource Group for which the Azure IoT Hub resource is organized within.iothub_name
– The Name of the Azure IoT Hub that contains the Shared Access Policy.
Here’s an example of using Terraform and the azurerm_iothub_shared_access_policy
resource type to create a data
reference to the existing Shared Access Policy:
# Create an IoT Hub Access Policy
data "azurerm_iothub_shared_access_policy" "b59iothub_iothubowner" {
name = "iothubowner"
resource_group_name = azurerm_resource_group.b59.name
iothub_name = azurerm_iothub.b59iothub.name
}
To configure the Linked Hub to connect an Azure IoT Hub to the Device Provisioning Service, a linked_hub
block needs to be added to the existing azurerm_iothub_dps
resource. There are two required properties of this block to be configured:
connection_string
– The connection string to connect to Azure IoT Hub.location
– The Azure Region of the Azure IoT Hub.
# Create a Device Provisioning Service
resource "azurerm_iothub_dps" "b59dps" {
name = "b59dps"
resource_group_name = azurerm_resource_group.b59.name
location = azurerm_resource_group.b59.location
sku {
name = "S1"
capacity = 1
}
linked_hub {
connection_string = data.azurerm_iothub_shared_access_policy.b59iothub_iothubowner.primary_connection_string
location = azurerm_iothub.b59iothub.location
}
}
Using the above example of referencing the existing iothubowner
Shared Access Policy of the IoT Hub, the linked_hub.connection_string
will be set to either the primary_connection_string
or secondary_connection_string
of the data.azurerm_iothub_shared_access_policy
that was defined in the Terraform code.
Related: There are times when declarative Infrastructure as Code (IaC) with Terraform doesn’t fit the need. For those occasions, the Azure CLI offers an amazing command-line experience. We recommend you check out the “Azure CLI: Manage Azure IoT Hub Device Provisioning Service (DPS)” article to learn how to do this from the command-line with the Azure CLI.
Full Code Example
Here’s a combined, complete Terraform code example for creating an Azure IoT Hub, a Device Provisioning Service, and linking them together:
provider "azurerm" {
# AzureRM provider 2.x
version = "~>2.0"
# v2.x required "features" block
features {}
}
# Create a resource group
resource "azurerm_resource_group" "b59" {
name = "b59-iot-rg"
location = "North Central US"
}
# Create an Azure IoT Hub
resource "azurerm_iothub" "b59iothub" {
name = "b59iothub"
resource_group_name = azurerm_resource_group.b59.name
location = azurerm_resource_group.b59.location
sku {
name = "S1"
capacity = 1
}
}
# Create an IoT Hub Access Policy
data "azurerm_iothub_shared_access_policy" "b59iothub_iothubowner" {
name = "iothubowner"
resource_group_name = azurerm_resource_group.b59.name
iothub_name = azurerm_iothub.b59iothub.name
}
# Create a Device Provisioning Service
resource "azurerm_iothub_dps" "b59dps" {
name = "b59dps"
resource_group_name = azurerm_resource_group.b59.name
location = azurerm_resource_group.b59.location
sku {
name = "S1"
capacity = 1
}
linked_hub {
connection_string = data.azurerm_iothub_shared_access_policy.b59iothub_iothubowner.primary_connection_string
location = azurerm_iothub.b59iothub.location
}
}
Keep in mind that there are unique name requirements for resources in Azure when running this Azure IoT Terraform code example. You will likely need to rename the resources, otherwise you will receive “resource with this name already exists” type of error messages when attempting to run this Terraform code as-is.
Happy automating the deployment and management of your Azure IoT Hub and DPS solution infrastructure using Terraform!
Great post i must say and thanks for the information. Education is definitely a sticky subject. However, is still among the leading topics of our time. I appreciate your post and look forward to more.
Good information, Chris. Do you know of any way to use terraform to create an IoT Device within the IoT Hub? I have a small number of devices that I would like to automate and don’t need the scale of the DPS yet.
The “azurerm” Terraform provider doesn’t support managing IoT Devices within the IoT Hub device registry. For this, you can use the Azure CLI to automate the management of your devices. Although, if you have more than a handful of devices, then you may still want to think about using DPS for your solution. Thanks!
Hi Chris, that’s a nice article. Thank you for that.
Do you know how to also define the DSP enrollment groups (for symmetrical keys and certificates) that needs to be configured with Terraform?
It looks like the Azure ARM provider for Terraform doesn’t support managing DPS enrollment groups. For now, you’ll need to use the Azure CLI or PowerShell to automate this piece. Thanks!