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:
-
Register your Hook as a private extension in the CloudFormation registry.
-
Test your Hook to make sure it meets all necessary requirements for being published in the CloudFormation registry.
-
Publish your Hook to the CloudFormation registry.
Note
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 AWS CloudFormation 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 duringpreCreate
,preUpdate
andpreDelete
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_
: Use files withn
_pre_create.jsonpreCreate
handlers for specifying inputs for creating the resource. -
inputs_
: Use files withn
_pre_update.jsonpreUpdate
handlers for specifying inputs for updating the resource. -
inputs_
: Use files withn
_pre_delete.jsonpreDelete
handlers for specifying inputs for deleting the resource. -
inputs_
: For specifying invalid inputs to test.n
_invalid.json
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.
inputs_1_pre_create.json
-
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" } } }
inputs_1_pre_update.json
-
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" } } }
inputs_1_invalid.json
-
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." } } }
inputs_1_invalid_pre_update.json
-
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.