hashicorp / terraform-provider-azurerm

Terraform provider for Azure Resource Manager
https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs
Mozilla Public License 2.0
4.5k stars 4.59k forks source link

Support for Azure Device Provisioning Service Enrollment Groups #11101

Open DaveOHenry opened 3 years ago

DaveOHenry commented 3 years ago

Community Note

Description

I created an Azure IOT hub and a linked a Device Provisioning Service via Terraform. Unfortunately there seems to be no support for Enrollment Groups in azurerm_iothub_dps currently: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/iothub_dps

New or Affected Resource(s)

References

https://docs.microsoft.com/en-us/rest/api/iot-dps/createorupdateenrollmentgroup/createorupdateenrollmentgroup

kensykora commented 3 years ago

Proposal for what it might look like

resource "azurerm_iothub_dps_enrollment_group" "mygroup" {
  name = "mygroup"
  resource_group_name = "myrg"
  iothub_dps_name = azurerm_iothub_dps.mydps.name

  attestation = {
    type = "certificate"
    certificate = { # xor with key below
        iot_edge_device = false
        primary = base64encode(file("mycert.cer"))
        secondary = base64encode(file("mycert.cer"))
    }
    key = { # xor with certificate
      auto_generate = false
      primary_key = "****"
      secondary_key = "****"
    }
  }
  distribution = "evenly_weighted"
  iot_hubs = [
    azurerm_iothub.myhub.id
  ]
  initial_twin_state = {
    tags = {
      abc = 123
    },
    properties = {
       desired = {
         config_a = 123
       }
    }
  }
}
LeonardoSanBenitez commented 2 years ago

Yes, this feature would be great. I think that would be good support not only for Enrollment Groups, for also for Individual Enrollments

esierrapena commented 2 years ago

Any update on this? Really interesting one.

Thanks!

Ramanean commented 1 year ago

Any update on this?

dennisholmer commented 1 year ago

Meanwhile, I'm using a workaround something along these lines. Seem to be working pretty well:

device-provisioning-service.tf
--------------------------------
resource "null_resource" "dps_main_upsert_enrollments" {
  triggers = {
    # Add any parameters to the enrollments script here. This key then ensures the script is only run if a parameter or the script content changes.
    should_run = "${filesha256("./scripts/enrollments.sh")}|${azurerm_resource_group.main.name}|${azurerm_iothub_dps.main.name}"
  }

  provisioner "local-exec" {
    command = "./scripts/enrollments.sh ${azurerm_resource_group.main.name} ${azurerm_iothub_dps.main.name}"
    interpreter = ["bash", "-c"]
  }
}

Then you can add whatever enrollment Azure CLI commands you want like this. This is an example of adding a symmetric key individual enrollment. Check Azure CLI commands documentation for more info:

./scripts/enrollments.sh
--------------------------------
#!/bin/sh

resource_group_name=$1
dps_name=$2
eid="maintained-by-terraform"

enrollment=$(az iot dps enrollment show --eid $eid --resource-group $resource_group_name --dps-name $dps_name 2>/dev/null)

if [ -z "$enrollment" ]
then
    echo 'Creating enrollment...'
    enrollment=$(az iot dps enrollment create --at symmetricKey --eid $eid --resource-group $resource_group_name --dps-name $dps_name)
fi
survivant commented 1 year ago

thanks, I was looking for that feature. I'll give it a try

emibcn commented 1 year ago

In the meanwhile, I use this null_resource in a module:

##### variables.tf

variable "subscription_id" {
  description = "Subscription to use to create all resources. Defaults to default subscription."
  default     = "{subscriptionId}"
}

variable "resource-group" {
  description = "The Resource Group where all resources will be added"
}

variable "iothub" {
  description = "The IoTHub where add the enrollment group"
}

variable "iothub-hostname" {
  description = "The IoTHub where add the enrollment group"
}

variable "dps" {
  description = "The DPS where add the enrollment group"
}

variable "enrollment-name" {
  description = "The enrollment group name"
}

variable "initial-twin-tags" {
  default = {}
  description = "The Initial Twin for the DPS EnrollmentGroup associated to the IoTHub."
}

##### main.tf

# Create DPS Enrollment Group, which is not yet supported by Terraform
# Note: Keys (primary and secondary) are created automatically if not passed
# Note: Needs extra plugin `azure-iot` installed
# Note: azure-iot extension for Azure CLI requires AZ version 2.17.1 or higher
# - https://www.terraform.io/docs/language/resources/provisioners/local-exec.html
# - https://www.terraform.io/docs/language/expressions/strings.html#indented-heredocs
# - https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource
# - https://docs.microsoft.com/en-us/cli/azure/iot/dps/enrollment-group?view=azure-cli-latest
# - https://github.com/hashicorp/terraform-provider-azurerm/issues/11101

locals {
  # Set here enrollment options
  # Note: If no certificate_path and not root_ca_name (nor secondaries), attestation type will be "Symmetric Key"
  # Note: Keys (primary and secondary) are created automatically if not passed
  enrollment_envs = {
    SUBSCRIPTION       = var.subscription_id
    RG                 = var.resource-group
    DPS                = var.dps
    ALLOC_POLICY       = "hashed"
    EDGE_ENABLED       = "true"
    IOT_HOSTNAME       = var.iothub-hostname
    PROVISION_STATUS   = "enabled"
    REPROVISION_POLICY = "reprovisionandmigratedata"

    NAME = var.enrollment-name
    INITIAL_TWIN = jsonencode({
      tags = var.initial-twin-tags
    })
  }
}

resource "null_resource" "enrollment-group" {
  # Re-launch this resource whenever one or more of these change
  triggers = local.enrollment_envs

  # Needs this resources to be created before running
  depends_on = [
    var.resource-group,
    var.dps
  ]

  # Remove resource on triggers change
  # TODO: Translate to Python SDK
  provisioner "local-exec" {
    environment = self.triggers
    when        = destroy
    command     = <<-EOT
      set -e

      echo "Enrollment group changed. Removing."
      az iot dps enrollment-group delete \
        --subscription "$SUBSCRIPTION" \
        --resource-group "$RG" \
        --dps-name "$DPS" \
        --enrollment-id "$NAME"
    EOT
  }

  # Create resource
  # TODO: Translate to Python SDK
  provisioner "local-exec" {
    environment = self.triggers
    command     = <<-EOT
      set -e

      # First, test if resource already exists
      ACTION="create"
      if az iot dps enrollment-group list \
           --subscription "$SUBSCRIPTION" \
           --resource-group "$RG" \
           --dps-name "$DPS" \
         | grep "\"$NAME\"" > /dev/null
      then
          ACTION="update"
          echo "Enrollment group already exists. Updating."
      fi

      # Create or update the enrollment group
      # Note: Needs extra az plugin `azure-iot` installed
      az iot dps enrollment-group "$ACTION" \
        --subscription "$SUBSCRIPTION" \
        --resource-group "$RG" \
        --dps-name "$DPS" \
        --enrollment-id "$NAME" \
        --edge-enabled "$EDGE_ENABLED" \
        --iot-hubs "$IOT_HOSTNAME" \
        --initial-twin-properties "$INITIAL_TWIN" \
        --provisioning-status "$PROVISION_STATUS" \
        --reprovision-policy "$REPROVISION_POLICY" \
        --allocation-policy "$ALLOC_POLICY"
    EOT
  }
}

Then you can use it like:

module "enrollment-group" {
  source            = "./dps-enrollment/"
  subscription_id   = var.subscription_id
  resource-group    = data.azurerm_resource_group.resource-group.name
  iothub            = azurerm_iothub.iothub.name
  iothub-hostname   = azurerm_iothub.iothub.hostname
  dps               = azurerm_iothub_dps.dps.name
  enrollment-name   = "${azurerm_iothub_dps.dps.name}-main"
  initial-twin-tags = var.initial-twin-tags
}
ramondeklein commented 1 year ago

Seems that IOT DPS enrollment groups are in the Go SDK for a while now: https://github.com/Azure/azure-sdk-for-go/issues/15098

pregress commented 1 year ago

@catriona-m as mentioned by @ramondeklein could you remove the label: sdk/not-yet-supported

cmergenthaler commented 11 months ago

Are there any updates on this?

emibcn commented 9 months ago

Are there any updates on this?