Introduction to CloudFormation Custom Resources

Configuration to check behavior of CloudFormation Custom resources

One of the features of CloudFormation is custom resources.

Custom resources enable you to write custom provisioning logic in templates that AWS CloudFormation runs anytime you create, update (if you changed the custom resource), or delete stacks.

Custom resources

In this article, we will check the behavior of Lambda-backed custom resources.


Diagram of introduction to CloudFormation Custom Resources.

Create CloudFormation stacks and configure a Lambda function in it as a custom resource.
Configure function to log to CloudWatch Logs each time the function is executed.
The runtime for the function is Python 3.8.

CloudFormation template files

The above configuration is built using CloudFormation.
The CloudFormation template is located at the following URL

awstut-fa/043 at main · awstut-an-r/awstut-fa
Contribute to awstut-an-r/awstut-fa development by creating an account on GitHub.

Explanation of key points of template files

Lambda functions for custom resources

Check the Lambda function that works as a backend for custom resources.

    Type: AWS::Lambda::Function
        ZipFile: |
          import cfnresponse
          import datetime
          response_data = {}
          def lambda_handler(event, context):
              now =
              message = '{datetime} Request Type: {request_type}, Test Resource Property: {property}'.format(
              response_data['message'] = message
              cfnresponse.send(event, context, cfnresponse.SUCCESS, response_data)
            except Exception as e:
              cfnresponse.send(event, context, cfnresponse.FAILED, response_data)
      FunctionName: !Sub "${Prefix}-function"
      Handler: !Ref Handler
      Runtime: !Ref Runtime
      Role: !GetAtt FunctionRole.Arn
Code language: YAML (yaml)

Basically the same as a Lambda function.
Code and ZipFile properties allow inline definition of the code to be executed by the function.
For more information on the basics of Lambda functions, please refer to the following page

For Python, a module (cfnresponse) is available for creating Lambda-backed custom resources.
This module will be used in this case.

You can check the operation details of CloudFormation.
The content of the operation can be obtained by event[‘RequestType’].
By using this value as a reference, you can implement a process that is limited to specific operations in the CloudFormation stack.
For example, the following image

if event['RequestType'] == 'Create':

elif event['RequestType'] == 'Update':

elif event['RequestType'] == 'Delete':
Code language: Python (python)

When creating a custom resource, certain arguments can be passed to the Lambda function.
Arguments can be defined in the form of properties of the custom resource.
You can get them in the form event[‘ResourceProperties’][].
This is checked again on the custom resource side.

The function must give a given response at the end of the process.

The custom resource provider processes the AWS CloudFormation request and returns a response of SUCCESS or FAILED to the pre-signed URL.

Custom resources

This process can be implemented using the send function of the cfnresponse module described earlier.
The response can be passed as the third argument to the send function, in this case “cfnresponse.SUCCESS” or “cfnresponse.FAILED” in this code.
For more information on cfnresponse, please refer to the following page

cfn-response module - AWS CloudFormation
When you use the ZipFile property to specify your function's source code and that function interacts with an AWS CloudFormation custom resource, you can load th...

The result of the work performed by the function can be passed to the CloudFormation stack side as some kind of return value.
The return value is set as an argument to the send function described above.
Specifically, it is passed as the fourth argument, “response_data” in this code.

Based on the above, the following is a summary of the process to be executed by this function.

  • Create a string (message) based on the content and arguments of the CloudFormation operation and the current date and time
  • Set the message as the return value when sending a response (SUCCESS) with cfnresponse.send
  • If the above process fails, send a response (FAILED) in cfnresponse.send in the form of exception handling.

Note that, for the use of cfnresponse, the return value is required even when sending FAILED.
So it is set to pass an empty dictionary.

Custom Resources

Check custom resources.

    Type: Custom::CustomResource
      ServiceToken: !Ref FunctionArn
      TestProperty: !Ref Prefix
      #TestProperty: !Sub "${Prefix}-Updated"
    Value: !GetAtt CustomResource.message
Code language: YAML (yaml)

The Type property of a custom resource can be defined by the user according to a naming convention.

Use the AWS::CloudFormation::CustomResource or Custom::MyCustomResourceTypeName resource type to define custom resources in your templates.

Custom resources

The ServiceToken property sets the ARN of the resource to run on the backend.
In this case, the aforementioned Lambda function will run, so set the ARN for this function.

TestProperty is an argument passed to the aforementioned function.
This time, set this property to the string “fa-043”.

To check the return value of the custom resource, retrieve the return value in the Outputs section.
Use the built-in function Fn::GetAtt to reference the value (message) set in the function through the custom resource.


Behavior when creating CloudFormation stacks

Create a CloudFormation stack from the AWS CLI.
After placing the template file in the specified S3 bucket, execute the following command

$ aws cloudformation create-stack \
--stack-name [stack-name] \
--template-url https://[bacuket-name].s3.[region-name]
--capabilities CAPABILITY_IAM
Code language: Bash (bash)

For more information on creating a stack, please see the following page

The following is the Lambda function log generated during stack creation.

CloudFormation Custom Resources Test 1.

The “Request Type: Create” indicates that the function was executed when the stack was created.
Also, “Test Resource Property: fa-043” indicates that the function is able to reference the value of a custom resource property.

We also check the return value.

CloudFormation Custom Resources Test 2.

In the Outputs of the stack, we see a string similar to the one in the log we just checked.
You can also get the return value from the custom resource in this way.

Behavior when updating custom resources

Next, update the description of the custom resource in the template file and execute the changes.
First, update the custom resource as follows

    Type: Custom::CustomResource
      ServiceToken: !Ref FunctionArn
      #TestProperty: !Ref Prefix
      TestProperty: !Sub "${Prefix}-Updated"
Code language: YAML (yaml)

The value of TestProperty has been updated.

After re-uploading this template file to the S3 bucket, run the following command

$ aws cloudformation update-stack \
--stack-name [stack-name] \
--template-url https://[bucket-name].s3.[region-name] \
--capabilities CAPABILITY_IAM
Code language: Bash (bash)

The following log is generated during a stack change.

CloudFormation Custom Resources Test 3.

In this case, “Request Type: Update” indicates that a function was executed at the time of the stack change.
Also, “Test Resource Property: fa-043-Updated” indicates that the function was able to reference the value of the custom resource property after the change.

Behavior when deleting CloudFormation stacks

Delete the CloudFormation stack from the AWS CLI

$ aws cloudformation delete-stack \
--stack-name fa-043
Code language: Bash (bash)

The following log is generated when deleting the stack.

CloudFormation Custom Resources Test 4.

This time, “Request Type: Delete” indicates that the function was executed when deleting the stack.


We have confirmed the behavior of Lambda-backed custom resources.
By referencing the value of RequestType, we found that we can implement processing tailored to specific operations (stack creation, deletion, etc.).