原文链接:https://aws.amazon.com/cn/blogs/china/connect-your-devices-to-aws-iot-securely-1/
区域:cn-northwest-1 接收设备名称:IoTDemo/#
1. 新建ec2 选择IAM角色AWSIoTDeviceAccessWorkshop,选择开放了22端口的安全组
虚机配置:安装 sudo yum install lrzsz
aws --version查看aws cli版本,若为1.0版本python为2.X版本,则需要重装aws cli到2.0版本
2. 卸载并重装aws cli:
卸载aws cli:
pip3 uninstall awscli
sudo rm -rf /usr/local/aws
sudo rm /usr/local/bin/aws
重装aws cli:
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
重装完后新开窗查看aws cli版本
注意:只有ec2-user用户python和aws版本会升级,root用户不会升级,原因未知。若不升级aws cli版本,照原文档中步骤,会提示版本过低。
继续使用ec2-user用户,不要使用root用户。root用户的版本还是1版本
sudo -s 切换用户后,exit进行退出
3. 配置操作环境
aws configure权限 区域为cn-northwest-1
准备操作目录。
mkdir -p ~/awsIoTAccessDemo cd ~/awsIoTAccessDemo/
下载证书
① wget https://www.amazontrust.com/repository/AmazonRootCA1.pem
② Public-Primary-Certification-Authority-G5.pem证书到 https://docs.broadcom.com/docs/verisign-class-3-public-primary-certification-authority-g5-en 下载
安装依赖
sudo yum install python3-pip3 jq -y pip3 install boto3 --user pip3 install AWSIoTPythonSDK --user pip3 install flask --user pip3 install paho-mqtt --user
获取 Account Id
account_id=`aws sts get-caller-identity | jq .Account|sed 's/"//g'`
获取 Account 的 IoT Endpoint 前缀
endpoint_prefix=`aws iot describe-endpoint \
| jq .endpointAddress | sed 's/"//g'| awk -F . '{print $1}'`
把 Account Id 和 IoT 的 Endpoint 前缀配置到环境变量中。
echo "export account_id=$account_id" >> ~/.bashrc echo "export endpoint_prefix=$endpoint_prefix" >> ~/.bashrc
echo $accout_id 命令查看account_id是否有值,endpoint_prefix同理。 cat ~/.bashrc 命令,查看bashrc文件是否已经新增了account_id等的值
4. 创建IAM身份及权限
若之前存在IotDeviceUser用户及对应策略,从IAM控制台,角色和策略中,删除
创建一个 IAM 用户,IoTDeviceUser
aws iam create-user --user-name IoTDeviceUser
为 IoTDeviceUser 用户创建 Access Key
aws iam create-access-key \
--user-name IoTDeviceUser > /tmp/IoT_demo_access_key
记录下 AccessKeyId 和 SecretAccessKey
AccessKeyId=`cat /tmp/IoT_demo_access_key| jq .AccessKey.AccessKeyId| sed 's/"//g'`
SecretAccessKey=`cat /tmp/IoT_demo_access_key| jq .AccessKey.SecretAccessKey| sed 's/"//g'`
echo $ 变量名,查看AccessKeyId和SecretAccessKey的值,若值不存在,可cat /tmp/IoT_demo_access_key查看文件的值,若文件中值不存在,可在控制台删除IAM用户,重复4中的内容。
5. 设备接入HTTP协议
为设备创建 IAM Policy,代理名称:IoTDeviceIAMHttpPolicy。注意修改区域,cn-northwest-1
device_IAM_http_policy_arn=`aws iam create-policy \ --policy-name IoTDeviceIAMHttpPolicy \ --policy-document "{ \"Version\": \"2012-10-17\", \"Statement\": [ { \"Sid\": \"VisualEditor0\", \"Effect\": \"Allow\", \"Action\": \"iot:Publish\", \"Resource\": [ \"arn:aws-cn:iot:cn-northwest-1:${account_id}:topic/IoTDemo/device_IAM_http\" ] } ] }" | jq .Policy.Arn | sed 's/"//g'`
把 IAM Policy 绑定 IAM 用户
aws iam attach-user-policy --user-name IoTDeviceUser \
--policy-arn ${device_IAM_http_policy_arn}
生成设备模拟程序, 注意修改区域
python代码,parser传入参数。device_name设备名称,即使用ec2模拟设备的ec2名称。
boto3.client初始化推送,client.publish进行推送
cat <<EOF > ~/awsIoTAccessDemo/device_IAM_http.py #!/usr/bin/env python # -*- coding: utf-8 -*- import boto3 import argparse import json #获取参数 parser = argparse.ArgumentParser(description='Send data to IoT Core') parser.add_argument('--data', default="data from device_IAM_http", help='data to IoT core topic') parser.add_argument('--AccessKeyId', required=True, help='AccessKeyId') parser.add_argument('--SecretAccessKey', required=True, help='SecretAccessKey') args = parser.parse_args() data = args.data access_key_id = args.AccessKeyId secret_access_key = args.SecretAccessKey device_name = 'device_IAM_http' region = 'cn-northwest-1' topic = "IoTDemo/"+device_name iot_data_client = boto3.client('iot-data',region_name=region,aws_access_key_id=access_key_id,aws_secret_access_key=secret_access_key) response = iot_data_client.publish( topic=topic, qos=0, payload=json.dumps({"source":device_name, "data":data}) ) EOF
打开aws控制台,搜索iot,测试-订阅主题- IoTDemo/# -订阅
运行设备模拟程序,注意使用python3。--data "推送内容"
python3 device_IAM_http.py --data "data from device IAM http." \ --AccessKeyId ${AccessKeyId} --SecretAccessKey ${SecretAccessKey}
aws控制台会收到消息
6. 设备使用 MQTT OVER WEBSOCKET 接入
为设备创建IAM Policy,代理名称:IoTDeviceIAMWebsocketPolicy。注意修改区域
device_IAM_websocket_policy_arn=`aws iam create-policy \ --policy-name IoTDeviceIAMWebsocketPolicy \ --policy-document "{ \"Version\": \"2012-10-17\", \"Statement\": [ { \"Sid\": \"VisualEditor0\", \"Effect\": \"Allow\", \"Action\": [ \"iot:Publish\", \"iot:Receive\" ], \"Resource\": \"arn:aws-cn:iot:cn-northwest-1:${account_id}:topic/IoTDemo/device_IAM_websocket\" }, { \"Sid\": \"VisualEditor1\", \"Effect\": \"Allow\", \"Action\": \"iot:Connect\", \"Resource\": \"arn:aws-cn:iot:cn-northwest-1:${account_id}:client/device_IAM_websocket\" }, { \"Sid\": \"VisualEditor2\", \"Effect\": \"Allow\", \"Action\": \"iot:Subscribe\", \"Resource\": \"arn:aws-cn:iot:cn-northwest-1:${account_id}:topicfilter/IoTDemo/device_IAM_websocket\" } ] }" | jq .Policy.Arn | sed 's/"//g'`
把 IAM Policy 绑定 IAM 用户,将代理绑定到IoTDeviceUser用户
aws iam attach-user-policy --user-name IoTDeviceUser \
--policy-arn ${device_IAM_websocket_policy_arn}
生成设备模拟程序
cat <<EOF > ~/awsIoTAccessDemo/device_IAM_websocket.py #!/usr/bin/env python # -*- coding: utf-8 -*- from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient import json import time import sys import argparse parser = argparse.ArgumentParser(description='Send data to IoT Core') parser.add_argument('--endpoint_prefix', required=True, help='endpoint prefix') parser.add_argument('--AccessKeyId', required=True, help='AccessKeyId') parser.add_argument('--SecretAccessKey', required=True, help='SecretAccessKey') args = parser.parse_args() endpoint_prefix = args.endpoint_prefix access_key_id = args.AccessKeyId secret_access_key = args.SecretAccessKey device_name = 'device_IAM_websocket' region = 'cn-northwest-1' private_topic = "IoTDemo/"+device_name base_path = "." server_root_ca_file = base_path + "/AmazonRootCA1.pem" endpoint = "%s.iot.cn-northwest-1.amazonaws.com.cn" % endpoint_prefix port = 443 # Custom MQTT message callback def customCallback(client, userdata, message): print("Received a new message: ") print(message.payload) print("from topic: ") print(message.topic) print("--------------\n\n") def pub_msg(): try: pri_loopCount = 0 while True: print ("please input:"), msg = raw_input() private_data = msg message = {} message['message'] = json.dumps({"source":device_name, "data":private_data}) message['sequence'] = pri_loopCount messageJson = json.dumps(message) myAWSIoTMQTTClient.publish(private_topic, messageJson, 1) pri_loopCount += 1 time.sleep(2) except: sys.exit() if __name__ == '__main__': # Init AWSIoTMQTTClient myAWSIoTMQTTClient = None myAWSIoTMQTTClient = AWSIoTMQTTClient(device_name, useWebsocket=True) myAWSIoTMQTTClient.configureEndpoint(endpoint, port) myAWSIoTMQTTClient.configureCredentials(server_root_ca_file) myAWSIoTMQTTClient.configureIAMCredentials(access_key_id, secret_access_key) # AWSIoTMQTTClient connection configuration myAWSIoTMQTTClient.configureAutoReconnectBackoffTime(1, 32, 20) myAWSIoTMQTTClient.configureOfflinePublishQueueing(-1) # Infinite offline Publish queueing myAWSIoTMQTTClient.configureDrainingFrequency(2) # Draining: 2 Hz myAWSIoTMQTTClient.configureConnectDisconnectTimeout(10) # 10 sec myAWSIoTMQTTClient.configureMQTTOperationTimeout(5) # 5 sec # Connect and subscribe to AWS IoT myAWSIoTMQTTClient.connect() myAWSIoTMQTTClient.subscribe(private_topic, 1, customCallback) time.sleep(2) pub_msg() EOF
运行设备模拟程序。 注意使用python3
python3 device_IAM_websocket.py --endpoint_prefix ${endpoint_prefix} \ --AccessKeyId ${AccessKeyId} --SecretAccessKey ${SecretAccessKey}
此设备模拟程序会一直运行,接受输入的数据,发送到 AWS IoT Core,同时也订阅自己发送消息的 topic。
输入要发送到 AWS IoT 的消息,如 “data from device IAM websocket.”,设备会接收到自己发送的这个消息。同时,在4.3章节中打开的控制台中也可以看到此消息。
执行 Ctrl+C 停止程序
7. 资源清理(可选)
aws iam detach-user-policy --user-name IoTDeviceUser --policy-arn arn:aws-cn:iam::${account_id}:policy/IoTDeviceIAMHttpPolicy aws iam detach-user-policy --user-name IoTDeviceUser --policy-arn arn:aws-cn:iam::${account_id}:policy/IoTDeviceIAMWebsocketPolicy aws iam delete-policy --policy-arn arn:aws-cn:iam::${account_id}:policy/IoTDeviceIAMHttpPolicy aws iam delete-policy --policy-arn arn:aws-cn:iam::${account_id}:policy/IoTDeviceIAMWebsocketPolicy AccessKeyId=`cat /tmp/IoT_demo_access_key| jq .AccessKey.AccessKeyId| sed 's/"//g'` aws iam delete-access-key --access-key-id $AccessKeyId --user-name IoTDeviceUser aws iam delete-user --user-name IoTDeviceUser rm -f /tmp/IoT_demo_access_key
照aws原文中踩坑后,自己总结备忘