Controllare l'accesso a hub IoT di Azure servizio Device Provisioning (DPS) con firme di accesso condiviso e token di sicurezza

Questo articolo descrive le opzioni disponibili per proteggere il servizio Device Provisioning (DPS) hub IoT di Azure. Il servizio di provisioning usa l'autenticazione e le autorizzazioni per concedere l'accesso a ogni endpoint. Le autorizzazioni consentono al processo di autenticazione di limitare l'accesso a un'istanza del servizio in base alle funzionalità.

Questo articolo illustra:

  • Il processo di autenticazione e i token usati dal servizio di provisioning per verificare le autorizzazioni per le API REST del servizio e del dispositivo.

  • Le diverse autorizzazioni che è possibile concedere a un'app back-end per accedere all'API del servizio.

Authentication

L'API del dispositivo supporta l'autenticazione basata su chiave e basata su certificati X.509.

L'API del servizio supporta l'autenticazione basata su chiave per le app back-end.

Quando si usa l'autenticazione basata su chiave, il servizio Device Provisioning usa token di sicurezza per autenticare i servizi per evitare l'invio di chiavi in transito. Inoltre, i token di sicurezza hanno una validità limitata in termini di tempo e portata. Gli SDK per il provisioning di dispositivi IoT di Azure generano automaticamente token senza richiedere alcuna configurazione speciale.

In alcuni casi potrebbe essere necessario usare direttamente le API REST del servizio Device Provisioning HTTP, senza usare gli SDK. Le sezioni seguenti descrivono come eseguire l'autenticazione direttamente nelle API REST.

Autenticazione dell'API del dispositivo

L'API del dispositivo viene usata dai dispositivi per attestare il servizio Device Provisioning e ricevere una connessione hub IoT.

Nota

Per ricevere una connessione autenticata, i dispositivi devono prima essere registrati nel servizio Device Provisioning tramite una registrazione. Usare l'API del servizio per registrare un dispositivo a livello di codice tramite una registrazione.

Un dispositivo deve eseguire l'autenticazione all'API del dispositivo come parte del processo di provisioning. Il metodo usato da un dispositivo per l'autenticazione viene definito quando si configura un gruppo di registrazione o una registrazione singola. Indipendentemente dal metodo di autenticazione, il dispositivo deve rilasciare https PUT all'URL seguente per effettuare il provisioning.

    https://global.azure-devices-provisioning.net/[ID_Scope]/registrations/[registration_id]/register?api-version=2021-06-01

Se si usa l'autenticazione basata su chiave, viene passato un token di sicurezza nell'intestazione della richiesta di autorizzazione HTTP nel formato seguente:

    SharedAccessSignature sig={signature}&se={expiry}&skn={policyName}&sr={URL-encoded-resourceURI} 

Struttura del token di sicurezza per l'autenticazione basata su chiave

Il token di sicurezza viene passato nell'intestazione della richiesta di autorizzazione HTTP nel formato seguente:

    SharedAccessSignature sig={signature}&se={expiry}&skn={policyName}&sr={URL-encoded-resourceURI} 

I valori previsti sono:

Valore Descrizione
{signature} Stringa della firma HMAC-SHA256 nel formato: {URL-encoded-resourceURI} + "\n" + expiry. Importante: la chiave viene decodificata da Base64 e usata come chiave per eseguire il calcolo HMAC-SHA256.
{expiry} Stringhe UTF8 per il numero di secondi trascorsi dalle 00:00:00 UTC dell'1 gennaio 1970.
{URL-encoded-resourceURI} Codifica URL minuscola di {ID_Scope}/registrations/{registration_id}
{policyName} Per l'API del dispositivo, questo criterio è sempre "registrazione".

Il frammento di codice Python seguente mostra una funzione denominata generate_sas_token che calcola il token dagli input uri, key, policy_name, expiry per una singola registrazione usando un tipo di autenticazione con chiave simmetrica.


from base64 import b64encode, b64decode, encode 
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)) 
    signature = b64encode(HMAC(b64decode(key), sign_key.encode('utf-8'), sha256).digest()) 

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

    return 'SharedAccessSignature ' + urlencode(rawtoken) 

print(generate_sas_token("myIdScope/registrations/mydeviceregistrationid", "00mysymmetrickey", "registration"))

Il risultato dovrebbe essere simile all'output seguente:


SharedAccessSignature sr=myIdScope%2Fregistrations%2Fmydeviceregistrationid&sig=SDpdbUNk%2F1DSjEpeb29BLVe6gRDZI7T41Y4BPsHHoUg%3D&se=1630175722&skn=registration 

L'esempio seguente mostra come viene quindi usata la firma di accesso condiviso per l'autenticazione con l'API dispositivo.


curl -L -i -X PUT -H 'Content-Type: application/json' -H 'Content-Encoding:  utf-8' -H 'Authorization: [token]' -d '{"registrationId": "[registration_id]"}' https://global.azure-devices-provisioning.net/[ID_Scope]/registrations/[registration_id]/register?api-version=2021-06-01 

Se si usa un gruppo di registrazione basato su chiavi simmetriche, è necessario prima generare una device symmetric chiave usando la chiave del gruppo di registrazione. Usare la chiave primaria o secondaria del gruppo di registrazione per calcolare un HMAC-SHA256 dell'ID di registrazione per il dispositivo. Il risultato viene quindi convertito in formato Base64 per ottenere la chiave del dispositivo derivata. Per visualizzare esempi di codice, vedere Come effettuare il provisioning dei dispositivi usando gruppi di registrazione con chiave simmetrica. Dopo aver derivato la chiave simmetrica del dispositivo, è possibile registrare il dispositivo usando gli esempi precedenti.

Avviso

Per evitare di includere la chiave master del gruppo nel codice del dispositivo, il processo di derivazione della chiave del dispositivo deve essere eseguito dal dispositivo.

Autenticazione basata su certificati

Se è stata configurata una registrazione singola o un gruppo di registrazione per l'autenticazione basata su certificati X.509, il dispositivo dovrà usare il certificato X.509 emesso per attestare l'API del dispositivo. Fare riferimento agli articoli seguenti su come configurare la registrazione e generare il certificato del dispositivo.

Dopo aver configurato la registrazione e aver rilasciato il certificato del dispositivo, l'esempio seguente illustra come eseguire l'autenticazione all'API del dispositivo con il certificato X.509 del dispositivo.


curl -L -i -X PUT –cert ./[device_cert].pem –key ./[device_cert_private_key].pem -H 'Content-Type: application/json' -H 'Content-Encoding:  utf-8' -d '{"registrationId": "[registration_id]"}' https://global.azure-devices-provisioning.net/[ID_Scope]/registrations/[registration_id]/register?api-version=2021-06-01 

Autenticazione dell'API del servizio

L'API del servizio viene usata per recuperare lo stato di registrazione e rimuovere le registrazioni del dispositivo. Il servizio viene usato anche dalle app back-end per gestire a livello di codice sia singoli gruppi che gruppi di registrazione. L'API del servizio supporta l'autenticazione basata su chiave per le app back-end.

È necessario disporre delle autorizzazioni appropriate per accedere a uno degli endpoint dell'API del servizio. Un'app back-end, ad esempio, deve includere un token contenente le credenziali di sicurezza con ogni messaggio inviato al servizio.

hub IoT di Azure servizio Device Provisioning concede l'accesso agli endpoint verificando il token rispetto ai criteri di accesso condiviso. Le credenziali di sicurezza, ad esempio le chiavi asimmetriche, non vengono mai trasmesse in rete.

Controllo dell'accesso e autorizzazioni

Per concedere le autorizzazioni è possibile procedere nei modi seguenti:

  • Criteri di autorizzazione dell'accesso condiviso. I criteri di accesso condiviso possono concedere qualsiasi combinazione di autorizzazioni. È possibile definire i criteri nel portale di Azure o a livello di codice usando le API REST del servizio Device Provisioning. Un servizio di provisioning appena creato ha i criteri predefiniti seguenti:

  • provisioningserviceowner: criteri con tutte le autorizzazioni. Per informazioni dettagliate, vedere Autorizzazioni.

Nota

Il servizio Device Provisioning viene protetto tramite la sottoscrizione di Azure, analogamente a tutti i provider in Azure Resource Manager.

Per altre informazioni sulla creazione e sull'uso di token di sicurezza, vedere la sezione seguente.

Il protocollo HTTP è l'unico protocollo supportato e implementa l'autenticazione includendo un token valido nell'intestazione della richiesta Authorization.

Esempio

SharedAccessSignature sr = 
   mydps.azure-devices-provisioning.net&sig=kPszxZZZZZZZZZZZZZZZZZAhLT%2bV7o%3d&se=1487709501&skn=provisioningserviceowner`\

Nota

Gli SDK del servizio Device Provisioning in hub IoT generano automaticamente i token durante la connessione al servizio.

Token di sicurezza

Il servizio Device Provisioning usa i token di sicurezza per autenticare i servizi ed evitare l'invio in rete delle chiavi. Inoltre, i token di sicurezza hanno una validità limitata in termini di tempo e portata. Gli SDK del servizio Device Provisioning in hub IoT generano automaticamente i token senza richiedere una configurazione speciale. In alcuni scenari è necessario generare e usare direttamente i token di sicurezza. Questi scenari includono l'uso diretto di superfici HTTP.

Struttura dei token di sicurezza

I token di sicurezza consentono di concedere a servizi l'accesso con limite temporale a funzionalità specifiche del servizio Device Provisioning in hub IoT. Per ottenere l'autorizzazione per connettersi al servizio di provisioning, i dispositivi e i servizi devono inviare i token di sicurezza firmati con una chiave di accesso condiviso o una chiave simmetrica.

Un token firmato con una chiave di accesso condiviso concede l'accesso a tutte le funzionalità associate alle autorizzazioni dei criteri di accesso condiviso.

Il token di sicurezza ha il formato seguente:

SharedAccessSignature sig={signature}&se={expiry}&skn={policyName}&sr={URL-encoded-resourceURI}

Ecco i valori previsti

Valore Descrizione
{signature} Stringa della firma HMAC-SHA256 nel formato: {URL-encoded-resourceURI} + "\n" + expiry. Importante: la chiave viene decodificata da Base64 e usata come chiave per eseguire il calcolo HMAC-SHA256.
{expiry} Stringhe UTF8 per il numero di secondi trascorsi dalle 00:00:00 UTC dell'1 gennaio 1970.
{URL-encoded-resourceURI} Codifica URL con lettere minuscole dell'URI della risorsa con lettere minuscole Prefisso URI (per segmento) degli endpoint a cui è possibile accedere tramite questo token e che inizia con il nome host del servizio Device Provisioning in hub IoT senza il protocollo. Ad esempio, mydps.azure-devices-provisioning.net.
{policyName} Nome del criterio di accesso condiviso a cui fa riferimento il token.

Nota

il prefisso dell'URI viene calcolato in base al segmento e non in base al carattere. Ad esempio /a/b è un prefisso per /a/b/c ma non per /a/bc.

Il frammento seguente di Node.js mostra una funzione denominata generateSasToken che calcola il token dagli input resourceUri, signingKey, policyName, expiresInMins. Nelle sezioni successive viene illustrato nel dettaglio come inizializzare gli input a seconda del caso d'uso.

var generateSasToken = function(resourceUri, signingKey, policyName, expiresInMins) {
    resourceUri = encodeURIComponent(resourceUri);

    // Set expiration in seconds
    var expires = (Date.now() / 1000) + expiresInMins * 60;
    expires = Math.ceil(expires);
    var toSign = resourceUri + '\n' + expires;

    // Use crypto
    var hmac = crypto.createHmac('sha256', new Buffer(signingKey, 'base64'));
    hmac.update(toSign);
    var base64UriEncoded = encodeURIComponent(hmac.digest('base64'));

    // Construct authorization string
    var token = "SharedAccessSignature sr=" + resourceUri + "&sig="
    + base64UriEncoded + "&se=" + expires + "&skn="+ policyName;
    return token;
};

Per fare un confronto, l'equivalente in termini di codice Python per generare un token di sicurezza è:

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, sha256).digest())

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

    return 'SharedAccessSignature ' + urlencode(rawtoken)

Nota

Poiché la validità temporale del token viene verificata sui computer del servizio Device Provisioning in hub IoT, lo sfasamento dell'orologio del computer che genera il token deve essere minimo.

Usare token di sicurezza da componenti del servizio

I componenti del servizio possono generare token di sicurezza solo usando criteri di accesso condiviso che concedono le autorizzazioni appropriate, come illustrato prima.

Di seguito vengono indicate le funzioni del servizio esposte sugli endpoint:

Endpoint Funzionalità
{your-service}.azure-devices-provisioning.net/enrollments Fornisce operazioni di registrazione del dispositivo con il servizio Device Provisioning.
{your-service}.azure-devices-provisioning.net/enrollmentGroups Fornisce operazioni per la gestione dei gruppi di registrazione del dispositivo.
{your-service}.azure-devices-provisioning.net/registrations/{id} Fornisce operazioni per il recupero e la gestione dello stato delle registrazioni dei dispositivi.

Ad esempio, un servizio generato usando un criterio di accesso condiviso creato in modo predefinito denominato enrollmentread crea un token con i parametri seguenti:

  • URI della risorsa: {mydps}.azure-devices-provisioning.net,
  • chiave di firma: una delle chiavi del criterio enrollmentread ,
  • nome criterio: enrollmentread,
  • qualsiasi ora di scadenza time.backn

Create a shared access policy for your Device Provisioning Service instance in the portal

var endpoint ="mydps.azure-devices-provisioning.net";
var policyName = 'enrollmentread'; 
var policyKey = '...';

var token = generateSasToken(endpoint, policyKey, policyName, 60);

Il risultato, che concede l'accesso in lettura a tutti i record di registrazione, sarà:

SharedAccessSignature sr=mydps.azure-devices-provisioning.net&sig=JdyscqTpXdEJs49elIUCcohw2DlFDR3zfH5KqGJo4r4%3D&se=1456973447&skn=enrollmentread

SDK ed esempi

Argomenti di riferimento:

Gli argomenti di riferimento seguenti offrono altre informazioni sul controllo dell'accesso al servizio Device Provisioning in hub IoT.

Autorizzazioni per il servizio Device Provisioning

La tabella seguente elenca le autorizzazioni che è possibile usare per controllare l'accesso al servizio Device Provisioning in hub IoT.

Autorizzazione Note
ServiceConfig Concede l'accesso per la modifica delle configurazioni del servizio.
Questa autorizzazione viene usata dai servizi cloud back-end.
EnrollmentRead Concede l'accesso in lettura alle registrazioni dei dispositivi e ai gruppi di registrazione.
Questa autorizzazione viene usata dai servizi cloud back-end.
EnrollmentWrite Concede l'accesso in scrittura alle registrazioni dei dispositivi e ai gruppi di registrazione.
Questa autorizzazione viene usata dai servizi cloud back-end.
RegistrationStatusRead Concede l'accesso in lettura allo stato della registrazione dei dispositivi.
Questa autorizzazione viene usata dai servizi cloud back-end.
RegistrationStatusWrite Concede l'accesso con autorizzazione di eliminazione allo stato della registrazione dei dispositivi.
Questa autorizzazione viene usata dai servizi cloud back-end.