0

I've performed this example

https://learn.microsoft.com/en-us/azure/iot-dps/quick-enroll-device-x509-java

It does not appear under "registration records" under the enrolment group but it throws this error:

PROVISIONING_DEVICE_STATUS_FAILED, Exception: com.microsoft.azure.sdk.iot.provisioning.device.internal.exceptions.ProvisioningDeviceHubException: Signing certificate info did not match chain elements

Registration:

public class DeviceRegistration {
String idScope;
String globalEndpoint;
String clientCert;
String clientCertPrivateKey;
String signerCert;

public DeviceRegistration(String idScope, String globalEndpoint, String clientCert, String clientCertPrivateKey, String signerCert) {
    this.idScope = idScope;
    this.globalEndpoint = globalEndpoint;
    this.clientCert = clientCert;
    this.clientCertPrivateKey = clientCertPrivateKey;
    this.signerCert = signerCert;
}

public void register(ProvisioningDeviceClientRegistrationCallback callback) throws Exception {
    Collection<String> signerCertificates = new LinkedList<>();
    signerCertificates.add(signerCert);
    ProvisioningDeviceClient provisioningDeviceClient = null;

    SecurityProvider securityProviderX509 = new SecurityProviderX509Cert(clientCert, clientCertPrivateKey, signerCertificates);
    provisioningDeviceClient = ProvisioningDeviceClient.create(globalEndpoint, idScope, ProvisioningDeviceClientTransportProtocol.HTTPS,
                                                               securityProviderX509);

    provisioningDeviceClient.registerDevice(callback, this);

}

private static String loadFile(String filename) throws Exception {
    File f = new File(filename);
    if (!f.exists())
        throw new Exception("File not found: " + filename);
    BufferedReader reader = new BufferedReader(new FileReader(f));
    char[] buffer = new char[(int) f.length()];
    reader.read(buffer);
    reader.close();
    return new String(buffer);
}

public static void main(String[] args){
    try {
        CountDownLatch countDownLatch = new CountDownLatch(1);
        DeviceRegistration deviceRegistration = new DeviceRegistration(args[0], args[1], loadFile(args[2]), loadFile(args[3]), loadFile(args[4]));
        deviceRegistration.register(new ProvisioningDeviceClientRegistrationCallback() {
            @Override
            public void run(ProvisioningDeviceClientRegistrationResult provisioningDeviceClientRegistrationResult, Exception e, Object context) {
                if (provisioningDeviceClientRegistrationResult.getProvisioningDeviceClientStatus() == ProvisioningDeviceClientStatus.PROVISIONING_DEVICE_STATUS_ASSIGNED) {
                    System.out.println("IotHUb Uri : " + provisioningDeviceClientRegistrationResult.getIothubUri());
                    System.out.println("Device ID : " + provisioningDeviceClientRegistrationResult.getDeviceId());
                    countDownLatch.countDown();
                } else {
                    System.out.println("Result: "+provisioningDeviceClientRegistrationResult.getProvisioningDeviceClientStatus()+", Exception: "+e);
                }
            }
        });
        countDownLatch.await();
    } catch (Exception e) {
        e.printStackTrace();
    }

}}
muelli
  • 11
  • 4

1 Answers1

0

Delete the individual enrollment and make sure that you've gone through the verification of your X.509 signing cert (in the Certificates tab in the Azure portal). If you have both an enrollment group and an individual enrollment for a device, the individual enrollment takes precedence.

  • Have done this already. Cert is verified and individual enrolment has been deleted. When I run the example again, it is shown under individual enrolment... – muelli Jun 12 '18 at 17:37
  • 1
    Your code is creating an individual enrollment. Is that code for the device you're simulating? Devices should never create enrollments. Here's the sample code for creating an enrollment group: https://github.com/Azure/azure-iot-sdk-java/blob/master/provisioning/provisioning-samples/service-enrollment-group-sample/src/main/java/samples/com/microsoft/azure/sdk/iot/ServiceEnrollmentGroupSample.java – nberdy - MSFT Jun 12 '18 at 23:50
  • I was under the impression (the docs are not very clear about this) that I have 1) create a group 2) enroll the device under that group and 3) register the device (first contact). I have created a group with the example you mentioned above. I assume I can just register. Did that (example from the docs) and nothing happens (timeout). The groups registration recs are empty. – muelli Jun 13 '18 at 06:21
  • Thanks for posting the code! The beauty of groups is that you don't have to enroll the device under the group - you just have to create the group, then every device that has a cert signed by the cert associated with the group will be able to register. Your code is still creating an individual enrollment and not a group like you want. If you already have an enrollment group created (maybe because you created one in the portal), try this: make sure you do not have an individual enrollment, make sure the device cert chains up to the signing cert, then run the simulated device. – nberdy - MSFT Jun 13 '18 at 16:28
  • Also here's the sample device code for Java: https://github.com/Azure/azure-iot-sdk-java/blob/master/provisioning/provisioning-samples/provisioning-X509-sample/src/main/java/samples/com/microsoft/azure/sdk/iot/ProvisioningX509Sample.java – nberdy - MSFT Jun 13 '18 at 16:36
  • Thanks so much for your patience! I've updated the question above to the current status. I'm doing a device enrollment similar to the example (in fact, I've copied that). Problem was that the signer cert was missing. So I've added it to the list (see snippet). Then I'm getting the error you see above (signer cert doesn't match CA cert). It is not clear to me what I need to put into "". Is that the client cert? Or the client cert plus the root cert? The MS docs are quite poor here... Thanks. – muelli Jun 13 '18 at 20:00
  • Well, I've now deleted the group and the certificate under "Certificate" in DPS. Generated a new cert, added it under "Certificates", verified it - OK. Then I've generated another cert for the group with a different CN. Added the group programmatically - OK. So the cert under "Certificates" and the one for the group are now different (differ in their CN). Then I ran the above program with client cert, private key, signer all derived from the group cert and I'm getting: – muelli Jun 13 '18 at 20:35
  • Result: PROVISIONING_DEVICE_STATUS_FAILED, Exception: com.microsoft.azure.sdk.iot.provisioning.device.internal.exceptions.ProvisioningDeviceHubException: CA certificate not found – muelli Jun 13 '18 at 20:36
  • Okay, it sounds like we've narrowed down the problem at least. It sounds like you have three certs: the root cert that you uploaded and verified, an intermediate cert generated from the root cert that you put in the enrollment group, and the leaf cert generated from the intermediate cert. So the cert chain for your device's cert should look like (CN=root cert)-->(CN=intermediate cert)-->(CN=device cert). Could you please verify that your certs chain in this way? – nberdy - MSFT Jun 13 '18 at 23:07
  • No. I'm using the DiceEmulator from the MS sample. It creates only these certs: root, client (intermediate), signer. So I uploaded the root into "Certificates" of DPS and used client (intermediate) cert to create the enrolment group. But which cert should the device use? IMO it needs another intermediate signed with the root or a previous intermediate. – muelli Jun 14 '18 at 11:02
  • What I want to achieve is this: Upload/verify the root under "Certificates" of the DPS as the only manual action. The rest should be done automatically. Create one enrollment group and register all my clients as devices under it. Retrieving IoT hub URI and device name and send/receive messages. I wanted to use the DiceEmulator to create the certs behind the scenes. – muelli Jun 14 '18 at 11:05
  • I'm one step further. I have registered the root cert under "Certificates" and verified it - Ok. Then I've manually created an enrollment group but did not use the intermediate but pointed it to the root cert from above. Then I ran the device registration programmatically and it shows up under "Registration Records" of the group. But there is one missing piece in the puzzle: It always uses the group name as the device id. There is no method in the ProvisioningDeviceClient class to set the device id programmatically. Also not in the callback. How can I programmatically set the device id? – muelli Jun 14 '18 at 11:38
  • I'm glad to hear you're further along! When using an enrollment group, DPS always uses the CN of the device's certificate as the device ID. – nberdy - MSFT Jun 14 '18 at 16:15
  • So this would require me to sign a device cert with the root cert of the group. This is not possible with the DiceSimulator. So I can't use group enrollment but must fallback to individual or use openssl which I don't want. – muelli Jun 14 '18 at 16:23
  • Any update on this issue? I too am stuck in this and is not able to add a different device using the same certificate. @AndreasMüller were you able to find a solution? – Alex Dec 28 '18 at 13:49