Publishing hooks for public use - CloudFormation Command Line Interface

Publishing hooks for public use

Developing a public extension for CloudFormation

To develop a public third-party hook, develop your hook as a private extension. Then, in each AWS Region in which you want to make the extension publicly available:

  1. Register your hook as a private extension in the CloudFormation registry.

  2. Test your hook to make sure it meets all necessary requirements for being published in the CloudFormation registry.

  3. Publish your hook to the CloudFormation registry.


    Before you publish any extension in a given Region, you must first register as an extension publisher in that Region.

    To do this in multiple Regions simultaneously, see Publishing your extension in multiple Regions using StackSets.

After you've developed and registered your hook, you can make it publicly available to general CloudFormation users by publishing it to the CloudFormation registry, as a third-party public extension.

Public third-party hooks enable you to offer CloudFormation users to proactively inspect the configuration of AWS resources before provisioning. As with private hooks, public hooks are treated the same as any hook published by AWS within CloudFormation.

Hooks published to the registry are visible by all CloudFormation users in the AWS Regions in which they're published. Users can then activate your extension in their account, which makes it available for use in their templates. For more information, see Using public extensions in CloudFormation in the CloudFormation User Guide.

Testing registered hooks

In order to publish your hook, it must pass all test requirements defined for it. The following is a list of requirements needed before publishing your hook as a third-party extension.

Each handler and target is tested twice. Once for SUCCESS and once for FAILED.

  • For SUCCESS response case:

    • Status must be SUCCESS.

    • Must not return an error code.

    • Callback delay should be set to 0 seconds, if specified.

  • For FAILED response case:

    • Status must be FAILED.

    • Must return an error code.

    • Must have a message in response.

    • Callback delay should be set to 0 seconds, if specified.

  • For IN_PROGRESS response case:

    • Must not return an error code.

    • Result field must not be set in response.

Specifying input data for use in contract tests

By default, the CloudFormation performs contract tests using input properties generated from the patterns you define in your hook schema. However, most hooks are complex enough that the input properties for precreating or preupdating provisioning stacks requires an understanding of the resource being provisioned. To address this, you can specify the input the CloudFormation uses when performing its contract tests.

CloudFormation offers two ways for you to specify the input data for it to use when performing contract tests:

  • Overrides file

    Using an overrides file provides a light-weight way of specifying input data for certain specific properties for the CloudFormation to use during preCreate, preUpdate and preDelete operations testing.

  • Input files

    You can also use multiple input files to specify contract test input data if:

    • You want or need to specify different input data for create, update, and delete operations, or invalid data with which to test.

    • You want to specify multiple different input data sets.

Specifying input data using an override file

The following is an example of Amazon S3 hook's input data using the overrides file.

{ "CREATE_PRE_PROVISION": { "AWS::S3::Bucket": { "resourceProperties": { "/BucketName": "encryptedbucket-us-west-2-contractor", "/BucketEncryption/ServerSideEncryptionConfiguration": [ { "BucketKeyEnabled": true, "ServerSideEncryptionByDefault": { "KMSMasterKeyID": "KMS-KEY-ARN", "SSEAlgorithm": "aws:kms" } } ] } }, "AWS::SQS::Queue": { "resourceProperties": { "/QueueName": "MyQueueContract", "/KmsMasterKeyId": "hellocontract" } } }, "UPDATE_PRE_PROVISION": { "AWS::S3::Bucket": { "resourceProperties": { "/BucketName": "encryptedbucket-us-west-2-contractor", "/BucketEncryption/ServerSideEncryptionConfiguration": [ { "BucketKeyEnabled": true, "ServerSideEncryptionByDefault": { "KMSMasterKeyID": "KMS-KEY-ARN", "SSEAlgorithm": "aws:kms" } } ] }, "previousResourceProperties": { "/BucketName": "encryptedbucket-us-west-2-contractor", "/BucketEncryption/ServerSideEncryptionConfiguration": [ { "BucketKeyEnabled": true, "ServerSideEncryptionByDefault": { "KMSMasterKeyID": "KMS-KEY-ARN", "SSEAlgorithm": "aws:kms" } } ] } } }, "INVALID_UPDATE_PRE_PROVISION": { "AWS::S3::Bucket": { "resourceProperties": { "/BucketName": "encryptedbucket-us-west-2-contractor", "/BucketEncryption/ServerSideEncryptionConfiguration": [ { "BucketKeyEnabled": true, "ServerSideEncryptionByDefault": { "KMSMasterKeyID": "KMS-KEY-ARN", "SSEAlgorithm": "AES256" } } ] }, "previousResourceProperties": { "/BucketName": "encryptedbucket-us-west-2-contractor", "/BucketEncryption/ServerSideEncryptionConfiguration": [ { "BucketKeyEnabled": true, "ServerSideEncryptionByDefault": { "KMSMasterKeyID": "KMS-KEY-ARN", "SSEAlgorithm": "aws:kms" } } ] } } }, "INVALID": { "AWS::SQS::Queue": { "resourceProperties": { "/QueueName": "MyQueueContract", "/KmsMasterKeyId": "KMS-KEY-ARN" } } } }

Specifying input data using input files

Use input files to specify different kinds of input data for the CloudFormation to use: preCreate input, preUpdate input, and invalid input. Each kind of data is specified in a separate file. You can also specify multiple sets of input data for contract tests.

To specify input files for the CloudFormation to use in contract testing, add an inputs folder to the root directory of your hooks project. Then add your input files.

Specify which kind of input data a file contains by using the following naming conventions, where n is an integer:

  • inputs_n_pre_create.json: Use files with preCreate handlers for specifying inputs for creating the resource.

  • inputs_n_pre_update.json: Use files with preUpdate handlers for specifying inputs for updating the resource.

  • inputs_n_pre_delete.json: Use files with preDelete handlers for specifying inputs for deleting the resource.

  • inputs_n_invalid.json: For specifying invalid inputs to test.

To specify multiple sets of input data for contract tests, increment the integer in the file names to order your input data sets. For example, your first set of input files should be named inputs_1_pre_create.json, inputs_1_pre_update.json, and inputs_1_pre_invalid.json. Your next set would be named inputs_2_pre_create.json, inputs_2_pre_update.json, and inputs_2_pre_invalid.json, and so on.

Each input file is a JSON file containing only the resource properties to be used in testing.

The following is an example directory for inputs for Amazon S3 specifying input data using input files.


The following is an example of the inputs_1_pre_create.json contract test.

{ "AWS::S3::Bucket": { "resourceProperties": { "AccessControl": "BucketOwnerFullControl", "AnalyticsConfigurations": [], "BucketEncryption": { "ServerSideEncryptionConfiguration": [ { "BucketKeyEnabled": true, "ServerSideEncryptionByDefault": { "KMSMasterKeyID": "KMS-KEY-ARN", "SSEAlgorithm": "aws:kms" } } ] }, "BucketName": "encryptedbucket-us-west-2" } }, "AWS::SQS::Queue": { "resourceProperties": { "QueueName": "MyQueue", "KmsMasterKeyId": "KMS-KEY-ARN" } } }

The following is an example of the inputs_1_pre_update.json contract test.

{ "AWS::S3::Bucket": { "resourceProperties": { "BucketEncryption": { "ServerSideEncryptionConfiguration": [ { "BucketKeyEnabled": true, "ServerSideEncryptionByDefault": { "KMSMasterKeyID": "KMS-KEY-ARN", "SSEAlgorithm": "aws:kms" } } ] }, "BucketName": "encryptedbucket-us-west-2" }, "previousResourceProperties": { "BucketEncryption": { "ServerSideEncryptionConfiguration": [ { "BucketKeyEnabled": true, "ServerSideEncryptionByDefault": { "KMSMasterKeyID": "KMS-KEY-ARN", "SSEAlgorithm": "aws:kms" } } ] }, "BucketName": "encryptedbucket-us-west-2" } } }

The following is an example of the inputs_1_invalid.json contract test.

{ "AWS::S3::Bucket": { "resourceProperties": { "AccessControl": "BucketOwnerFullControl", "AnalyticsConfigurations": [], "BucketEncryption": { "ServerSideEncryptionConfiguration": [ { "ServerSideEncryptionByDefault": { "SSEAlgorithm": "AES256" } } ] }, "BucketName": "encryptedbucket-us-west-2" } }, "AWS::SQS::Queue": { "resourceProperties": { "NotValid": "The property of this resource is not valid." } } }

The following is an example of the inputs_1_invalid_pre_update.json contract test.

{ "AWS::S3::Bucket": { "resourceProperties": { "BucketEncryption": { "ServerSideEncryptionConfiguration": [ { "BucketKeyEnabled": true, "ServerSideEncryptionByDefault": { "KMSMasterKeyID": "KMS-KEY-ARN", "SSEAlgorithm": "AES256" } } ] }, "BucketName": "encryptedbucket-us-west-2" }, "previousResourceProperties": { "BucketEncryption": { "ServerSideEncryptionConfiguration": [ { "BucketKeyEnabled": true, "ServerSideEncryptionByDefault": { "KMSMasterKeyID": "KMS-KEY-ARN", "SSEAlgorithm": "aws:kms" } } ] }, "BucketName": "encryptedbucket-us-west-2" } } }

For more information, see Testing your public extension before publishing.