0

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?

Engineer999
  • 3,683
  • 6
  • 33
  • 71
  • have you considered using other tools, like `openssl`? – Michał Krzywański Apr 19 '19 at 19:19
  • @michalk, I have, and also using bouncycastle, but how to then activate the certificate on the AWS IoT cloud ? – Engineer999 Apr 19 '19 at 19:27
  • As you said you have your CA private key and CA certificate in PEM format, that contains public key of certificate. With those files, you could try to generate a certificate signed with CA cert. [Here](https://gist.github.com/fntlnz/cf14feb5a46b2eda428e000157447309) is an example of doing it with `openssl`. The second step of generating CSR based on CA key and PEM is most important for you. – Michał Krzywański Apr 19 '19 at 19:33
  • @michalk . I have done this already thanks. (I should have mentioned in the question) . I need to do all this in Java tho and then register the resulting signed certificate on the cloud. Even doing that part in bash, to generate the signed certificate would be fine, but I still can't find any Java API to then register and activate the certificate on the AWS IoT platform. – Engineer999 Apr 19 '19 at 20:01
  • Have you figured out how to sign the certificate with CAs in java yet? – AI_ROBOT May 22 '20 at 03:01

2 Answers2

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);
Dalton Cézane
  • 3,672
  • 2
  • 35
  • 60
0

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);
    }
    
}
Sarojkanta
  • 11
  • 2