Code Monkey home page Code Monkey logo

aws-iot-certificate-vending-machine's Introduction

AWS Iot Certificate Vending Machine

You can use the CVM allows the device to apply for their own certificate and installation.

README Languages: Chinese blog(中文)

Background Information

In order to ensure the secured communication between IoT devices and AWS IoT Core, Devices may use X.509 certificates to connect to AWS IoT using TLS mutual authentication protocols. AWS Cloud security mechanisms protect data as it moves between AWS IoT and other devices or AWS services.

Background

This mutual TLS authentication mode requires that a device certificate meets either of the following two conditions:

  1. The certificate used on the IoT device is issued by AWS IoT Core
  2. The CA certificate which is used to sign IoT device certificate is pre-imported into a customer’s AWS account and associated with their AWS IoT Core environment AWS understands that customers will have devices that currently do not have the ability to meet condition 1 or 2 immediately. Therefore, we have provided a reference application called, Certificate Vending Machine, which demonstrates how customers can provision devices with certificates created in AWS IoT.

When to use Certificate Vending Machine?

Certificate Vending Machine (CVM) is an ideal fit for customers who do not have certificates pre-installed on the devices and are unable to obtain CA certificates to pre-create device certificates during their manufacturing process. On this occasion, you can use CVM system which allows the device to apply for their own certificate and then install the certificate into storage on the device. This document provides the design ideas and associated source code, which can help customers quickly develop a CVM system. Since the original IoT device does not contain a certificate for TLS mutual authentication, we need to pay attention to three points.

  • When IoT devices and the CVM system are communicating, a trusted DNS environment is needed in order to prevent the man-in-middle attack along with using other secured communication method, such as HTTPS.
  • When an IoT device requests a certificate, it should have a unique identifier. The identifier, such as serial number, client ID or product ID, will be used for policy binding and to ensure that the device is a valid device.
  • All certificates submitted by the CVM system are AWS IoT Core signed certificates. If you need to use a custom CA certificate, refer to the Just-in-time Registration (JITR) certificate authentication method.

Implementation Methodology

The entire implementation can be divided into three modules: IoT devices, CVM system and AWS IoT Core.

  • IoT device side
  • Request a device certificate via HTTPS connection.
  • Submit the device serial number and the registration token when requested. Registration token is a one-time token to avoid device serial number spoofing.
  • CVM system
  • Provides remote access to IoT devices for certificate application.
  • Generates secured certificate for each IoT device that can be used to communicate to AWS IoT Core.
  • Uses database, like DynamoDB, to store information such as the device ID, key registration information, and the applied device certificate.
  • Associates IoT Thing Name, Certificate Policy, and Certificate ID by querying the association table in DynamoDB. In parallel, CVM modifies the certificate status attribute in DynamoDB to ensure that a device can only register for a single active certificate.
  • IoT Core
  • Response to API calls to generate the certificate and key pairs.

The basic workflow of the CVM system is as follows:

workflow

The architecture of CVM system is as follows:

Architecture

Using the API Gateway and Lambda solution for scalability, the detailed workflow is shown as follows:

  1. When IoT device requests access to IoT platform, it triggers a certificate application to CVM system. Then IoT device sends the appropriate API calls to the API Gateway for IoT device certificate application.
  2. AWS API Gateway invokes Lambda to initiate certificate request to IoT Core.
  3. After receiving the request from API Gateway, Lambda checks DynamoDB to validate if the request is legitimate and applies for a certificate to the backend IoT Core.
  4. The CVM system uses the AWS SDK to make a series of API calls to AWS IoT Core. These API calls perform actions such as creating a new thing in the AWS IoT Thing Registry and creating an associated device certificate.
  5. AWS IoT Core generates a device certificate, key pairs and returns the certificate information and the certificate ID to CVM system.
  6. Lambda uses a series of API calls to associate Thing Name, Certificate, and Policy on IoT Thing registry by querying pre-created DynamoDB association table according to product serial number.
  7. Update all the associated information of the current device to DynamoDB association table
  8. Lastly, the CVM system returns the certificate to the IoT devices

Security

In order to ensure the security of the CVM system, the AWS Lambda function needs to be scoped to the minimum permissions needed in order to create certificates. The following example shows how to assign the correct IAM role privilege to the CVM system.

First of all, you need to understand the CVM system needs to have the IAM authority to complete the certificate application and the issuance process.

  • Access AWS DynamoDB for querying, modifying, and updating device associations in DynamoDB table
  • Access the IoT platform to apply for IoT device certificates

The policy template for IAM role as follows, you should modify it more specifically for the minimum privilege.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "IoTCWlogsPolicy",
            "Effect": "Allow",
            "Action": [
                "logs:*",
                "iot:CreateThing",
                "iot:AttachPolicy",
                "iot:AttachThingPrincipal",
                "iot:CreatePolicy",
                "iot:CreateKeysAndCertificate"
            ],
            "Resource": "*"
        },
        {
            "Sid": "dynamodPolicy",
            "Effect": "Allow",
            "Action": [
                "dynamodb:Query",
                "dynamodb:UpdateItem"
            ],
            "Resource": "arn:aws:dynamodb:REGION:123456789012:table/TableName"
        }
    ]
}

Secondly, you need to allow lambda assume this role by adding trust relationship.

policy

In addition to the IAM authority division, you need to create an association table on DynamoDB for the binding relationship between the device, the certificate and policy. Specifically, you need to create the following database fields in DynamoDB:

  • Product id: IoT device ID
  • Access Token: IoT Token
  • timestamp: certificate request timestamp
  • applyState: request status (if the certificate is set to -1, it means that the device has already registered the certificate)
  • certID: certificate ID associated with the device

How do I deploy this?

1. Deploy the CVM to your AWS account

The solution is available as a AWS CloudFormation SAM template, and included in this repository (template.yml). Click the following button to deploy it to your AWS account in the us-east-1 region:

cloudformation-launch-stack

You will need to provide some parameters to point AWS Lambda.

When the cloudformation CREATE_COMPLETE, you can see the output of Cloudformation.

[cloudformation-stack-output]

2. Add Sample Device Data to your Device Dynamodb

You must create item in your device dynamodb table, or you will see access deny.

[Add Sample Data about serialNumber & deviceToken ]

3. Use output API Gateway Link to invoke your CVM

Please use the link from the first step. https://XXXXX.execute-api.us-east-1.amazonaws.com/PROD/getcert?serialNumber=ascas&deviceToken=zxcz

Code Description

The following CVM system reference source code uses the IoT interface provided by the AWS Node.js SDK to complete the certificate request and add the associated Thing Name and Policy.

// Create cert
  iot.createKeysAndCertificate(params, function(err, certdata) {
    console.log("certdata:");
    console.log(certdata);
    
    if (err) console.log(err, err.stack); // an error occurred
    else{
      
       // Create IoT Policy for above cert
       var params = {
        policyDocument: config.PILICY_DOCUMENT, /* required */
        policyName: serialNumber /* required */
      };
      iot.createPolicy(params, function(err, data) {
        if (err) console.log(err, err.stack); // an error occurred
        else{
          console.log(data);
          
          // Attach policy for cert
          var params = {
            policyName: serialNumber, /* required */
            target: certdata.certificateArn /* required */
          };
          iot.attachPolicy(params, function(err, data) {

Reference Link:

http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Iot.html

License

This library is licensed under the Apache 2.0 License.

aws-iot-certificate-vending-machine's People

Contributors

brightsparc avatar cncoder avatar eercanayar avatar jveldboom avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aws-iot-certificate-vending-machine's Issues

CVM create multiple certificates

I need the template.yaml to creat the CVM, and the accessToken and serialNumber can create multiple certificates ,but just return once. So,need I do extra something to avoid it?

the second creatition log is:
2018-04-18T11:13:25.351Z 81e505c0-42f9-11e8-8dcd-5360239d60ce { certificateArn: 'arn:aws:iot:us-east-1:506128028316:cert/5596bd96e0c1219b61f2a03742add29415513eb6c08d6d4788f69bd85e12809c',
certificateId: '5596bd96e0c1219b61f2a03742add29415513eb6c08d6d4788f69bd85e12809c',
certificatePem: '-----BEGIN CERTIFICATE-----\nMIIDWTCCAkGgAwIBAgIUE2bS8YcsygTpkMq6Rtr/feBXuRgwDQYJKoZIhvcNAQEL\nBQAwTTFLMEkGA1UECwxCQW1hem9uIFdlYiBTZXJ2aWNlcyBPPUFtYXpvbi5jb20g\nSW5jLiBMPVNlYXR0bGUgU1Q9V2FzaGluZ3RvbiBDPVVTMB4XDTE4MDQxODExMTEy\nNVoXDTQ5MTIzMTIzNTk1OVowHjEcMBoGA1UEAwwTQVdTIElvVCBDZXJ0aWZpY2F0\nZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALtgSKmSQADPNUaushpm\nLkmsZMxchFQCey412TFObBV11c5qar3R/svKe3os54hKj26c0ZgOTXRc0iyamTQF\nTZi4CDgkTQCMFW3Tgxh9M6Vrod81HlwbY0M7OhizP8iQIrieZyZdVTZhCUlM4Vpg\n/JAnXn7an2u8Yn6Pz6BBjssLoUu2J5F7DcTLvYuz9GnaAJkjju7bAghfTeV+8zkR\nXK5AwaF/DCj5UslGRjcHg/2G2oF7756iYFTHrIwl/7Aro0bMFqC1COWq3draqc1O\n/nYBTZM5l9n0wLTuMWPKHBWXvU3zGhvh2T7dhuEusxTwVVrFWNCO8Dd9VE7yV6Ol\nUU8CAwEAAaNgMF4wHwYDVR0jBBgwFoAUn6U7r6r9aZ/Y5cFEb7OoXT9Z86gwHQYD\nVR0OBBYEFFgSG7bOFp76sc0+sWmj/F+2K5BLMAwGA1UdEwEB/wQCMAAwDgYDVR0P\nAQH/BAQDAgeAMA0GCSqGSIb3DQEBCwUAA4IBAQC7Qi1U1bWeoV0aueQ38U0y5wT+\nLDE+drrbHTrfFnk7hLqXs1MWRqjjbwiNCXAKAzrIgDg3LAEIhbU3NhEe0wweYQj0\nNqEJfPNAZhEOOu0tlRKWTX7f54tIu83m5fwsvnYJv5h3dVmJqMyfzzBjbSJBP5Ar\nrvf8J93mlEnJjfv+vcX0WSAkH4MOoGs70a/DnDSzvG1GR2NlOq6f9JYnL09Qp9nB\nZMW7pEkmL6BzFHSpQL/n50KuJwvYSX49tEN1Z0dbjS8lLhTcSfvf7ZLAi/P4FqfL\nF4eMEVY2xrEzLxx73iknPvXzqQs4Hqvp3LgGYUjg7UEGJUfDIKzZWG8746vC\n-----END CERTIFICATE-----\n',
keyPair:
{ PublicKey: '-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu2BIqZJAAM81Rq6yGmYu\nSaxkzFyEVAJ7LjXZMU5sFXXVzmpqvdH+y8p7eizniEqPbpzRmA5NdFzSLJqZNAVN\nmLgIOCRNAIwVbdODGH0zpWuh3zUeXBtjQzs6GLM/yJAiuJ5nJl1VNmEJSUzhWmD8\nkCdeftqfa7xifo/PoEGOywuhS7YnkXsNxMu9i7P0adoAmSOO7tsCCF9N5X7zORFc\nrkDBoX8MKPlSyUZGNweD/YbagXvvnqJgVMesjCX/sCujRswWoLUI5ard2tqpzU7+\ndgFNkzmX2fTAtO4xY8ocFZe9TfMaG+HZPt2G4S6zFPBVWsVY0I7wN31UTvJXo6VR\nTwIDAQAB\n-----END PUBLIC KEY-----\n',
PrivateKey: '-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAu2BIqZJAAM81Rq6yGmYuSaxkzFyEVAJ7LjXZMU5sFXXVzmpq\nvdH+y8p7eizniEqPbpzRmA5NdFzSLJqZNAVNmLgIOCRNAIwVbdODGH0zpWuh3zUe\nXBtjQzs6GLM/yJAiuJ5nJl1VNmEJSUzhWmD8kCdeftqfa7xifo/PoEGOywuhS7Yn\nkXsNxMu9i7P0adoAmSOO7tsCCF9N5X7zORFcrkDBoX8MKPlSyUZGNweD/YbagXvv\nnqJgVMesjCX/sCujRswWoLUI5ard2tqpzU7+dgFNkzmX2fTAtO4xY8ocFZe9TfMa\nG+HZPt2G4S6zFPBVWsVY0I7wN31UTvJXo6VRTwIDAQABAoIBACDJAQ3CjDZYCx9Z\n88nQtSqo4l4rle/JG1qDi4QoD5tVqdpbHmAmPSnVPPOspbpgKWaWQ8oSPpUspI2v\nYz0J7IDbOnzwRRTibeFwj9CaH45DHeibN7uwAxdBZrHpszBZn+mjtbKtw/om0mQj\n8o5IyAhFCzCw+hH0vVsduJt2vRBjpMnm8hfVBvutz4xPAAeu4C6hSwyqBDq/5Ioh\nuFHNyWpU4AD5/ITjB+AQfgOGN1dDIjIWkloSnp7+IPeZGD6Sk7iBcSc47zWfh4t7\n4V4HB88x9HgSe+ty6tVB+7cDwe3IhnlIVPUgXsOByMN0OMi6Iyk4eaN6pAKWDo5K\nX921eiECgYEA58vOKLAIWyQSAkKIdBKByrtPJw18LD+CcgG3Od4axReNqL92LkOy\nXZZuMv7NOd5VlRFZCahbzzKuGTu6ztqNgUcybo8K0pStJiBovyVmapWNf7jDQVr0\nwi6/DuLnw/d0Rji3Q5KM9J81gxnu9M1EBvzj2qqOjZ/Ga8Nu7Dg51x8CgYEAzvET\nxmGXKJO29U4/bhBrnSFf1QckjAzzd7edm/ES33jpYkpnZtylwTlazuH1gmomJKj7\nFUbHrcjlIpROtSloO98GRmHxgiRHsuIsgwDXl44q/NjEQIeks4fiid4xG5rnBp09\n14flP59xclN448l408t7Z2w1Cem2ZEjJIwpSL9ECgYB+PAzjNbLnR8aS+n7rj6Sl\nrsqVfw+P3WqCAhMx7ZZwnbolG1gWLAH4W9NZ7FAB4uaCzzbJPqn5NiWAUnoS6w1D\nSW3argX71sJRUDcbWhfjldzAoPOdJRbEpcahKcuEesAU+hA8OZSQKCBxbG8pXJxe\nndzNGjOWR1w9FerTtG8ziwKBgAROmC7E0TSS/nfUjRVpWhQHIct5PpV7n4WaWLlq\nJw5nodPd4JEPfpOq8ezkXwu70ddpfPBQbM99Iue5VnoGxpiYZ7UHTNN8ldFvS6Xe\nWp5Y4yQoDs2ZBSCHb3uXGEaOzsggda0KswbD9sR+YEG9a7pcvdDFO8VdC+LCcQ09\npcBBAoGBAIAK75kv2qOZhTbkk/T4UuohQuwG0iqCPReG2/inH5gsfeRmblSrq50W\nqC1xhMbQosBR7t9OGkCF1yypW8qW3a8wh2JoOXV1tbjc6lC9DTsuVL/VXi3s1IbG\nJkWq4RTi9oTCwudLYUZyQuB6+2HCDP7SkWeCdEiH6vnbqEnufCSt\n-----END RSA PRIVATE KEY-----\n' } }
2018-04-18T11:13:25.531Z 81e505c0-42f9-11e8-8dcd-5360239d60ce { ResourceAlreadyExistsException: Policy cannot be created - name already exists (name=value1)
at Object.extractError (/var/runtime/node_modules/aws-sdk/lib/protocol/json.js:48:27)
at Request.extractError (/var/runtime/node_modules/aws-sdk/lib/protocol/rest_json.js:52:8)
at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:105:20)
at Request.emit (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:77:10)
at Request.emit (/var/runtime/node_modules/aws-sdk/lib/request.js:683:14)
at Request.transition (/var/runtime/node_modules/aws-sdk/lib/request.js:22:10)
at AcceptorStateMachine.runTo (/var/runtime/node_modules/aws-sdk/lib/state_machine.js:14:12)
at /var/runtime/node_modules/aws-sdk/lib/state_machine.js:26:10
at Request. (/var/runtime/node_modules/aws-sdk/lib/request.js:38:9)
at Request. (/var/runtime/node_modules/aws-sdk/lib/request.js:685:12)
message: 'Policy cannot be created - name already exists (name=value1)',
code: 'ResourceAlreadyExistsException',
time: 2018-04-18T11:13:25.528Z,
requestId: '8370610f-42f9-11e8-a62d-6119292db4d5',
statusCode: 409,
retryable: false,
retryDelay: 28.728075605593983 } 'ResourceAlreadyExistsException: Policy cannot be created - name already exists (name=value1)\n at Object.extractError (/var/runtime/node_modules/aws-sdk/lib/protocol/json.js:48:27)\n at Request.extractError (/var/runtime/node_modules/aws-sdk/lib/protocol/rest_json.js:52:8)\n at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:105:20)\n at Request.emit (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:77:10)\n at Request.emit (/var/runtime/node_modules/aws-sdk/lib/request.js:683:14)\n at Request.transition (/var/runtime/node_modules/aws-sdk/lib/request.js:22:10)\n at AcceptorStateMachine.runTo (/var/runtime/node_modules/aws-sdk/lib/state_machine.js:14:12)\n at /var/runtime/node_modules/aws-sdk/lib/state_machine.js:26:10\n at Request. (/var/runtime/node_modules/aws-sdk/lib/request.js:38:9)\n at Request. (/var/runtime/node_modules/aws-sdk/lib/request.js:685:12)'
image

"null" response after API gateway request

Hi,
when we request the API gateway(URL) for second time with the same serialNumber and deviceToken it shows the "null" response, instead of null response i want to show other message like Access deny etc.. Can you elaborate how you pass the "null" in response and how it change?
Thanks

Best policy practices for production

In config.js line 11;

// In actual production, the policy document should be generated dynamically.

Isn't it a waste that generating a policy for every single thing? Assume that thousands of devices for an IoT solution. I think it should be only a single policy which allows publish and subscribe to topics by their certificate ID's. An example from AWS IoT docs is like this:

{
    "Version": "2012-10-17",
    "Statement": [{
        "Effect": "Allow",
        "Action":["iot:Publish"],
        "Resource": ["arn:aws:iot:us-east-1:123456789012:topic/${iot:CertificateId}"]
    },
    {
        "Effect": "Allow",
        "Action": ["iot:Connect"],
        "Resource": ["*"]
    }]
}

What do you think about this, what are your recommendations about that?

Access denied by S3 when create CVM template

An error occurred at creation of AWS IOT Certificate Vending machine in CloudFormation operation:
Your access has been denied by S3, please make sure your request credentials have permission to GetObject for pubz/cvm-iot.zip. S3 Error Code: AccessDenied. S3 Error Message: Access Denied (Service: AWSLambda; Status Code: 403; Error Code: AccessDeniedException; Request ID: 98b6421b-a700-11e8-b7f3-3ddf2523b8eb)
Please HELP asap I need this working very soon.

Thanks

how to ensure one serialNumber only has one cert

In index.js, you said should write the certificate ID/Arn to indicate that the device has applied for a certificate. And the user can not apply again.
I do not understand this code, how to ensure one sn has one cert. Is it:

  1. DDB do not allow set certinfo the same value?

Looking forward to your reply.

image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.