乐趣区

关于iot:利用Amazon-Lambda实现Amazon-IoT设备证书的即时注册

背景介绍

为了保障通信的安全性,Amazon IoT设施与 Amazon IoT Core 的 MQTT 通信应用基于证书的 TLS 1.2 双向认证体系。所谓的双向认证,即意味着 Amazon IoT 设施端需装置 Amazon IoT 设施证书,并且,签发该证书所应用的 CA 证书须要被 Amazon IoT Core 授信,从而实现 Amazon IoT Core 对 Amazon IoT 设施端的认证。并且,Amazon IoT 设施也会验证 Amazon IoT Core 的身份。

为了保障 Amazon IoT 设施和 Amazon IoT Core 的双向平安对接,对于 Amazon IoT 设施端,须要装置两类证书:

  1. Amazon IoT 设施证书
  2. Amazon IoT 平台的 CA 证书
  • Amazon IoT
    https://aws.amazon.com/cn/iot/

何时应用设施证书的即时注册

当用户心愿应用从第三方机构购买或者自签发的 CA 证书,并将由 CA 证书签发的设施证书的设施连贯到 Amazon IoT Core 时,能够利用即时注册性能来实现。如果心愿间接利用 Amazon IoT CA 证书签发的设施证书对设施进行注册激活,能够参考 Amazon Certificate Vending Machine 计划。

  • Amazon Certificate Vending Machine
    https://aws.amazon.com/cn/blo…

实现步骤如下:

  1. 创立 CA 证书并在 Amazon IoT Core 上注册和激活。
  2. 应用该 CA 证书签发设施证书并装置在 Amazon IoT 设施上。
  3. 创立 Amazon Lambda 函数实现设施证书在 Amazon IoT Core 上的主动注册。
  4. Amazon IoT 设施与 Amazon IoT Core 的第一次连贯。

筹备工作

本文中的 Amazon IoT 设施会应用一台 Amazon Linux EC2 实例模仿,并应用 MQTT Mosquitto Client 工具来模仿 MQTT 音讯交互过程。理论利用中的 Amazon IoT 设施须要集成 Amazon IoT SDK 以实现和 Amazon IoT Core 的交互。此外,接下来的所有操作都是以亚马逊云科技北京区为示例。

Amazon Linux EC2 实例上默认装置了亚马逊云科技命令行工具 Amazon AWSCLI,如读者应用其余实例或者本人的电脑,请参考 此链接 来装置 Amazon AWSCLI。

  • Amazon Linux EC2
    https://aws.amazon.com/cn/ec2/
  • 此链接:
    https://docs.aws.amazon.com/z…

第一步:创立 CA 证书并在 Amazon IoT Core 上注册和激活

在实在场景中,用户的设施证书常常是由两头 CA 证书 (Intermediate CA Certificate) 签发而来,而不是由根 CA 签发(Root CA Certificates)。为了不便起见,本步骤会跳过两头 CA 证书,间接用根证书签发设施证书。并且因为理论购买 CA 证书会让笔者付出 N 个月的薪水,这里咱们会应用 OpenSSL 来自签发证书,用户能够依据本人的理论状况抉择不同的签发形式。

登陆 Amazon EC2 实例并执行如下命令创立私钥和对应的 CA 证书:

$ mkdir cert
$ cd cert
$ openssl genrsa -out CA_Private.key 2048
$ openssl req -x509 -new -nodes -key CA_Private.key -sha256 -days 365 -out CA_Certificate.pem

左右滑动查看更多

咱们须要将这个 CA 证书注册到 Amazon IOT Core。为了平安,Amazon IOT Core 提供了相应的审核流程确保你同时持有 CA 证书和对应的私钥。因而,在最终注册 CA 证书之前,咱们还须要依照流程生成一份用于验证 CA 证书和私钥持有者身份的两头证书(请留神这份证书并不是下面创立的 CA 证书)。上面这个 Amazon AWSCLI 命令会返回一个随机生成的认证码,这个认证码会和你的账户绑定。记录下这个认证码,很快咱们就会用到。

$ aws iot get-registration-code

再次应用 OpenSSL 生成用于验证身份的私钥和证书申请文件(Amazon CSR – Amazon Certificate Signing Request)。

$ openssl genrsa -out Verification_Private.key 2048
$ openssl req -new -key Verification_Private.key -out Verification.csr

左右滑动查看更多

在创立 Amazon CSR 的过程中,你会被提醒输出如下一些内容,将前一步记录下的认证码填入到 Common Name 中:

…Organization Name (eg, company) []:Organizational Unit Name (eg, section)Common Name (e.g. server FQDN or YOUR name) []: XXXXXREGISTRATIONCODEXXXXX…

接下来,应用 CA 证书和私钥,以及下面创立的 Amazon CSR 来生成一份用于验证身份的两头证书。

$ openssl x509 -req -in Verification.csr -CA CA_Certificate.pem -CAkey 
CA_Private.key -CAcreateserial -out Verification.crt -days 365 -sha256

左右滑动查看更多

最初,通过如下命令导入 CA 证书和两头证书,Amazon IoT Core 会实现 CA 证书的注册和激活。同时,通过设置–allow-auto-registration 的形式开启设施连贯 Amazon IoT Core 时设施证书的主动注册。这个命令的输入会返回对应 CA 证书在 Amazon IoT Core 上的 ID(caCertificateId)。

$ aws iot register-ca-certificate --ca-certificate
file://CA_Certificate.pem --verification-certificate 
file://Verification.crt --set-as-active --allow-auto-registration

左右滑动查看更多

第二步:应用 CA 证书签发设施证书

当咱们创立并注册好 CA 证书之后,就能够开始用这个 CA 证书来签发设施证书了,步骤如下:

创立一个设施证书的私钥 Device.key 和对应的证书申请文件 Device_Certificate.csr。

$ openssl genrsa -out Device.key 2048
$ openssl req -new -key Device.key -out Device_Certificate.csr

左右滑动查看更多

应用 CA 证书,CA 证书私钥和证书申请文件签发设施证书 Device_Certificate.crt。

$ openssl x509 -req -in Device_Certificate.csr -CA CA_Certificate.pem -CAkey 
CA_Private.key -CAcreateserial -out Device_Certificate.crt -days 365 -sha256

左右滑动查看更多

在创立好设施证书并在设施上装置实现后,你可能要问,那我如何注册并应用设施证书呢?你当然能够通过 Amazon AWSCLI 命令行甚至图形界面在 Amazon IoT Core 上实现注册,然而面对着千千万万的 Amazon IoT 设施,应该没有人想这样手动去做。接下来咱们就会介绍利用 Amazon Lambda 函数,在设施第一次连贯 Amazon IoT Core 时,主动实现设施证书的注册过程。

第三步:创立 Amazon Lambda 函数和 Amazon IoT 规定实现设施证书在 Amazon IoT Core 上的激活和权限附加

当 Amazon IoT 设施第一次连贯 Amazon IoT Core 时,如果它集成的设施证书是由已在 Core 上注册的 CA 证书签发而来,那么相应的设施证书会实现主动注册,注册后的默认状态为“PENDING_ACTIVATION”,意味着尽管设施证书曾经胜利注册,然而还处于期待激活的状态。同时,这个连贯动作默认会发一条音讯到 Amazon IoT Core 的 MQTT Topic“$aws/events/certificates/registered/”上,这条音讯事件会是如下的格局:

{

"certificateId": "<certificateID>",

"caCertificateId": "<caCertificateId>",

"timestamp": "<timestamp>",

"certificateStatus": "PENDING_ACTIVATION",

"awsAccountId": "<awsAccountId>",

"certificateRegistrationTimestamp": "<certificateRegistrationTimestamp>"

}

左右滑动查看更多

大家都晓得 Amazon Lambda 函数的执行能够由事件来触发,那么接下来咱们会做两件事:

  1. 创立一个 Amazon Lambda 函数,接管传入的事件,执行代码逻辑去激活设施证书并附加上一条 Policy 去给予这个设施相应的权限。
  2. 创立一 Amazon IoT 规定,订阅 MQTT Topic“$aws/events/certificates/registered/”,当有音讯发到这个 Topic 上时,将音讯转发给 Amazon Lambda 函数解决(激活证书并附加 Policy)。

首先,咱们来创立这个 Amazon Lambda 函数:

  1. 登陆到 Amazon Console 并进入 Amazon Lambda 页面。
  • Amazon Lambda
    https://console.amazonaws.cn/…

  1. 点击“创立函数”后抉择“从头开始创作”。
  2. 填入“名称”,运行语言选择“Node.js 6.10”,角色抉择“创立自定义角色”。

  1. 在新弹出的窗口中,Amazon IAM 角色抉择“创立新的 Amazon IAM 角色”,填入角色名称,点击“查看策略文档”,点击“编辑”。

  1. 点击“编辑”会弹出一个窗口,提醒在编辑之前务必读一下相干文档,这里咱们间接点击确定按钮。当然如果有工夫的话,还是倡议先读一下文档。
  2. 用如下的策略替换现有策略,能够看到这里咱们为 Amazon Lambda 函数增加了更新证书和附加 Policy 的权限,点击“容许”实现角色和策略的配置。
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws-cn:logs:*:*:*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "iot:UpdateCertificate",
        "iot:CreatePolicy",
        "iot:AttachPrincipalPolicy"
      ],
      "Resource": "*"
    }
  ]
}

左右滑动查看更多

7. 点击创立函数进入函数配置界面,替换函数以后的代码为:

/** 
This node.js Lambda function code creates and attaches an IoT policy to the 
just-in-time registered certificate. It also activates the certificate. The Lambda
function is attached as a rule engine action to the registration topic 
$aws/events/certificates/registered/<caCertificateID>
**/

var AWS = require('aws-sdk');

exports.handler = function (event, context, callback) {

  // 依据理论部署区域写入,在 certificateARN 一处也是。var region = "cn-north-1";
  var accountId = event.awsAccountId.toString().trim();
  var iot = new AWS.Iot({
    'region': region,
    apiVersion: '2015-05-28'
  });

  var certificateId = event.certificateId.toString().trim();

  // 这里你能够替换成你想要的 topic 名称
  var topicName = `JITR/test`;
  var certificateARN = `arn:aws-cn:iot:${region}:${accountId}:cert/${certificateId}`;
  var policyName = `Policy_${certificateId}`;
  // 定义 Policy 并赋予权限,容许 IoT 设施连贯,公布,订阅和承受音讯
  var policy = {
    "Version": "2012-10-17",
    "Statement": [
      {
        "Action": [
          "iot:Publish",
          "iot:Subscribe",
          "iot:Connect",
          "iot:Receive"
        ],
        "Effect": "Allow",
        "Resource": ["*"]
      }
    ]
  };

  /*
  创立 Policy
  */
  iot.createPolicy({policyDocument: JSON.stringify(policy),
    policyName: policyName
  }, (err, data) => {

    //Ignore if the policy already exists
    if (err && (!err.code || err.code !== 'ResourceAlreadyExistsException')) {console.log(err);
      callback(err, data);
      return;
    }
    console.log(data);
    /*
    附加 Policy 到设施证书上
    */
    iot.attachPrincipalPolicy({

      policyName: policyName,
      principal: certificateARN
    }, (err, data) => {

      //Ignore if the policy is already attached
      if (err && (!err.code || err.code !== 'ResourceAlreadyExistsException')) {console.log(err);
        callback(err, data);
        return;
      }
      console.log(data);
      /*
      激活证书
      */
      iot.updateCertificate({
        certificateId: certificateId,
        newStatus: 'ACTIVE'
      }, (err, data) => {if (err) {console.log(err, err.stack);
          callback(err, data);
        } else {console.log(data);
          callback(null, "Success, created, attached policy and activated the certificate" + certificateId);
        }
      });
    });
  });
}

左右滑动查看更多

8. 点击页面右上角的“保留”来实现 Amazon Lambda 函数的创立。

在 Amazon Lambda 函数创立实现后,咱们持续创立 Amazon IoT 规定:

  1. 进入 Amazon IoT 界面。
  2. 点击页面左侧的“口头”,而后点击右上角的“创立”。

  1. 在创立规定页面中填入规定的“名称”和“形容”,在“属性”一栏填入一个星号“*”。

  1. 在创立规定页面中的“主题筛选条件”里填入“$aws/events/certificates/registered/”,留神这外面的要替换成之前用 OpenSSL 签发的 CA 证书的 ID,这个 ID 能够通过在 Amazon IoT 界面的左侧点击“平安”->“CA”来取得。

  1. 在设置一个或多个操作中点击“增加操作”,抉择“调用 Amazon Lambda 函数,传递音讯数据”,而后点击“配置操作”。

  1. 函数名称抉择之前创立的 Amazon Lambda 函数名称,而后点击“增加操作”。

7. 点击“创立规定”实现 Amazon IoT 规定的配置。

到此为止,Amazon Lambda 函数和 Amazon IoT 规定创立实现。接下来,咱们来尝试连贯设施到 Amazon IoT Core 上。

第四步:Amazon IoT 设施与 Amazon IoT Core 的第一次连贯

为了模仿一台设施,你能够装置 Amazon IoT SDK,通过本人的代码调用亚马逊云科技来实现所有的性能。这里咱们为了简化步骤和节约工夫,抉择间接在之前创立的 Amazon EC2 上装置 MQTT Mosquitto Client 工具。

  • MQTT Mosquitto Client:
    https://mosquitto.org/

登陆到 Amazon EC2 实例并执行如下命令:

$ sudo wget http://download.opensuse.org/repositories/home:/oojah:/mqtt/CentOS_CentOS-7/home:oojah:mqtt.repo -O /etc/yum.repos.d/mqtt.repo

$ sudo yum install mosquitto mosquitto-clients -y

# 如果下面的命令执行时报依赖短少的谬误,能够加上 --skip-broken 再执行一遍即可
$ sudo yum install mosquitto mosquitto-clients -y --skip-broken

左右滑动查看更多

进入到之前创立的 cert 目录。

$ cd cert

合并 CA 证书和设施证书到一个新的证书造成无效的证书链。

$ cat Device_Certificate.crt CA_Certificate.pem > Device_CA_Certificate.crt

左右滑动查看更多

执行 mosquitto_pub 命令去公布一个音讯到对应的 topic 下面,这也是设施与 Amazon IoT Core 的第一次连贯。如果你回忆一下之前的步骤,到目前为止咱们的设施证书还只存在于设施下面,并没有在 Amazon IoT Core 上注册,那么接下来见证奇观的时刻就要到啦!

$ mosquitto_pub --cafile root-CA.crt --cert Device_CA_Certificate.crt --key Device.key -h xxxxxxxxxxxxxx.iot.cn-north-1.amazonaws.com.cn -p 8883 -q 1 -t JITR/test -i anyclientID --tls-version tlsv1.2 -m "Hello" -d

左右滑动查看更多

  • 命令中的 -cafile 是 Amazon IoT Core 的 CA 证书,用于设施去验证 Amazon IoT Core 的身份,这个文件能够通过此 链接 取得
  • 命令中的 -cert 是合并 CA 证书和设施证书后的证书链
  • 命令中的 -key 是设施的私钥
  • 命令中的 - h 是 Amazon IoT Core 的接入点,能够通过在 Amazon IoT 界面中左下角点击“设置”取得
  • 命令中的 - t 是你要公布音讯到哪一个 topic 上,这里我是公布到 JITR/test,你能够抉择本人想要公布的 topic
  • 命令中的 - i 能够依照你心愿的名字命名

在第一次执行这个命令后,你会看到如下的报错,那么这是为什么呢?

Client anyclientID sending CONNECT
Error: The connection was lost.

实际上设施在第一次连贯 Amazon IoT Core 的时候,设施证书还没有注册,所以 TLS 认证会失败。这个连贯动作会公布一条注册音讯到“$aws/events/certificates/registered/”下面,接下来 Amazon Lambda 函数接管到这个音讯后,会实现设施证书的注册,附加 Policy,那么咱们再次执行这个命令就能够胜利了。

$ mosquitto_pub --cafile root-CA.crt --cert Device_CA_Certificate.crt --key Device.key -h xxxxxxxxxxxxxx.iot.cn-north-1.amazonaws.com.cn -p 8883 -q 1 -t JITR/test -i anyclientID --tls-version tlsv1.2 -m "Hello" -d

左右滑动查看更多

输入如下:

Client anyclientID sending CONNECT
Client anyclientID received CONNACK
Client anyclientID sending PUBLISH (d0, q1, r0, m1, 'JITR/test', ... (5 bytes))
Client anyclientID received PUBACK (Mid: 1)
Client anyclientID sending DISCONNECT

左右滑动查看更多

这里要留神的是,在理论环境中,用户的代码逻辑里要负责解决这一个过程,也就是说在第一次连贯失败后须要主动重连一次或屡次来实现证书的注册与设施的激活。

这时进入 Amazon IoT 界面,点击左侧的平安后,在证书页面中能够看到咱们的设施证书曾经注册实现并激活了。

参考链接

  • Just-in-Time Registration of Device Certificates on Amazon IoT: 
    https://aws.amazon.com/blogs/…

本篇作者


郭松
亚马逊云科技解决方案架构师
负责企业级客户的架构征询及设计优化,同时致力于 Amazon IoT 和存储服务在国内和寰球企业客户的利用和推广。退出亚马逊云科技之前在 EMC 研发核心负责零碎工程师,对企业级存储利用的高可用架构,计划及性能调优有深入研究。

退出移动版