'Create a self-signed certificate in Java for AWS IoT

I have a root CA certificate along with its private key (CAcert.pem and CApvtkey.key).

The root CA certificate has been registered on the AWS IoT core. This will be used to self-sign and validate other certificates for authentication.

I am trying to create certificates signed by my root CA certificate using Java, but not much luck.

The AWS IoT Java SDK provides functions to generate certificates, and to register/activate them on AWS, but I can't figure out how to sign them with my root CA certificate and activate them.

What I have is this only :

  //Previous code sets up thing name etc...

  CreateThingResult resp1 = client.createThing(thingRequest);

  CreateKeysAndCertificateRequest req = new CreateKeysAndCertificateRequest();
  req.setSetAsActive(true);
  CreateKeysAndCertificateResult resp2 = client.createKeysAndCertificate(req);

  client.attachThingPrincipal(new AttachThingPrincipalRequest().
            withPrincipal(resp2.getCertificateArn()).withThingName("Java-App_Thing"));

Would anybody have an idea how I can create my certificates which will be signed by my CA certificate?



Solution 1:[1]

So the documentation is pretty vague on AWS. I had the same issue. Here is how I fixed it. Assuming you registered your CA with AWS IoT, even if you enable auto registration for the CA you uploaded, AWS IoT will not allow devices to connect. The Certs will have a couple of options for JiT(Just in Time) registration.

  1. Create Lamba to activate devices with certain conditions;
  2. List to Event on MQTT to activate the cert;
  3. Register the Public key.

Options 1 and 2 are described in AWS Docs https://docs.aws.amazon.com/iot/latest/developerguide/auto-register-device-cert.html

Steps to do option 3:

  1. Register the Thing
software.amazon.awssdk.services.iot.IotClient iotClient = IotClient.create()
//This allows AWS Credentials to be picked up using DefaultAWSCredentialsProviderChain
CreateThingRequest thingToBeCreated =
CreateThingRequest.builder().thingName("Unique Id of Device").build();
iotClient.createThing(thingToBeCreated);
  1. Register and activate the Public Key of the device.
RegisterCertificateRequest registerCertificateRequest = RegisterCertificateRequest.builder()
.caCertificatePem("CA Pem as String")
.certificatePem("Device Public Key in Pem as String")
.setAsActive(true)
.build();
final RegisterCertificateResponse registerCertificateResponse = iotClient.registerCertificate(registerCertificateRequest);

  1. Attach the Cert to the thing.
AttachThingPrincipalRequest attachThingPrincipalRequest = AttachThingPrincipalRequest.builder()
.thingName("Unique Id of Device")
.principal(registerCertificateResponse.certificateArn())
.build();
iotClient.attachThingPrincipal(attachThingPrincipalRequest);
  1. Optional, attach policies to the thing so it can connect.
AttachPolicyRequest attachPolicyRequest = AttachPolicyRequest.builder()
.policyName("policy_that_allow_device_connections")
.target(registerCertificateResponse.certificateArn())
.build();
iotClient.attachPolicy(attachPolicyRequest);

Solution 2:[2]

Thanks!!! above steps are working for me and code requires below dependency,

<dependency>
    <groupId>software.amazon.awssdk</groupId>
    <artifactId>iot</artifactId>
    <version>2.17.121</version>
</dependency>

Also here I used another library for the same process. Steps are,

  1. Register the RootCA with Verification certificate in AWS IoT core
  2. Create the thing and attach device certificate and policy to connect programatically

So now in detail:

  1. Register the RootCA with Verification certificate in AWS IoT core

    Follow the link https://docs.aws.amazon.com/iot/latest/developerguide/register-CA-cert.html

  2. Create the thing and attach device certificate and policy to connect programatically

Below steps needed to do the process programatically,

Dependencies needed:

<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-iot-device-sdk-java</artifactId>
    <version>1.3.9</version>
</dependency>

<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-java-sdk-core</artifactId>
    <version>1.12.150</version>
</dependency>

<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-java-sdk-iot</artifactId>
    <version>1.12.150</version>
</dependency>

Aws config class:

public class AwsConfig {

    @Bean
    public AWSIot getIotClient() {
        return AWSIotClientBuilder.standard()
                .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials("users_aws_access_key", "users_aws_secret_key")))
                .withRegion("users_aws_region").build();
    }   
}

Service class:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.amazonaws.services.iot.model.AttachPolicyRequest;
import com.amazonaws.services.iot.model.AttachPolicyResult;
import com.amazonaws.services.iot.model.AttachThingPrincipalRequest;
import com.amazonaws.services.iot.model.AttachThingPrincipalResult;
import com.amazonaws.services.iot.model.CertificateStatus;
import com.amazonaws.services.iot.model.CreateThingRequest;
import com.amazonaws.services.iot.model.CreateThingResult;
import com.amazonaws.services.iot.model.DescribeThingRequest;
import com.amazonaws.services.iot.model.DescribeThingResult;
import com.amazonaws.services.iot.model.RegisterCertificateRequest;
import com.amazonaws.services.iot.model.RegisterCertificateResult;
import com.amazonaws.services.iot.model.ResourceNotFoundException;

@Service
public class RegisterService {

    @Autowired
    private AwsConfig iotClient;

    public String RegisterDevice() {

        // check if thing Already exists
        if (!describeThing("Unique Id of Device")) {

            // Thing Creation
            CreateThingResult response = iotClient.getIotClient()
                    .createThing(new CreateThingRequest().withThingName("Unique Id of Device/Thing"));

            // Register and activate the Public Key of the device
            RegisterCertificateResult registerCert = iotClient.getIotClient()
                    .registerCertificate(new RegisterCertificateRequest().withCaCertificatePem("CA Pem as String")
                            .withCertificatePem("Device Public Key in Pem as String").withStatus(CertificateStatus.ACTIVE));

            // Attach the Cert to the thing
            AttachThingPrincipalResult attachThingPrincipalResult = iotClient.getIotClient().attachThingPrincipal(
                    new AttachThingPrincipalRequest()
                        .withThingName("Unique Id of Device/Thing").withPrincipal(registerCert.getCertificateArn()));

            // Attach policies to the thing so it can connect
            AttachPolicyResult policyResult = iotClient.getIotClient()
                    .attachPolicy(new AttachPolicyRequest()
                        .withPolicyName("policy_that_allow_device_connections").withTarget(registerCert.getCertificateArn()));

            return "Thing Created Successfully";
        }   
        
        // Thing exists
        return "Thing Already Exists on IoT Console";
    }

    private boolean describeThing(String thingName) {
        if (thingName == null) {
            return false;
        }
        try {
            describeThingResponse(thingName);
            return true;
        } catch (ResourceNotFoundException e) {
            // e.printStackTrace();
            return false;
        }
    }

    private DescribeThingResult describeThingResponse(String thingName) {
        DescribeThingRequest describeThingRequest = new DescribeThingRequest();
        describeThingRequest.setThingName(thingName);
        return iotClient.getIotClient().describeThing(describeThingRequest);
    }
    
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Dalton Cézane
Solution 2