亚马逊AWS官方博客

Certification Vending Machine: 智能设备接入AWS IoT平台解决方案

作者:刘洪曦 谢佰臻

背景介绍

AWS IoT平台为了保证终端设备通信的安全性,终端设备与 AWS IoT平台的MQTT通信使用基于证书的TLS 1.2双向认证体系。即IoT平台会验证当前设备使用的证书是否可信,同时,终端设备也会验证IoT平台使用的CA证书是否可信。

这种双向TLS验证模式就会要求设备上所使用的证书需要具备以下条件之一:

  1. IoT终端设备上所使用的证书为AWS IoT平台所签发的
  2. IoT终端设备上所使用的证书的CA证书预先导入了AWS IoT平台

所以开发者应该尽量确保每个设备上在出厂前,为每个设备写入独立的证书,并要求该证书为IoT平台所信任的证书。这种方式也是最安全高效的。

何时应当使用 Certificate Vending Machine?

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

通过此项目的设计思想和相关源码,开发者可以快速开发出符合自己项目需求的CVM系统。但是需要注意,由于原设备没有IoT证书进行TLS双向认证,所以进行CVM的过程中需要注意三点:

  1. IoT设备与CVM系统通信时,原生并没有安全保护手段,所以需要在受信的DNS环境下进行,以防中间人攻击。或者采用其他安全链接的方式,例如使用HTTPS与CVM 服务器交互。
  2. IoT设备在利用CVM系统申请证书时,由于不具备用于标识设备的证书,所以IoT设备本身应该具备唯一标识符用于设备的身份标识,例如序列号,client ID或者product ID等,通过该身份标识进行证书申请及策略绑定。
  3. 所有通过CVM系统申请获发的证书的跟证书,均为AWS IoT平台默认使用的CA根证书。如果需要使用自定义的CA跟证书,请参考JITR证书认证方式。

CVM实现原理

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

A.智能设备端

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

B. CVM 系统

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

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

CVM系统的具体架构如下:

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

具体如下:

  1. IoT终端设备升级时请求接入IoT平台,发送相应API 请求到API Gateway申请IoT 证书
  2. AWS API Gateway调用申请证书的Lambda向IoT平台发起证书申请
  3. Lambda接收到请求后, 查询DynamoDB校验请求合法性
  4. 确认当前请求合法之后,通过API的形式,向IoT平台申请证书
  5. IoT平台返回当前IoT终端设备对应的证书,以及当前证书的certificate ID
  6. 通过查找DynamoDB中预先创建的对应关系,根据产品序列号,为当前申请到的证书附加对应的Thing Name(产品属性) 以及Policy(权限)
  7. Lambda进行证书的策略的绑定及DynamoDB关联关系表的更新
  8. 最终CVM将证书返回给IoT终端设备

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

  1. IoT终端设备升级时请求接入IoT平台,向CVM  Server申请IoT 证书
  2. EC2接收到请求后,访问Device DB 校验请求合法性
  3. CVM Server通过API的形式,向IoT平台发起获取IoT安全证书的请求
  4. IoT平台返回当前IoT终端设备对应的证书,以及当前证书的certificate ID
  5.  通过查找DynamoDB中预先创建的对应关系,根据产品序列号,为当前证书附加对应的Thing Name(产品属性) 以及Policy(权限)
  6. 更新当前设备的所有关联信息到DynamoDB的关联关系表中
  7. CVM将证书返回给IoT终端设备

安全性说明

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

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

  • 访问AWS DynamoDB,用于查询、修改、更新DynamoDB中的设备关联表
  • 访问IoT 平台,用于申请IoT终端设备证书

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

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

核心代码说明

以下的CVM server代码使用了 AWS Node.js SDK 提供的IOT接口完成证书申请以及附加对用的thingName和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系统服务器端源码(EC2):

https://github.com/cncoder/cvm/tree/master/server

CVM系统服务器端源码(Lambda):

https://github.com/cncoder/cvm/tree/serverless/server

智能设备端源码:

https://github.com/cncoder/cvm/tree/serverless/device

参考链接

http://docs.thinkwithwp.com/AWSJavaScriptSDK/latest/AWS/Iot.html

 

作者介绍:

刘洪曦,AWS解决方案架构师,负责基于AWS的云计算方案架构的咨询和设计,同时致力于帮助海外企业在AWS云服务的应用和推广。在加入AWS之前曾在思科担任网络顾问工程师,负责亚太区域物联网及安全业务的拓展及架构设计,在物联网,数据安全,网络架构有丰富部署实践经验。

谢佰臻,亚马逊AWS解决方案架构师实习生,擅长网站架设与网络应用开发,熟悉使用Node.js、Html5、Mysql数据库,对于Serverless 架构有自己的理解和实践经验。