本系列文章前面两篇介绍了 AWS IoT 支持的所有协议,认证和授权方式的原理和细节,以及其分别所适应的场景。并介绍了设备使用 IAM 身份认证和 Amazon Cognito 身份接入 AWS IoT 的参考步骤和参考代码。接下来本文介绍设备使用 X.509 证书身份认证方式接入 AWS IoT 的参考步骤和参考代码。
您可以使用 X.509 证书来认证设备。认证通过后,再通过 X.509 证书绑定的 IoT Policy 对请求进行鉴权。X.509 证书是设备默认的认证方式,如果没有特殊需求,一般建议使用这种方式。
device_x509_http_crt_arn=`aws iot create-keys-and-certificate \
--set-as-active --certificate-pem-outfile device_x509_http.crt \
--public-key-outfile device_x509_http.pem --private-key-outfile device_x509_http.key \
| jq .certificateArn | sed 's/"//g'`
为设备创建 IoT Policy。
aws iot create-policy --policy-name IoTPolicyForDeviceX509Http \
--policy-document "{
\"Version\": \"2012-10-17\",
\"Statement\": [
{
\"Effect\": \"Allow\",
\"Action\": \"iot:Publish\",
\"Resource\": [
\"arn:aws-cn:iot:cn-north-1:${account_id}:topic/IoTDemo/device_x509_http\"
]
}
]
}"
把 IoT Policy 绑定到设备证书。
aws iot attach-policy --policy-name IoTPolicyForDeviceX509Http \
--target ${device_x509_http_crt_arn}
生成设备模拟程序。
cat <<EOF > ~/awsIoTAccessDemo/device_x509_http.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import argparse
import os
#获取参数
parser = argparse.ArgumentParser(description='Send data to IoT Core')
parser.add_argument('--data', default="data from device x509 http",
help='data to IoT')
parser.add_argument('--endpoint_prefix', required=True,
help='your iot endpoint prefix.')
parser.add_argument('--client_cert', required=True,
help='your client cert file.')
parser.add_argument('--client_key', required=True,
help='your client key file.')
args = parser.parse_args()
private_data = args.data
endpoint_prefix = args.endpoint_prefix
client_cert = args.client_cert
client_key = args.client_key
device_name = 'device_x509_http'
region = 'cn-north-1'
private_topic = "IoTDemo/"+device_name
server_root_ca_file = "./AmazonRootCA1.pem"
client_cert_file = "./%s" % client_cert
client_key_file = "./%s" % client_key
#port 8444. 443需要支持ALPN
iot_endpoint = "https://%s.ats.iot.cn-north-1.amazonaws.com.cn:8443/topics/" % endpoint_prefix
data = "{\\\\\"source\\\\\":\\\\\"%s\\\\\", \\\\\"data\\\\\":\\\\\"%s\\\\\"}" % (device_name, private_data)
endpoint = iot_endpoint + private_topic
command = "curl --tlsv1.2 --cacert %s --cert %s --key %s -X POST -d \"%s\" %s" % (server_root_ca_file,client_cert_file,client_key_file,data,endpoint)
os.system(command)
EOF
运行设备模拟程序。
python device_x509_http.py --data "data from device x509 http." \
--endpoint_prefix ${endpoint_prefix} \
--client_cert ./device_x509_http.crt \
--client_key ./device_x509_http.key
在本系列文章第一篇的第4.3章节打开的控制台中查看AWS IoT收到的消息。
2.2 设备使用 MQTT 协议接入
为设备创建证书。
device_x509_mqtt_crt_arn=`aws iot create-keys-and-certificate \
--set-as-active --certificate-pem-outfile device_x509_mqtt.crt \
--public-key-outfile device_x509_mqtt.pem --private-key-outfile device_x509_mqtt.key \
| jq .certificateArn | sed 's/"//g'`
为设备创建 IoT Policy。
aws iot create-policy --policy-name IoTPolicyForDeviceX509Mqtt \
--policy-document "{
\"Version\": \"2012-10-17\",
\"Statement\": [
{
\"Sid\": \"VisualEditor0\",
\"Effect\": \"Allow\",
\"Action\": [
\"iot:Publish\",
\"iot:Receive\"
],
\"Resource\": \"arn:aws-cn:iot:cn-north-1:${account_id}:topic/IoTDemo/device_x509_mqtt\"
},
{
\"Sid\": \"VisualEditor1\",
\"Effect\": \"Allow\",
\"Action\": \"iot:Connect\",
\"Resource\": \"arn:aws-cn:iot:cn-north-1:${account_id}:client/device_x509_mqtt\"
},
{
\"Sid\": \"VisualEditor2\",
\"Effect\": \"Allow\",
\"Action\": \"iot:Subscribe\",
\"Resource\": \"arn:aws-cn:iot:cn-north-1:${account_id}:topicfilter/IoTDemo/device_x509_mqtt\"
}
]
}"
把 IoT Policy 绑定到设备证书。
aws iot attach-policy --policy-name IoTPolicyForDeviceX509Mqtt \
--target ${device_x509_mqtt_crt_arn}
生成设备模拟程序。
cat <<EOF > ~/awsIoTAccessDemo/device_x509_mqtt.py
#coding:utf-8
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient
import json
import time
import sys
import commands
import boto3
import argparse
parser = argparse.ArgumentParser(description='Send data to IoT Core')
parser.add_argument('--endpoint_prefix', required=True,
help='your iot endpoint prefix.')
parser.add_argument('--client_cert', required=True,
help='your client cert file.')
parser.add_argument('--client_key', required=True,
help='your client key file.')
args = parser.parse_args()
endpoint_prefix = args.endpoint_prefix
client_cert = args.client_cert
client_key = args.client_key
device_name = 'device_x509_mqtt'
region = 'cn-north-1'
private_topic = "IoTDemo/"+device_name
base_path = "./"
server_root_ca_file = base_path + "AmazonRootCA1.pem"
client_cert_file = base_path + client_cert
client_key_file = base_path + client_key
endpoint = "%s.ats.iot.cn-north-1.amazonaws.com.cn" % endpoint_prefix
port = 8883
# 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)
myAWSIoTMQTTClient.configureEndpoint(endpoint, port)
myAWSIoTMQTTClient.configureCredentials(server_root_ca_file, client_key_file, client_cert_file)
# 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
运行设备模拟程序。
python device_x509_mqtt.py \
--endpoint_prefix ${endpoint_prefix} \
--client_cert ./device_x509_mqtt.crt \
--client_key ./device_x509_mqtt.key
此设备模拟程序会一直运行,接受输入的数据,发送到AWS IoT Core,同时也订阅自己发送消息的topic。
输入要发送到 AWS IoT 的消息,如 “data from device X.509 MQTT.”,设备会接收到自己发送的这个消息。同时,在本系列文章第一篇的 4.3章节中打开的控制台中也可以看到此消息。
执行 Ctrl+C 停止程序。
3. 资源清理(可选)
target3=`aws iot list-targets-for-policy --policy-name IoTPolicyForDeviceX509Http | jq .targets[0] | sed 's/"//g'`
aws iot detach-policy --policy-name IoTPolicyForDeviceX509Http --target $target3
aws iot delete-policy --policy-name IoTPolicyForDeviceX509Http
cert_id3=`echo $target3| awk -F '/' '{print $2}'`
aws iot update-certificate --certificate-id $cert_id3 --new-status INACTIVE
aws iot delete-certificate --certificate-id $cert_id3
target4=`aws iot list-targets-for-policy --policy-name IoTPolicyForDeviceX509Mqtt | jq .targets[0] | sed 's/"//g'`
aws iot detach-policy --policy-name IoTPolicyForDeviceX509Mqtt --target $target4
aws iot delete-policy --policy-name IoTPolicyForDeviceX509Mqtt
cert_id4=`echo $target4| awk -F '/' '{print $2}'`
aws iot update-certificate --certificate-id $cert_id4 --new-status INACTIVE
aws iot delete-certificate --certificate-id $cert_id4
本篇作者