From 60b4a048e0d72da0595ad98f24e9e39d6da8b961 Mon Sep 17 00:00:00 2001 From: Johny Mattsson Date: Tue, 17 Aug 2021 16:04:51 +1000 Subject: [PATCH] Added support for AWS IoT on port 443. --- README.md | 8 ++++++++ src/certstore.js | 7 +++++-- src/main.js | 4 +++- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4fc8f90..9df586d 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,14 @@ When chariotd exists due to communications failure and there are multiple certif In order to easily handle certificate rotation chariotd is designed around the concept of certificate stores rather than single certificate. A certificate store is simply a base directory containing an `endpoint.txt` file listing the AWS IoT endpoint the certificates apply to, and a number of sub directories with each containing a certificate and associated private key. +The `endpoint.txt` may contain either just the hostname of the IoT endpoint, +or hostname and port number in the form of `hostname:port`. The latter can +be used to switch from the standard MQTTS port (8883) to the HTTPS port (443). +This can be necessary when located behind a restrictive firewall which does +not permit outbound MQTTS traffic, but does allow HTTPS. Internally, the +ALPN TLS option is automatically set to `x-amzn-mqtt-ca` whenever port +443 is specified. + Example: ``` /path/to/certstore/ diff --git a/src/certstore.js b/src/certstore.js index a8e0890..7be9e2d 100644 --- a/src/certstore.js +++ b/src/certstore.js @@ -41,8 +41,10 @@ CertStore.prototype.rotatePreferred = function() { // returns [ { certId:, certPath:, caPath:, host:, clientId: }, ... ] CertStore.prototype.getCerts = function() { - const endpoint = + const endpoint_raw = fs.readFileSync(`${this._basedir}/endpoint.txt`, utf8).trim(); + const endpoint = (endpoint_raw.indexOf(':') != -1) ? + endpoint_raw.split(':') : [ endpoint_raw, null ]; // Get ordered list of subdirs, most recent first const dirs = fs.readdirSync(this._basedir, { withFileTypes: true }) .filter(dirent => dirent.isDirectory()) @@ -58,7 +60,8 @@ CertStore.prototype.getCerts = function() { certId: x.name, certPath: `${this._basedir}/${x.name}/${x.name}-certificate.pem.crt`, keyPath: `${this._basedir}/${x.name}/${x.name}-private.pem.key`, - host: endpoint, + host: endpoint[0], + port: endpoint[1], caPath: this._caPath, clientId: this._clientId, })); diff --git a/src/main.js b/src/main.js index 91244f5..5fd9cfe 100755 --- a/src/main.js +++ b/src/main.js @@ -212,8 +212,10 @@ function connect() { console.info('Connecting to AWS IoT Core...'); const keepalive = options.keepalive != null ? +options.keepalive : 1200; + const alpn = (ourcerts.preferred.port == 443) ? + { ALPNProtocols: [ 'x-amzn-mqtt-ca' ] } : undefined; const comms = awsiot.thingShadow( - Object.assign({ keepalive }, ourcerts.preferred)); + Object.assign({ keepalive }, ourcerts.preferred, alpn)); const registered = {}; ++comms_attempts; comms.on('connect', () => {