import React, { Component } from "react"; import { API } from "aws-amplify"; import { Grid, Row, Col, Button, ProgressBar, Alert, FormGroup, ControlLabel, FormControl, HelpBlock, Well } from "react-bootstrap"; import { Card } from "components/Card/Card.jsx"; class DeviceRegistration extends Component { constructor(props) { super(props); this.goBack = this.goBack.bind(this); this.register = this.register.bind(this); this.finish = this.finish.bind(this); this.handleSerialNumberChange = this.handleSerialNumberChange.bind(this); this.handleDeviceNameChange = this.handleDeviceNameChange.bind(this); this.handleModelNumberChange = this.handleModelNumberChange.bind(this); this.state = { step: 0, serialNumber: '', deviceName: '', modelNumber: '', isLoading: false, error: false, serialNumberValidateState: null, showSerialNumberHelpBlock: false, deviceNameValidateState: null, showDeviceNameHelpBlock: false, modelNumberValidateState: null, showModelNumberHelpBlock: false, isRegistering: false, }; }; componentDidMount() { // Checks if the previous page sends a state. // It would only happens when the device is pending to be registered, and a user wants to see the registration instruction again. const state = this.props.location.state; if (state) { let deviceId = state.deviceId; this.setState({ step: 1, serialNumber: deviceId }); } } goBack() { this.props.history.push('/devices'); } // Handles input changes handleSerialNumberChange = (event) => { this.setState({ serialNumber: event.target.value }, () => { this.serialNumberValidate(); }); } handleDeviceNameChange = (event) => { this.setState({ deviceName: event.target.value }, () => { this.validateInput('deviceName'); }); } handleModelNumberChange = (event) => { this.setState({ modelNumber: event.target.value }, () => { this.validateInput('modelNumber'); }); } // Validates serial number serialNumberValidate = () => { let serialNumber = this.state.serialNumber; let regexp = /^[a-zA-Z0-9-_:]+$/; let pass = regexp.test(serialNumber); if (pass) { this.setState({ showSerialNumberHelpBlock: false, serialNumberValidateState: null, }); } else { this.setState({ showSerialNumberHelpBlock: true, serialNumberValidateState: 'error', }); } return pass; } // Validates inputs validateInput = (type) => { let regexp = /^[a-zA-Z0-9-_.,:/@#]+$/; let pass = false; let input = ''; switch (type) { case 'deviceName': { input = this.state.deviceName; pass = regexp.test(input); if (pass) { this.setState({ showDeviceNameHelpBlock: false, deviceNameValidateState: null, }); } else { this.setState({ showDeviceNameHelpBlock: true, deviceNameValidateState: 'error', }); } break; } case 'modelNumber': { input = this.state.modelNumber; pass = regexp.test(input); if (pass) { this.setState({ showModelNumberHelpBlock: false, modelNumberValidateState: null, }); } else { this.setState({ showModelNumberHelpBlock: true, modelNumberValidateState: 'error', }); } break; } default : { // do nothing break; } } return pass; } // Registers device register = async () => { this.setState({ error: false, }); if (!this.state.isRegistering) { this.setState({ isRegistering: true }); let isSerialNumberValidated = this.serialNumberValidate(); let isDeviceNameValidated = this.validateInput('deviceName'); let isModelNumberValidated = this.validateInput('modelNumber'); if (!isSerialNumberValidated || !isDeviceNameValidated || !isModelNumberValidated) { this.props.handleNotification('Check input variables', 'error', 'pe-7s-check', 5); this.setState({ isRegistering: false }); } else { this.setState({ isLoading: true }); let token = await this.props.getToken(); let apiName = 'smart-product-api'; let path = 'registration'; let params = { body: { modelNumber: this.state.modelNumber, deviceId: this.state.serialNumber, deviceName: this.state.deviceName, }, headers: { 'Authorization': token } }; API.post(apiName, path, params) .then(response => { this.setState({ step: 1 }); }) .catch(error => { let message = error.response; if (message === undefined) { message = error.message; } else { message = error.response.data.message; } this.setState({ error: message, }); }) .finally(() => { this.setState({ isLoading: false, isRegistering: false, }); }); } } else { this.props.handleNotification('Device is still registering', 'warning', 'pe-7s-close-circle', 5); } } finish = () => { let deviceId = this.state.serialNumber; this.props.history.push(`/devices/${deviceId}`); } render() { const { isLoading, error, serialNumberValidateState, showSerialNumberHelpBlock, deviceNameValidateState, showDeviceNameHelpBlock, modelNumberValidateState, showModelNumberHelpBlock, } = this.state; if (this.state.step === 1) { return (
To finish the registration, you can follow the below instruction.
  • Login to the device with SSH, and register your CA certificate. $ openssl genrsa -out sampleCACertificate.key 2048
    $ openssl req -x509 -new -nodes -key sampleCACertificate.key -sha256 -days 365 -out sampleCACertificate.pem
  • Get registration code using the AWS CLI, and copy "registrationCode". $ aws iot get-registration-code
  • Create a CSR. During the creation process, enter the registration code into the "Common Name" field.
    $ openssl genrsa -out privateKeyVerification.key 2048
    $ openssl req -new -key privateKeyVerification.key -out privateKeyVerification.csr
    ...
    Common Name (e.g. server FQDN or YOUR name) []: registrationCode
  • Use your first sample CA certificate and the CSR to create a new certificate. $ openssl x509 -req -in privateKeyVerification.csr -CA sampleCACertificate.pem -CAkey sampleCACertificate.key -CAcreateserial -out privateKeyVerification.crt -days 365 -sha256
  • Use the verification certificate to register your sample CA certificate, and copy "certificateId". $ aws iot register-ca-certificate --ca-certificate file://sampleCACertificate.pem --verification-certificate file://privateKeyVerification.crt
  • Activate the CA certificate, and enable the auto-registration-status. $ aws iot update-ca-certificate --new-status ACTIVE --new-auto-registration-status ENABLE --certificate-id <certificateId>
  • Create a device certificate. During the creation process, enter the serial number into the "Common Name" field. $ openssl genrsa -out deviceCert.key 2048
    $ openssl req -new -key deviceCert.key -out deviceCert.csr
    ...
    Common Name (e.g. server FQDN or YOUR name) []: {this.state.serialNumber}

    $ openssl x509 -req -in deviceCert.csr -CA sampleCACertificate.pem -CAkey sampleCACertificate.key -CAcreateserial -out deviceCert.crt -days 365 -sha256
  • Download the root certificate. $ curl -o root.cert https://www.amazontrust.com/repository/AmazonRootCA1.pem
  • Get AWS IoT endpoint, and copy the value. $ aws iot describe-endpoint --endpoint-type iot:Data-ATS --output text
  • Try to connect to AWS IoT using the device certificate. $ cat deviceCert.crt sampleCACertificate.pem > deviceCertAndCACert.crt
    $ mosquitto_pub --cafile root.cert --cert deviceCertAndCACert.crt --key deviceCert.key -p 8883 -q 1 -t foo/bar -i anyclientID --tls-version tlsv1.2 -m "Hello" -d -h YOUR_IOT_ENDPOINT
  • You will see a TLS failure when you run the command because AWS IoT disconnects the connection after the registration of the device certificate.
  • Click "Finish" to see your device.
For more information, please refer to Just-in-Time Registration of Device Certificates on AWS IoT.
} />
); } else { return (
Serial Number { showSerialNumberHelpBlock && Must contain only alphanumeric characters and/or the following: -_: } Device Name { showDeviceNameHelpBlock && Must contain only alphanumeric characters and/or the following: -_.,:/@# } Model Number { showModelNumberHelpBlock && Must contain only alphanumeric characters and/or the following: -_.,:/@# }
} />
{ isLoading &&
} { error && {this.state.error} }
); } } } export default DeviceRegistration;