aws-cloudformation-custom-resource-helper

repository·main·Indexed 18 days ago

https://github.com/aws-cloudformation/custom-resource-helper

A Python library designed to simplify the creation of AWS CloudFormation Custom Resources. It manages CloudFormation responses, timeouts, and logging, and provides polling mechanisms for operations exceeding the 15-minute Lambda execution limit via CloudWatch Events. It includes the CfnResource helper and decorators for create, update, and delete lifecycle methods.

Tokens
1.6K
Snippets
6
Records
6
Agent score
14%

What's inside crhelper

  1. How polling works for long-running operations

    main

    If an operation exceeds the 15-minute Lambda timeout, you can use polling. By defining @helper.poll_create, @helper.poll_update, or @helper.poll_delete decorators, crhelper will not send an immediate response to CloudFormation. Instead, it creates a CloudWatch Events schedule to re-invoke the Lambda every 2 minutes.

    Polling Logic:

    1. The matching @helper.poll_* function is called during re-invocation.
    2. If the function returns None, the schedule runs again in 2 minutes.
    3. Once complete, return a PhysicalResourceID or True (to generate one). The schedule is then deleted and the response is sent to CloudFormation.

    Required IAM Permissions: To use polling, the Lambda's IAM role must have the following permissions:

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": [
            "lambda:AddPermission",
            "lambda:RemovePermission",
            "events:PutRule",
            "events:DeleteRule",
            "events:PutTargets",
            "events:RemoveTargets"
          ],
          "Resource": "*"
        }
      ]
    }
    @helper.create
    def create(event, context):
        # This function will now trigger the polling mechanism
        pass
    
    @helper.poll_create
    def poll_create(event, context):
        # Logic to check if creation is complete
        # Return True or a PhysicalResourceId when done
        return True
  2. Implement CloudFormation lifecycle methods with decorators

    main

    Use decorators provided by the CfnResource instance to define the logic for different CloudFormation events. The helper(event, context) call in your main handler manages the execution flow.

    • @helper.create: Logic for resource creation. Can return a PhysicalResourceId string. If None is returned, an ID is automatically generated.
    • @helper.update: Logic for resource updates. If an update results in a new resource, return the new ID.
    • @helper.delete: Logic for resource deletion. This method should not return anything and should handle cases where the resource is already gone.

    To pass data back to CloudFormation in the response, update the helper.Data dictionary. If polling is enabled, this data is placed in event['CrHelperData'].

    from crhelper import CfnResource
    
    helper = CfnResource()
    
    @helper.create
    def create(event, context):
        # Add response data to the helper
        helper.Data.update({"test": "testdata"})
        
        # Raising an exception sends a failure response to CloudFormation
        if not helper.Data.get("test"):
            raise ValueError("error message")
        
        return "MyResourceId"
    
    @helper.update
    def update(event, context):
        pass
    
    @helper.delete
    def delete(event, context):
        pass
    
    def handler(event, context):
        helper(event, context)
  3. Deploying with AWS CDK

    main

    You can deploy a Custom Resource using crhelper via the AWS CDK CustomResource construct.

    Important Note: crhelper is not intended to be used with the AWS CDK Provider construct. Instead, point the serviceToken directly to the ARN of the Lambda function running crhelper.

    from aws_cdk import (
        aws_lambda as _lambda,
        CustomResource,
    )
    
    crhelper_lambda = _lambda.Function(...)
    
    custom_resource = CustomResource(
        self, 
        'MyCustomResource',
        service_token=crhelper_lambda.function_arn,
        properties={
            'No1': 1,
            'No2': 2
        },
    )
  4. Initialize the CfnResource helper

    main

    Import CfnResource from crhelper to manage CloudFormation responses. You can configure logging, sleep times, and SSL verification during initialization.

    Available arguments for CfnResource:

    • json_logging (bool): Enable JSON formatted logging.
    • log_level (str): Set the logging level.
    • boto_level (str): Set the logging level for boto3.
    • sleep_on_delete (int): Seconds to sleep during a delete operation.
    • ssl_verify (bool | str): Controls SSL certificate verification. Use False to disable verification or provide a path to a CA cert bundle.
    from crhelper import CfnResource
    
    # Example initialization with custom settings
    helper = CfnResource(json_logging=False, log_level='DEBUG', boto_level='CRITICAL', sleep_on_delete=120, ssl_verify=None)
  5. Configure SSL certificate verification

    main

    You can control how the underlying boto3 clients verify SSL certificates using the ssl_verify argument in the CfnResource constructor:

    • False: Do not validate SSL certificates (SSL is still used, but verification is skipped).
    • 'path/to/cert/bundle.pem': Use a specific CA certificate bundle file instead of the default botocore bundle.
    # Disable verification
    helper = CfnResource(ssl_verify=False)
    
    # Use custom CA bundle
    helper = CfnResource(ssl_verify='path/to/cert/bundle.pem')