如何在CloudFormation模板中获取AWS IOT端点URL?

6
我希望我的一些Lambda资源能够使用 aws-sdkAWS.IotData({ endpoint: url }) 函数将数据推送到AWS IOT端点,其中端点是必需的参数。
目前,我通过环境变量将端点URL传递给我的Lambda。然而,当放入SAM / CF模板中时,我找不到检索IOT端点URL的方法,以便我可以简单地使用!Ref引用它。
浏览 AWS资源类型参考,我没有找到与IOT端点对应的资源。
似乎只能手动配置IOT端点,通过AWS控制台(启用/禁用),如下图所示: IOT Endpoint AWS Console 如何控制IOT端点或至少从SAM / CF模板中读取IOT URL的任何建议,而无需使用aws-cli进行脚本处理?
2个回答

7

如果有人对使用CloudFormation自定义资源的解决方案感兴趣,我编写了一个简单的Lambda和CF模板,为其他CF堆栈提供IOT终端节点地址。

template.yaml

AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Resources:
  IotEndpointProvider:
    Type: 'AWS::Serverless::Function'
    Properties:
      FunctionName: IotEndpointProvider
      Handler: iotEndpointProvider.handler
      Runtime: nodejs6.10
      CodeUri: .
      MemorySize: 128
      Timeout: 3
      Policies:
        - Version: '2012-10-17'
          Statement:
          - Effect: Allow
            Action: 
              - iot:DescribeEndpoint
            Resource:
              - '*'
  IotEndpoint:
    Type: 'Custom::IotEndpoint'
    Properties:
      ServiceToken: !GetAtt IotEndpointProvider.Arn
Outputs:
  IotEndpointAddress:
    Value: !GetAtt IotEndpoint.IotEndpointAddress
    Export:
      Name: IotEndpointAddress

iotEndpointProvider.js

var aws = require("aws-sdk");

exports.handler = function(event, context) {
    console.log("REQUEST RECEIVED:\n" + JSON.stringify(event));

    // For Delete requests, immediately send a SUCCESS response.
    if (event.RequestType == "Delete") {
        sendResponse(event, context, "SUCCESS");
        return;
    }

    const iot = new aws.Iot();
    iot.describeEndpoint({}, (err, data) => {
    let responseData, responseStatus;
        if (err) {
            responseStatus = "FAILED";
            responseData = { Error: "describeEndpoint call failed" };
            console.log(responseData.Error + ":\n", err);
        } else  {
            responseStatus = "SUCCESS";
            responseData = { IotEndpointAddress: data.endpointAddress };
            console.log('response data: ' + JSON.stringify(responseData));
        }

        sendResponse(event, context, responseStatus, responseData);
    });
};

// Send response to the pre-signed S3 URL 
function sendResponse(event, context, responseStatus, responseData) {

    var responseBody = JSON.stringify({
        Status: responseStatus,
        Reason: "See the details in CloudWatch Log Stream: " + context.logStreamName,
        PhysicalResourceId: context.logStreamName,
        StackId: event.StackId,
        RequestId: event.RequestId,
        LogicalResourceId: event.LogicalResourceId,
        Data: responseData
    });

    console.log("RESPONSE BODY:\n", responseBody);

    var https = require("https");
    var url = require("url");

    var parsedUrl = url.parse(event.ResponseURL);
    var options = {
        hostname: parsedUrl.hostname,
        port: 443,
        path: parsedUrl.path,
        method: "PUT",
        headers: {
            "content-type": "",
            "content-length": responseBody.length
        }
    };

    console.log("SENDING RESPONSE...\n");

    var request = https.request(options, function(response) {
        console.log("STATUS: " + response.statusCode);
        console.log("HEADERS: " + JSON.stringify(response.headers));
        // Tell AWS Lambda that the function execution is done  
        context.done();
    });

    request.on("error", function(error) {
        console.log("sendResponse Error:" + error);
        // Tell AWS Lambda that the function execution is done  
        context.done();
    });

    // write data to request body
    request.write(responseBody);
    request.end();
}

这是否意味着每次我需要获取 endPoint URL 时都必须调用此 Lambda 函数? - Giorgi_Mdivani
1
这取决于您的需求,但在这种情况下,Lambda函数将作为自定义资源被触发,在CloudFormation模板部署期间提供URL给所有需要知道该URL的资源。 - Jacek M
感谢您的回答,您能告诉我如何在同一存储库及其他存储库中引用该URL吗?我可以像这样做吗 - 环境: IOT_END_POINT: ${self:Outputs.IotEndPointAddress}? - Giorgi_Mdivani
我对CloudFormation还非常陌生,仍在摸索很多东西。 - Giorgi_Mdivani

3
很抱歉,你无法提供IoT端点,因为与IoT端点相关的唯一API调用是DescribeEndpoint
您可以创建一个支持Lambda CloudFormation自定义资源。 Lambda函数将执行DescribeEndpoint调用(根据Lambda运行时的AWS SDK选择),并返回端点的URL,以便您的其他CloudFormation资源可以使用它。
这里有一个关于Lambda支持的自定义资源的好例子:http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-custom-resources-lambda.html

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接