Last active
April 22, 2025 05:13
-
-
Save DoumanAsh/13e71bd93ceab2d807e0b4b65c1e763d to your computer and use it in GitHub Desktop.
AWS IoT Core Provisioning script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { mqtt5, iot, iotidentity } from 'aws-iot-device-sdk-v2'; | |
///Ensure at least once delivery should be enough most of the time | |
const QOS = mqtt5.QoS.AtLeastOnce; | |
///Environment config | |
const CONFIG = { | |
endpoint: process.env.IOT_CORE_ENDPOINT!, | |
cert: process.env.IOT_CORE_CERTIFICATE!, | |
priv_key: process.env.IOT_CORE_PKEY!, | |
client_id: process.env.IOT_CORE_CLIENT_ID, | |
//registration parameters should be JSON matching template | |
provisioning_template_name: process.env.IOT_CORE_PROVISIONING_TEMPLATE!, | |
provisioning_template_params: JSON.parse(process.env.IOT_CORE_PROVISIONING_PARAMS!), | |
}; | |
function unexpected_error(error: any) { | |
console.error("Unexpected error: %s\n%s", error, error.stack); | |
} | |
///Creates MQTT config | |
// | |
//Following environment variables are used to infer config | |
// | |
//- IOT_CORE_ENDPOINT - required endpoint hostname | |
//- IOT_CORE_CERTIFICATE = required x509 certificate in PEM format | |
//- IOT_CORE_PKEY - required pirvate key corresponding to IOT_CORE_CERTIFICATE in order to establish TLS connection | |
//- IOT_CORE_CLIENT_ID - optional client id. If not specified, uses random `test-*` | |
function create_mqtt_config(): mqtt5.Mqtt5ClientConfig { | |
const properties = { | |
clientId: CONFIG.client_id || "test-" + Math.floor(Math.random() * 100000000), | |
keepAliveIntervalSeconds: 120 | |
}; | |
return iot.AwsIotMqtt5ClientConfigBuilder.newDirectMqttBuilderWithMtlsFromMemory(CONFIG.endpoint, CONFIG.cert, CONFIG.priv_key).withSessionBehavior(mqtt5.ClientSessionBehavior.Clean).withConnectProperties(properties).build(); | |
} | |
///Performs finalization of device registration by submitting CSR response token with necessary template parameters | |
function initiate_iot_device_registration(csr_response: iotidentity.model.CreateKeysAndCertificateResponse, iot_identity: iotidentity.IotIdentityClient) { | |
const subscribe_register_thing = { | |
templateName: CONFIG.provisioning_template_name | |
} | |
function on_register_accepted(error?: iotidentity.IotIdentityError, response?: iotidentity.model.RegisterThingResponse) { | |
if (error) { | |
console.error("Unexpected error: %s", error); | |
} else if (response) { | |
console.log("#### Device registration complete:\n # name='%s'\n # certificate_id='%s'\n # private_key:\n%s\n # certificate:\n%s\n", response.thingName ? response.thingName : '', csr_response.certificateId, csr_response.privateKey, csr_response.certificatePem); | |
if (response.deviceConfiguration) { | |
console.log("Device configuration:", response.deviceConfiguration); | |
} | |
} | |
} | |
function on_register_rejected(error?: iotidentity.IotIdentityError, response?: iotidentity.model.ErrorResponse) { | |
if (response) { | |
console.error("CSR is rejected:\n statusCode=%s\n errorCode=%s\n errorMessage=%s", response.statusCode, response.errorCode, response.errorMessage); | |
} | |
if (error) { | |
console.error("Unexpected error: %s", error); | |
} | |
} | |
console.log("subscribeToRegisterThing(templateName='%s') SEND", subscribe_register_thing.templateName); | |
const subscription_ongoing = [ | |
iot_identity.subscribeToRegisterThingAccepted(subscribe_register_thing, QOS, on_register_accepted), | |
iot_identity.subscribeToRegisterThingRejected(subscribe_register_thing, QOS, on_register_rejected), | |
]; | |
Promise.all(subscription_ongoing).then(() => { | |
console.debug("subscribeToRegisterThing() DONE"); | |
const register_thing_request = { | |
parameters: CONFIG.provisioning_template_params, | |
templateName: CONFIG.provisioning_template_name, | |
certificateOwnershipToken: csr_response.certificateOwnershipToken | |
}; | |
iot_identity.publishRegisterThing(register_thing_request, QOS).then(() => { | |
console.debug("publishRegisterThing() SENT"); | |
}).catch(unexpected_error) | |
}).catch(unexpected_error) | |
} | |
///Initiates provisioning using provided mqtt client | |
// | |
//Requires connection to be successfully established. | |
function initiate_iot_provisioning(client: mqtt5.Mqtt5Client) { | |
const iot_identity = iotidentity.IotIdentityClient.newFromMqtt5Client(client); | |
function on_csr_accepted(error?: iotidentity.IotIdentityError, response?: iotidentity.model.CreateKeysAndCertificateResponse) { | |
if (error) { | |
console.error("Unexpected error: %s", error); | |
} else if (response) { | |
console.log("publishCreateCertificateFromCsr() DONE") | |
initiate_iot_device_registration(response, iot_identity); | |
} | |
} | |
function on_csr_rejected(error?: iotidentity.IotIdentityError, response?: iotidentity.model.ErrorResponse) { | |
if (response) { | |
console.error("CSR is rejected:\n statusCode=%s\n errorCode=%s\n errorMessage=%s", response.statusCode, response.errorCode, response.errorMessage); | |
} | |
if (error) { | |
console.error("Unexpected error: %s", error); | |
} | |
} | |
const ongoing = [ | |
iot_identity.subscribeToCreateKeysAndCertificateAccepted({}, QOS, on_csr_accepted), | |
iot_identity.subscribeToCreateKeysAndCertificateRejected({}, QOS, on_csr_rejected), | |
]; | |
Promise.all(ongoing).then(() => { | |
console.debug("subscribeToCreateCertificateFromCsr() DONE"); | |
iot_identity.publishCreateKeysAndCertificate({}, QOS).then(() => { | |
console.debug("publishCreateCertificateFromCsr() SENT"); | |
}).catch(unexpected_error) | |
}).catch(unexpected_error) | |
} | |
function initiate_mqtt_connection(config: mqtt5.Mqtt5ClientConfig) { | |
const client = new mqtt5.Mqtt5Client(config); | |
client.once("connectionSuccess", (data) => { | |
console.log("Connection successful", data) | |
initiate_iot_provisioning(client) | |
}); | |
client.on("connectionFailure", (data) => { | |
console.log("Connection failed", data) | |
}); | |
console.log("Connecting..."); | |
client.start(); | |
} | |
function main() { | |
const config = create_mqtt_config(); | |
initiate_mqtt_connection(config) | |
} | |
main() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"devDependencies": { | |
"@types/bun": "latest", | |
"typescript": "^5.8.3", | |
"typescript-language-server": "^4.3.4" | |
}, | |
"dependencies": { | |
"aws-iot-device-sdk-v2": "^1.21.3" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment