2

我希望我的一些Lambda資源能夠使用aws-sdkAWS.IotData({ endpoint: url })函數推送到AWS IOT端點,其中endpoint是必需的參數。如何從CloudFormation模板中獲取AWS IOT端點URL?

現在,我通過環境變量將端點URL傳遞給我的Lambda。但是,當放入SAM/CF模板時,我無法找到檢索我的IOT端點URL的方式,以便我可以簡單地使用!Ref它。

通過AWS resource type reference瀏覽我沒有找到任何與IOT端點相對應的資源。

好像IOT端點只能手動調配,通過AWS控制檯(啓用/禁用),如下面的截圖:

IOT Endpoint AWS Console

如何過度配置的IOT具有控制權的任何建議端點或至少從SAM/CF模板中讀取IOT URL,而無需使用aws-cli編寫腳本?

回答

1

恐怕您無法配置IoT端點,因爲與物聯網端點相關的唯一API調用是DescribeEndpoint

您可以做的是創建一個支持Lambda的CloudFormation自定義資源。 Lambda函數將執行DescribeEndpoint調用(根據Lambda的運行時使用您選擇的AWS開發工具包)並返回端點的URL,以便其他CloudFormation資源可以使用它。

下面是Lambda支持的自定義資源的一個很好的示例:http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-custom-resources-lambda.html

1

對於任何對CloudFormation Custom Resource解決方案感興趣的人,我寫了一個簡單的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 
     Runtime: nodejs6.10 
     CodeUri: . 
     MemorySize: 128 
     Timeout: 3 
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(); 
} 
相關問題