Compartilhar via


Como usar chaves simétricas por HTTPS sem um SDK

Neste artigo de instruções, você provisionará um dispositivo usando chaves simétricas por HTTPS sem usar um SDK do dispositivo DPS em IoT do Azure. A maioria das linguagens fornece bibliotecas para enviar solicitações HTTP, mas, em vez de se concentrar em uma linguagem específica, neste artigo, você usará a ferramenta de linha de comando cURL para enviar e receber por HTTPS.

Você pode seguir as etapas neste artigo em um computador Linux ou Windows. No caso de execuções em WSL (Subsistema do Windows para Linux) ou em um computador Linux, você poderá inserir todos os comandos no seu sistema local em um prompt do Bash. No caso de execuções no Windows, insira todos os comandos no seu sistema local em um prompt do GitBash.

Há caminhos diferentes neste artigo, dependendo do tipo de entrada de registro que você escolher usar. Depois de instalar os prerrequisitos, leia a Visão geral antes de continuar.

Pré-requisitos

  • Se você não tiver uma assinatura do Azure, crie uma conta gratuita antes de começar.

  • Conclua as etapas em Configurar o Serviço de Provisionamento de Dispositivos no Hub IoT com o portal do Azure.

  • Verifique se o Python 3.7 ou posterior está instalado no computador. Verifique sua versão do Python executando python --version.

  • No caso de execuções no Windows, instale a versão mais recente do Git. Verifique se o Git foi adicionado às variáveis de ambiente que podem ser acessadas pela janela de comando. Confira Ferramentas de cliente Git do Software Freedom Conservancy para obter a versão mais recente das ferramentas git a serem instaladas, que inclui o Git Bash, o aplicativo de linha de comando que você pode usar para interagir com seu repositório Git local. No Windows, insira todos os comandos no seu sistema local em um prompt do GitBash.

  • CLI do Azure. Você tem duas opções para executar comandos da CLI do Azure neste artigo:

    • Usar o Azure Cloud Shell, um shell interativo que executa comandos da CLI no navegador. Essa opção é recomendada porque não é preciso instalar nada. Se estiver usando o Cloud Shell pela primeira vez, faça logon no portal do Azure. Siga as etapas do Guia de início rápido do Cloud Shell para Iniciar o Cloud Shell e Selecionar o ambiente Bash.
    • Opcionalmente, execute a CLI do Azure no computador local. Se a CLI do Azure já estiver instalado, execute az upgrade para atualizar a CLI e as extensões para a versão atual. Para instalar a CLI do Azure, consulte Instalar a CLI do Azure.
  • No caso de execuções em um ambiente Linux ou WSL, abra um prompt do Bash para executar comandos localmente. No caso de execuções em um ambiente do Windows, abra um prompt do GitBash.

Visão geral

Para este artigo, você pode usar um registro individual ou um grupo de registros para provisionar por meio do DPS.

Depois de criar a entrada de grupo de registros ou registro individual, continue para criar um token SAS e registrar seu dispositivo com DPS.

Usar um registro individual

Se quiser criar um novo registro individual a ser usado para este artigo, você poderá usar o comando az iot dps enrollment create para criar um registro individual para atestado de chave simétrica.

O comando a seguir cria uma entrada de registro com a política de alocação padrão para sua instância do DPS e permite que o DPS atribua as chaves primária e secundária ao dispositivo:

az iot dps enrollment create -g {resource_group_name} --dps-name {dps_name} --enrollment-id {enrollment_id} --attestation-type symmetrickey
  • Substitua o nome do seu grupo de recursos e a instância do DPS.

  • A ID do registro é a ID do registro do dispositivo. A ID do registro é uma cadeia de caracteres que não diferencia maiúsculas de minúsculas (até 128 caracteres) de caracteres alfanuméricos mais os caracteres especiais: '-', '.', '_', ':'. O último caractere deve ser alfanumérico ou um traço ('-'). Verifique se a ID do registro que você usa no comando segue esse formato.

As chaves simétricas atribuídas são retornadas na propriedade atestado na resposta:


{
  "allocationPolicy": null,
  "attestation": {
    "symmetricKey": {
      "primaryKey": "G3vn0IZH9oK3d4wsxFpWBtd2KUrtjI+39dZVRf26To8w9OX0LaFV9yZ93ELXY7voqHEUsNhnb9bt717UP87KxA==",
      "secondaryKey": "4lNxgD3lUAOEOied5/xOocyiUSCAgS+4b9OvXLDi8ug46/CJzIn/3rN6Ys6gW8SMDDxMQDaMRnIoSd1HJ5qn/g=="
    },
    "tpm": null,
    "type": "symmetricKey",
    "x509": null
  },

  ...

}

Anote a chave primária e a ID do registro para sua entrada de registro individual. Você as usará mais adiante neste artigo.

Se desejar usar um registro individual existente para este artigo, poderá obter a chave primária com o comando az iot dps enrollment show:

az iot dps enrollment show -g {resource_group_name} --dps-name {dps_name} --enrollment-id {enrollment_id} --show-keys true

Usar um grupo de registros

Se quiser criar um novo grupo de registros a ser usado para este artigo, você poderá usar o comando az iot dps enrollment-group create para criar um grupo de registros para atestado de chave simétrica.

O comando a seguir cria uma entrada de grupo de registros com a política de alocação padrão para sua instância do DPS e permite que o DPS atribua as chaves primária e secundária ao grupo de registros:

az iot dps enrollment-group create -g {resource_group_name} --dps-name {dps_name} --enrollment-id {enrollment_id}
  • Substitua o nome do seu grupo de recursos e a instância do DPS.

  • A ID do registro é uma cadeia de caracteres que não diferencia maiúsculas de minúsculas (até 128 caracteres) de símbolos alfanumérico e caracteres especiais: '-', '.', '_' e ':'. O último caractere deve ser alfanumérico ou um traço ('-'). Pode ser qualquer nome que você escolher usar para o grupo de registros.

As chaves simétricas atribuídas são retornadas na propriedade atestado na resposta:


{
  "allocationPolicy": null,
  "attestation": {
    "symmetricKey": {
      "primaryKey": "G3vn0IZH9oK3d4wsxFpWBtd2KUrtjI+39dZVRf26To8w9OX0LaFV9yZ93ELXY7voqHEUsNhnb9bt717UP87KxA==",
      "secondaryKey": "4lNxgD3lUAOEOied5/xOocyiUSCAgS+4b9OvXLDi8ug46/CJzIn/3rN6Ys6gW8SMDDxMQDaMRnIoSd1HJ5qn/g=="
    },
    "tpm": null,
    "type": "symmetricKey",
    "x509": null
  },

  ...

}

Anote a chave primária.

Se desejar usar um registro individual existente para este artigo, poderá obter a chave primária com o comando az iot dps enrollment-group show:

az iot dps enrollment-group show -g {resource_group_name} --dps-name {dps_name} --enrollment-id {enrollment_id} --show-keys true

Derivar uma chave de dispositivo

Ao usar o atestado de chave simétrica com registros em grupo, você não usa as chaves de registro de grupo diretamente. Em vez disso, você obtém uma chave exclusiva para cada dispositivo da chave do grupo de registro. Para obter mais informações, consulte Registros de grupo com de chaves simétricas.

Nesta seção, você gerará uma chave do dispositivo da chave primária do grupo de registros para calcular um HMAC-SHA256 da ID de registro exclusiva para o dispositivo. Em seguida, o resultado será convertido no formato Base64.

  1. Gere sua chave exclusiva usando openssl. Você usará o script de shell do Bash a seguir. Substitua {primary-key} pela Chave Primária do grupo de registros que você copiou anteriormente e substitua {contoso-simdevice} pela ID de registro que deseja usar para o dispositivo. A ID do registro é uma cadeia de caracteres que não diferencia maiúsculas de minúsculas (até 128 caracteres) de caracteres alfanuméricos mais os caracteres especiais: '-', '.', '_', ':'. O último caractere deve ser alfanumérico ou um traço ('-').

    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 | base64
    
  2. O script produzirá algo como a seguinte chave:

    p3w2DQr9WqEGBLUSlFi1jPQ7UWQL4siAGy75HFTFbf8=
    

Anote a chave do dispositivo derivada e a ID de registro usada para gerá-la. Você as usará na próxima seção.

Você também pode usar a CLI do Azure ou o PowerShell para derivar uma chave do dispositivo. Para saber mais, confira Derivar uma chave do dispositivo.

Criar um token SAS

Ao usar o atestado de chave simétrica, os dispositivos são autenticados com o DPS usando um token SAS (Assinatura de Acesso Compartilhado). Para o provisionamento de dispositivos por meio de um registro individual, o token é assinado usando a chave primária ou secundária definida na entrada do registro. Para um provisionamento de dispositivo por meio de um grupo de registro, o token é assinado usando uma chave de dispositivo derivada, que, por sua vez, foi gerada usando o conjunto de chaves primárias ou secundárias na entrada do grupo de registros. O token especifica um tempo de expiração e um URI de recurso de destino.

O script Python a seguir pode ser usado para gerar um token SAS:

from base64 import b64encode, b64decode
from hashlib import sha256
from time import time
from urllib.parse import quote_plus, urlencode
from hmac import HMAC

def generate_sas_token(uri, key, policy_name, expiry=3600):
     ttl = time() + expiry
     sign_key = "%s\n%d" % ((quote_plus(uri)), int(ttl))
     print(sign_key)
     signature = b64encode(HMAC(b64decode(key), sign_key.encode('utf-8'), sha256).digest())

     rawtoken = {
         'sr' :  uri,
         'sig': signature,
         'se' : str(int(ttl))
     }

     if policy_name is not None:
         rawtoken['skn'] = policy_name

     return 'SharedAccessSignature ' + urlencode(rawtoken)

uri = '[resource_uri]'
key = '[device_key]'
expiry = [expiry_in_seconds]
policy= '[policy]'

print(generate_sas_token(uri, key, policy, expiry))

Em que:

  • [resource_uri] é o URI do recurso que você está tentando acessar com esse token. Para o DPS, é do formulário [dps_id_scope]/registrations/[dps_registration_id], em que [dps_id_scope] é o escopo da ID da instância do DPS e [dps_registration_id] é a ID de registro usada para o seu dispositivo.

    Você pode obter o escopo da ID para a instância do DPS no painel Visão geral da instância no portal do Azure ou usar o comando az iot dps show da CLI do Azure (substitua os espaços reservados pelo nome do grupo de recursos e a instância do DPS):

    az iot dps show -g {resource_group_name} --name {dps_name}
    
  • [device_key] é a chave do dispositivo associada ao seu dispositivo. Essa chave é especificada ou gerada automaticamente para você em um registro individual ou uma chave derivada para um registro de grupo.

  • [expiry_in_seconds] é o período de validade desse token SAS em segundos.

  • [policy] é a política à qual a chave do dispositivo está associada. Para registro de dispositivo do DPS, a política é codificada em "registro".

Um conjunto de exemplos de entradas para um dispositivo chamado my-symkey-device com um período de validade de 30 dias pode ter esta aparência.

uri = '0ne00111111/registrations/my-symkey-device'
key = '18RQk/hOPJR9EbsJlk2j8WA6vWaj/yi+oaYg7zmxfQNdOyMSu+SJ8O7TSlZhDJCYmn4rzEiVKIzNiVAWjLxrGA=='
expiry = 2592000
policy='registration'

Modifique o script para o seu dispositivo e a instância do DPS e salve como um arquivo Python. Por exemplo, generate_token.py. Execute o script, por exemplo, python generate_token.py. Ele deve gerar um token SAS semelhante ao seguinte:

0ne00111111%2Fregistrations%2Fmy-symkey-device
1663952627
SharedAccessSignature sr=0ne00111111%2Fregistrations%2Fmy-symkey-device&sig=eNwg52xQdFTNf7bgPAlAJBCIcONivq%2Fck1lf3wtxI4A%3D&se=1663952627&skn=registration

Copie e salve toda a linha que começa com SharedAccessSignature. Essa linha é o token SAS. Ele é necessário nas seções a seguir.

Para saber mais sobre como usar tokens SAS com o DPS e sua estrutura, confira Controlar o acesso ao DPS com SAS.

Registre seu dispositivo

Chame a API REST Registrar dispositivo para provisionar seu dispositivo por meio do DPS.

Use o comando curl a seguir:

curl -L -i -X PUT -H 'Content-Type: application/json' -H 'Content-Encoding:  utf-8' -H 'Authorization: [sas_token]' -d '{"registrationId": "[registration_id]"}' https://global.azure-devices-provisioning.net/[dps_id_scope]/registrations/[registration_id]/register?api-version=2019-03-31

Em que:

  • -L informa ao curl para seguir redirecionamentos HTTP.

  • –i informa ao curl para incluir cabeçalhos de protocolo na saída. Esses cabeçalhos não são estritamente necessários, mas podem ser úteis.

  • -X PUT informa ao curl que esse é um comando HTTP PUT. Necessário para essa chamada à API.

  • -H 'Content-Type: application/json' informa ao DPS que estamos postando conteúdo JSON e deve ser 'application/json'.

  • -H 'Content-Encoding: utf-8' informa ao DPS a codificação que estamos usando para o corpo da mensagem. Defina como o valor adequado para o sistema operacional/cliente, porém, geralmente é utf-8.

  • -H 'Authorization: [sas_token]' informa ao DPS para autenticar usando o token SAS. Substitua [sas_token] pelo token gerado em Criar um token SAS.

  • -d '{"registrationId": "[registration_id]"}', o parâmetro –d é o 'data' ou o corpo da mensagem que estamos postando. Deve ser JSON, na forma de '{"registrationId":"[registration_id"}'. Observe que, para o curl, ele é encapsulado em aspas simples. Caso contrário, você precisará escapar das aspas duplas no JSON.

  • Por fim, o último parâmetro é a URL para a qual postar. Para DPS "regular" (ou seja, não local), o ponto de extremidade do DPS global, global.azure-devices-provisioning.net é usado: https://global.azure-devices-provisioning.net/[dps_id_scope]/registrations/[registration_id]/register?api-version=2019-03-31. Observe que você precisa substituir [dps_scope_id] e [registration_id] pelos valores apropriados.

Por exemplo:

curl -L -i -X PUT -H 'Content-Type: application/json' -H 'Content-Encoding:  utf-8' -H 'Authorization: SharedAccessSignature sr=0ne00111111%2Fregistrations%2Fmy-symkey-device&sig=eNwg52xQdFTNf7bgPAlAJBCIcONivq%2Fck1lf3wtxI4A%3D&se=1663952627&skn=registration' -d '{"registrationId": "my-symkey-device"}' https://global.azure-devices-provisioning.net/0ne00111111/registrations/my-symkey-device/register?api-version=2021-06-01

Uma chamada bem-sucedida terá uma resposta semelhante à seguinte:

HTTP/1.1 202 Accepted
Date: Wed, 31 Aug 2022 22:02:49 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Location: https://global.azure-devices-provisioning.net/0ne00111111/registrations/my-symkey-device/register
Retry-After: 3
x-ms-request-id: a021814f-0cf6-4ce9-a1e9-ead7eb5118d9
Strict-Transport-Security: max-age=31536000; includeSubDomains

{"operationId":"5.316aac5bdc130deb.b1e02da8-c3a0-4ff2-a121-7ea7a6b7f550","status":"assigning"}

A resposta contém uma ID de operação e um status. Nesse caso, o status é definido como assigning. O registro de DPS é, potencialmente, uma operação de execução longa e, portanto, é feito de forma assíncrona. Normalmente, você sondará o status usando a API REST de Pesquisa de status da operação para determinar quando o dispositivo foi atribuído ou se ocorreu uma falha.

Os valores de status válidos para DPS são:

  • assigned: o valor retornado da chamada de status indicará a qual Hub IoT o dispositivo foi atribuído.

  • assigning: a operação ainda está em execução.

  • disabled: o registro está desabilitado no DPS e, portanto, o dispositivo não pode ser atribuído.

  • failed: falha na atribuição. Haverá um errorCode e errorMessage retornados em um registro registrationState na resposta para indicar o que falhou.

  • unassigned

Para chamar a API Pesquisa de status da operação, use o seguinte comando curl:

curl -L -i -X GET -H 'Content-Type: application/json' -H 'Content-Encoding:  utf-8' -H 'Authorization: [sas_token]' https://global.azure-devices-provisioning.net/[dps_id_scope]/registrations/[registration_id]/operations/[operation_id]?api-version=2019-03-31

Você usará o mesmo escopo de ID, ID de registro e token SAS como fez na solicitação Registrar dispositivo. Use a ID da operação que foi retornada na resposta Registrar dispositivo.

Por exemplo:

curl -L -i -X GET -H 'Content-Type: application/json' -H 'Content-Encoding:  utf-8' -H 'Authorization: SharedAccessSignature sr=0ne00111111%2Fregistrations%2Fmy-symkey-device&sig=eNwg52xQdFTNf7bgPAlAJBCIcONivq%2Fck1lf3wtxI4A%3D&se=1663952627&skn=registration' https://global.azure-devices-provisioning.net/0ne00111111/registrations/my-symkey-device/operations/5.316aac5bdc130deb.f4f1828c-4dab-4ca9-98b2-dfc63b5835d6?api-version=2021-06-01

A saída a seguir mostra a resposta para um dispositivo que tenha sido atribuído com êxito. Observe que a propriedade status é assigned e que a propriedade registrationState.assignedHub está definida como o hub IoT em que o dispositivo foi provisionado.

HTTP/1.1 200 OK
Date: Wed, 31 Aug 2022 22:05:23 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
x-ms-request-id: ffb98d42-023e-4e75-afb0-1807ff091cbb
Strict-Transport-Security: max-age=31536000; includeSubDomains

{
   "operationId":"5.316aac5bdc130deb.b1e02da8-c3a0-4ff2-a121-7ea7a6b7f550",
   "status":"assigned",
   "registrationState":{
      "registrationId":"my-symkey-device",
      "createdDateTimeUtc":"2022-08-31T22:02:50.5163352Z",
      "assignedHub":"MyExampleHub.azure-devices.net",
      "deviceId":"my-symkey-device",
      "status":"assigned",
      "substatus":"initialAssignment",
      "lastUpdatedDateTimeUtc":"2022-08-31T22:02:50.7370676Z",
      "etag":"IjY5MDAzNTUyLTAwMDAtMDMwMC0wMDAwLTYzMGZkYThhMDAwMCI="
   }
}

Enviar uma mensagem de telemetria

Antes de enviar uma mensagem de telemetria, você precisa criar um token SAS para o hub IoT ao qual o dispositivo foi atribuído. Assine esse token usando a mesma chave primária ou a chave de dispositivo derivada que usou para assinar o token SAS para sua instância do DPS.

Criar um token SAS para o hub IoT

Para criar o token SAS, você pode executar o mesmo código que usou para criar o token para sua instância do DPS com as seguintes alterações:

uri = '[resource_uri]'
key = '[device_key]'
expiry = [expiry_in_seconds]
policy= None

Em que:

  • [resource_uri] é o URI do recurso que você está tentando acessar com esse token. Para um dispositivo que envia mensagens para um hub IoT, ele é do formulário [iot-hub-host-name]/devices/[device-id].

    • Para [iot-hub-host-name], use o nome do host do Hub IoT retornado na propriedade assignedHub na seção anterior.

    • Para [device-id], use a Identidade do dispositivo retornada na propriedade deviceId na seção anterior.

  • [device_key] é a chave do dispositivo associada ao seu dispositivo. Essa chave é especificada ou gerada automaticamente para você em um registro individual ou uma chave derivada para um registro de grupo. (É a mesma chave que você usou anteriormente para criar um token para DPS.)

  • [expiry_in_seconds] é o período de validade desse token SAS em segundos.

  • policy=None Nenhuma política é necessária para um dispositivo que envia telemetria para um hub IoT e, portanto, esse parâmetro é definido como None.

Um exemplo de conjunto de entradas para um dispositivo chamado my-symkey-device enviando para um Hub IoT chamado MyExampleHub com um período de validade de token de uma hora pode ter esta aparência:

uri = 'MyExampleHub.azure-devices.net/devices/my-symkey-device'
key = '18RQk/hOPJR9EbsJlk2j8WA6vWaj/yi+oaYg7zmxfQNdOyMSu+SJ8O7TSlZhDJCYmn4rzEiVKIzNiVAWjLxrGA=='
expiry = 3600
policy= None

A saída a seguir mostra um token SAS de exemplo para estas entradas:

SharedAccessSignature sr=MyExampleHub.azure-devices.net%2Fdevices%2Fmy-symkey-device&sig=f%2BwW8XOKeJOtiPc9Iwjc4OpExvPM7NlhM9qxN2a1aAM%3D&se=1663119026

Para saber mais sobre como criar tokens SAS para Hub IoT, incluindo código de exemplo em outras linguagens de programação, consulte Controlar o acesso ao Hub IoT usando assinaturas de acesso compartilhado.

Observação

Como conveniência, você pode usar o comando az iot hub generate-sas-token da CLI do Azure para obter um token SAS para um dispositivo registrado com um hub IoT. Por exemplo, o comando a seguir gera um token SAS com uma duração de uma hora. Para o {iothub_name}, você só precisa da primeira parte do nome do host, por exemplo, MyExampleHub.

az iot hub generate-sas-token -d {device_id} -n {iothub_name}

Enviar dados para o hub IoT

Você chama a API REST Enviar evento de dispositivo do Hub IoT para enviar telemetria para o dispositivo.

Use o comando curl a seguir:

curl -L -i -X POST -H 'Content-Type: application/json' -H 'Content-Encoding:  utf-8' -H 'Authorization: [sas_token]' -d '{"temperature": 30}' https://[assigned_iot_hub_name].azure-devices.net/devices/[device_id]/messages/events?api-version=2020-03-13

Em que:

  • -X POST informa ao curl que esse é um comando HTTP POST. Necessário para essa chamada à API.

  • -H 'Content-Type: application/json' informa ao Hub IoT que estamos postando conteúdo JSON e deve ser 'application/json'.

  • -H 'Content-Encoding: utf-8' informa ao Hub IoT a codificação que estamos usando para o corpo da mensagem. Defina como o valor adequado para o sistema operacional/cliente, porém, geralmente é utf-8.

  • -H 'Authorization: [sas_token]' informa ao Hub IoT para autenticar usando o token SAS. Substitua [sas_token] pelo token gerado para o hub IoT atribuído.

  • -d '{"temperature": 30}', o parâmetro –d é o 'data' ou o corpo da mensagem que estamos postando. Para este artigo, estamos postando um único ponto de dados de temperatura. O tipo de conteúdo foi especificado como application/json e, portanto, para essa solicitação, o corpo é JSON. Observe que, para o curl, ele é encapsulado em aspas simples. Caso contrário, você precisará escapar das aspas duplas no JSON.

  • O último parâmetro é a URL para a qual postar. Para a API Enviar evento de dispositivo, a URL é: https://[assigned_iot_hub_name].azure-devices.net/devices/[device_id]/messages/events?api-version=2020-03-13

    • Substitua [assigned_iot_hub_name] pelo nome do hub IoT ao qual seu dispositivo foi atribuído.

    • Substitua [device_id] pela ID do dispositivo que foi atribuída quando você registrou seu dispositivo. Para dispositivos que provisionam por meio de grupos de registros, a ID do dispositivo será a ID de registro. Para registros individuais, você pode, opcionalmente, especificar uma ID do dispositivo diferente da ID de registro na entrada de registro.

Por exemplo, para um dispositivo com uma ID de dispositivo de my-symkey-device enviando de um ponto de dados telemétricos para um hub IoT chamado MyExampleHub:

curl -L -i -X POST -H 'Content-Type: application/json' -H 'Content-Encoding:  utf-8' -H 'Authorization: SharedAccessSignature sr=MyExampleHub.azure-devices.net%2Fdevices%2Fmy-symkey-device&sig=f%2BwW8XOKeJOtiPc9Iwjc4OpExvPM7NlhM9qxN2a1aAM%3D&se=1663119026' -d '{"temperature": 30}' https://MyExampleHub.azure-devices.net/devices/my-symkey-device/messages/events?api-version=2020-03-13

Uma chamada bem-sucedida terá uma resposta semelhante à seguinte:

HTTP/1.1 204 No Content
Content-Length: 0
Vary: Origin
Server: Microsoft-HTTPAPI/2.0
x-ms-request-id: 9e278582-3561-417b-b807-76426195920f
Date: Wed, 14 Sep 2022 00:32:53 GMT

Próximas etapas