@nordicsemiconductor/asset-tracker-cloud-aws
Version:
A reference implementation of a serverless backend for an IoT product developed using AWS CDK in TypeScript.
403 lines (402 loc) • 18 kB
JavaScript
function _array_like_to_array(arr, len) {
if (len == null || len > arr.length) len = arr.length;
for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
return arr2;
}
function _array_without_holes(arr) {
if (Array.isArray(arr)) return _array_like_to_array(arr);
}
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
try {
var info = gen[key](arg);
var value = info.value;
} catch (error) {
reject(error);
return;
}
if (info.done) {
resolve(value);
} else {
Promise.resolve(value).then(_next, _throw);
}
}
function _async_to_generator(fn) {
return function() {
var self = this, args = arguments;
return new Promise(function(resolve, reject) {
var gen = fn.apply(self, args);
function _next(value) {
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
}
function _throw(err) {
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
}
_next(undefined);
});
};
}
function _iterable_to_array(iter) {
if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
}
function _non_iterable_spread() {
throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _to_consumable_array(arr) {
return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
}
function _unsupported_iterable_to_array(o, minLen) {
if (!o) return;
if (typeof o === "string") return _array_like_to_array(o, minLen);
var n = Object.prototype.toString.call(o).slice(8, -1);
if (n === "Object" && o.constructor) n = o.constructor.name;
if (n === "Map" || n === "Set") return Array.from(n);
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
}
function _ts_generator(thisArg, body) {
var f, y, t, g, _ = {
label: 0,
sent: function() {
if (t[0] & 1) throw t[1];
return t[1];
},
trys: [],
ops: []
};
return g = {
next: verb(0),
"throw": verb(1),
"return": verb(2)
}, typeof Symbol === "function" && (g[Symbol.iterator] = function() {
return this;
}), g;
function verb(n) {
return function(v) {
return step([
n,
v
]);
};
}
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while(_)try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [
op[0] & 2,
t.value
];
switch(op[0]){
case 0:
case 1:
t = op;
break;
case 4:
_.label++;
return {
value: op[1],
done: false
};
case 5:
_.label++;
y = op[1];
op = [
0
];
continue;
case 7:
op = _.ops.pop();
_.trys.pop();
continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
_ = 0;
continue;
}
if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
_.label = op[1];
break;
}
if (op[0] === 6 && _.label < t[1]) {
_.label = t[1];
t = op;
break;
}
if (t && _.label < t[2]) {
_.label = t[2];
_.ops.push(op);
break;
}
if (t[2]) _.ops.pop();
_.trys.pop();
continue;
}
op = body.call(thisArg, _);
} catch (e) {
op = [
6,
e
];
y = 0;
} finally{
f = t = 0;
}
if (op[0] & 5) throw op[1];
return {
value: op[0] ? op[1] : void 0,
done: true
};
}
}
import { atHostHexfile, connect, createPrivateKeyAndCSR, flashCertificate, getIMEI } from '@nordicsemiconductor/device-helpers';
import chalk from 'chalk';
import { promises as fs } from 'fs';
import os from 'os';
import path from 'path';
import { createDeviceCertificate, defaultDeviceCertificateValidityInDays } from '../jitp/createDeviceCertificate.js';
import { getCurrentCA } from '../jitp/currentCA.js';
import { deviceFileLocations } from '../jitp/deviceFileLocations.js';
import { readlineDevice } from '../jitp/readlineDevice.js';
import run from '@bifravst/run';
export var defaultPort = '/dev/ttyACM0';
export var defaultSecTag = 42;
export var createAndProvisionDeviceCertCommand = function(param) {
var certsDir = param.certsDir;
return {
command: 'create-and-provision-device-cert',
options: [
{
flags: '-e, --expires <expires>',
description: "Validity of device certificate in days. Defaults to ".concat(defaultDeviceCertificateValidityInDays, " days.")
},
{
flags: '-p, --port <port>',
description: "The port the device is connected to, defaults to ".concat(defaultPort)
},
{
flags: '--dk',
description: "Connected device is a 9160 DK"
},
{
flags: '-s, --sec-tag <secTag>',
description: "Use this secTag, defaults to ".concat(defaultSecTag)
},
{
flags: '-X, --delete-private-key',
description: "Delete the private key (needed if a private key exists with the secTag)"
},
{
flags: '-a, --at-host <atHost>',
description: "Flash at_host from this file"
},
{
flags: '--debug',
description: "Log debug messages"
},
{
flags: '-S, --simulated-device',
description: "Use a simulated (soft) device. Useful if you do not have physical access to the device. Will print the AT commands sent to the device allows to provide responses on the command line."
},
{
flags: '-c, --ca <caId>',
description: "ID of the CA certificate to use. Defaults to the last created one."
}
],
action: function() {
var _ref = _async_to_generator(function(param) {
var dk, expires, port, atHost, secTag, debug, deletePrivateKey, simulatedDevice, caId, connection, deviceId, csr, deviceFiles, tempDir, deviceCSRDERLocation, caCert, clientCert, effectiveSecTag;
return _ts_generator(this, function(_state) {
switch(_state.label){
case 0:
dk = param.dk, expires = param.expires, port = param.port, atHost = param.atHost, secTag = param.secTag, debug = param.debug, deletePrivateKey = param.deletePrivateKey, simulatedDevice = param.simulatedDevice, caId = param.caId;
if (!(simulatedDevice === true)) return [
3,
2
];
console.log(chalk.magenta("Flashing certificate"), chalk.blue('(simulated device)'));
return [
4,
readlineDevice()
];
case 1:
connection = _state.sent();
return [
3,
4
];
case 2:
console.log(chalk.magenta("Flashing certificate"), chalk.blue(port !== null && port !== void 0 ? port : defaultPort));
return [
4,
connect({
atHostHexfile: atHost !== null && atHost !== void 0 ? atHost : dk === true ? atHostHexfile['9160dk'] : atHostHexfile['thingy91'],
device: port !== null && port !== void 0 ? port : defaultPort,
warn: console.error,
debug: debug === true ? console.debug : undefined,
progress: debug === true ? console.log : undefined,
inactivityTimeoutInSeconds: 10
})
];
case 3:
connection = _state.sent().connection;
_state.label = 4;
case 4:
return [
4,
getIMEI({
at: connection.at
})
];
case 5:
deviceId = _state.sent();
console.log(chalk.magenta("IMEI"), chalk.blue(deviceId));
return [
4,
createPrivateKeyAndCSR({
at: connection.at,
secTag: secTag !== null && secTag !== void 0 ? secTag : defaultSecTag,
deletePrivateKey: deletePrivateKey !== null && deletePrivateKey !== void 0 ? deletePrivateKey : false
})
];
case 6:
csr = _state.sent();
deviceFiles = deviceFileLocations({
certsDir: certsDir,
deviceId: deviceId
});
return [
4,
fs.mkdtemp(path.join(os.tmpdir(), path.sep))
];
case 7:
tempDir = _state.sent();
deviceCSRDERLocation = path.join(tempDir, "".concat(deviceId, "-csr.der"));
return [
4,
fs.writeFile(deviceCSRDERLocation, csr)
];
case 8:
_state.sent();
// Convert to PEM
return [
4,
run({
command: 'openssl',
args: [
'req',
'-inform',
'DER',
'-in',
deviceCSRDERLocation,
'-out',
deviceFiles.csr
]
})
];
case 9:
_state.sent();
return [
4,
createDeviceCertificate({
deviceId: deviceId,
certsDir: certsDir,
caId: caId !== null && caId !== void 0 ? caId : getCurrentCA({
certsDir: certsDir
}),
log: function() {
for(var _len = arguments.length, message = new Array(_len), _key = 0; _key < _len; _key++){
message[_key] = arguments[_key];
}
var _console;
(_console = console).log.apply(_console, _to_consumable_array(message.map(function(m) {
return chalk.magenta(m);
})));
},
debug: function() {
for(var _len = arguments.length, message = new Array(_len), _key = 0; _key < _len; _key++){
message[_key] = arguments[_key];
}
var _console;
(_console = console).log.apply(_console, _to_consumable_array(message.map(function(m) {
return chalk.cyan(m);
})));
},
daysValid: expires !== undefined ? parseInt(expires, 10) : undefined
})
];
case 10:
_state.sent();
console.log(chalk.green("Certificate for device ".concat(chalk.yellow(deviceId), " generated.")));
return [
4,
fs.readFile(path.resolve(process.cwd(), 'data', 'AmazonRootCA1.pem'), 'utf-8')
];
case 11:
caCert = _state.sent();
return [
4,
fs.readFile(deviceFiles.certWithCA, 'utf-8')
];
case 12:
clientCert = _state.sent();
effectiveSecTag = secTag !== null && secTag !== void 0 ? secTag : defaultSecTag;
if (!(simulatedDevice === true)) return [
3,
14
];
return [
4,
connection.end()
];
case 13:
_state.sent();
console.log('');
console.log(chalk.white('Please program the certificates using the certificate manager.'));
console.log('');
console.log(chalk.whiteBright('for'), chalk.whiteBright.bold('CA certificate:'));
console.log(chalk.blueBright(caCert));
console.log('');
console.log(chalk.whiteBright('for'), chalk.whiteBright.bold('Client certificate:'));
console.log(chalk.blueBright(clientCert));
console.log('');
console.log(chalk.whiteBright('for'), chalk.whiteBright.bold('Security tag:'), chalk.blueBright(effectiveSecTag));
console.log('');
return [
3,
17
];
case 14:
return [
4,
flashCertificate({
at: connection.at,
caCert: caCert,
secTag: effectiveSecTag,
clientCert: clientCert
})
];
case 15:
_state.sent();
return [
4,
connection.end()
];
case 16:
_state.sent();
_state.label = 17;
case 17:
console.log();
console.log(chalk.green('Certificate written to device'), chalk.blueBright(deviceId));
process.exit();
return [
2
];
}
});
});
return function(_) {
return _ref.apply(this, arguments);
};
}(),
help: 'Generate a certificate for the connected device using device-generated keys, signed with the CA, and flash it to the device.'
};
};