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?
openssl
, there's surely others way to do it, maybe there's a magic function to do it in AWS-SDK, but the way I know is troughopenssl
. In the link I gave you, the part you need is "Creating a Device Certificate Using Your CA Certificate". "Attempt to connect" mean that your device try to connect to amazon, if Amazon know about your CA, it will know that this new certificate he doesn't know, come from your CA. – severin.julien