Compartir a través de


Control del acceso a Azure IoT Hub Device Provisioning Service (DPS) con firmas de acceso compartido y tokens de seguridad

En este artículo se describen las opciones disponibles para proteger azure IoT Hub Device Provisioning Service (DPS). El servicio de aprovisionamiento usa la autenticación y los permisos para conceder acceso a cada punto de conexión. Los permisos permiten que el proceso de autenticación limite el acceso a una instancia de servicio en función de la funcionalidad.

En este artículo se describe lo siguiente:

  • El proceso de autenticación y los tokens que usa el servicio de aprovisionamiento para comprobar los permisos en las API REST de servicio y dispositivo.

  • Los distintos permisos que puede conceder a una aplicación de back-end para acceder a la API de servicio.

Autenticación

La API de dispositivos admite la autenticación de dispositivos basada en clave y en certificados X.509.

La API de servicio admite la autenticación basada en claves para aplicaciones de back-end.

Al usar la autenticación basada en claves, el Device Provisioning Service emplea tokens de seguridad para autenticar servicios, evitando así el envío de claves a través de la conexión. Además, los tokens de seguridad están limitados en tiempo de validez y ámbito. Los SDK de aprovisionamiento de dispositivos de Azure IoT Hub generan automáticamente tokens sin necesidad de ninguna configuración especial.

En algunos casos, es posible que tenga que usar las API REST del servicio HTTP Device Provisioning directamente, sin usar los SDK. En las secciones siguientes se describe cómo autenticarse directamente en las API REST.

Autenticación de API de dispositivo

Los dispositivos usan Device API para atestiguar el Servicio de Aprovisionamiento de Dispositivos y recibir una conexión con el IoT Hub.

Nota:

Para recibir una conexión autenticada, los dispositivos deben registrarse primero en Device Provisioning Service a través de una inscripción. Use la API de servicio para registrar mediante programación un dispositivo a través de una inscripción.

Un dispositivo debe autenticarse en device API como parte del proceso de aprovisionamiento. El método que usa un dispositivo para autenticarse se define al configurar un grupo de inscripción o una inscripción individual. Sea cual sea el método de autenticación, el dispositivo debe emitir un HTTPS PUT a la siguiente dirección URL para aprovisionarse a sí mismo.

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

Si usa la autenticación basada en claves, se pasa un token de seguridad en el encabezado de solicitud de autorización HTTP con el formato siguiente:

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

Estructura de tokens de seguridad para la autenticación basada en claves

El token de seguridad se pasa en el encabezado de solicitud de autorización HTTP con el formato siguiente:

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

Los valores esperados son:

Importancia Description
{signature} Cadena de firma HMAC-SHA256 del formulario: {URL-encoded-resourceURI} + "\n" + expiry.  Importante: La clave se descodifica de base64 y se usa como clave para realizar el cálculo HMAC-SHA256.
{expiry} Cadenas UTF8 para el número de segundos transcurridos desde el tiempo 00:00:00 UTC el 1 de enero de 1970.
{URL-encoded-resourceURI} Codificación de URL en minúsculas de {ID_Scope}/registrations/{registration_id}
{policyName} Para la API de Dispositivo, esta política siempre es "registro".

El siguiente fragmento de código de Python muestra una función denominada generate_sas_token que calcula el token de las entradas uri, key, policy_name, expiry para una inscripción individual mediante un tipo de autenticación de clave simétrica.


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"))

El resultado debe ser similar al siguiente resultado:


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

En el ejemplo siguiente se muestra cómo se usa la firma de acceso compartido para autenticarse con la API de 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 

Si usa un grupo de inscripción basado en claves simétricas, primero debe generar una device symmetric clave mediante la clave de grupo de inscripción. Use la clave principal o secundaria del grupo de inscripción para calcular un HMAC-SHA256 del identificador de registro del dispositivo. A continuación, el resultado se convierte en formato Base64 para obtener la clave de dispositivo derivada. Para ver ejemplos de código, consulte Derivar una clave de dispositivo. Una vez derivada la clave simétrica del dispositivo, puede registrar el dispositivo mediante los ejemplos anteriores.

Advertencia

Para evitar incluir la clave maestra de grupo en el código del dispositivo, el proceso de derivación de la clave de dispositivo debe realizarse fuera del dispositivo.

Autenticación basada en certificados

Si configura una inscripción individual o un grupo de inscripción para la autenticación basada en certificados X.509, el dispositivo debe usar su certificado X.509 emitido para atestiguar la API de dispositivo. Consulte los artículos siguientes sobre cómo configurar la inscripción y generar el certificado de dispositivo.

Una vez configurada la inscripción y el certificado de dispositivo emitido, en el ejemplo siguiente se muestra cómo autenticarse en Device API con el certificado 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 

Autenticación de API de servicio

La API de servicio se usa para recuperar el estado de registro y quitar registros de dispositivos. Las aplicaciones back-end también usan el servicio para administrar mediante programación grupos individuales y grupos de inscripción. La API de servicio admite la autenticación basada en claves para aplicaciones de back-end.

Debe tener los permisos adecuados para acceder a cualquiera de los puntos de conexión de la API de servicio. Por ejemplo, una aplicación back-end debe incluir un token que contenga credenciales de seguridad junto con todos los mensajes que envía al servicio.

Azure IoT Hub Device Provisioning Service concede acceso a los puntos de conexión comprobando el token con las directivas de acceso compartido. Las credenciales de seguridad, como las claves simétricas, nunca se envían a través de la conexión.

Control de acceso y permisos

Puede conceder permisos de las siguientes maneras:

  • Directivas de autorización de acceso compartido. Las directivas de acceso compartido pueden conceder cualquier combinación de permisos. Puede definir directivas en Azure Portal o mediante programación mediante las API REST del servicio Device Provisioning. Un servicio de aprovisionamiento recién creado tiene la siguiente directiva predeterminada:

  • provisioningserviceowner: directiva con todos los permisos. Consulte permisos para obtener información detallada.

Nota:

El proveedor de recursos de Device Provisioning Service se protege mediante la suscripción de Azure, igual que todos los proveedores en Azure Resource Manager.

Para obtener más información sobre cómo construir y usar tokens de seguridad, consulte la sección siguiente.

HTTP es el único protocolo admitido e implementa la autenticación mediante la inclusión de un token válido en el encabezado de solicitud de autorización .

Example

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

Nota:

Los SDK de Azure IoT Hub Device Provisioning Service generan automáticamente tokens al conectarse al servicio.

Tokens de seguridad

El servicio de aprovisionamiento de dispositivos utiliza tokens de seguridad para autenticar servicios y así evitar el envío de claves durante la transmisión. Además, los tokens de seguridad están limitados en tiempo de validez y ámbito. Los SDK de Azure IoT Hub Device Provisioning Service generan automáticamente tokens sin necesidad de ninguna configuración especial. Algunos escenarios requieren que genere y use tokens de seguridad directamente. Estos escenarios incluyen el uso directo de la superficie HTTP.

Estructura de tokens de seguridad

Se utilizan tokens de seguridad para conceder acceso temporal a los servicios a una funcionalidad específica en el IoT Hub Device Provisioning Service. Para obtener la autorización para conectarse al servicio de aprovisionamiento, los servicios deben enviar tokens de seguridad firmados con un acceso compartido o una clave simétrica.

Un token firmado con una clave de acceso compartido concede acceso a toda la funcionalidad asociada a los permisos de directiva de acceso compartido.

El token de seguridad tiene el siguiente formato:

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

Estos son los valores esperados

Importancia Description
{signature} Cadena de firma HMAC-SHA256 del formulario: {URL-encoded-resourceURI} + "\n" + expiry. Importante: La clave se descodifica de base64 y se usa como clave para realizar el cálculo HMAC-SHA256.
{expiry} Cadenas UTF8 para el número de segundos transcurridos desde el tiempo 00:00:00 UTC el 1 de enero de 1970.
{URL-encoded-resourceURI} Codificación de dirección URL en minúsculas del identificador URI del recurso en minúsculas. Prefijo de URI (por segmento) de los puntos de conexión a los que se puede acceder con este token, empezando por el nombre de host del servicio IoT Device Provisioning (sin protocolo). Por ejemplo: mydps.azure-devices-provisioning.net.
{policyName} Nombre de la directiva de acceso compartido a la que hace referencia este token.

Nota:

El prefijo URI se calcula por segmento y no por carácter. Por ejemplo, /a/b es un prefijo para /a/b/c pero no para /a/bc.

El siguiente fragmento de código de Node.js muestra una función denominada generateSasToken que calcula el token a partir de las entradas resourceUri, signingKey, policyName, expiresInMins. En las secciones siguientes se detalla cómo inicializar las distintas entradas para los distintos casos de uso de tokens.

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;
};

Como comparación, el código de Python equivalente para generar un token de seguridad es:

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:

Dado que la validez temporal del token se valida en las máquinas del servicio IoT Device Provisioning, el desfase en el reloj de la máquina que genera el token debe ser mínimo.

Uso de tokens de seguridad procedentes de componentes de servicio

Los componentes de servicio solo pueden generar tokens de seguridad mediante directivas de acceso compartido que conceden los permisos adecuados, como se explicó anteriormente.

Estas son las funciones de servicio expuestas en los puntos de conexión:

Punto final Funcionalidad
{your-service}.azure-devices-provisioning.net/enrollments Proporciona operaciones de inscripción de dispositivos mediante el Servicio de Provisión de Dispositivos (Device Provisioning Service).
{your-service}.azure-devices-provisioning.net/enrollmentGroups Proporciona operaciones para administrar grupos de inscripción de dispositivos.
{your-service}.azure-devices-provisioning.net/registrations/{id} Proporciona operaciones para recuperar y administrar el estado de los registros de dispositivos.

Por ejemplo, un servicio generado mediante una directiva de acceso compartido creada previamente denominada enrollmentread crearía un token con los parámetros siguientes:

  • URI de recurso: {mydps}.azure-devices-provisioning.net,
  • clave de firma: una de las claves de la directiva enrollmentread ,
  • nombre de directiva: enrollmentread,
  • cualquier fecha de expiración.backn
var endpoint ="mydps.azure-devices-provisioning.net";
var policyName = 'enrollmentread'; 
var policyKey = '...';

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

El resultado, que concedería acceso para leer todos los registros de inscripción, sería:

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

SDK y ejemplos

Artículos de referencia:

Los siguientes artículos de referencia proporcionan más información sobre cómo controlar el acceso al servicio IoT Device Provisioning.

Permisos de Device Provisioning Service

En la tabla siguiente se enumeran los permisos que puede usar para controlar el acceso al servicio IoT Device Provisioning.

Permiso Notas
ServiceConfig Concede acceso para cambiar las configuraciones del servicio.
Los servicios en la nube de back-end usan este permiso.
EnrollmentRead Concede acceso de lectura de los grupos de inscripción y las inscripciones de dispositivos.
Los servicios en la nube de back-end usan este permiso.
EnrollmentWrite Concede acceso de escritura de los grupos de inscripción y las inscripciones de dispositivos.
Los servicios en la nube de back-end usan este permiso.
RegistrationStatusRead Concede acceso de lectura al estado de registro del dispositivo.
Los servicios en la nube de back-end usan este permiso.
RegistrationStatusWrite Concede acceso de eliminación del estado de registro de los dispositivos.
Los servicios en la nube de back-end usan este permiso.