Conexión de dispositivos con certificados X.509 para una aplicación de IoT Central

IoT Central admite firmas de acceso compartido (SAS) y certificados X.509 para proteger la comunicación entre un dispositivo y la aplicación. En el tutorial Creación y conexión de un aplicación cliente a una aplicación de Azure IoT Central se usa SAS. En este artículo, aprenderá a modificar el ejemplo de código para usar certificados X.509. Los certificados X.509 se recomiendan en entornos de producción. Para más información, consulte Conceptos de autenticación de dispositivos.

En esta guía, se muestran dos formas de usar certificados X.509: en inscripciones de grupo, que se usan normalmente en un entorno de producción, y en inscripciones individuales, que resultan útiles para las pruebas. En el artículo también se describe cómo implementar certificados de dispositivo para mantener la conectividad cuando expiran los certificados.

Esta guía se basa en los ejemplos que se muestran en el tutorial Creación y conexión de un aplicación cliente a la aplicación de Azure IoT Central, que usan C#, Java, JavaScript y Python. Para obtener un ejemplo en el que se usa el lenguaje de programación C, vea Aprovisionamiento de varios dispositivos X.509 mediante grupos de inscripción.

Requisitos previos

Para completar los pasos de esta guía paso a paso, primero debe completar el tutorial Creación y conexión de una aplicación cliente a la aplicación de Azure IoT Central. Usted modifica el código que utilizó en el tutorial cuando sigue los pasos de esta guía.

En esta guía paso a paso, generará algunos certificados X.509 de prueba. Para poder generar estos certificados, necesita lo siguiente:

  • Una máquina de desarrollo con la versión 6 de Node.js o una posterior instalada. Puede ejecutar node --version en la línea de comandos para comprobar la versión. En las instrucciones de este tutorial se da por hecho que se ejecuta el comando node en el símbolo del sistema de Windows. No obstante, puede usar Node.js en muchos otros sistemas operativos.
  • Una copia local del repositorio de GitHub de SDK de Microsoft Azure IoT para Node.js que contiene los scripts para generar los certificados X.509 de prueba. Use este vínculo para descargar una copia del repositorio: Descargar el archivo ZIP. Después, descomprima el archivo en una ubicación conveniente en la máquina local.

Uso de la inscripción de grupo

Use certificados X.509 con una inscripción de grupo en un entorno de producción. En una inscripción de grupo, agregue un certificado X.509 raíz o intermedio a la aplicación de IoT Central. Los dispositivos con certificados hoja derivados del certificado raíz o intermedio pueden conectarse a la aplicación.

Generación de certificados raíz y de dispositivo

En esta sección, se usa un certificado X.509 para conectar un dispositivo con un certificado derivado del certificado del grupo de inscripciones de IoT Central.

Advertencia

Esta forma de generar certificados X.509 es solo para pruebas. En un entorno de producción, debe usar su mecanismo oficial y seguro para la generación de certificados.

  1. Vaya al script del generador de certificados en el SDK de Microsoft Azure IoT para Node.js que descargó. Instale los paquetes necesarios:

    cd azure-iot-sdk-node/provisioning/tools
    npm install
    
  2. Cree un certificado raíz y luego derive un certificado de dispositivo mediante la ejecución del script:

    node create_test_cert.js root mytestrootcert
    node create_test_cert.js device sample-device-01 mytestrootcert
    

    Sugerencia

    Un identificador de dispositivo puede contener letras, números y el carácter -.

Estos comandos producen los siguientes certificados raíz y de dispositivo:

filename contenido
mytestrootcert_cert.pem Parte pública del certificado X.509 raíz
mytestrootcert_key.pem Clave privada del certificado X.509 raíz
mytestrootcert_fullchain.pem Cadena de claves completa del certificado X.509 raíz
mytestrootcert.pfx Archivo PFX del certificado X509 raíz
sampleDevice01_cert.pem Parte pública del certificado X.509 de dispositivo
sampleDevice01_key.pem Clave privada del certificado X.509 de dispositivo
sampleDevice01_fullchain.pem Cadena de claves completa del certificado X.509 de dispositivo
sampleDevice01.pfx Archivo PFX del certificado X509 de dispositivo

Tome nota de la ubicación de estos archivos. Lo necesitará más adelante.

Creación de una inscripción de grupo

  1. Abra la aplicación de IoT Central, vaya a Permisos, en el panel izquierdo, y seleccione Grupos de conexiones de dispositivos.

  2. Seleccione + Nuevo para crear un nuevo grupo de inscripción con el nombre MyX509Group y el tipo de atestación Certificados (X.509). Puede crear grupos de inscripción para dispositivos IoT o dispositivos IoT Edge.

  3. En el grupo de inscripciones que ha creado, seleccione Administrar principal.

  4. En el panel Certificado principal, seleccione Agregar certificado.

  5. Cargue el archivo de certificado raíz llamado mytestrootcert_cert.pem generado anteriormente.

  6. Si utiliza una autoridad de certificación intermedia o raíz en la que confía y sabe que es el propietario total del certificado, puede dar fe de que ha verificado el certificado estableciendo el estado del certificado verificado al cargar en Activado. De lo contrario, establezca el estado del certificado comprobado al cargar en Desactivado.

  7. Si establece el estado del certificado comprobado al cargar en Desactivado, seleccione Generar código de verificación.

  8. Copie el código de verificación, cópielo y, a continuación, cree un certificado de verificación X.509. Por ejemplo, en el símbolo del sistema:

    node create_test_cert.js verification --ca mytestrootcert_cert.pem --key mytestrootcert_key.pem --nonce  {verification-code}
    
  9. Seleccione Comprobar para cargar el certificado de verificación firmado verification_cert.pem para completar la comprobación.

  10. El estado del certificado principal ahora está Comprobado:

    Screenshot that shows a verified X509 certificate.

Ahora podrá conectar los dispositivos que tengan un certificado X.509 derivado de este certificado raíz principal.

Después de guardar el grupo de inscripciones, tome nota del ámbito de identificador. Lo necesitará más adelante.

Ejecución del código del dispositivo de ejemplo

Si usa Windows, los certificados X.509 deben estar en el almacén de certificados de Windows para que el ejemplo funcione. En el Explorador de Windows, haga doble clic en los archivos PFX que generó anteriormente (mytestrootcert.pfx y sampleDevice01.pfx). En el Asistente para importar certificados, seleccione Usuario actual como ubicación del almacén, introduzca 1234 como contraseña y deje que el asistente elija automáticamente el almacén de certificados. El asistente importa los certificados en el almacén personal del usuario actual.

Haga lo siguiente para modificar el código de ejemplo a fin de usar los certificados X.509:

  1. En la solución de Visual Studio IoTHubDeviceSamples, abra el archivo Parameter.cs en el proyecto TemperatureController.

  2. Agregue las dos definiciones de parámetros siguientes a la clase:

    [Option(
        'x',
        "CertificatePath",
        HelpText = "(Required if DeviceSecurityType is \"dps\"). \nThe device PFX file to use during device provisioning." +
        "\nDefaults to environment variable \"IOTHUB_DEVICE_X509_CERT\".")]
    public string CertificatePath { get; set; } = Environment.GetEnvironmentVariable("IOTHUB_DEVICE_X509_CERT");
    
    [Option(
        'p',
        "CertificatePassword",
        HelpText = "(Required if DeviceSecurityType is \"dps\"). \nThe password of the PFX certificate file." +
        "\nDefaults to environment variable \"IOTHUB_DEVICE_X509_PASSWORD\".")]
    public string CertificatePassword { get; set; } = Environment.GetEnvironmentVariable("IOTHUB_DEVICE_X509_PASSWORD");
    

    Guarde los cambios.

  3. En la solución de Visual Studio IoTHubDeviceSamples, abra el archivo Program.cs en el proyecto TemperatureController.

  4. Agregue las instrucciones siguientes using :

    using System.Security.Cryptography.X509Certificates;
    using System.IO;
    
  5. Agregue el siguiente método a la clase :

    private static X509Certificate2 LoadProvisioningCertificate(Parameters parameters)
    {
        var certificateCollection = new X509Certificate2Collection();
        certificateCollection.Import(
            parameters.CertificatePath,
            parameters.CertificatePassword,
            X509KeyStorageFlags.UserKeySet);
    
        X509Certificate2 certificate = null;
    
        foreach (X509Certificate2 element in certificateCollection)
        {
            Console.WriteLine($"Found certificate: {element?.Thumbprint} {element?.Subject}; PrivateKey: {element?.HasPrivateKey}");
            if (certificate == null && element.HasPrivateKey)
            {
                certificate = element;
            }
            else
            {
                element.Dispose();
            }
        }
    
        if (certificate == null)
        {
            throw new FileNotFoundException($"{parameters.CertificatePath} did not contain any certificate with a private key.");
        }
    
        Console.WriteLine($"Using certificate {certificate.Thumbprint} {certificate.Subject}");
    
        return certificate;
    }
    
  6. En el método SetupDeviceClientAsync, sustituya el bloque de código de case "dps" por el código siguiente:

    case "dps":
        s_logger.LogDebug($"Initializing via DPS");
        Console.WriteLine($"Loading the certificate...");
        X509Certificate2 certificate = LoadProvisioningCertificate(parameters);
        DeviceRegistrationResult dpsRegistrationResult = await ProvisionDeviceAsync(parameters, certificate, cancellationToken);
        var authMethod = new DeviceAuthenticationWithX509Certificate(dpsRegistrationResult.DeviceId, certificate);
        deviceClient = InitializeDeviceClient(dpsRegistrationResult.AssignedHub, authMethod);
        break;
    
  7. Reemplace el método ProvisionDeviceAsync con el código siguiente:

    private static async Task<DeviceRegistrationResult> ProvisionDeviceAsync(Parameters parameters, X509Certificate2 certificate, CancellationToken cancellationToken)
    {
        SecurityProvider security = new SecurityProviderX509Certificate(certificate);
        ProvisioningTransportHandler mqttTransportHandler = new ProvisioningTransportHandlerMqtt();
        ProvisioningDeviceClient pdc = ProvisioningDeviceClient.Create(parameters.DpsEndpoint, parameters.DpsIdScope, security, mqttTransportHandler);
    
        var pnpPayload = new ProvisioningRegistrationAdditionalData
        {
            JsonData = PnpConvention.CreateDpsPayload(ModelId),
        };
        return await pdc.RegisterAsync(pnpPayload, cancellationToken);
    }
    

    Guarde los cambios.

Para ejecutar el ejemplo:

  1. Agregue las siguientes variables de entorno al proyecto:

    • IOTHUB_DEVICE_X509_CERT: <full path to folder that contains PFX files>sampleDevice01.pfx
    • IOTHUB_DEVICE_X509_PASSWORD: 1234.
  2. Compile y ejecute la aplicación. Compruebe que el dispositivo se aprovisiona correctamente.

Haga lo siguiente para modificar el código de ejemplo a fin de usar los certificados X.509:

  1. Vaya a la carpeta azure-iot-sdk-java/device/iot-device-samples/pnp-device-sample/temperature-controller-device-sample que contiene el archivo pom.xml y la carpeta src para el ejemplo de dispositivo del controlador de temperatura.

  2. Edite el archivo pom.xml para agregar la siguiente configuración de dependencias en el nodo <dependencies>:

    <dependency>
        <groupId>com.microsoft.azure.sdk.iot.provisioning.security</groupId>
        <artifactId>${x509-provider-artifact-id}</artifactId>
        <version>${x509-provider-version}</version>
    </dependency>
    

    Guarde los cambios.

  3. Abra el archivo src/main/java/samples/com/microsoft/azure/sdk/iot/device/TemperatureController.java en el editor de texto.

  4. Reemplace la importación de SecurityProviderSymmetricKey por las siguientes importaciones:

    import com.microsoft.azure.sdk.iot.provisioning.security.SecurityProvider;
    import com.microsoft.azure.sdk.iot.provisioning.security.hsm.SecurityProviderX509Cert;
    import com.microsoft.azure.sdk.iot.provisioning.security.exceptions.SecurityProviderException;
    
  5. Agregue la siguiente importación:

    import java.nio.file.*;
    
  6. Agregue SecurityProviderException a la lista de excepciones que el método main genera:

    public static void main(String[] args) throws IOException, URISyntaxException, ProvisioningDeviceClientException, InterruptedException, SecurityProviderException {
    
  7. Reemplace el método initializeAndProvisionDevice con el código siguiente:

    private static void initializeAndProvisionDevice() throws ProvisioningDeviceClientException, IOException, URISyntaxException, InterruptedException, SecurityProviderException {
        String deviceX509Key = new String(Files.readAllBytes(Paths.get(System.getenv("IOTHUB_DEVICE_X509_KEY"))));
        String deviceX509Cert = new String(Files.readAllBytes(Paths.get(System.getenv("IOTHUB_DEVICE_X509_CERT"))));
        SecurityProvider securityProviderX509 = new SecurityProviderX509Cert(deviceX509Cert, deviceX509Key, null);
        ProvisioningDeviceClient provisioningDeviceClient;
        ProvisioningStatus provisioningStatus = new ProvisioningStatus();
    
        provisioningDeviceClient = ProvisioningDeviceClient.create(globalEndpoint, scopeId, provisioningProtocol, securityProviderX509);
    
        AdditionalData additionalData = new AdditionalData();
        additionalData.setProvisioningPayload(com.microsoft.azure.sdk.iot.provisioning.device.plugandplay.PnpHelper.createDpsPayload(MODEL_ID));
    
        provisioningDeviceClient.registerDevice(new ProvisioningDeviceClientRegistrationCallbackImpl(), provisioningStatus, additionalData);
    
        while (provisioningStatus.provisioningDeviceClientRegistrationInfoClient.getProvisioningDeviceClientStatus() != ProvisioningDeviceClientStatus.PROVISIONING_DEVICE_STATUS_ASSIGNED)
        {
            if (provisioningStatus.provisioningDeviceClientRegistrationInfoClient.getProvisioningDeviceClientStatus() == ProvisioningDeviceClientStatus.PROVISIONING_DEVICE_STATUS_ERROR ||
                    provisioningStatus.provisioningDeviceClientRegistrationInfoClient.getProvisioningDeviceClientStatus() == ProvisioningDeviceClientStatus.PROVISIONING_DEVICE_STATUS_DISABLED ||
                    provisioningStatus.provisioningDeviceClientRegistrationInfoClient.getProvisioningDeviceClientStatus() == ProvisioningDeviceClientStatus.PROVISIONING_DEVICE_STATUS_FAILED)
            {
                provisioningStatus.exception.printStackTrace();
                System.out.println("Registration error, bailing out");
                break;
            }
            System.out.println("Waiting for Provisioning Service to register");
            Thread.sleep(MAX_TIME_TO_WAIT_FOR_REGISTRATION);
        }
    
        ClientOptions options = new ClientOptions();
        options.setModelId(MODEL_ID);
    
        if (provisioningStatus.provisioningDeviceClientRegistrationInfoClient.getProvisioningDeviceClientStatus() == ProvisioningDeviceClientStatus.PROVISIONING_DEVICE_STATUS_ASSIGNED) {
            System.out.println("IotHUb Uri : " + provisioningStatus.provisioningDeviceClientRegistrationInfoClient.getIothubUri());
            System.out.println("Device ID : " + provisioningStatus.provisioningDeviceClientRegistrationInfoClient.getDeviceId());
    
            String iotHubUri = provisioningStatus.provisioningDeviceClientRegistrationInfoClient.getIothubUri();
            String deviceId = provisioningStatus.provisioningDeviceClientRegistrationInfoClient.getDeviceId();
    
            log.debug("Opening the device client.");
            deviceClient = DeviceClient.createFromSecurityProvider(iotHubUri, deviceId, securityProviderX509, IotHubClientProtocol.MQTT, options);
            deviceClient.open();
        }
    }
    

    Guarde los cambios.

Para ejecutar el ejemplo:

  1. En el entorno de shell, agregue las dos variables de entorno siguientes. Asegúrese de proporcionar la ruta de acceso completa a los archivos PEM y use el delimitador de ruta de acceso correcto para el sistema operativo:

    set IOTHUB_DEVICE_X509_CERT=<full path to folder that contains PEM files>sampleDevice01_cert.pem
    set IOTHUB_DEVICE_X509_KEY=<full path to folder that contains PEM files>sampleDevice01_key.pem
    

    Sugerencia

    Establezca las otras dos variables de entorno necesarias cuando complete el tutorial Creación y conexión de un aplicación cliente a una aplicación de Azure IoT Central.

  2. Compile y ejecute la aplicación. Compruebe que el dispositivo se aprovisiona correctamente.

Haga lo siguiente para modificar el código de ejemplo a fin de usar los certificados X.509:

  1. Vaya a la carpeta azure-iot-sdk-node/device/samples/javascript que contiene la aplicación pnp_temperature_controller.js y ejecute el siguiente comando para instalar el paquete X.509:

    npm install azure-iot-security-x509 --save
    
  2. Abra el archivo pnp_temperature_controller.js en un editor de texto.

  3. Edite las instrucciones require para incluir el código siguiente:

    const fs = require('fs');
    const X509Security = require('azure-iot-security-x509').X509Security;
    
  4. Agregue las cuatro líneas siguientes a la sección "DPS connection information" (Información de conexión de DPS) para inicializar la variable deviceCert:

    const deviceCert = {
      cert: fs.readFileSync(process.env.IOTHUB_DEVICE_X509_CERT).toString(),
      key: fs.readFileSync(process.env.IOTHUB_DEVICE_X509_KEY).toString()
    };
    
  5. Edite la función provisionDevice que crea el cliente; para ello, reemplace la primera línea por el código siguiente:

    var provSecurityClient = new X509Security(registrationId, deviceCert);
    
  6. En la misma función, modifique la línea que establece la variable deviceConnectionString como se indica a continuación:

    deviceConnectionString = 'HostName=' + result.assignedHub + ';DeviceId=' + result.deviceId + ';x509=true';
    
  7. En la función main, agregue la siguiente línea después de la línea que llama a Client.fromConnectionString:

    client.setOptions(deviceCert);
    

    Guarde los cambios.

Para ejecutar el ejemplo:

  1. En el entorno de shell, agregue las dos variables de entorno siguientes. Asegúrese de proporcionar la ruta de acceso completa a los archivos PEM y use el delimitador de ruta de acceso correcto para el sistema operativo:

    set IOTHUB_DEVICE_X509_CERT=<full path to folder that contains PEM files>sampleDevice01_cert.pem
    set IOTHUB_DEVICE_X509_KEY=<full path to folder that contains PEM files>sampleDevice01_key.pem
    

    Sugerencia

    Establezca las otras dos variables de entorno necesarias cuando complete el tutorial Creación y conexión de un aplicación cliente a una aplicación de Azure IoT Central.

  2. Ejecute el script y compruebe que el dispositivo se ha aprovisionado correctamente:

    node pnp_temperature_controller.js
    

Haga lo siguiente para modificar el código de ejemplo a fin de usar los certificados X.509:

  1. Vaya a la carpeta azure-iot-device/samples/pnp y abra el archivo temp_controller_with_thermostats.py en un editor de texto.

  2. Use la siguiente instrucción from para importar la funcionalidad de X.509:

    from azure.iot.device import X509
    
  3. Modifique la primera parte de la función provision_device como se muestra a continuación:

    async def provision_device(provisioning_host, id_scope, registration_id, x509, model_id):
        provisioning_device_client = ProvisioningDeviceClient.create_from_x509_certificate(
            provisioning_host=provisioning_host,
            registration_id=registration_id,
            id_scope=id_scope,
            x509=x509,
        )
    
  4. En la función main, reemplace la línea que establece la variable symmetric_key por el código siguiente:

    x509 = X509(
        cert_file=os.getenv("IOTHUB_DEVICE_X509_CERT"),
        key_file=os.getenv("IOTHUB_DEVICE_X509_KEY"),
    )
    
  5. En la función main, reemplace la llamada a la función provision_device por el código siguiente:

    registration_result = await provision_device(
        provisioning_host, id_scope, registration_id, x509, model_id
    )
    
  6. En la función main, reemplace la llamada a la función IoTHubDeviceClient.create_from_symmetric_key por el código siguiente:

    device_client = IoTHubDeviceClient.create_from_x509_certificate(
        x509=x509,
        hostname=registration_result.registration_state.assigned_hub,
        device_id=registration_result.registration_state.device_id,
        product_info=model_id,
    )
    

    Guarde los cambios.

Para ejecutar el ejemplo:

  1. En el entorno de shell, agregue las dos variables de entorno siguientes. Asegúrese de proporcionar la ruta de acceso completa a los archivos PEM y use el delimitador de ruta de acceso correcto para el sistema operativo:

    set IOTHUB_DEVICE_X509_CERT=<full path to folder that contains PEM files>sampleDevice01_cert.pem
    set IOTHUB_DEVICE_X509_KEY=<full path to folder that contains PEM files>sampleDevice01_key.pem
    

    Sugerencia

    Establezca las otras dos variables de entorno necesarias cuando complete el tutorial Creación y conexión de un aplicación cliente a una aplicación de Azure IoT Central.

  2. Ejecute el script y compruebe que el dispositivo se ha aprovisionado correctamente:

    python temp_controller_with_thermostats.py
    

Compruebe que la telemetría aparece en la vista del dispositivo en la aplicación de IoT Central:

Screenshot showing telemetry from a device that connected using X.509.

Uso de la inscripción individual

Use certificados X.509 con una inscripción individual para probar el dispositivo y la solución. En una inscripción individual, no hay ningún certificado X.509 intermedio o raíz en la aplicación de IoT Central. Los dispositivos usan un certificado X.509 autofirmado para conectarse a la aplicación.

Generación de un certificado de dispositivo autofirmado

En esta sección, se usa un certificado X.509 autofirmado para conectar dispositivos para la inscripción individual; su uso permite la inscripción de un único dispositivo. Los certificados autofirmados son solo para pruebas.

Advertencia

Esta forma de generar certificados X.509 es solo para pruebas. En un entorno de producción, debe usar su mecanismo oficial y seguro para la generación de certificados.

Cree un certificado X.509 autofirmado de dispositivo mediante la ejecución de los siguientes comandos:

  cd azure-iot-sdk-node/provisioning/tools
  node create_test_cert.js device mytestselfcertprimary
  node create_test_cert.js device mytestselfcertsecondary 

Sugerencia

Un identificador de dispositivo puede contener letras, números y el carácter -.

Estos comandos generan los siguientes certificados de dispositivo:

filename contenido
mytestselfcertprimary_cert.pem Parte pública del certificado X.509 de dispositivo primario
mytestselfcertprimary_key.pem Clave privada del certificado X.509 de dispositivo primario
mytestselfcertprimary_fullchain.pem Cadena de claves completa del certificado X.509 de dispositivo primario
mytestselfcertprimary.pfx Archivo PFX del certificado X509 de dispositivo primario
mytestselfcertsecondary_cert.pem Parte pública del certificado X.509 de dispositivo secundario
mytestselfcertsecondary_key.pem Clave privada del certificado X.509 de dispositivo secundario
mytestselfcertsecondary_fullchain.pem Cadena de claves completa del certificado X.509 de dispositivo secundario
mytestselfcertsecondary.pfx Archivo PFX del certificado X509 de dispositivo secundario

Creación de una inscripción individual

  1. En la aplicación de Azure IoT Central, seleccione Dispositivos y cree otro dispositivo con mytestselfcertprimary como Id. de dispositivo en la plantilla del dispositivo termostato. Tome nota del valor de ámbito de id., ya que lo usará más adelante.

  2. Abra el dispositivo que acaba de crear y seleccione Conectar.

  3. Seleccione Inscripción individual como Tipo de autenticación y Certificados (X.509) como método de autenticación.

  4. Cargue el archivo mytestselfcertprimary_cert.pem que generó anteriormente como certificado principal.

  5. Cargue el archivo mytestselfcertsecondary_cert.pem que generó anteriormente como certificado secundario. Después, seleccione Guardar.

  6. El dispositivo ahora tiene una inscripción individual con certificados X.509.

    Screenshot that shows how to connect a device using an X.509 individual enrollment.

Ejecución de un dispositivo de inscripción individual de ejemplo

Si usa Windows, los certificados X.509 deben estar en el almacén de certificados de Windows para que el ejemplo funcione. En el Explorador de Windows, haga doble clic en los archivos PFX que generó anteriormente (mytestselfcertprimary.pfx y mytestselfcertsecondary.pfx). En el Asistente para importar certificados, seleccione Usuario actual como ubicación del almacén, introduzca 1234 como contraseña y deje que el asistente elija automáticamente el almacén de certificados. El asistente importa los certificados en el almacén personal del usuario actual.

Haga lo siguiente para modificar el código de ejemplo a fin de usar los certificados X.509:

  1. En la solución de Visual Studio IoTHubDeviceSamples, abra el archivo Parameter.cs en el proyecto TemperatureController.

  2. Agregue las dos definiciones de parámetros siguientes a la clase:

    [Option(
        'x',
        "CertificatePath",
        HelpText = "(Required if DeviceSecurityType is \"dps\"). \nThe device PFX file to use during device provisioning." +
        "\nDefaults to environment variable \"IOTHUB_DEVICE_X509_CERT\".")]
    public string CertificatePath { get; set; } = Environment.GetEnvironmentVariable("IOTHUB_DEVICE_X509_CERT");
    
    [Option(
        'p',
        "CertificatePassword",
        HelpText = "(Required if DeviceSecurityType is \"dps\"). \nThe password of the PFX certificate file." +
        "\nDefaults to environment variable \"IOTHUB_DEVICE_X509_PASSWORD\".")]
    public string CertificatePassword { get; set; } = Environment.GetEnvironmentVariable("IOTHUB_DEVICE_X509_PASSWORD");
    

    Guarde los cambios.

  3. En la solución de Visual Studio IoTHubDeviceSamples, abra el archivo Program.cs en el proyecto TemperatureController.

  4. Agregue las instrucciones siguientes using :

    using System.Security.Cryptography.X509Certificates;
    using System.IO;
    
  5. Agregue el siguiente método a la clase :

    private static X509Certificate2 LoadProvisioningCertificate(Parameters parameters)
    {
        var certificateCollection = new X509Certificate2Collection();
        certificateCollection.Import(
            parameters.CertificatePath,
            parameters.CertificatePassword,
            X509KeyStorageFlags.UserKeySet);
    
        X509Certificate2 certificate = null;
    
        foreach (X509Certificate2 element in certificateCollection)
        {
            Console.WriteLine($"Found certificate: {element?.Thumbprint} {element?.Subject}; PrivateKey: {element?.HasPrivateKey}");
            if (certificate == null && element.HasPrivateKey)
            {
                certificate = element;
            }
            else
            {
                element.Dispose();
            }
        }
    
        if (certificate == null)
        {
            throw new FileNotFoundException($"{parameters.CertificatePath} did not contain any certificate with a private key.");
        }
    
        Console.WriteLine($"Using certificate {certificate.Thumbprint} {certificate.Subject}");
    
        return certificate;
    }
    
  6. En el método SetupDeviceClientAsync, sustituya el bloque de código de case "dps" por el código siguiente:

    case "dps":
        s_logger.LogDebug($"Initializing via DPS");
        Console.WriteLine($"Loading the certificate...");
        X509Certificate2 certificate = LoadProvisioningCertificate(parameters);
        DeviceRegistrationResult dpsRegistrationResult = await ProvisionDeviceAsync(parameters, certificate, cancellationToken);
        var authMethod = new DeviceAuthenticationWithX509Certificate(dpsRegistrationResult.DeviceId, certificate);
        deviceClient = InitializeDeviceClient(dpsRegistrationResult.AssignedHub, authMethod);
        break;
    
  7. Reemplace el método ProvisionDeviceAsync con el código siguiente:

    private static async Task<DeviceRegistrationResult> ProvisionDeviceAsync(Parameters parameters, X509Certificate2 certificate, CancellationToken cancellationToken)
    {
        SecurityProvider security = new SecurityProviderX509Certificate(certificate);
        ProvisioningTransportHandler mqttTransportHandler = new ProvisioningTransportHandlerMqtt();
        ProvisioningDeviceClient pdc = ProvisioningDeviceClient.Create(parameters.DpsEndpoint, parameters.DpsIdScope, security, mqttTransportHandler);
    
        var pnpPayload = new ProvisioningRegistrationAdditionalData
        {
            JsonData = PnpConvention.CreateDpsPayload(ModelId),
        };
        return await pdc.RegisterAsync(pnpPayload, cancellationToken);
    }
    

    Guarde los cambios.

Para ejecutar el ejemplo:

  1. Agregue las siguientes variables de entorno al proyecto:

    • IOTHUB_DEVICE_DPS_DEVICE_ID: mytestselfcertprimary
    • IOTHUB_DEVICE_X509_CERT: <full path to folder that contains PFX files>mytestselfcertprimary.pfx
    • IOTHUB_DEVICE_X509_PASSWORD: 1234.
  2. Compile y ejecute la aplicación. Compruebe que el dispositivo se aprovisiona correctamente.

Haga lo siguiente para modificar el código de ejemplo a fin de usar los certificados X.509:

  1. Vaya a la carpeta azure-iot-sdk-java/device/iot-device-samples/pnp-device-sample/temperature-controller-device-sample que contiene el archivo pom.xml y la carpeta src para el ejemplo de dispositivo del controlador de temperatura.

  2. Edite el archivo pom.xml para agregar la siguiente configuración de dependencias en el nodo <dependencies>:

    <dependency>
        <groupId>com.microsoft.azure.sdk.iot.provisioning.security</groupId>
        <artifactId>${x509-provider-artifact-id}</artifactId>
        <version>${x509-provider-version}</version>
    </dependency>
    

    Guarde los cambios.

  3. Abra el archivo src/main/java/samples/com/microsoft/azure/sdk/iot/device/TemperatureController.java en el editor de texto.

  4. Reemplace la importación de SecurityProviderSymmetricKey por las siguientes importaciones:

    import com.microsoft.azure.sdk.iot.provisioning.security.SecurityProvider;
    import com.microsoft.azure.sdk.iot.provisioning.security.hsm.SecurityProviderX509Cert;
    import com.microsoft.azure.sdk.iot.provisioning.security.exceptions.SecurityProviderException;
    
  5. Agregue la siguiente importación:

    import java.nio.file.*;
    
  6. Agregue SecurityProviderException a la lista de excepciones que el método main genera:

    public static void main(String[] args) throws IOException, URISyntaxException, ProvisioningDeviceClientException, InterruptedException, SecurityProviderException {
    
  7. Reemplace el método initializeAndProvisionDevice con el código siguiente:

    private static void initializeAndProvisionDevice() throws ProvisioningDeviceClientException, IOException, URISyntaxException, InterruptedException, SecurityProviderException {
        String deviceX509Key = new String(Files.readAllBytes(Paths.get(System.getenv("IOTHUB_DEVICE_X509_KEY"))));
        String deviceX509Cert = new String(Files.readAllBytes(Paths.get(System.getenv("IOTHUB_DEVICE_X509_CERT"))));
        SecurityProvider securityProviderX509 = new SecurityProviderX509Cert(deviceX509Cert, deviceX509Key, null);
        ProvisioningDeviceClient provisioningDeviceClient;
        ProvisioningStatus provisioningStatus = new ProvisioningStatus();
    
        provisioningDeviceClient = ProvisioningDeviceClient.create(globalEndpoint, scopeId, provisioningProtocol, securityProviderX509);
    
        AdditionalData additionalData = new AdditionalData();
        additionalData.setProvisioningPayload(com.microsoft.azure.sdk.iot.provisioning.device.plugandplay.PnpHelper.createDpsPayload(MODEL_ID));
    
        provisioningDeviceClient.registerDevice(new ProvisioningDeviceClientRegistrationCallbackImpl(), provisioningStatus, additionalData);
    
        while (provisioningStatus.provisioningDeviceClientRegistrationInfoClient.getProvisioningDeviceClientStatus() != ProvisioningDeviceClientStatus.PROVISIONING_DEVICE_STATUS_ASSIGNED)
        {
            if (provisioningStatus.provisioningDeviceClientRegistrationInfoClient.getProvisioningDeviceClientStatus() == ProvisioningDeviceClientStatus.PROVISIONING_DEVICE_STATUS_ERROR ||
                    provisioningStatus.provisioningDeviceClientRegistrationInfoClient.getProvisioningDeviceClientStatus() == ProvisioningDeviceClientStatus.PROVISIONING_DEVICE_STATUS_DISABLED ||
                    provisioningStatus.provisioningDeviceClientRegistrationInfoClient.getProvisioningDeviceClientStatus() == ProvisioningDeviceClientStatus.PROVISIONING_DEVICE_STATUS_FAILED)
            {
                provisioningStatus.exception.printStackTrace();
                System.out.println("Registration error, bailing out");
                break;
            }
            System.out.println("Waiting for Provisioning Service to register");
            Thread.sleep(MAX_TIME_TO_WAIT_FOR_REGISTRATION);
        }
    
        ClientOptions options = new ClientOptions();
        options.setModelId(MODEL_ID);
    
        if (provisioningStatus.provisioningDeviceClientRegistrationInfoClient.getProvisioningDeviceClientStatus() == ProvisioningDeviceClientStatus.PROVISIONING_DEVICE_STATUS_ASSIGNED) {
            System.out.println("IotHUb Uri : " + provisioningStatus.provisioningDeviceClientRegistrationInfoClient.getIothubUri());
            System.out.println("Device ID : " + provisioningStatus.provisioningDeviceClientRegistrationInfoClient.getDeviceId());
    
            String iotHubUri = provisioningStatus.provisioningDeviceClientRegistrationInfoClient.getIothubUri();
            String deviceId = provisioningStatus.provisioningDeviceClientRegistrationInfoClient.getDeviceId();
    
            log.debug("Opening the device client.");
            deviceClient = DeviceClient.createFromSecurityProvider(iotHubUri, deviceId, securityProviderX509, IotHubClientProtocol.MQTT, options);
            deviceClient.open();
        }
    }
    

    Guarde los cambios.

Para ejecutar el ejemplo:

  1. En el entorno de shell, agregue las dos variables de entorno siguientes. Asegúrese de proporcionar la ruta de acceso completa a los archivos PEM y use el delimitador de ruta de acceso correcto para el sistema operativo:

    set IOTHUB_DEVICE_DPS_DEVICE_ID=mytestselfcertprimary
    set IOTHUB_DEVICE_X509_CERT=<full path to folder that contains PEM files>mytestselfcertprimary_cert.pem
    set IOTHUB_DEVICE_X509_KEY=<full path to folder that contains PEM files>mytestselfcertprimary_key.pem
    

    Sugerencia

    Establezca las otras dos variables de entorno necesarias cuando complete el tutorial Creación y conexión de un aplicación cliente a una aplicación de Azure IoT Central.

  2. Compile y ejecute la aplicación. Compruebe que el dispositivo se aprovisiona correctamente.

También puede repetir los pasos anteriores para el certificado mytestselfcertsecondary.

Haga lo siguiente para modificar el código de ejemplo a fin de usar los certificados X.509:

  1. Vaya a la carpeta azure-iot-sdk-node/device/samples/javascript que contiene la aplicación pnp_temperature_controller.js y ejecute el siguiente comando para instalar el paquete X.509:

    npm install azure-iot-security-x509 --save
    
  2. Abra el archivo pnp_temperature_controller.js en un editor de texto.

  3. Edite las instrucciones require para incluir el código siguiente:

    const fs = require('fs');
    const X509Security = require('azure-iot-security-x509').X509Security;
    
  4. Agregue las cuatro líneas siguientes a la sección "DPS connection information" (Información de conexión de DPS) para inicializar la variable deviceCert:

    const deviceCert = {
      cert: fs.readFileSync(process.env.IOTHUB_DEVICE_X509_CERT).toString(),
      key: fs.readFileSync(process.env.IOTHUB_DEVICE_X509_KEY).toString()
    };
    
  5. Edite la función provisionDevice que crea el cliente; para ello, reemplace la primera línea por el código siguiente:

    var provSecurityClient = new X509Security(registrationId, deviceCert);
    
  6. En la misma función, modifique la línea que establece la variable deviceConnectionString como se indica a continuación:

    deviceConnectionString = 'HostName=' + result.assignedHub + ';DeviceId=' + result.deviceId + ';x509=true';
    
  7. En la función main, agregue la siguiente línea después de la línea que llama a Client.fromConnectionString:

    client.setOptions(deviceCert);
    

    Guarde los cambios.

Para ejecutar el ejemplo:

  1. En el entorno de shell, agregue las dos variables de entorno siguientes. Asegúrese de proporcionar la ruta de acceso completa a los archivos PEM y use el delimitador de ruta de acceso correcto para el sistema operativo:

    set IOTHUB_DEVICE_DPS_DEVICE_ID=mytestselfcertprimary
    set IOTHUB_DEVICE_X509_CERT=<full path to folder that contains PEM files>mytestselfcertprimary_cert.pem
    set IOTHUB_DEVICE_X509_KEY=<full path to folder that contains PEM files>mytestselfcertprimary_key.pem
    

    Sugerencia

    Establezca las otras dos variables de entorno necesarias cuando complete el tutorial Creación y conexión de un aplicación cliente a una aplicación de Azure IoT Central.

  2. Ejecute el script y compruebe que el dispositivo se ha aprovisionado correctamente:

    node pnp_temperature_controller.js
    

También puede repetir los pasos anteriores para el certificado mytestselfcertsecondary.

Haga lo siguiente para modificar el código de ejemplo a fin de usar los certificados X.509:

  1. Vaya a la carpeta azure-iot-device/samples/pnp y abra el archivo temp_controller_with_thermostats.py en un editor de texto.

  2. Use la siguiente instrucción from para importar la funcionalidad de X.509:

    from azure.iot.device import X509
    
  3. Modifique la primera parte de la función provision_device como se muestra a continuación:

    async def provision_device(provisioning_host, id_scope, registration_id, x509, model_id):
        provisioning_device_client = ProvisioningDeviceClient.create_from_x509_certificate(
            provisioning_host=provisioning_host,
            registration_id=registration_id,
            id_scope=id_scope,
            x509=x509,
        )
    
  4. En la función main, reemplace la línea que establece la variable symmetric_key por el código siguiente:

    x509 = X509(
        cert_file=os.getenv("IOTHUB_DEVICE_X509_CERT"),
        key_file=os.getenv("IOTHUB_DEVICE_X509_KEY"),
    )
    
  5. En la función main, reemplace la llamada a la función provision_device por el código siguiente:

    registration_result = await provision_device(
        provisioning_host, id_scope, registration_id, x509, model_id
    )
    
  6. En la función main, reemplace la llamada a la función IoTHubDeviceClient.create_from_symmetric_key por el código siguiente:

    device_client = IoTHubDeviceClient.create_from_x509_certificate(
        x509=x509,
        hostname=registration_result.registration_state.assigned_hub,
        device_id=registration_result.registration_state.device_id,
        product_info=model_id,
    )
    

    Guarde los cambios.

Para ejecutar el ejemplo:

  1. En el entorno de shell, agregue las dos variables de entorno siguientes. Asegúrese de proporcionar la ruta de acceso completa a los archivos PEM y use el delimitador de ruta de acceso correcto para el sistema operativo:

    set IOTHUB_DEVICE_DPS_DEVICE_ID=mytestselfcertprimary
    set IOTHUB_DEVICE_X509_CERT=<full path to folder that contains PEM files>mytestselfcertprimary_cert.pem
    set IOTHUB_DEVICE_X509_KEY=<full path to folder that contains PEM files>mytestselfcertprimary_key.pem
    

    Sugerencia

    Establezca las otras dos variables de entorno necesarias cuando complete el tutorial Creación y conexión de un aplicación cliente a una aplicación de Azure IoT Central.

  2. Ejecute el script y compruebe que el dispositivo se ha aprovisionado correctamente:

    python temp_controller_with_thermostats.py
    

También puede repetir los pasos anteriores para el certificado mytestselfcertsecondary.

Conexión de un dispositivo IoT Edge

En esta sección se da por supuesto que usa una inscripción de grupo para conectar el dispositivo de IoT Edge. Siga los pasos descritos en las secciones anteriores para lo siguiente:

Para conectar el dispositivo IoT Edge a IoT Central mediante el certificado X.509 de dispositivo:

  • Copie lo archivos de certificado de dispositivo y clave en el dispositivo IoT Edge. En el ejemplo de inscripción de grupo anterior, estos archivos se denominaban sampleDevice01_key.pem y sampleDevice01_cert.pem.

  • En el dispositivo IoT Edge, edite la sección provisioning en el archivo de configuración /etc/aziot/config.toml como se indica a continuación:

    # DPS X.509 provisioning configuration
    provisioning:
      source: "dps"
      global_endpoint: "https://global.azure-devices-provisioning.net"
      scope_id: "<SCOPE_ID>"
      attestation:
        method: "x509"
    #   registration_id: "<OPTIONAL REGISTRATION ID. LEAVE COMMENTED OUT TO REGISTER WITH CN OF identity_cert>"
        identity_cert: "file:///<path>/sampleDevice01_cert.pem"
        identity_pk: "file:///<path>/sampleDevice01_key.pem"
    #  always_reprovision_on_startup: true
    #  dynamic_reprovisioning: false
    
    [provisioning]
    source = "dps"
    global_endpoint = "https://global.azure-devices-provisioning.net"
    id_scope = "<SCOPE_ID>"
    
    [provisioning.attestation]
    method = "x509"
    registration_id = "env-sens-001"
    identity_pk = "file:///<path>/envSens001_key.pem"
    identity_cert = "file:///<path>/envSens001_cert.pem"
    

    Sugerencia

    No es necesario agregar un valor para registration_id. IoT Edge puede usar el valor CN del certificado X.509.

  • Ejecute el siguiente comando para reiniciar el entorno de ejecución de IoT Edge:

    sudo iotedge config apply
    

Para más información, vea Create and provision IoT Edge devices at scale on Linux using X.509 certificates (Creación y aprovisionamiento de dispositivos IoT Edgea gran escala en Linux mediante certificados X.509).

Conexión del dispositivo de bajada a IoT Edge

IoT Edge usa certificados X.509 para proteger la conexión entre los dispositivos de bajada y un dispositivo IoT Edge que actúa como puerta de enlace transparente. Para más información sobre la configuración de este escenario, vea Conexión de un dispositivo de bajada a una puerta de enlace Azure IoT Edge.

Actualice sus certificados de dispositivo X.509

Durante el ciclo de vida de su aplicación IoT Central, es posible que necesite renovar sus certificados X.509. Por ejemplo:

  • Si tiene una brecha de seguridad, la implementación de certificados es un procedimiento recomendado de seguridad para ayudar a proteger el sistema.
  • Los certificados X.509 tienen fecha de caducidad. La frecuencia de implementación de los certificados depende de las necesidades de seguridad de la solución. Los clientes con soluciones que implican datos muy confidenciales pueden renovar los certificados a diario, mientras que otros lo hacen cada dos años.

Para una conectividad ininterrumpida, IoT Central permite configurar certificados X.509 principales y secundarios. Si los certificados principal y secundario tienen fechas de expiración diferentes, puede implementar el certificado expirado mientras los dispositivos continúan conectándose con el otro certificado.

Para más información, vea Asumir la metodología de infracción.

En esta sección se describe cómo implementar los certificados en IoT Central. Al implementar un certificado en IoT Central, también debe copiar el nuevo certificado de dispositivo en los dispositivos.

Obtención de nuevos certificados X.509

Obtenga nuevos certificados X.509 del proveedor de certificados. Use una herramienta como OpenSSL para crear sus propios certificados X.509. Este enfoque es muy útil para probar los certificados X.509, pero proporciona pocas garantías de seguridad. Use este enfoque solo para las pruebas, a menos que se prepare para actuar como proveedor de entidad de certificación propio.

Grupos de inscripción e infracciones de seguridad

Para actualizar un grupo de inscripción en respuesta a una infracción de seguridad, debe usar el siguiente enfoque para actualizar inmediatamente el certificado actual. Complete estos pasos para el certificado principal y el secundario, si ambos están en riesgo:

  1. Vaya a Permisos en el panel izquierdo y seleccione Grupos de conexiones de dispositivos.

  2. Seleccione el nombre del grupo de la lista de Grupos de inscripción.

  3. Para la actualización de certificados, seleccione Administrar principal o Administrar secundario.

  4. Agregue y verifique un certificado X.509 raíz en el grupo de inscripción.

Inscripciones individuales e infracciones de seguridad

Si está implementando certificados en respuesta a una infracción de seguridad, use el siguiente enfoque para actualizar inmediatamente el certificado actual. Complete estos pasos para el certificado principal y el secundario, si ambos están en riesgo:

  1. Seleccione Dispositivos y seleccione el dispositivo.

  2. Seleccione Conectar y seleccione el método de conexión Individual Enrollment (Inscripción individual).

  3. Seleccione el mecanismo Certificados (X.509).

  4. Para actualizar un certificado, seleccione el icono de carpeta para seleccionar el nuevo certificado que se va a cargar para la entrada de inscripción. Seleccione Guardar.

Grupos de inscripciones y expiración de certificados

Para controlar la expiración de los certificados, actualice el certificado actual inmediatamente mediante el siguiente enfoque:

  1. Vaya a Permisos en el panel izquierdo y seleccione Grupos de conexiones de dispositivos.

  2. Seleccione el nombre del grupo de la lista de Grupos de inscripción.

  3. Para la actualización del certificado, seleccione Administrar principal.

  4. Agregue y verifique un certificado X.509 raíz en el grupo de inscripción.

  5. Más tarde, cuando el certificado secundario caduque, vuelva y actualice el certificado secundario.

Inscripciones individuales y expiración de certificados

Si está implementando certificados para controlar las expiraciones de los certificados, debe usar la configuración del certificado secundario como se indica a continuación para reducir el tiempo de inactividad de los dispositivos que se intentan aprovisionar en la aplicación.

Cuando se aproxima la expiración del certificado secundario y necesita implementarse, puede pasar al uso de la configuración principal. La rotación entre los certificados principales y secundarios de este modo reduce el tiempo de inactividad de los dispositivos que se intentan aprovisionar en la aplicación.

  1. Seleccione Dispositivos y seleccione el dispositivo.

  2. Seleccione Conectar y seleccione el método de conexión Individual Enrollment (Inscripción individual).

  3. Seleccione el mecanismo Certificados (X.509).

  4. Para actualizar un certificado secundario, seleccione el icono de carpeta para seleccionar el nuevo certificado que se va a cargar para la entrada de inscripción. Seleccione Guardar.

  5. Más adelante, cuando el certificado principal haya expirado, vuelva y actualícelo.