Как с помощью сертификатов 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
    

    Совет

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

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

filename Содержимое
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). Группы регистрации можно создавать для устройств Интернета вещей или устройств IoT Edge.

  3. В созданной группе регистрации выберите "Управление основным".

  4. На панели "Основной сертификат" выберите "Добавить сертификат".

  5. Отправьте файл корневого сертификата с именем mytestrootcert_cert.pem , созданный ранее.

  6. Если вы используете промежуточный или корневой центр сертификации, которому вы доверяете и знаете, что у вас есть полное владение сертификатом, вы можете самостоятельно проверить, что сертификат проверен, задав состояние сертификата, проверенное при отправке в On. В противном случае задайте состояние сертификата, проверенное при отправке в Off.

  7. Если вы устанавливаете состояние сертификата, проверенное при отправке в off, выберите "Создать код проверки".

  8. Скопируйте код проверки, скопируйте его и создайте сертификат проверки X.509. Например, в командной строке:

    node create_test_cert.js verification --ca mytestrootcert_cert.pem --key mytestrootcert_key.pem --nonce  {verification-code}
    
  9. Нажмите кнопку "Проверить", чтобы отправить подписанный сертификат проверки verification_cert.pem, чтобы завершить проверку.

  10. Состояние первичного сертификата теперь проверено:

    Screenshot that shows a verified X509 certificate.

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

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

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

Если вы работаете в среде Windows, сертификаты X.509 нужно разместить в хранилище сертификатов Windows для правильной работы этого примера. В Windows Обозреватель дважды щелкните созданные ранее PFX-файлы и mytestrootcert.pfxsampleDevice01.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 showing telemetry from a device that connected using X.509.

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

Используйте сертификаты 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 

Совет

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

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

filename Содержимое
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) в качестве метода проверки подлинности.

  4. Отправьте файл mytestselfcertprimary_cert.pem, созданный ранее в качестве первичного сертификата.

  5. Отправьте файл mytestselfcertsecondary_cert.pem, созданный ранее в качестве дополнительного сертификата. Затем выберите Сохранить.

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

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

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

Если вы работаете в среде Windows, сертификаты X.509 нужно разместить в хранилище сертификатов Windows для правильной работы этого примера. В Windows Обозреватель дважды щелкните созданные ранее PFX-файлы и mytestselfcertprimary.pfxmytestselfcertsecondary.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/aziot/config.toml следующим образом:

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

    Совет

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

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

    sudo iotedge config apply
    

Дополнительные сведения см. в статье "Создание и подготовка устройств 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. Позже, когда истечет срок действия первичного сертификата, повторите этот процесс для обновления первичного сертификата.