Módulo cfn-response
En su plantilla de CloudFormation puede especificar una función de Lambda como destino de un recurso personalizado. Al utilizar la propiedad ZipFile
para especificar el código fuente de la función, puede cargar el módulo cfn-response
para enviar las respuestas desde su función de Lambda a un recurso personalizado. El módulo cfn-response
es una biblioteca que simplifica el envío de respuestas al recurso personalizado que invocó la función de Lambda. El módulo tiene un método send
que envía un objeto de respuesta a un recurso personalizado mediante una URL prefirmada de Amazon S3 (ResponseURL
).
El módulo cfn-response
solo está disponible si utiliza la propiedad ZipFile
para escribir el código fuente. No está disponible para el código fuente que se almacena en buckets de Amazon S3. Para un código de buckets de , debe escribir sus propias funciones para enviar respuestas.
nota
Después de ejecutar el método send
, la función de Lambda termina, así que todo lo que escriba después de este método se pasa por alto.
Carga del módulo cfn-response
Para las funciones de Node.js, utilice la función require()
para cargar el módulo cfn-response
. Por ejemplo, el siguiente ejemplo de código crea un objeto cfn-response
con el nombre response
:
var response = require('cfn-response');
Para Python, utilice la declaración import
para cargar el módulo cfnresponse
, tal y como se muestra en el ejemplo siguiente:
nota
Utilice esta declaración de importación exacto. Si utiliza otras variantes de la instrucción de importación, CloudFormation no incluirá el módulo de respuesta.
import cfnresponse
Parámetros del método send
Puede utilizar los siguientes parámetros con el método send
.
event
-
Los campos de una solicitud de recurso personalizado.
context
-
Un objeto, específico de las funciones de Lambda, que puede utilizar para especificar cuando la función y cualquier devolución de llamada han completado la ejecución o para obtener acceso a información desde el entorno de ejecución de Lambda. Para obtener más información, consulte Programming model (Node.js) (Modelo de programación [Node.js]) en la Guía para desarrolladores de AWS Lambda.
responseStatus
-
Independientemente de que la función se complete con éxito. Utilice las constantes del módulo
cfnresponse
para especificar el estado:SUCCESS
para las ejecuciones de éxito yFAILED
para ejecuciones fallidas. responseData
-
El campo
Data
de un objeto de respuesta de recursos personalizados. Los datos consisten en una lista de pares de nombre y valor. physicalResourceId
-
Opcional. El identificador único del recurso personalizado que invocó la función. De forma predeterminada, el módulo utiliza el nombre de la secuencia de registros de Amazon CloudWatch Logs que se asocia a la función de Lambda.
El valor devuelto para un
PhysicalResourceId
puede cambiar las operaciones de actualización de recursos personalizadas. Si el valor devuelto es el mismo, se considera una actualización normal. Si el valor devuelto es diferente, CloudFormation reconoce la actualización como un reemplazo y envía una solicitud de eliminación al antiguo recurso. Para obtener más información, consulteAWS::CloudFormation::CustomResource
. noEcho
-
Opcional. Indique si se enmascara la salida del recurso personalizado cuando se recupera con la función
Fn::GetAtt
. Si se establece entrue
, todos los valores devueltos se enmascaran con asteriscos (*****), excepto la información almacenada en las ubicaciones especificadas a continuación. De forma predeterminada, este valor esfalse
.importante
El uso del atributo
NoEcho
no enmascara ninguna información almacenada en lo que se muestra a continuación:-
La sección de la plantilla
Metadata
. CloudFormation no transforma, modifica ni redacta ninguna información que incluya en la secciónMetadata
. Para obtener más información, consulte Referencia sintáctica de la sección Metadata para las plantillas de CloudFormation. -
La sección de la plantilla
Outputs
. Para obtener más información, consulte Referencia sintáctica de la sección Outputs para las plantillas de CloudFormation. -
El atributo
Metadata
de una definición de recurso. Para obtener más información, consulte Atributo Metadata.
Recomendamos encarecidamente que no utilice estos mecanismos para incluir información confidencial, como contraseñas o secretos.
Para obtener más información sobre el uso de
NoEcho
para enmascarar información confidencial, consulte la práctica recomendada de No integre credenciales en sus plantillas. -
Ejemplos
Node.js
En el siguiente ejemplo Node.js, la función de Lambda en línea toma un valor de entrada y lo multiplica por 5. Las funciones en línea son especialmente útiles para las funciones más pequeñas, ya que le permiten especificar el código fuente directamente en la plantilla, en lugar de crear un paquete y cargarlo en un bucket de Amazon S3. La función utiliza el método cfn-response
send
para enviar el resultado de vuelta al recurso personalizado que invocó.
JSON
"ZipFile": { "Fn::Join": ["", [ "var response = require('cfn-response');", "exports.handler = function(event, context) {", " var input = parseInt(event.ResourceProperties.Input);", " var responseData = {Value: input * 5};", " response.send(event, context, response.SUCCESS, responseData);", "};" ]]}
YAML
ZipFile: > var response = require('cfn-response'); exports.handler = function(event, context) { var input = parseInt(event.ResourceProperties.Input); var responseData = {Value: input * 5}; response.send(event, context, response.SUCCESS, responseData); };
Python
En el siguiente ejemplo de Python, la función de Lambda en línea toma un valor de entero y lo multiplica por 5.
JSON
"ZipFile" : { "Fn::Join" : ["\n", [ "import json", "import cfnresponse", "def handler(event, context):", " responseValue = int(event['ResourceProperties']['Input']) * 5", " responseData = {}", " responseData['Data'] = responseValue", " cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, \"CustomResourcePhysicalID\")" ]]}
YAML
ZipFile: | import json import cfnresponse def handler(event, context): responseValue = int(event['ResourceProperties']['Input']) * 5 responseData = {} responseData['Data'] = responseValue cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData, "CustomResourcePhysicalID")
Código fuente del módulo
Código fuente de Node.js asíncrono
A continuación, se muestra el código fuente del módulo de respuesta para las funciones de Node.js si el controlador es asíncrono. Revíselo para entender qué hace el módulo y para obtener ayuda con la implementación de sus propias funciones de respuesta.
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: MIT-0 exports.SUCCESS = "SUCCESS"; exports.FAILED = "FAILED"; exports.send = function(event, context, responseStatus, responseData, physicalResourceId, noEcho) { return new Promise((resolve, reject) => { var responseBody = JSON.stringify({ Status: responseStatus, Reason: "See the details in CloudWatch Log Stream: " + context.logStreamName, PhysicalResourceId: physicalResourceId || context.logStreamName, StackId: event.StackId, RequestId: event.RequestId, LogicalResourceId: event.LogicalResourceId, NoEcho: noEcho || false, 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 } }; var request = https.request(options, function(response) { console.log("Status code: " + parseInt(response.statusCode)); resolve(context.done()); }); request.on("error", function(error) { console.log("send(..) failed executing https.request(..): " + error); reject(context.done(error)); }); request.write(responseBody); request.end(); }) }
Código fuente de Node.js
A continuación, se muestra el código fuente del módulo de respuesta para las funciones de Node.js si el controlador no es asíncrono. Revíselo para entender qué hace el módulo y para obtener ayuda con la implementación de sus propias funciones de respuesta.
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: MIT-0 exports.SUCCESS = "SUCCESS"; exports.FAILED = "FAILED"; exports.send = function(event, context, responseStatus, responseData, physicalResourceId, noEcho) { var responseBody = JSON.stringify({ Status: responseStatus, Reason: "See the details in CloudWatch Log Stream: " + context.logStreamName, PhysicalResourceId: physicalResourceId || context.logStreamName, StackId: event.StackId, RequestId: event.RequestId, LogicalResourceId: event.LogicalResourceId, NoEcho: noEcho || false, 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 } }; var request = https.request(options, function(response) { console.log("Status code: " + parseInt(response.statusCode)); context.done(); }); request.on("error", function(error) { console.log("send(..) failed executing https.request(..): " + error); context.done(); }); request.write(responseBody); request.end(); }
Código fuente Python
A continuación, se muestra el código fuente del módulo de respuesta de las funciones de Python:
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: MIT-0 from __future__ import print_function import urllib3 import json SUCCESS = "SUCCESS" FAILED = "FAILED" http = urllib3.PoolManager() def send(event, context, responseStatus, responseData, physicalResourceId=None, noEcho=False, reason=None): responseUrl = event['ResponseURL'] print(responseUrl) responseBody = { 'Status' : responseStatus, 'Reason' : reason or "See the details in CloudWatch Log Stream: {}".format(context.log_stream_name), 'PhysicalResourceId' : physicalResourceId or context.log_stream_name, 'StackId' : event['StackId'], 'RequestId' : event['RequestId'], 'LogicalResourceId' : event['LogicalResourceId'], 'NoEcho' : noEcho, 'Data' : responseData } json_responseBody = json.dumps(responseBody) print("Response body:") print(json_responseBody) headers = { 'content-type' : '', 'content-length' : str(len(json_responseBody)) } try: response = http.request('PUT', responseUrl, headers=headers, body=json_responseBody) print("Status code:", response.status) except Exception as e: print("send(..) failed executing http.request(..):", e)