[AWS IoT] Kinesis Firehoseに連携しLambdaまで繋げてみる – (2)AWS IoTの設定と動作確認

2016.02.13

はじめに

前回からの続きです。今回はAWS IoTで受信したメッセージをKinesis Firehoseに渡す設定について書きたいと思います。

AWS IoTの設定

1.Thingの作成

最初にThingを作成します。これはコマンド一つです。

$ aws iot create-thing --thing-name t-honda-iot-thing
{
    "thingArn": "arn:aws:iot:us-west-2:XXXXXXXXXXXX:thing/t-honda-iot-thing", 
    "thingName": "t-honda-iot-thing"
}

2.証明書の作成とキーの保存

証明書を作成し、キーを保存します。まずは証明書の作成し、後ほど使用するため結果をcert.jsonに出力します。

$ aws iot create-keys-and-certificate --set-as-active > cert.json
cert.json
{
    "certificateArn": "XXXXXX", 
    "certificatePem": "-----BEGIN CERTIFICATE-----\nXXXXXXXXX\n-----END CERTIFICATE-----\n", 
    "keyPair": {
        "PublicKey": "-----BEGIN PUBLIC KEY-----\nXXXXXXXXXX\n-----END PUBLIC KEY-----\n", 
        "PrivateKey": "-----BEGIN RSA PRIVATE KEY-----\nXXXXXXXXXX\n-----END RSA PRIVATE KEY-----\n"
    }, 
    "certificateId": "XXXXXXXXXX"
}

出力したcert.jsonよりPublicキー、Privateキーを取得します。Publicキーについては「iot_public_key.pem」というファイルを作成し、「keyPair」の「PublicKey」に書かれている値をコピーして保存します。Privateキーについては「iot_private_key.pem」というファイルを作成し、「PrivateKey」に書かれている値をコピーして保存します。

3.ポリシーの作成

ポリシーを作成します。ポリシーの詳細はiot_policy.jsonに記述しています。

$ aws iot create-policy --policy-name t-honda-iot-policy --policy-document file://iot_policy.json
{
    "policyName": "t-honda-iot-policy", 
    "policyArn": "arn:aws:iot:us-west-2:XXXXXXXXXXXX:policy/t-honda-iot-policy", 
    "policyDocument": "{\n    \"Version\": \"2012-10-17\", \n    \"Statement\": [{\n        \"Effect\": \"Allow\",\n        \"Action\":[\"iot:*\"],\n        \"Resource\": [\"*\"]\n    }]\n}", 
    "policyVersionId": "1"
}
iot_policy.json
{
    "Version": "2012-10-17", 
    "Statement": [{
        "Effect": "Allow",
        "Action":["iot:*"],
        "Resource": ["*"]
    }]
}

4.証明書の紐付け

証明書をポリシーとThingに紐づけます。まずはポリシーとの紐付けです。以下のコマンドを実行し、--principalには作成した証明書のArnを、--policy-nameにはポリシーの名称を渡します。

$ aws iot attach-principal-policy --principal arn:aws:iot:us-west-2:XXXXXXXXXXXX:cert/XXXXXXXXXXXXXXXXXXXXX --policy-name t-honda-iot-policy

次にThingとの紐付けです。以下のコマンドを実行し、--thing-nameにはThingの名称を、--principalには作成した証明書のArnを渡します。

$ aws iot attach-thing-principal --thing-name t-honda-iot-thing --principal arn:aws:iot:us-west-2:XXXXXXXXXXXX:cert/XXXXXXXXXXXXXXXXXXXXX

5.ロールの作成

AWS IoTを実行するためのロールを作成します。

$ aws iam create-role --role-name t-honda-iot-role --assume-role-policy-document file://iot_assume_role_policy.json
{
    "Role": {
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17", 
            "Statement": [
                {
                    "Action": "sts:AssumeRole", 
                    "Principal": {
                        "Service": "iot.amazonaws.com"
                    }, 
                    "Effect": "Allow", 
                    "Sid": ""
                }
            ]
        }, 
        "RoleId": "XXXXXXXXXXXXXXXXXXXX", 
        "CreateDate": "2016-02-11T04:39:40.374Z", 
        "RoleName": "t-honda-iot-role", 
        "Path": "/", 
        "Arn": "arn:aws:iam::XXXXXXXXXXXX:role/t-honda-iot-role"
    }
}
iot_assume_role_policy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "iot.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

作成したロールにロールポリシーを付与します。ロールポリシーの詳細はiot_role_policy.jsonに定義し、Kinesis FirehoseへPutする権限を付与します。

aws iam put-role-policy  --role-name t-honda-iot-role --policy-name t-honda-iot-role-policy --policy-document file://iot_role_policy.json
iot_role_policy.json
{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Action": "firehose:PutRecord",
    "Resource": "arn:aws:firehose:us-west-2:XXXXXXXXXXXX:deliverystream/t-honda-kinesis-to-s3"
  }
}

6.ルールの作成

ルールを作成します。iot_topic_rule_payload.jsonに詳細は定義し、「sql」では取得した全件を送信すること、送信先には前回作成したKinesis Firehoseの名称を指定します。

$ aws iot create-topic-rule --rule-name t_honda_iot_rule --topic-rule-payload file://iot_topic_rule_payload.json
iot_topic_rule_payload.json
{
    "sql": "select * from 'topic'", 
    "description": "", 
    "actions": [
        {
            "firehose": {
                "roleArn": "arn:aws:iam::XXXXXXXXXXXX:role/t-honda-iot-role", 
                "deliveryStreamName": "t-honda-kinesis-to-s3"
            }
        }
    ], 
    "ruleDisabled": false
}

以上でAWS IoTの設定ができました。

動作確認

実際に動作を確認してみます。IoT端末の代わりとしてruby-mqttを使用します。

1.ruby-mqttで実行するソース

以下のRubyスクリプトでruby-mqttよりAWS IoTにメッセージを送信します。

publish_firehose.rb
require "mqtt"
require "json"

hash = {
  timestamp: Time.now.strftime("%Y-%m-%d %H:%M:%S"),
  column1: "100",
  column2: "200",
  column3: "300"
}

MQTT::Client.connect(host: "XXXXXXXXXX.iot.us-west-2.amazonaws.com",
                     port: 8883,
                     ssl: true,
                     cert_file: "./pems/iot_cert.pem",
                     key_file: "./pems/iot_private_key.pem",
                     ca_file: "rootCA.pem") do |client|
  client.publish("topic", hash.to_json)
end

cert_file、key_fileは上記の証明書作成時に作成したpemを指定してください。またルート証明書を以下のコマンドで取得し、ca_fileとして指定します。

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

2.動作を確認する

以下のコマンドでRubyスクリプトを実行します。

$ bundle exec ruby publish_firehose.rb

S3のバケットにファイルが出力されていることを確認します。

aws_iot_kinesis_firehose_lambda_bucket

ファイルの内容
{"timestamp":"2016-02-11 15:03:59","column1":"100","column2":"200","column3":"300"}

LambdaのログをCloudWatchにて確認します。

aws_iot_kinesis_firehose_lambda_lambda_cloudwatch

IoTクライアントから送信したメッセージがLambdaに届いたことが確認できました。

まとめ

前回と今回とでAWS IoT → Kinesis Firehose → S3 → Lambdaとメッセージを伝える仕組みを作る事ができました。LambdaではJavaのプログラムを実行しているため、データの加工やRedshiftへの登録など色々と応用ができるかと思います。AWS IoTを使用した案件などで何かの助けになれば幸いです。

参考サイト

[新機能]Amazon Kinesis FirehoseでS3にデータを送ってみた #reinvent
AWS LambdaのファンクションをJavaで書く(S3イベント処理編)
ステップ 3: イベントソースを追加する(イベントを発行するように Amazon S3 を設定する)
イベント通知の有効化
Providing AWS Credentials in the AWS SDK for Java
AWS IoTとRuby製MQTTクライアントでPub/Subしてみた