最低限の実装でAWS IoTの動作を確認する

最低限実装シリーズ２つめ。AWS IoTです
スクリーンショットが面倒臭すぎるので、AWS CLIでやってます

TL;DR
-----

AWS IoTのルールでS3に飛ばしてるだけです

手順
----

前提: Linux上でやってます。[AWS CLI](https://aws.amazon.com/jp/cli/)と[jq](https://stedolan.github.io/jq/)、あと検証には[mosquitto](https://mosquitto.org/)も使うので、そのへんを準備しておいてください


```console
### AWS IoT ポリシの作成
$ cat << EOT | aws iot create-policy --policy-name testingAllPubSub --policy-document file:///dev/stdin
{
    "Version": "2012-10-17",
    "Statement": [{
        "Effect": "Allow",
        "Action":["iot:*"],
        "Resource": ["*"]
    }]
}
EOT

### AWS IoT X.509クライアント証明書の作成
$ aws iot create-keys-and-certificate > cert.json
$ aws iot update-certificate --certificate-id $(cat cert.json | jq .certificateId -r) --new-status ACTIVE
$ aws iot describe-certificate --certificate-id $(cat cert.json | jq .certificateId -r) --output text --query certificateDescription.certificatePem > cert.pem
$ cat cert.json | jq .keyPair.PrivateKey -r > private-key.pem

### AWS IoT X.509クライアント証明書にAWS IoTポリシの割り当て
$ aws iot attach-principal-policy --principal $(cat cert.json | jq .certificateArn -r) --policy-name testingAllPubSub

### AWS IoT ルールからS3へデータをputできるようにするIAMロールとポリシの作成
$ cat << EOT | aws iam create-role --role-name testing_awsiot_put_to_s3 --assume-role-policy-document file:///dev/stdin
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal":{
         "Service":"iot.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOT
$ cat << EOT | aws iam put-role-policy --role-name testing_awsiot_put_to_s3 --policy-name put_to_s3 --policy-document file:///dev/stdin
{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Action": "s3:PutObject",
        "Resource": "arn:aws:s3:::testing-awsiot/*"
    }
}
EOT

### データ保存先のS3バケットの作成
$ aws s3api create-bucket --bucket testing-awsiot --create-bucket-configuration LocationConstraint=ap-northeast-1

### AWS IoTルールの作成
$ cat << EOT | aws iot create-topic-rule --rule-name testing_awsiot_put_to_s3 --topic-rule-payload file:///dev/stdin
{
  "sql": "SELECT * FROM 'testing_awsiot/#'",
    "actions": [
    {
      "s3": {
        "roleArn": "$(aws iam get-role --role-name testing_awsiot_put_to_s3 | jq .Role.Arn -r)",
        "bucketName": "testing-awsiot",
        "key": "\${timestamp()}"
      }
    }
    ]
}
EOT

### ルートCA証明書をSymantecから入手します
$ curl https://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem > rootca.pem
```

以上で準備は完了です

検証
----

送信

```console
$ mosquitto_pub -h $(aws iot describe-endpoint | jq .endpointAddress -r) -p 8883 --cafile rootca.pem --cert cert.pem --key private-key.pem -t testing_awsiot/bar -m '{"bar":1}'
```

確認

```console
$ aws s3 ls s3://testing-awsiot
2016-11-12 14:08:32          9 1478927310903

$ aws s3 cp s3://testing-awsiot/$(aws s3 ls s3://testing-awsiot | head -1 | awk '{print $NF}') ./awsiot_test_data.json
download: s3://testing-awsiot/1478927310903 to ./awsiot_test_data.json

$ cat ./awsiot_test_data.json
{"bar":1}
```

あとかたづけ
------------

```console
## AWS IoTルールの削除
$ aws iot delete-topic-rule --rule-name testing_awsiot_put_to_s3

### S3バケットの削除 (S3バケットを空に→削除)
$ aws s3 rm s3://testing-awsiot --recursive
$ aws s3api delete-bucket --bucket testing-awsiot --region ap-northeast-1

### IAMロールの削除
$ aws iam delete-role-policy --role-name testing_awsiot_put_to_s3 --policy-name put_to_s3
$ aws iam delete-role --role-name testing_awsiot_put_to_s3

### AWS IoT X.509クライアント証明書の削除 (証明書の非活性化→割り当て済みAWS IoTポリシの解除→削除)
$ aws iot update-certificate --certificate-id $(cat cert.json | jq .certificateId -r) --new-status INACTIVE
$ aws iot detach-principal-policy --principal $(cat cert.json | jq .certificateArn -r) --policy-name testingAllPubSub
$ aws iot delete-certificate --certificate-id $(cat cert.json | jq .certificateId -r)

### AWS IoTポリシの削除
$ aws iot delete-policy --policy-name testingAllPubSub

### 本項で使用したファイルの削除
$ rm cert.json cert.pem private-key.pem rootca.pem awsiot_test_data.json
```

あとがき
-------

最低限シリーズって需要あるんかな？