亚马逊AWS官方博客

Certificate Vending Machine:IoT设备接入AWS IoT平台解决方案

背景介绍

为了保证通信的安全性,IoT设备与 AWS IoT平台的MQTT通信使用基于证书的TLS 1.2双向认证体系。所谓的双向认证,即意味着IoT设备端需安装 IoT设备证书,并且,该证书应该由IoT平台所使用的CA证书进行签发,从而完成IoT平台对IoT设备端的认证,反之亦然。

为了保证IoT设备和IoT平台的安全对接,对于IoT设备端,需要安装2类证书:

  1. IoT设备证书
  2. IoT平台CA证书

何时应当使用 Certificate Vending Machine?

对于部分已经出厂的IoT设备,可能在生产过程中没有预装任何证书,但是又希望这些设备连接至AWS IoT平台。此时,Certificate Vending Machine (简称CVM) 可以作为给IoT设备写入相关证书的可行方案,让IoT设备自行向CVM 服务器申请AWS IoT平台CA根证书与IoT设备证书,并且通过AWS IoT管理平台控制设备证书权限,确保物联网通信安全。

通过此文档的设计思想和相关源码,开发者可以快速开发出符合自己项目需求的CVM系统。但是需要注意,由于默认情况下,原设备没有任何证书进行申请证书阶段的TLS认证,所以使用CVM的过程中需要注意三点:

  1. IoT设备与CVM系统通信时,原生并没有安全保护手段,所以需要在受信的DNS环境下进行,以防中间人攻击。或者采用其他安全链接的方式,例如使用HTTPS与CVM 服务器交互(需要额外证书)。
  2. IoT设备在利用CVM系统申请证书时, IoT设备本身应该具备唯一标识符用于设备的身份标识,例如序列号,client ID或者product ID等,通过该身份标识符进行证书申请及策略绑定。
  3. 所有通过CVM系统申请获发的IoT设备证书的CA根证书,只可以为AWS IoT平台默认使用的CA根证书(VeriSign Class 3 Public Primary G5证书)。如果需要使用自定义的CA根证书来进行IoT设备证书的签发,请参考另一篇文档 – JITR证书注册方式,即,为每个设备在出厂前写入独立的IoT设备证书和CA 根证书。

CVM实现原理

整个CVM实现可以分为三个部分: IoT设备端、CVM 系统和AWS IoT 平台

A. IoT设备端需要完成的:

  • 通过HTTPS 请求证书。
  • 请求时携带设备序列号以及密钥。

B. CVM 系统需要完成的:

  • 向IoT设备提供远程访问API接口。
  • CVM系统作为代理向IoT平台申请每一个IoT设备的证书。
  • 通过校验设备的请求信息与数据库是否一致再决定是否为当前IoT设备申请证书, CVM使用内部Node.js 语言实现。
  • 使用AWS 高性能的NoSQL数据库DynamoDB做为后台用户数据库。该数据库用来保存IoT设备出厂时注册的设备ID、密钥和IoT平台CA根证书等信息。
  • CVM系统通过查询DynamoDB数据中的关联关系,将IoT Thing Name,Certificate Policy以及Certificate ID关联至一起。同时,修改DynamoDB里的证书状态标识符,避免同一台设备遭到攻击后,重复向IoT平台大量申请证书的可能性,从而保证证书与设备的关联唯一性。

CVM系统的基本工作流程如下:

 

CVM系统的具体架构如下:

为了使CVM服务端更具稳定与扩展性,可以使用AWS API Gateway 和Lambda 来部署CVM。通过这种方式,不需要长时间维护和管理部署在EC2上的CVM,而是通过IoT设备的证书申请的需求,灵活的调配AWS上的服务资源。

具体如下:

1)  IoT设备发送相应API 请求到API Gateway申请IoT 证书

2)  AWS API Gateway调用申请证书的Lambda向IoT平台发起证书申请

3)  Lambda接收到请求后, 查询DynamoDB校验请求合法性

4)  确认当前请求合法之后,通过API的形式,向IoT平台申请证书

5)  IoT平台返回新创建的IoT设备证书,以及IoT设备证书对应的certificate ID

6)  通过查找DynamoDB中预先创建的对应关系,根据产品序列号,为当前申请到的证书附加对应的Thing Name(设备属性)以及Policy(权限)

7)  利用Lambda进行IoT设备证书的策略的绑定以及DynamoDB关联关系表里的证书状态标识符更新

8)  最终CVM将IoT平台CA根证书和IoT设备证书返回给IoT设备

使用EC2 替代API Gateway与Lambda的解决方案,其工作流程与搭建lambda的模式基本一致,仅在IoT设备与CVM系统通信时的调用关系上有所区别

1)   IoT设备向CVM服务器申请IoT 设备证书

2)  EC2接收到请求后,访问MySQL 校验请求合法性

3)  确认当前请求合法之后,CVM通过API的形式,向IoT平台发起获取IoT设备证书的请求

4)  IoT平台返回当前IoT设备对应的证书,以及当前证书的certificate ID

5)  通过查找MySQL中预先创建的对应关系,根据产品序列号,为当前证书附加对应的Thing Name(产品属性) 以及Policy(权限)

6)  CVM更新 MySQL的关联关系表中的当前设备的所有关联信息以及证书状态标识符

7)  最终CVM将IoT CA根证书和设备证书返回给IoT设备

目前AWS IoT平台默认所用的根证书(VeriSign Class 3 Public Primary G5)可以到这里下载:

https://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem

安全性说明

为了保证CVM系统的安全性,EC2 或者Lambda 函数需要赋予合适的IAM 角色, 使得CVM系统只能进行其授予的工作权限,以下用lambda举例如何为CVM系统分配正确的IAM角色权限。

首先,需要明确CVM系统需要具备以下IAM权限才能完成证书的申请及颁发过程:

√ 访问AWS DynamoDB,用于查询、修改、更新DynamoDB中的设备关联表

√ 访问IoT 平台,用于申请IoT设备证书

除IAM进行权限划分之外,需要在DynamoDB上创建一张关联关系表,用于设备、证书及策略的绑定关系,具体来说,需要在DynamoDB中创建如下数据库字段:

  • productid : IoT设备ID
  • accessToken: IoT设备Token
  • timestamp : 证书申请时间戳
  • applyState : 申请状态(如果申请过证书设置为-1,标记此设备已经注册过证书了)
  • certID : 设备关联的证书ID

核心代码说明

以下的CVM server代码使用了 AWS Node.js SDK 提供的IoT接口完成证书申请以及附加对应的Thing Name和Policy。

//使用createKeysAndCertificate 接口创建证书,此接口返回创建后的证书ID以及证书

iot.createKeysAndCertificate (params = {}, callback) ⇒ AWS.Request

# 如果需要使用CSR进行证书生成,可以使用以下接口

# iot.createCertificateFromCsr(params = {}, callback) ⇒ AWS.Request

 //为证书附加策略,传入上述接口返回的证书ID

iot.attachPrincipalPolicy(params = {}, callback) ⇒ AWS.Request

//为证书添加thing,同样是传入上述返回的证书ID

iot.attachThingPrincipal(params = {}, callback) ⇒ AWS.Request

CVM系统源码

https://github.com/cncoder/Certificate-Vending-Machine

参考链接

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