如何在 Cloudformation 模板/CDK 中添加 AWS IoT 配置模板
Posted
技术标签:
【中文标题】如何在 Cloudformation 模板/CDK 中添加 AWS IoT 配置模板【英文标题】:How to add AWS IoT provisioning template in Cloudformation template / CDK 【发布时间】:2020-12-15 12:28:06 【问题描述】:我正在使用 Cloudformation 模板创建一个堆栈,其中包括 IoT 队列配置模板,根据 the document,IoT 配置模板正文应该是字符串类型。
我有这样的 IoT 队列配置模板:
"Parameters":
"SerialNumber":
"Type": "String"
,
"AWS::IoT::Certificate::Id":
"Type": "String"
,
"Resources":
"certificate":
"Properties":
"CertificateId":
"Ref": "AWS::IoT::Certificate::Id"
,
"Status": "Active"
,
"Type": "AWS::IoT::Certificate"
,
"policy":
"Properties":
"PolicyName": "mypolicy"
,
"Type": "AWS::IoT::Policy"
,
"thing":
"OverrideSettings":
"AttributePayload": "MERGE",
"ThingGroups": "REPLACE",
"ThingTypeName": "REPLACE"
,
"Properties":
"AttributePayload":
"SerialNumber":
"Ref": "SerialNumber"
,
"ThingName":
"Ref": "SerialNumber"
,
"Type": "AWS::IoT::Thing"
Cloudformation 模板是这样的:
AWSTemplateFormatVersion: '2010-09-09'
Description: "Template to create iot"
Resources:
FleetProvisioningTemplate:
Type: AWS::IoT::ProvisioningTemplate
Properties:
Description: Fleet provisioning template
Enabled: true
ProvisioningRoleArn: "arn:aws:iam::1234567890:role/IoT-role"
TemplateBody: String
TemplateName: mytemplate
我尝试将 IoT 配置模板的 JSON 字符串用于模板正文,但没有成功。我的问题是如何使用 Cloudformation 模板创建 IoT 配置模板?
更新 事实证明,我可以将 IoT 配置模板添加为“文字块”
AWSTemplateFormatVersion: '2010-09-09'
Description: "Template to create iot"
Resources:
FleetProvisioningTemplate:
Type: AWS::IoT::ProvisioningTemplate
Properties:
Description: Fleet provisioning template
Enabled: true
ProvisioningRoleArn: "arn:aws:iam::1234567890:role/IoT-role"
TemplateBody: |
"Parameters":
"SerialNumber":
"Type": "String"
,
"AWS::IoT::Certificate::Id":
"Type": "String"
,
"Resources":
"certificate":
"Properties":
"CertificateId":
"Ref": "AWS::IoT::Certificate::Id"
,
"Status": "Active"
,
"Type": "AWS::IoT::Certificate"
,
"policy":
"Properties":
"PolicyName": "cto-full-function-dev"
,
"Type": "AWS::IoT::Policy"
,
"thing":
"OverrideSettings":
"AttributePayload": "MERGE",
"ThingGroups": "DO_NOTHING",
"ThingTypeName": "REPLACE"
,
"Properties":
"AttributePayload": ,
"ThingGroups": [],
"ThingName":
"Ref": "SerialNumber"
,
"ThingTypeName": "cto"
,
"Type": "AWS::IoT::Thing"
TemplateName: mytemplate
但是,当我按照the cloudformation document 所说的那样添加 PreProvisioningHook 后,模板就会失败并出现无效请求错误。
AWSTemplateFormatVersion: '2010-09-09'
Description: "Template to create iot"
Resources:
LambdaHook:
Type: AWS::Lambda::Function
....
FleetProvisioningTemplate:
Type: AWS::IoT::ProvisioningTemplate
Properties:
Description: Fleet provisioning template
Enabled: true
ProvisioningRoleArn: "arn:aws:iam::1234567890:role/IoT-role"
PreProvisioningHook:
TargetArn:
"Fn::GetAtt": [
"LambdaHook",
"Arn"
]
PayloadVersion: "1.0"
TemplateBody: |
"Parameters":
"SerialNumber":
"Type": "String"
,
"AWS::IoT::Certificate::Id":
"Type": "String"
,
"Resources":
"certificate":
"Properties":
"CertificateId":
"Ref": "AWS::IoT::Certificate::Id"
,
"Status": "Active"
,
"Type": "AWS::IoT::Certificate"
,
"policy":
"Properties":
"PolicyName": "cto-full-function-dev"
,
"Type": "AWS::IoT::Policy"
,
"thing":
"OverrideSettings":
"AttributePayload": "MERGE",
"ThingGroups": "DO_NOTHING",
"ThingTypeName": "REPLACE"
,
"Properties":
"AttributePayload": ,
"ThingGroups": [],
"ThingName":
"Ref": "SerialNumber"
,
"ThingTypeName": "cto"
,
"Type": "AWS::IoT::Thing"
TemplateName: mytemplate
我也在here 上问过问题,但没有运气。有人遇到同样的问题并解决了吗?
【问题讨论】:
【参考方案1】:我终于想通了,但想分享一下,以防有人有同样的问题。
AWS IoT 文档未提及这一点,但如果您想为您的配置模板添加 PreProvisioningHook,您需要授予 IoT 对 lambda(AKA PreProvisioningHook)的访问权限,因此在 Cloudformation 模板中添加如下内容:
LambdaAddPermission:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:InvokeFunction
FunctionName: !GetAtt PreProvisionHook.Arn
Principal: iot.amazonaws.com
在 Provisioning Template 资源中,确保你有这个:
PreProvisioningHook:
PayloadVersion: '2020-04-01'
TargetArn:
"Fn::GetAtt": [
"PreProvisionHook",
"Arn"
]
【讨论】:
非常感谢!这修复了错误:提供的请求无效:验证配置挂钩期间访问被拒绝【参考方案2】:根据 Z Wang 的回答,这就是您在 AWS CDK 中的做法:
myLambda.addPermission('InvokePermission',
principal: new ServicePrincipal('iot.amazonaws.com'),
action: 'lambda:InvokeFunction',
);
【讨论】:
【参考方案3】:在 CDK 中,您也可以选择使用简写:
preProvisioningHookLambda.grantInvoke(new iam.ServicePrincipal('iot.amazonaws.com')) // allow iot to invoke this function
这是我供大家参考的TS代码:
import * as cdk from '@aws-cdk/core';
import * as iam from '@aws-cdk/aws-iam';
import * as lambdaNodeJS from '@aws-cdk/aws-lambda-nodejs';
import * as iot from "@aws-cdk/aws-iot";
const props =
stage: 'development'
const PolicyName = "DevicePolicy";
const templateName = 'DeviceProvisioningTemplateV1';
const templateBody =
Parameters:
SerialNumber:
Type: "String"
,
ModelType:
Type: "String"
,
"AWS::IoT::Certificate::Id":
Type: "String"
,
Resources:
certificate:
Properties:
CertificateId:
Ref: "AWS::IoT::Certificate::Id"
,
Status: "Active"
,
Type: "AWS::IoT::Certificate"
,
policy:
Properties:
PolicyName
,
Type: "AWS::IoT::Policy"
,
thing:
OverrideSettings:
AttributePayload: "MERGE",
ThingGroups: "DO_NOTHING",
ThingTypeName: "REPLACE"
,
Properties:
ThingGroups: [],
ThingName:
Ref: "SerialNumber"
,
Type: "AWS::IoT::Thing"
;
const preProvisioningHookLambda = new lambdaNodeJS.NodejsFunction(this, `provisioning-hook-lambda-$props?.stage`,
entry: './src/lambda/provisioning/hook.ts',
handler: 'handler',
bundling:
externalModules: [
]
,
timeout: cdk.Duration.seconds(5)
);
preProvisioningHookLambda.grantInvoke(new iam.ServicePrincipal('iot.amazonaws.com')) // allow iot to invoke this function
// Give the AWS IoT service permission to create or update IoT resources such as things and certificates in your account when provisioning devices
const provisioningRole = new iam.Role(this, `provisioning-role-arn-$props?.stage`,
assumedBy: new iam.ServicePrincipal('iot.amazonaws.com'),
);
provisioningRole.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSIoTThingsRegistration'));
new cdk.CfnOutput(this, 'provisioningRoleArn ', value: provisioningRole.roleArn || 'undefined' );
const provisioningTemplate = new iot.CfnProvisioningTemplate(this, `provisioning-hook-template-$props?.stage`,
provisioningRoleArn: provisioningRole.roleArn,
templateBody: JSON.stringify(templateBody),
enabled: true,
templateName,
preProvisioningHook:
payloadVersion: '2020-04-01',
targetArn: preProvisioningHookLambda.functionArn,
);
new cdk.CfnOutput(this, 'preProvisioningLambdaFunctionName ', value: preProvisioningHookLambda.functionName || 'undefined' );
new cdk.CfnOutput(this, 'provisioningTemplateName ', value: provisioningTemplate.templateName || 'undefined' );
【讨论】:
以上是关于如何在 Cloudformation 模板/CDK 中添加 AWS IoT 配置模板的主要内容,如果未能解决你的问题,请参考以下文章
如何在AWS CDK Policy Statement AddAction方法中嵌套键值对?
AWS - 如何使用 CDK/CloudFormation 将服务链接角色传递给自动缩放组?
如何在 AWS CDK 中使用 CfnParameter 而无需在运行时填写值