Contrôler l’accès au service Azure IoT Hub Device Provisioning (DPS) avec des signatures d’accès partagé et des jetons de sécurité
Cet article décrit les options disponibles permettant de sécuriser votre Service Azure IoT Hub Device Provisioning (DPS). Le service de provisionnement utilise une authentification et des autorisations pour accorder l’accès à chaque point de terminaison. Les autorisations permettent le processus d’authentification pour limiter l’accès à une instance de service en fonction des fonctionnalités.
Cet article aborde ce qui suit :
Le processus d’authentification et les jetons utilisés par le service d’approvisionnement pour vérifier les autorisations sur les API REST Service et de messagerie des appareils.
Les différentes autorisations que vous pouvez accorder à une application principale pour lui permettre d’accéder à l’API Service.
Authentification
L’API de messagerie des appareils prend en charge l’authentification des appareils basée sur les certificats basés sur les clés et X.509.
L’API Service prend en charge l’authentification basée sur les clés pour les applications principales.
Lors de l’utilisation basée sur les clés, le service de provisionnement d’appareils utilise des jetons de sécurité pour authentifier les services et éviter l’envoi de clés. En outre, la validité et la portée des jetons sont limitées dans le temps. Les kits SDK Azure IoT Device Provisioning génèrent automatiquement des jetons sans demander de configuration particulière.
Dans certains cas, vous pouvez avoir besoin d'utiliser les API REST HTTP Device Provisioning Service directement sans les SDK. Les sections suivantes décrivent comment s’authentifier directement sur les API REST.
Authentification avec l’API Device
L’API de messagerie des appareils est utilisée par les appareils pour attester auprès du service Device Provisioning et recevoir une connexion IoT Hub.
Remarque
Pour pouvoir recevoir une connexion authentifiée, les appareils doivent d’abord être inscrits auprès du service Device Provisioning par le biais d’une inscription. Utilisez l’API Service pour inscrire un appareil de façon programmatique par le biais d’une inscription.
Un appareil doit s’authentifier auprès de l’API de messagerie des appareils dans le cadre du processus de configuration. La méthode utilisée par un appareil pour l’authentification est définie lorsque vous configurez un groupe d’inscription ou une inscription individuelle. Quelle que soit la méthode d’authentification, l’appareil doit émettre une requête PUT HTTPS adjointe à l’URL suivante pour s’approvisionner lui-même.
https://global.azure-devices-provisioning.net/[ID_Scope]/registrations/[registration_id]/register?api-version=2021-06-01
Si vous utilisez l’authentification basée sur les clés, un jeton de sécurité est transmis à l’en-tête de requête HTTPAuthorization dans le format suivant :
SharedAccessSignature sig={signature}&se={expiry}&skn={policyName}&sr={URL-encoded-resourceURI}
Structure de jeton de sécurité pour l’authentification basée sur les clés
Le jeton de sécurité est transmis à l’en-tête de requête HTTPAuthorization dans le format suivant :
SharedAccessSignature sig={signature}&se={expiry}&skn={policyName}&sr={URL-encoded-resourceURI}
Les valeurs attendues sont les suivantes :
Valeur | Description |
---|---|
{signature} |
Une chaîne de signature HMAC-SHA256 sous la forme : {URL-encoded-resourceURI} + "\n" + expiry . Important : la clé est décodée à partir de base64 et utilisée comme clé pour effectuer le calcul HMAC-SHA256. |
{expiry} |
Chaînes UTF8 pour le nombre de secondes depuis l’époque 00:00:00 UTC 1er janvier 1970. |
{URL-encoded-resourceURI} |
Encodage d’URL en minuscules de {ID_Scope}/registrations/{registration_id} |
{policyName} |
Pour l’API de messagerie des appareils, cette stratégie est toujours « inscription ». |
L'extrait Python suivant montre une fonction appelée generate_sas_token
qui calcule le jeton à partir des entrées uri
, key
, policy_name
et expiry
pour une inscription individuelle en utilisant un type d’authentification à clé symétrique.
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"))
Le résultat doit ressembler à l'exemple suivant :
SharedAccessSignature sr=myIdScope%2Fregistrations%2Fmydeviceregistrationid&sig=SDpdbUNk%2F1DSjEpeb29BLVe6gRDZI7T41Y4BPsHHoUg%3D&se=1630175722&skn=registration
L’exemple suivant montre comment la signature d’accès partagé est ensuite utilisée pour s’authentifier auprès de l’API de messagerie des appareils.
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
Si vous utilisez un groupe d’inscription basé sur une clé symétrique, vous devez d’abord générer une clé device symmetric
à l’aide de la clé de groupe d’inscription. Utilisez la clé primaire ou secondaire du groupe d’inscription pour calculer un HMAC-SHA256 de l’ID d’inscription de l’appareil. Le résultat est ensuite converti au format Base64 pour obtenir la clé de l’appareil dérivée. Pour afficher des exemples de code, consultez Comment approvisionner des appareils à l’aide de groupes d’inscription avec des clés symétriques. Une fois la clé symétrique de l’appareil déduite, vous pouvez inscrire l’appareil à l’aide des exemples précédents.
Avertissement
Pour éviter d’inclure la clé principale de groupe dans le code de votre appareil, le processus de déduction de la clé d’appareil doit être effectué à partir de l’appareil.
Authentification par certificat
Si vous avez configuré un groupe d’inscription ou d’inscription individuel pour l’authentification basée sur un certificat X.509, l’appareil doit utiliser son certificat X.509 émis pour attester de l’API de messagerie des appareils. Reportez-vous aux articles suivants sur la configuration de l’inscription et la génération du certificat de l’appareil.
Démarrage rapide : Approvisionner un appareil X.509 simulé auprès d’Azure IoT Hub
Démarrage rapide : Inscrire des appareils X.509 auprès de Service Azure Device Provisioning
Une fois l’inscription configurée et le certificat de l’appareil émis, l’exemple suivant montre comment s’authentifier auprès de l’API de messagerie des appareils avec le certificat X.509 de l’appareil.
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
Authentification avec l’API Service
L’API Service permet de récupérer l’état d’inscription et de supprimer les inscriptions d’appareils à distance. Le service est également utilisé par les applications principales pour gérer par programmation les groupes individuels et les groupes d’inscriptions. L’API Service prend en charge l’authentification basée sur les clés pour les applications principales.
Pour accéder à tout point de terminaison API Service, vous devez disposer des autorisations appropriées. Par exemple, une application principale doit ajouter un jeton contenant des informations d’identification de sécurité à chaque message qu’elle envoie au service.
Le Service IoT Hub Device Provisioning accorde l’accès aux points de terminaison en vérifiant la validité du jeton par rapport aux stratégies d’accès partagé. Les informations d’identification de sécurité telles que les clés symétriques ne sont jamais envoyées sur le réseau.
Contrôle d’accès et autorisations
Vous pouvez accorder des autorisations de différentes manières :
Stratégies d’autorisation d’accès partagé. Les stratégies d’accès partagé peuvent accorder n’importe quelle combinaison d’autorisations. Vous pouvez définir des stratégies dans le portail Azure, ou programmatiquement avec des API REST du service Device Provisioning. Tout service de provisionnement créé comporte la stratégie par défaut suivante :
provisioningserviceowner : stratégie avec toutes les autorisations. Pour plus d’informations, consultez la page Autorisations.
Remarque
Le fournisseur de ressources du service Device Provisioning est sécurisé par le biais de votre abonnement Azure, comme le sont tous les fournisseurs dans Azure Resource Manager.
Pour plus d’informations sur la façon de construire et d’utiliser les jetons de sécurité, consultez la section suivante.
HTTP est le seul protocole pris en charge. Il implémente l’authentification en incluant un jeton valide dans l’en-tête de demande d’autorisation.
Exemple
SharedAccessSignature sr =
mydps.azure-devices-provisioning.net&sig=kPszxZZZZZZZZZZZZZZZZZAhLT%2bV7o%3d&se=1487709501&skn=provisioningserviceowner`\
Remarque
Les kits SDK du service Azure IoT Device Provisioning génèrent automatiquement des jetons durant la connexion au service.
Jetons de sécurité
Le service de provisionnement d’appareils utilise des jetons de sécurité pour authentifier les services et éviter l’envoi de clés. En outre, la validité et la portée des jetons sont limitées dans le temps. Les kits SDK du service Azure IoT Device Provisioning génèrent automatiquement des jetons sans nécessiter de configuration particulière. Certains scénarios nécessitent toutefois que vous génériez et utilisiez directement des jetons de sécurité. Ces scénarios incluent l’utilisation directe du protocole HTTP.
Structure du jeton de sécurité
Vous utilisez des jetons de sécurité pour permettre aux services d’accéder de manière limitée dans le temps à des caractéristiques spécifiques du service de provisionnement d’appareils IoT. Pour obtenir l’autorisation de se connecter au service de provisionnement, les services doivent envoyer des jetons de sécurité signés avec une clé d’accès partagé ou une clé symétrique.
Un jeton signé avec une clé d’accès partagé accorde un accès à toutes les fonctionnalités associées aux autorisations de stratégie d’accès partagé.
Le jeton de sécurité présente le format suivant :
SharedAccessSignature sig={signature}&se={expiry}&skn={policyName}&sr={URL-encoded-resourceURI}
Voici les valeurs attendues
Valeur | Description |
---|---|
{signature} | Une chaîne de signature HMAC-SHA256 sous la forme : {URL-encoded-resourceURI} + "\n" + expiry . Important : la clé est décodée à partir de base64 et utilisée comme clé pour effectuer le calcul HMAC-SHA256. |
{expiry} | Chaînes UTF8 pour le nombre de secondes depuis l’époque 00:00:00 UTC 1er janvier 1970. |
{URL-encoded-resourceURI} | Encodage de l’URL en minuscules à partir de l’URI de ressource en minuscules. Préfixe URI (par segment) des points de terminaison accessibles avec ce jeton, en commençant par le nom d’hôte du service de provisionnement d’appareils IoT (sans protocole). Par exemple : mydps.azure-devices-provisioning.net . |
{policyName} | Le nom de la stratégie d’accès partagé à laquelle ce jeton fait référence. |
Notes
le préfixe URI est calculé par segment et non par caractère. Par exemple /a/b
est un préfixe de /a/b/c
, mais pas de /a/bc
.
L’extrait de code Node.js suivant illustre une fonction appelée generateSasToken qui calcule le jeton à partir des entrées resourceUri, signingKey, policyName, expiresInMins
. Les sections suivantes décrivent en détail comment initialiser les différentes entrées pour les différents cas d’utilisation des jetons.
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;
};
À titre de comparaison, le code Python équivalent pour générer un jeton de sécurité est :
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)
Remarque
Dans la mesure où la validité temporelle du jeton est vérifiée sur les machines du service de provisionnement d’appareils IoT, la dérive de l’horloge de la machine qui génère le jeton doit être minimale.
Utilisation de jetons de sécurité de composants du service
Les composants de service peuvent uniquement créer des jetons de sécurité utilisant des stratégies d’accès partagé pour accorder les autorisations adaptées, comme expliqué précédemment.
Voici les fonctions de service exposées sur les points de terminaison :
Point de terminaison | Fonctionnalités |
---|---|
{your-service}.azure-devices-provisioning.net/enrollments |
Fournit les opérations relatives à l’inscription d’appareils auprès du service de provisionnement d’appareils. |
{your-service}.azure-devices-provisioning.net/enrollmentGroups |
Fournit les opérations relatives à la gestion des groupes d’inscription d’appareils. |
{your-service}.azure-devices-provisioning.net/registrations/{id} |
Fournit les opérations relatives à la récupération et à la gestion de l’état des inscriptions d’appareils. |
Par exemple, un service généré à l’aide d’une stratégie d’accès partagé précréée appelée enrollmentread
crée un jeton avec les paramètres suivants :
- URI de ressource :
{mydps}.azure-devices-provisioning.net
, - clé de signature : une des clés de la stratégie
enrollmentread
, - nom de la stratégie :
enrollmentread
, - n’importe quel délai d’expiration time.backn
var endpoint ="mydps.azure-devices-provisioning.net";
var policyName = 'enrollmentread';
var policyKey = '...';
var token = generateSasToken(endpoint, policyKey, policyName, 60);
Le résultat, qui revient à accorder l’accès en lecture à tous les dossiers d’inscription, est le suivant :
SharedAccessSignature sr=mydps.azure-devices-provisioning.net&sig=JdyscqTpXdEJs49elIUCcohw2DlFDR3zfH5KqGJo4r4%3D&se=1456973447&skn=enrollmentread
SDK et exemples
Rubriques de référence :
Les rubriques de référence suivantes fournissent des informations supplémentaires sur le contrôle de l’accès à votre service de provisionnement d’appareils IoT.
Autorisations liées au service de provisionnement d’appareils
Le tableau suivant répertorie les autorisations qui vous permettent de contrôler l’accès à votre service de provisionnement d’appareils IoT.
Autorisation | Notes |
---|---|
ServiceConfig | Accorde l’accès pour changer les configurations du service. Cette autorisation est utilisée par les services cloud principaux. |
EnrollmentRead | Accorde l’accès en lecture aux inscriptions d’appareils et aux groupes d’inscription. Cette autorisation est utilisée par les services cloud principaux. |
EnrollmentWrite | Accorde l’accès en écriture aux inscriptions d’appareils et aux groupes d’inscription. Cette autorisation est utilisée par les services cloud principaux. |
RegistrationStatusRead | Accorde l’accès en lecture à l’état d’inscription de l’appareil. Cette autorisation est utilisée par les services cloud principaux. |
RegistrationStatusWrite | Accorde l’accès permettant de supprimer l’état d’inscription de l’appareil. Cette autorisation est utilisée par les services cloud principaux. |