简体   繁体   English

其他设备的 Azure IoT 中心未经授权的访问

[英]Azure IoT Hub Unauthorized Access for Additional Devices

I have an issue attempting to register a second device through DPS to an IoT Hub using x509 certificates.我在尝试使用 x509 证书通过 DPS 将第二个设备注册到 IoT 中心时遇到问题。 My root certificate authority is present and validated on both the DPS and IoT Hub (generated through openssl).我的根证书颁发机构在 DPS 和 IoT 中心(通过 openssl 生成)上都存在并经过验证。 As for the client side certificate, I'm generating it once the application starts (if to doesn't already exist) in the below code.至于客户端证书,一旦应用程序启动(如果不存在),我就会在下面的代码中生成它。 What's bothering me is every single device gets enrolled into Azure DPS correctly but only the FIRST device gets authorized and registered.困扰我的是每台设备都正确注册到 Azure DPS,但只有第一个设备获得授权和注册。 Is it possibly something I'm doing during my client side certificate creation that is messing it up?这可能是我在创建客户端证书期间正在做的事情弄乱了它吗? Also the error is found in this line during device registration to the IoT Hub:此外,在设备注册到 IoT 中心期间,在此行中发现错误:

DeviceRegistrationResult result = await provisioningDeviceClient.RegisterAsync().ConfigureAwait(false);

Added error:添加错误:

2019/12/16 09:37:38.309|ERROR| 2019/12/16 09:37:38.309|错误| Error found attempting to start service The device failed to register @ the IoT Hub : The device failes to provision correctly: AMQP transport exception |尝试启动服务时发现错误设备无法注册@IoT 中心:设备无法正确配置:AMQP 传输异常 | Tidel.DeviceAgent.DeviceAgent | Tidel.DeviceAgent.DeviceAgent |

CLIENT SIDE CERTIFICATE GENERATION客户端证书生成

        X509Certificate2 caRootCertificate;
        X509Store caStore = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
        caStore.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);

        X509Certificate2Collection signerCollection = (X509Certificate2Collection)caStore.Certificates.Find(X509FindType.FindByIssuerName, "CERTNAME", true);

        caStore.Close();

        if (signerCollection.Count != 0)
        {
            caRootCertificate = signerCollection[0];

            using (var rsa = RSA.Create())
            {
                rsa.KeySize = 2048;

                var clientCertificateRequest = new CertificateRequest($"CN={_writableOptions.Value.RegistrationId}", rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);

                clientCertificateRequest.CertificateExtensions.Add(new X509BasicConstraintsExtension(false, false, 0, false));

                var issuerSubjectKey = caRootCertificate.Extensions["Subject Key Identifier"].RawData;
                var segment = new ArraySegment<byte>(issuerSubjectKey, 2, issuerSubjectKey.Length - 2);
                var authorityKeyIdentifier = new byte[segment.Count + 4];

                authorityKeyIdentifier[0] = 0x30;
                authorityKeyIdentifier[1] = 0x16;
                authorityKeyIdentifier[2] = 0x80;
                authorityKeyIdentifier[3] = 0x14; 
                segment.CopyTo(authorityKeyIdentifier, 4);
                clientCertificateRequest.CertificateExtensions.Add(new X509Extension("2.5.29.35", authorityKeyIdentifier, false));


                var sanBuilder = new SubjectAlternativeNameBuilder();
                sanBuilder.AddDnsName(_writableOptions.Value.RegistrationId);
                var sanExtension = sanBuilder.Build();
                clientCertificateRequest.CertificateExtensions.Add(sanExtension);

                clientCertificateRequest.CertificateExtensions.Add(new X509EnhancedKeyUsageExtension(new OidCollection { new Oid("1.3.6.1.5.5.7.3.2") }, false));
                clientCertificateRequest.CertificateExtensions.Add(new X509SubjectKeyIdentifierExtension(clientCertificateRequest.PublicKey, false));

                var notBefore = DateTimeOffset.UtcNow.AddDays(-1);

                if (notBefore < caRootCertificate.NotBefore)
                {
                    notBefore = new DateTimeOffset(caRootCertificate.NotBefore);
                }

                var notAfter = DateTimeOffset.UtcNow.AddDays(365);

                if (notAfter > caRootCertificate.NotAfter)
                {
                    notAfter = new DateTimeOffset(caRootCertificate.NotAfter);
                }

                var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
                var unixTime = Convert.ToInt64((DateTime.UtcNow - epoch).TotalSeconds);
                var serial = BitConverter.GetBytes(unixTime);

                using (var cert = clientCertificateRequest.Create(caRootCertificate, notBefore, notAfter, serial))
                {
                    X509Certificate2 client = cert.CopyWithPrivateKey(rsa);

                    return await Task.FromResult(client);
                }
            }
        }
        else
        {
            throw new FileNotFoundException($"Could not find a root certificate.");
        }

DEVICE ENROLLMENT TO DPS设备注册到 DPS

    Attestation attestation = X509Attestation.CreateFromClientCertificates(new X509Certificate2(certificate.Export(X509ContentType.Cert)));

    IndividualEnrollment individualEnrollment = new IndividualEnrollment(_writableOptions.Value.RegistrationId, attestation)
    {
        DeviceId = _writableOptions.Value.DeviceId,
        ProvisioningStatus = ProvisioningStatus.Enabled
    };

    individualEnrollmentResult = await _provisioningServiceClient.CreateOrUpdateIndividualEnrollmentAsync(individualEnrollment).ConfigureAwait(false);

DEVICE REGISTRATION TO IOT HUB设备注册到 IOT HUB

using (var certificatePassword = new X509Certificate2(certificate.GetRawCertData(), _writableOptions.Value.CertPass))
{
    using (var security = new SecurityProviderX509Certificate(certificatePassword))
    {
        using (var transport = new ProvisioningTransportHandlerAmqp(TransportFallbackType.TcpOnly))
        {
            ProvisioningDeviceClient provisioningDeviceClient = ProvisioningDeviceClient.Create(_writableOptions.Value.AzureEndpoint, _writableOptions.Value.IdScope, security, transport);
            DeviceRegistrationResult result = await provisioningDeviceClient.RegisterAsync().ConfigureAwait(false);
            IAuthenticationMethod authenticationMethod = new DeviceAuthenticationWithX509Certificate(result.DeviceId, certificate);
            DeviceClient deviceClient = DeviceClient.Create(result.AssignedHub, authenticationMethod, TransportType.Amqp_Tcp_Only);

            return await Task.FromResult(deviceClient);
       }
     }
}

I figured out the issue.我想通了这个问题。 When the certificate was generated in the store, I was using FindByIssuerName to locate the certificate.在商店中生成证书时,我使用 FindByIssuerName 来定位证书。

X509Certificate2Collection signerCollection = (X509Certificate2Collection)caStore.Certificates.Find(X509FindType.FindByIssuerName, "CERTNAME", true);

After investigating further, there were TWO certificates with the exact same name in the store.进一步调查后,商店里有两个名称完全相同的证书。 The issue: MMC snap-in was only showing one certificate.问题:MMC 管理单元只显示一个证书。 After looking around, it was suggested somewhere to run a storerepair command on the store.环顾四周后,建议在某处对商店运行 storerepair 命令。 After running the store repair command, I could then see both certificates in MMC and was able to remove the offending certificate preventing the valid one from being detected.运行 store repair 命令后,我可以在 MMC 中看到两个证书,并且能够删除有问题的证书,从而阻止检测到有效证书。

Windows Version: Windows Embedded 8.1 Industry Pro Windows 版本:Windows Embedded 8.1 Industry Pro

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM