Как с помощью сертификатов X.509 подключать устройства к приложению IoT Central

IoT Central поддерживает подписанные URL-адрес (SAS) и сертификаты X.509 для защиты обмена данными между устройством и приложением. В руководстве Создание клиентского приложения и его подключение к приложению Azure IoT Central используется SAS. Из этой статьи вы узнаете, как изменить пример кода для использования сертификатов X.509. Сертификаты X.509 рекомендуется использовать в рабочих средах. Дополнительные сведения см. в основных понятиях проверки подлинности устройств.

В этом руководстве описаны два способа использования сертификатов X.509: групповые регистрации обычно используются в рабочей среде, а отдельные регистрации лучше использовать для тестирования. Также в этой статье показано, как правильно развертывать сертификаты устройств, чтобы сохранять возможность подключения при истечении срока действия сертификатов.

Это руководство основано на примерах из статьи Руководство по созданию клиентского приложения и его подключению к приложению Azure IoT Central для языков C#, Java, JavaScript и Python. Примеры для языка программирования C можно найти в статье Руководство по инициализации нескольких устройств X.509 с помощью групп регистрации.

Предварительные требования

Выполните инструкции из статье Руководство по созданию клиентского приложения и его подключению к приложению Azure IoT Central. Среди прочего, установите необходимые компоненты для выбранного языка программирования.

В этом руководстве показано, как создать несколько тестовых сертификатов X.509. Для этого вам потребуется следующее:

  • Компьютер для разработки с установленным Node.js 6 или более поздней версии. Вы можете запустить node --version в командной строке, чтобы проверить версию. В инструкциях этого руководства предполагается, что вы выполняете команду node в командной строке Windows. Но вы можете использовать Node.js во множестве других операционных системах.
  • Локальная копия репозитория GitHub пакета SDK Интернета вещей Microsoft Azure для Node.js со скриптами для создания тестовых сертификатов X.509. Используйте эту ссылку, чтобы скачать копию репозитория: Скачать ZIP-файл. Затем распакуйте файл в подходящее расположение на локальном компьютере.

Использование групповой регистрации

Используйте сертификаты X.509 с групповой регистрацией в рабочей среде. При регистрации группы вы добавляете корневой или промежуточный сертификат X.509 в приложение IoT Central. Устройства с конечными сертификатами, полученными из корневого или промежуточного сертификата, могут подключаться к приложению.

Создание корневого сертификата и сертификата устройства

В этом разделе вы примените сертификат X.509 для подключения устройства с производным сертификатом от сертификата группы развертывания IoT Central.

Предупреждение

Такой способ создания сертификатов X.509 предназначен только для тестирования. Для рабочей среды следует использовать официальный, безопасный механизм создания сертификатов.

  1. Перейдите к скрипту генератора сертификатов из скачанного пакета SDK Интернета вещей Microsoft Azure для Node.js. Установите необходимые пакеты.

    cd azure-iot-sdk-node/provisioning/tools
    npm install
    
  2. Создайте корневой сертификат, а затем выберете сертификат устройства, выполнив следующий сценарий:

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

    Совет

    Код устройства может содержать только буквы, цифры и символ -.

Эти команды создают корневой сертификат и сертификат устройства.

имя_файла содержимое
mytestrootcert_cert.pem Открытая часть корневого сертификата X.509
mytestrootcert_key.pem Закрытый ключ для корневого сертификата X.509
mytestrootcert_fullchain.pem Вся цепочка ключей для корневого сертификата X.509
mytestrootcert.pfx PFX-файл для корневого сертификата X509.
sampleDevice01_cert.pem Открытая часть сертификата устройства X.509
sampleDevice01_key.pem Закрытый ключ для сертификата устройства X.509
sampleDevice01_fullchain.pem Вся цепочка ключей для сертификата устройства X.509
sampleDevice01.pfx PFX-файл для сертификата X509 устройства.

Запишите место расположения этих файлов. Он понадобится вам позже.

Создание групповой регистрации

  1. Откройте приложение IoT Central и перейдите к разрешениям на панели слева и выберите группы подключений устройств.

  2. Выберите +Создать и создайте группу регистрации с именем MyX509Group с типом аттестации сертификатов (X.509).

  3. Откройте созданную группу регистрации и выберите Управление основным сертификатом.

  4. Выберите параметр "Файл" и отправьте файл корневого сертификата с именем mytestrootcert_cert.pem, который вы создали ранее:

    Certificate Upload

  5. Чтобы завершить проверку, создайте код проверки, скопируйте его, а затем используйте его для создания сертификата проверки X.509 в командной строке:

    node create_test_cert.js verification --ca mytestrootcert_cert.pem --key mytestrootcert_key.pem --nonce  {verification-code}
    
  6. Щелкните Проверить, чтобы отправить подписанный сертификат проверки verification_cert.pem для завершения проверки:

    Verified Certificate

Теперь вы можете подключать устройства с сертификатом X.509, производным от этого основного корневого сертификата.

После сохранения группы регистрации запишите область идентификаторов.

Запуск примера кода устройства

Если вы работаете в среде Windows, сертификаты X.509 нужно разместить в хранилище сертификатов Windows для правильной работы этого примера. В обозревателе Windows дважды щелкните все PFX-файлы, созданные ранее, mytestrootcert.pfx и sampleDevice01.pfx. В мастере импорта сертификатов выберите текущего пользователя в качестве расположения хранилища, введите 1234 пароль и позвольте мастеру автоматически выбрать хранилище сертификатов. Мастер импортирует сертификаты в личное хранилище текущего пользователя.

Чтобы изменить пример кода для использования сертификатов X.509, выполните следующие действия.

  1. В решении Visual Studio IoTHubDeviceSamples откройте файл Parameter.cs в проекте TemperatureController.

  2. Добавьте в класс следующие два определения параметров:

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

    Сохраните изменения.

  3. В решении Visual Studio IoTHubDeviceSamples откройте файл Program.cs в проекте TemperatureController.

  4. Добавьте следующие операторы using :

    using System.Security.Cryptography.X509Certificates;
    using System.IO;
    
  5. Добавьте в класс следующий метод:

    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. В методе SetupDeviceClientAsync замените блок кода case "dps" следующим кодом:

    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. Замените метод ProvisionDeviceAsync следующим кодом:

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

    Сохраните изменения.

Для выполнения образца:

  1. Добавьте в проект следующие переменные среды:

    • IOTHUB_DEVICE_X509_CERT: <full path to folder that contains PFX files>sampleDevice01.pfx
    • IOTHUB_DEVICE_X509_PASSWORD: 1234.
  2. Создайте и запустите приложение. Убедитесь, что устройство успешно подготавливается к работе.

Чтобы изменить пример кода для использования сертификатов X.509, выполните следующие действия.

  1. Перейдите в папку azure-iot-sdk-java/device/iot-device-samples/pnp-device-sample/temperature-controller-device-sample, где находятся файл pom.xml и папка src для примера устройства контроллера температуры.

  2. Измените файл pom.xml, чтобы добавить следующую конфигурацию зависимостей в узел <dependencies>:

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

    Сохраните изменения.

  3. Откройте файл src/main/java/samples/com/microsoft/azure/sdk/iot/device/TemperatureController.java в текстовом редакторе.

  4. Замените инструкцию импорта SecurityProviderSymmetricKey следующими инструкциями:

    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. Добавьте следующую инструкцию import:

    import java.nio.file.*;
    
  6. Добавьте SecurityProviderException в список исключений, которые создает метод main:

    public static void main(String[] args) throws IOException, URISyntaxException, ProvisioningDeviceClientException, InterruptedException, SecurityProviderException {
    
  7. Замените метод initializeAndProvisionDevice следующим кодом:

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

    Сохраните изменения.

Для выполнения образца:

  1. В среде оболочки задайте следующие две переменные среды. Обязательно предоставьте полный путь к PEM-файлам и используйте правильный разделитель пути для используемой операционной системы:

    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
    

    Совет

    Другие необходимые переменные среды задаются при выполнении руководства Создание и подключение клиентского приложения к приложению Azure IoT Central.

  2. Создайте и запустите приложение. Убедитесь, что устройство успешно подготавливается к работе.

Чтобы изменить пример кода для использования сертификатов X.509, выполните следующие действия.

  1. Перейдите в папку azure-iot-sdk-node/device/samples/javascript , содержащую приложение pnp_temperature_controller.js , и выполните следующую команду, чтобы установить пакет X.509:

    npm install azure-iot-security-x509 --save
    
  2. Откройте файлpnp_temperature_controller.js в текстовом редакторе.

  3. Измените инструкции require, включив в них следующий код:

    const fs = require('fs');
    const X509Security = require('azure-iot-security-x509').X509Security;
    
  4. Добавьте следующие четыре строки в раздел "Сведения о подключении DPS", чтобы инициализировать переменную deviceCert:

    const deviceCert = {
      cert: fs.readFileSync(process.env.IOTHUB_DEVICE_X509_CERT).toString(),
      key: fs.readFileSync(process.env.IOTHUB_DEVICE_X509_KEY).toString()
    };
    
  5. Измените функцию provisionDevice, которая создает клиент, заменив первую строку следующим кодом:

    var provSecurityClient = new X509Security(registrationId, deviceCert);
    
  6. В той же функции измените строку, которая задает переменную deviceConnectionString, следующим образом:

    deviceConnectionString = 'HostName=' + result.assignedHub + ';DeviceId=' + result.deviceId + ';x509=true';
    
  7. В функции main добавьте следующую строку после строки, которая вызывает Client.fromConnectionString:

    client.setOptions(deviceCert);
    

    Сохраните изменения.

Для выполнения образца:

  1. В среде оболочки задайте следующие две переменные среды. Обязательно предоставьте полный путь к PEM-файлам и используйте правильный разделитель пути для используемой операционной системы:

    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
    

    Совет

    Другие необходимые переменные среды задаются при выполнении руководства Создание и подключение клиентского приложения к приложению Azure IoT Central.

  2. Выполните этот скрипт и проверьте, успешно ли подготовлено устройство:

    node pnp_temperature_controller.js
    

Чтобы изменить пример кода для использования сертификатов X.509, выполните следующие действия.

  1. Перейдите в папку azure-iot-device/samples/pnp и откройте файл temp_controller_with_thermostats.py в текстовом редакторе.

  2. Добавьте следующую инструкцию from, чтобы импортировать функциональные возможности X.509:

    from azure.iot.device import X509
    
  3. Измените первую часть функции provision_device следующим образом:

    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. В функции main замените строку, в которой задана переменная symmetric_key, следующим кодом:

    x509 = X509(
        cert_file=os.getenv("IOTHUB_DEVICE_X509_CERT"),
        key_file=os.getenv("IOTHUB_DEVICE_X509_KEY"),
    )
    
  5. В функции main замените вызов функции provision_device следующим кодом:

    registration_result = await provision_device(
        provisioning_host, id_scope, registration_id, x509, model_id
    )
    
  6. В функции main замените вызов функции IoTHubDeviceClient.create_from_symmetric_key следующим кодом:

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

    Сохраните изменения.

Для выполнения образца:

  1. В среде оболочки задайте следующие две переменные среды. Обязательно предоставьте полный путь к PEM-файлам и используйте правильный разделитель пути для используемой операционной системы:

    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
    

    Совет

    Другие необходимые переменные среды задаются при выполнении руководства Создание и подключение клиентского приложения к приложению Azure IoT Central.

  2. Выполните этот скрипт и проверьте, успешно ли подготовлено устройство:

    python temp_controller_with_thermostats.py
    

Убедитесь, что телеметрия успешно отображается в представлении устройств в приложении IoT Central:

Screenshot that shows telemetry arriving in your IoT Central application.

Использование индивидуальной регистрации

Используйте сертификаты X.509 с отдельной регистрацией для тестирования устройства и решения. В отдельной регистрации в приложении IoT Central отсутствует корневой или промежуточный сертификат X.509. Устройства используют самозаверяющий сертификат X.509 для подключения к приложению.

Создание самозаверяющего сертификата устройства

В этом разделе используется самозаверяющий сертификат X.509, чтобы подключать устройства для отдельной регистрации, которая используется для регистрации одного устройства. Самозаверяющие сертификаты используются только для тестирования.

Предупреждение

Такой способ создания сертификатов X.509 предназначен только для тестирования. Для рабочей среды следует использовать официальный, безопасный механизм создания сертификатов.

Создайте самозаверяющий сертификат устройства X.509, выполнив следующие команды:

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

Совет

Код устройства может содержать только буквы, цифры и символ -.

Эти команды создают следующие сертификаты устройств:

имя_файла содержимое
mytestselfcertprimary_cert.pem Общедоступная часть сертификата X509 основного устройства
mytestselfcertprimary_key.pem Закрытый ключ для сертификата X509 первичного устройства
mytestselfcertprimary_fullchain.pem Вся цепочка ключей для основного сертификата X509 устройства.
mytestselfcertprimary.pfx PFX-файл для основного сертификата X509 устройства.
mytestselfcertsecondary_cert.pem Общедоступная часть сертификата X509 вторичного устройства
mytestselfcertsecondary_key.pem Закрытый ключ для сертификата X509 вторичного устройства
mytestselfcertsecondary_fullchain.pem Вся цепочка ключей для дополнительного сертификата X509 устройства.
mytestselfcertsecondary.pfx PFX-файл для дополнительного сертификата X509 устройства.

Создание отдельной регистрации

  1. В приложении IoT Central Azure выберите Устройстваи создайте новое устройство с идентификатором устройстваmytestselfcertprimary из шаблона устройства термостата. Запишите значение области идентификатора, оно вам потребуется позже.

  2. Откройте созданное устройство и нажмите кнопку Подключить.

  3. Выберите Отдельная регистрация в качестве метода подключения и Сертификаты (X.509) в качестве механизма:

    Individual enrollment

  4. Выберите параметр "Файл" в разделе основного сертификата и отправьте файл сертификата с именем mytestselfcertprimary_cert.pem, который был создан ранее.

  5. Выберите параметр файла для дополнительного сертификата и отправьте файл сертификата с именем mytestselfcertsecondary_cert.pem. Затем нажмите кнопку "Сохранить":

    Individual enrollment Certificate Upload

Теперь устройство подготовлено с помощью сертификата X.509.

Запуск примера устройства с отдельной регистрацией

Если вы работаете в среде Windows, сертификаты X.509 нужно разместить в хранилище сертификатов Windows для правильной работы этого примера. В обозревателе Windows дважды щелкните все PFX-файлы, созданные ранее, mytestselfcertprimary.pfx и mytestselfcertsecondary.pfx. В мастере импорта сертификатов выберите текущего пользователя в качестве расположения хранилища, введите 1234 пароль и позвольте мастеру автоматически выбрать хранилище сертификатов. Мастер импортирует сертификаты в личное хранилище текущего пользователя.

Чтобы изменить пример кода для использования сертификатов X.509, выполните следующие действия.

  1. В решении Visual Studio IoTHubDeviceSamples откройте файл Parameter.cs в проекте TemperatureController.

  2. Добавьте в класс следующие два определения параметров:

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

    Сохраните изменения.

  3. В решении Visual Studio IoTHubDeviceSamples откройте файл Program.cs в проекте TemperatureController.

  4. Добавьте следующие операторы using :

    using System.Security.Cryptography.X509Certificates;
    using System.IO;
    
  5. Добавьте в класс следующий метод:

    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. В методе SetupDeviceClientAsync замените блок кода case "dps" следующим кодом:

    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. Замените метод ProvisionDeviceAsync следующим кодом:

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

    Сохраните изменения.

Для выполнения образца:

  1. Добавьте в проект следующие переменные среды:

    • 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. Создайте и запустите приложение. Убедитесь, что устройство успешно подготавливается к работе.

Чтобы изменить пример кода для использования сертификатов X.509, выполните следующие действия.

  1. Перейдите в папку azure-iot-sdk-java/device/iot-device-samples/pnp-device-sample/temperature-controller-device-sample, где находятся файл pom.xml и папка src для примера устройства контроллера температуры.

  2. Измените файл pom.xml, чтобы добавить следующую конфигурацию зависимостей в узел <dependencies>:

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

    Сохраните изменения.

  3. Откройте файл src/main/java/samples/com/microsoft/azure/sdk/iot/device/TemperatureController.java в текстовом редакторе.

  4. Замените инструкцию импорта SecurityProviderSymmetricKey следующими инструкциями:

    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. Добавьте следующую инструкцию import:

    import java.nio.file.*;
    
  6. Добавьте SecurityProviderException в список исключений, которые создает метод main:

    public static void main(String[] args) throws IOException, URISyntaxException, ProvisioningDeviceClientException, InterruptedException, SecurityProviderException {
    
  7. Замените метод initializeAndProvisionDevice следующим кодом:

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

    Сохраните изменения.

Для выполнения образца:

  1. В среде оболочки задайте следующие две переменные среды. Обязательно предоставьте полный путь к PEM-файлам и используйте правильный разделитель пути для используемой операционной системы:

    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
    

    Совет

    Другие необходимые переменные среды задаются при выполнении руководства Создание и подключение клиентского приложения к приложению Azure IoT Central.

  2. Создайте и запустите приложение. Убедитесь, что устройство успешно подготавливается к работе.

Вы можете также повторить описанные выше действия для сертификата mytestselfcertsecondary.

Чтобы изменить пример кода для использования сертификатов X.509, выполните следующие действия.

  1. Перейдите в папку azure-iot-sdk-node/device/samples/javascript , содержащую приложение pnp_temperature_controller.js , и выполните следующую команду, чтобы установить пакет X.509:

    npm install azure-iot-security-x509 --save
    
  2. Откройте файлpnp_temperature_controller.js в текстовом редакторе.

  3. Измените инструкции require, включив в них следующий код:

    const fs = require('fs');
    const X509Security = require('azure-iot-security-x509').X509Security;
    
  4. Добавьте следующие четыре строки в раздел "Сведения о подключении DPS", чтобы инициализировать переменную deviceCert:

    const deviceCert = {
      cert: fs.readFileSync(process.env.IOTHUB_DEVICE_X509_CERT).toString(),
      key: fs.readFileSync(process.env.IOTHUB_DEVICE_X509_KEY).toString()
    };
    
  5. Измените функцию provisionDevice, которая создает клиент, заменив первую строку следующим кодом:

    var provSecurityClient = new X509Security(registrationId, deviceCert);
    
  6. В той же функции измените строку, которая задает переменную deviceConnectionString, следующим образом:

    deviceConnectionString = 'HostName=' + result.assignedHub + ';DeviceId=' + result.deviceId + ';x509=true';
    
  7. В функции main добавьте следующую строку после строки, которая вызывает Client.fromConnectionString:

    client.setOptions(deviceCert);
    

    Сохраните изменения.

Для выполнения образца:

  1. В среде оболочки задайте следующие две переменные среды. Обязательно предоставьте полный путь к PEM-файлам и используйте правильный разделитель пути для используемой операционной системы:

    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
    

    Совет

    Другие необходимые переменные среды задаются при выполнении руководства Создание и подключение клиентского приложения к приложению Azure IoT Central.

  2. Выполните этот скрипт и проверьте, успешно ли подготовлено устройство:

    node pnp_temperature_controller.js
    

Вы можете также повторить описанные выше действия для сертификата mytestselfcertsecondary.

Чтобы изменить пример кода для использования сертификатов X.509, выполните следующие действия.

  1. Перейдите в папку azure-iot-device/samples/pnp и откройте файл temp_controller_with_thermostats.py в текстовом редакторе.

  2. Добавьте следующую инструкцию from, чтобы импортировать функциональные возможности X.509:

    from azure.iot.device import X509
    
  3. Измените первую часть функции provision_device следующим образом:

    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. В функции main замените строку, в которой задана переменная symmetric_key, следующим кодом:

    x509 = X509(
        cert_file=os.getenv("IOTHUB_DEVICE_X509_CERT"),
        key_file=os.getenv("IOTHUB_DEVICE_X509_KEY"),
    )
    
  5. В функции main замените вызов функции provision_device следующим кодом:

    registration_result = await provision_device(
        provisioning_host, id_scope, registration_id, x509, model_id
    )
    
  6. В функции main замените вызов функции IoTHubDeviceClient.create_from_symmetric_key следующим кодом:

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

    Сохраните изменения.

Для выполнения образца:

  1. В среде оболочки задайте следующие две переменные среды. Обязательно предоставьте полный путь к PEM-файлам и используйте правильный разделитель пути для используемой операционной системы:

    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
    

    Совет

    Другие необходимые переменные среды задаются при выполнении руководства Создание и подключение клиентского приложения к приложению Azure IoT Central.

  2. Выполните этот скрипт и проверьте, успешно ли подготовлено устройство:

    python temp_controller_with_thermostats.py
    

Вы можете также повторить описанные выше действия для сертификата mytestselfcertsecondary.

Подключение устройства IoT Edge

В этом разделе предполагается, что вы используете групповую регистрацию для подключения устройства IoT Edge. Примените шаги из предыдущего раздела, чтобы выполнить следующие действия.

Чтобы подключить устройство IoT Edge к IoT Central с помощью сертификата X.509, сделайте следующее:

  • Скопируйте файлы сертификата устройства и ключа на устройство IoT Edge. В предыдущем примере групповой регистрации эти файлы назывались sampleDevice01_key.pem и sampleDevice01_cert.pem.

  • На устройстве IoT Edge измените раздел provisioning в файле конфигурации /etc/iotedge/config.yaml следующим образом:

    # 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
    

    Совет

    Вам не нужно добавлять значение для registration_id. IoT Edge может взять значение CN из сертификата X.509.

  • Выполните следующую команду, чтобы перезапустить среду выполнения IoT Edge:

    sudo systemctl restart iotedge
    

Дополнительные сведения см. в статье "Создание и подготовка IoT Edge устройств в большом масштабе в Linux с помощью сертификатов X.509".

Подключение подчиненное устройство для IoT Edge

IoT Edge использует сертификаты X.509 для защиты подключения между подчиненными устройствами и устройством IoT Edge, выполняющим роль прозрачного шлюза. Дополнительные сведения о настройке этого сценария см. в статье Подключение подчиненного устройства к шлюзу Azure IoT Edge.

Развертывание сертификатов устройств X.509

На протяжении всего жизненного цикла приложения IoT Central вам придется регулярно развертывать сертификаты X.509. Например:

  • Если у вас есть брешь в безопасности, скользящие сертификаты — лучший способ защитить вашу систему.
  • У сертификатов X.509 ограничен срок действия. Частота, с которой вы развертываете сертификаты, зависит от требований безопасности вашего решения. Клиенты с решениями, содержащими конфиденциальные данные, могут развертывать сертификаты ежедневно, а остальные — каждые два года.

Чтобы всегда сохранять возможность подключения, IoT Central позволяет вам настроить первичный и вторичный сертификаты X.509. Если у первичного и вторичного сертификатов будут разные даты окончания срока действия, вы сможете обновлять сертификат с истекшим сроком действия, не мешая устройствам подключаться с другим сертификатом.

Дополнительные сведения см. в разделе Метод предполагаемого нарушения.

В этом разделе описано, как развертывать сертификаты в IoT Central. При развертывании сертификата в IoT Central следует также скопировать новый сертификат устройства на все устройства.

Получение новых сертификатов X.509

Получите новые сертификаты X.509 у своего поставщика сертификатов. Вы можете создавать собственные сертификаты X.509 с помощью такого средства, как OpenSSL. Этот способ отлично подходит для тестирования сертификатов X.509, но предоставляет слабые гарантии безопасности. Используйте этот подход только для тестирования, если вы не готовы использовать собственный центр сертификации.

Группы регистрации и бреши в системе безопасности

Чтобы обновить групповую регистрацию для устранения бреши в безопасности, вы должны использовать описанный ниже подход, который позволяет немедленно обновить текущий сертификат. Выполните эти шаги для первичного и вторичного сертификатов, если они оба скомпрометированы:

  1. Перейдите к разрешениям на панели слева и выберите группы подключений устройств.

  2. Выберите имя группы в списке в разделе "Группы регистрации".

  3. Для обновления сертификата выберите Управление основным или Управление дополнительным.

  4. Добавьте и проверьте корневой сертификат X.509 в группе регистрации.

Индивидуальные регистрации и бреши в системе безопасности

Если вы обновляете сертификаты в ответ на нарушение безопасности, используйте следующий подход для немедленного обновления текущего сертификата. Выполните эти шаги для первичного и вторичного сертификатов, если они оба скомпрометированы:

  1. Выберите Устройства и выберите устройство.

  2. Выберите Подключиться и выберите метод подключения как Индивидуальная регистрация

  3. В качестве механизма выберите Сертификаты (X.509) .

  4. Для обновления сертификата щелкните значок папки, чтобы выбрать новый сертификат, который будет загружен для записи о регистрации. Щелкните Сохранить.

Группы регистрации и истечение срока действия сертификата

В случае истечения срока действия сертификата используйте следующий подход для немедленного обновления текущего сертификата.

  1. Перейдите к разрешениям на панели слева и выберите группы подключений устройств.

  2. Выберите имя группы в списке в разделе "Группы регистрации".

  3. Для обновления сертификата выберите Управление основным.

  4. Добавьте и проверьте корневой сертификат X.509 в группе регистрации.

  5. Позже, когда срок действия вторичного сертификата истечет, вернитесь и обновите этот вторичный сертификат.

Индивидуальные регистрации и истечение срока действия сертификата

Если вы развертываете сертификаты из-за истечения срока действия предыдущих, используйте конфигурацию вторичного сертификата следующим образом, чтобы сократить время простоя для устройств, пытающихся выполнить подготовку.

Когда срок действия вторичного сертификата приближается к истечению и его необходимо обновить, вы можете использовать первичную конфигурацию. Таким образом, переключение между первичным и вторичным сертификатами сокращает время простоя для устройств, пытающихся выполнить подготовку.

  1. Выберите Устройства и выберите устройство.

  2. Выберите Подключиться и выберите метод подключения как Индивидуальная регистрация

  3. В качестве механизма выберите Сертификаты (X.509) .

  4. Для обновления вторичного сертификата щелкните значок папки, чтобы выбрать новый сертификат, который будет загружен для записи о регистрации. Щелкните Сохранить.

  5. Позже, когда истечет срок действия первичного сертификата, повторите этот процесс для обновления первичного сертификата.

Следующие шаги

Теперь, когда вы узнали, как подключать устройства с помощью сертификатов X.509, рекомендуется узнать, как отслеживать подключение устройств с помощью Azure CLI.