AWS IoT Core 设备双向认证与证书自动化签发实践
AWS IoT Core 双向认证机制
AWS IoT Core 采用基于 TLS 1.2 的双向认证(mTLS)机制来保障设备与云端通信的安全。在此架构下,设备端必须持有受信任的 X.509 证书,同时 AWS IoT Core 也会向设备出示其根证书(Amazon Root CA)以供身份验证。
要使设备成功接入,其使用的证书必须满足以下条件之一:
- 证书由 AWS IoT 平台托管的 CA 直接签发。
- 证书由自定义 CA 签发,且该自定义 CA 证书已预先注册并激活在 AWS IoT Core 中。
设备证书获取方案
方案一:证书分发机 (Certificate Vending Machine, CVM)
适用于出厂时未预装证书的设备。设备通过安全的初始通道(如基于 UUID 和预共享密钥的认证)连接至企业自建的后端服务,后端服务调用 AWS IoT API 生成由 AWS 根 CA 签发的设备证书,并下发给设备。此方案的核心在于企业需自行开发并维护证书分发服务,同时通过 AWS IoT 控制台集中管控证书权限。
方案二:自定义 CA 即时注册 (JITR)
适用于企业拥有自有 PKI 体系的场景。通过将自有 CA 证书导入 AWS IoT Core,设备使用自有 CA 签发的证书首次连接时,可触发即时注册(Just In Time Registration)。
1. 证明自有 CA 所有权并注册
为确保安全性,AWS IoT Core 要求注册自定义 CA 时,必须证明申请者同时持有该 CA 证书及其对应的私钥。
首先,生成自签名 CA 证书及其私钥:
mkdir -p iot-certs && cd iot-certs
# 生成 CA 私钥
openssl genrsa -out my_ca_private.key 2048
# 生成自签名 CA 证书 (有效期 10 年)
openssl req -x509 -new -nodes -key my_ca_private.key -sha256 -days 3650 -out my_ca_cert.pem
获取 AWS IoT 的注册验证码:
aws iot get-registration-code
# 输出示例: {"registrationCode": "a1b2c3d4e5f6..."}
生成用于验证的私钥和 CSR,并将获取到的注册码作为 Common Name (CN):
openssl genrsa -out verify_private.key 2048
openssl req -new -key verify_private.key -out verify.csr
# 在交互提示中,将 Common Name 设置为上一步获取的 registrationCode
使用自有 CA 签发验证证书:
openssl x509 -req -in verify.csr -CA my_ca_cert.pem -CAkey my_ca_private.key -CAcreateserial -out verify_cert.crt -days 3650 -sha256
将 CA 证书和验证证书注册到 AWS IoT,并开启自动注册功能:
aws iot register-ca-certificate \
--ca-certificate file://my_ca_cert.pem \
--verification-certificate file://verify_cert.crt \
--set-as-active \
--allow-auto-registration
2. 签发设备证书
生成设备端的私钥和 CSR,并使用自有 CA 进行签发:
openssl genrsa -out device_private.key 2048
openssl req -new -key device_private.key -out device.csr
openssl x509 -req -in device.csr -CA my_ca_cert.pem -CAkey my_ca_private.key -CAcreateserial -out device_cert.crt -days 3650 -sha256
3. 配置自动化证书激活 (Lambda)
当设备首次使用新证书连接 AWS IoT Core 时,由于证书尚未激活,连接会被拒绝。此时,AWS IoT 会将证书状态设为 PENDING_ACTIVATION,并向 $aws/events/certificates/registered/<certificateId> 主题发布事件。
通过配置 IoT Rule 捕获该事件并触发 Lambda 函数,可实现证书的自动化激活与权限绑定。以下是使用 AWS SDK for JavaScript v3 重构的 Lambda 处理逻辑:
import { IoTClient, CreatePolicyCommand, AttachPolicyCommand, UpdateCertificateCommand } from "@aws-sdk/client-iot";
const iotClient = new IoTClient({ region: process.env.AWS_REGION || "cn-north-1" });
export const handler = async (event) => {
const certId = event.certificateId;
const awsAccount = event.awsAccountId;
const region = process.env.AWS_REGION || "cn-north-1";
const principalArn = `arn:aws-cn:iot:${region}:${awsAccount}:cert/${certId}`;
const policyName = `AutoGenPolicy_${certId.substring(0, 8)}`;
const policyDocument = {
Version: "2012-10-17",
Statement: [{
Effect: "Allow",
Action: ["iot:Connect", "iot:Publish", "iot:Subscribe", "iot:Receive"],
Resource: ["*"]
}]
};
try {
// 1. 创建设备专属策略
await iotClient.send(new CreatePolicyCommand({
policyName,
policyDocument: JSON.stringify(policyDocument)
}));
} catch (err) {
// 忽略策略已存在的异常
if (err.name !== 'ResourceAlreadyExistsException') throw err;
}
// 2. 将策略附加到设备证书主体
await iotClient.send(new AttachPolicyCommand({
policyName,
target: principalArn
}));
// 3. 将证书状态更新为激活
await iotClient.send(new UpdateCertificateCommand({
certificateId: certId,
newStatus: "ACTIVE"
}));
return { statusCode: 200, body: `Certificate ${certId} provisioned successfully.` };
};
4. 客户端连接验证
使用 Mosquitto 客户端进行测试。在连接前,需将设备证书与 CA 证书合并为完整的证书链:
cat device_cert.crt my_ca_cert.pem > device_cert_chain.crt
首次尝试发布消息,由于证书处于 PENDING_ACTIVATION 状态,连接将被拒绝。等待 Lambda 函数执行完毕(证书状态变为 ACTIVE)后,再次执行连接与发布命令:
mosquitto_pub \
--cafile AmazonRootCA1.pem \
--cert device_cert_chain.crt \
--key device_private.key \
-h <your-endpoint>.iot.cn-north-1.amazonaws.com.cn \
-p 8883 \
-q 1 \
-t "sensors/temperature" \
-i "device_001" \
--tls-version tlsv1.2 \
-m '{"temp": 25.5}' \
-d
此时设备将成功建立 MQTT 连接,并可在 AWS IoT 控制台的 "Test" 界面或订阅客户端中接收到发布的消息。
方案三:自定义 CA 即时配置 (JITP)
JITP (Just In Time Provisioning) 的流程与 JITR 高度相似,核心区别在于 JITP 不仅会自动注册和激活证书,还会根据预先在 AWS IoT Core 中定义的 Provisioning Template(配置模板),自动创建 AWS IoT Thing(设备实体),并将证书、策略与 Thing 进行绑定,从而实现设备身份的完整自动化配置。