I am using NodeJS along with AWS JS SDK and AWS IoT Device JS SDK in order to automatically create a new thing and assign certificates and policies to it once it connects to my server.
I was following "Just-in-Time Registration" article in order to create, register and activate my CA certificate. As far as I can tell, the CA certificate is successfully added to AWS IoT, activated and enabled for auto-registration.
What I don't understand is how is this step performed (quote from mentioned article):
When a device attempts to connect with an X.509 certificate that is not known to AWS IoT but was signed by a CA that was registered with AWS IoT, the device certificate will be auto-registered by AWS IoT in a new PENDING_ACTIVATION state.
How do I make an "attempt" to connect? Since I was using aws-iot-device-sdk-js
SDK, with manually created certificates, I was usually connecting my device like this:
const device = deviceModule.device({
host: 'myendpoint.iot.us-east-1.amazonaws.com',
region: 'us-east-1',
keyPath: `certs/${deviceID}.key`,
certPath: `certs/${deviceID}.pem`,
caPath: 'certs/rootCA.pem',
clientId: deviceID,
baseReconnectTimeMs: 4000,
keepalive: 30,
protocol: 'mqtts',
});
But now I don't have certificate and key to include in keyPath
and certPath
and I cannot instantiate my device without it.
I tried to create certificates myself, using createKeysAndCertificate()
from AWS SDK, saving them to disk, attaching a policy manually, attaching a principal manually even tried to mark certificate as "active" manually, something along these lines:
iot.createThing({ thingName: deviceID }, (err, d) => {
if (err) {
console.log(err);
} else {
allThings[d.thingName] = d;
iot.createKeysAndCertificate({ setAsActive: true }, (e, c) => {
if (e) {
console.log(e);
} else {
fs.writeFile(`certs/${deviceID}.pem`, c.certificatePem, (ef, f) => {
if (ef) throw ef;
});
fs.writeFile(`certs/${deviceID}.key`, c.keyPair.PrivateKey, (ef, f) => {
if (ef) throw ef;
});
iot.attachPrincipalPolicy({
policyName: 'my-testing-policy',
principal: c.certificateArn,
}, (ee, cc) => {
if (ee) {
console.log(ee);
} else {
iot.attachThingPrincipal({
principal: c.certificateArn,
thingName: deviceID,
}, (prerr, prdata) => {
if (prerr) {
console.log(prerr);
} else {
iot.acceptCertificateTransfer({
certificateId: c.certificateId,
setAsActive: true,
}, (ce, cd) => {
if (err) {
console.log(err);
} else {
console.log('cert activated.');
}
});
}
});
}
});
}
});
}
});
But after all this, when I try to publish something I am presented with an error:
Error: unable to get local issuer certificate
at Error (native)
at TLSSocket.<anonymous> (_tls_wrap.js:1092:38)
at emitNone (events.js:86:13)
at TLSSocket.emit (events.js:185:7)
at TLSSocket._finishInit (_tls_wrap.js:610:8)
at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:440:38)
I also tried to subscribe to specific topic, as mentioned in the same article above, aws/events/certificates/registered/e3f0a30...
but I've never seen a single message on that topic...
What am I missing here? How do I trigger device certificate and private key generation properly just by using my Just-in-Time certificate?