【问题标题】:How to add AWS IoT provisioning template in Cloudformation template / CDK如何在 Cloudformation 模板/CDK 中添加 AWS IoT 配置模板
【发布时间】: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 上问过问题,但没有运气。有人遇到同样的问题并解决了吗?

【问题讨论】:

    标签: amazon-web-services amazon-cloudformation iot


    【解决方案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' });
      

      【讨论】:

        猜你喜欢
        • 2017-10-30
        • 2017-11-19
        • 2016-10-29
        • 1970-01-01
        • 2023-03-19
        • 2020-07-22
        • 2017-06-04
        • 2018-07-21
        • 2020-03-13
        相关资源
        最近更新 更多