] }
Results: CloudFormation successfully created the stack by verifying that the AWS::S3::Bucket resource contained server-side encryption before provisioning the resource.
To provision a stack (example 2)
Provision a non-compliant stack
1. Author a template that specifies an S3 bucket. For example aes256-bucket.yml.
AWSTemplateFormatVersion: 2010-09-09 Description: |
This CloudFormation template provisions an encrypted S3 Bucket Resources:
EncryptedS3Bucket:
Type: 'AWS::S3::Bucket' Properties:
BucketName: !Sub 'encryptedbucket-${AWS::Region}-${AWS::AccountId}' BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256 BucketKeyEnabled: true Outputs:
EncryptedBucketName:
Value: !Ref EncryptedS3Bucket
2. Create a stack, and specify your template in the AWS CLI. In the following example, specify the stack name as my-hook-stack and the template name as aes256-bucket.yml.
aws cloudformation create-stack \ --stack-name my-hook-stack \
--template-body file://aes256-bucket.yml
3. (Optional) View your stack progress by specifying your stack name. In the following example, specify the stack name my-hook-stack.
aws cloudformation describe-stack-events \ --stack-name my-hook-stack
Use the describe-stack-events operation to see the hook failure while creating the bucket. The following is an example output of the command.
{ "StackEvents": [ ...
{
"StackId": "arn:aws:cloudformation:us-west-2:ACCOUNT_ID:stack/my-hook-stack/2c693970-f57e-11eb-a0fb-061a2a83f0b9",
"EventId": "S3Bucket-CREATE_FAILED-2021-08-04T23:47:03.305Z", "StackName": "my-hook-stack",
"LogicalResourceId": "S3Bucket", "PhysicalResourceId": "",
"ResourceType": "AWS::S3::Bucket",
"Timestamp": "2021-08-04T23:47:03.305000+00:00", "ResourceStatus": "CREATE_FAILED",
Walkthrough: Python
"ResourceStatusReason": "The following hook(s) failed:
[MyCompany::Testing::MyTestHook]", "ResourceProperties": "{}",
"ClientRequestToken": "Console-CreateStack-abe71ac2-ade4-a762-0499-8d34d91d6a92"
}, ...
] }
Results: The hook invocation failed the stack configuration and stopped the resource from provisioning. The stack failed due to the Amazon S3 bucket encryption configured incorrectly. The hook type configuration requires aws:kms while this bucket uses AES256.
Use a CloudFormation template to pass hook validation
1. To create a stack and pass the hook validation, update the template so that your resource uses an encrypted S3 bucket. This example uses the template kms-bucket-and-queue.yml.
AWSTemplateFormatVersion: 2010-09-09 Description: |
This CloudFormation template provisions an encrypted S3 Bucket Resources:
EncryptedS3Bucket:
Type: 'AWS::S3::Bucket' Properties:
BucketName: !Sub 'encryptedbucket-${AWS::Region}-${AWS::AccountId}' BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
QueueName: 'encryptedqueue-${AWS::Region}-${AWS::AccountId}' KmsMasterKeyId: !Ref EncryptionKey
EncryptionKey:
Type: 'AWS::KMS::Key' DeletionPolicy: Retain Properties:
Description: KMS key used to encrypt the resource type artifacts EnableKeyRotation: true
Value: !Ref EncryptedS3Bucket EncryptedQueueName:
Value: !Ref EncryptedQueue
Note
Hook won't be invoked for skipped resources.Walkthrough: Python
2. Create a stack and specify your template. In this example, the stack name is my-encrypted-bucket-stack.
aws cloudformation create-stack \
--stack-name my-encrypted-bucket-stack \
--template-body file://kms-bucket-and-queue.yml
3. (Optional) View your stack progress by specifying the stack name.
aws cloudformation describe-stack-events \ --stack-name my-encrypted-bucket-stack
Use the describe-stack-events command to view the response. The following is an example of the describe-stack-events command.
{ "StackEvents": [ ...
{
"StackId": "arn:aws:cloudformation:us-west-2:ACCOUNT_ID:stack/my-encrypted-bucket-stack/82a97150-f57a-11eb-8eb2-06a6bdcc7779",
"EventId": "EncryptedS3Bucket-CREATE_COMPLETE-2021-08-04T23:23:20.973Z", "StackName": "my-encrypted-bucket-stack",
"LogicalResourceId": "EncryptedS3Bucket",
"PhysicalResourceId": "encryptedbucket-us-west-2-ACCOUNT_ID", "ResourceType": "AWS::S3::Bucket",
"Timestamp": "2021-08-04T23:23:20.973000+00:00", "ResourceStatus": "CREATE_COMPLETE",
"ResourceProperties":
"{\"BucketName\":\"encryptedbucket-us-west-2-071617338693\",\"BucketEncryption\":{\"ServerSideEncryptionConfiguration\":
[{\"BucketKeyEnabled\":\"true\",\"ServerSideEncryptionByDefault\":{\"SSEAlgorithm\":
\"aws:kms\",\"KMSMasterKeyID\":\"ENCRYPTION_KEY_ARN\"}}]}}",
"ClientRequestToken": "Console-CreateStack-39df35ac-ca00-b7f6-5661-4e917478d075"
}, {
"StackId": "arn:aws:cloudformation:us-west-2:ACCOUNT_ID:stack/my-encrypted-bucket-stack/82a97150-f57a-11eb-8eb2-06a6bdcc7779",
"EventId": "EncryptedS3Bucket-CREATE_IN_PROGRESS-2021-08-04T23:22:59.410Z", "StackName": "my-encrypted-bucket-stack",
"LogicalResourceId": "EncryptedS3Bucket",
"PhysicalResourceId": "encryptedbucket-us-west-2-ACCOUNT_ID", "ResourceType": "AWS::S3::Bucket",
"Timestamp": "2021-08-04T23:22:59.410000+00:00", "ResourceStatus": "CREATE_IN_PROGRESS",
"ResourceStatusReason": "Resource creation Initiated", "ResourceProperties":
"{\"BucketName\":\"encryptedbucket-us-west-2-071617338693\",\"BucketEncryption\":{\"ServerSideEncryptionConfiguration\":
[{\"BucketKeyEnabled\":\"true\",\"ServerSideEncryptionByDefault\":{\"SSEAlgorithm\":
\"aws:kms\",\"KMSMasterKeyID\":\"ENCRYPTION_KEY_ARN\"}}]}}",
"ClientRequestToken": "Console-CreateStack-39df35ac-ca00-b7f6-5661-4e917478d075"
}, {
"StackId": "arn:aws:cloudformation:us-west-2:ACCOUNT_ID:stack/my-encrypted-bucket-stack/82a97150-f57a-11eb-8eb2-06a6bdcc7779",
"EventId": "EncryptedS3Bucket-6516081f-c1f2-4bfe-a0f0-cefa28679994", "StackName": "my-encrypted-bucket-stack",
"LogicalResourceId": "EncryptedS3Bucket", "PhysicalResourceId": "",
"ResourceType": "AWS::S3::Bucket",
"Timestamp": "2021-08-04T23:22:58.349000+00:00", "ResourceStatus": "CREATE_IN_PROGRESS",
Walkthrough: Python
"ResourceStatusReason": "Hook invocations complete. Resource creation initiated",
"ClientRequestToken": "Console-CreateStack-39df35ac-ca00-b7f6-5661-4e917478d075"
}, ...
] }
Results: CloudFormation successfully created the stack by verifying that the AWS::S3::Bucket resource contained server-side encryption before provisioning the resource.
Subscribing to hook invocation events in Amazon EventBridge
Before running create-stack, you can create an Amazon EventBridge rule to subscribe to your hook invocation events. These rules won't poll directly, but you can set a target to receive the service events.
To create infrastructure to receive hook invocation events, provide the following:
• Something to receive EventBridge events. For example, an Amazon Simple Queue Service (Amazon SQS) queue and queue policy. For more information, see Creating an Amazon SQS queue (console) and Configuring access policy (console).
• An EventBridge rule. For more information, see Create a rule in Amazon EventBridge.
To subscribe to hook invocation events in Amazon EventBridge
1. Create a CloudFormation template to invoke a hook event. The following example uses the template EventBridgeInfra.yml.
Resources:
HooksInvocationEventQueue:
Type: 'AWS::SQS::Queue' DeletionPolicy: Delete UpdateReplacePolicy: Delete Properties:
QueueName: HooksInvocationEventQueue HooksInvocationEventQueuePolicy:
Type: 'AWS::SQS::QueuePolicy' Properties:
PolicyDocument:
Id: HooksInvocationEventQueuePolicy Version: 2012-10-17
Statement:
- Sid: SendHooksEventToTheQueue Effect: Allow
Principal:
Service: events.amazonaws.com Action:
- 'sqs:SendMessage' Resource: !GetAtt
- HooksInvocationEventQueue - Arn
Queues:
- !Ref HooksInvocationEventQueue HooksInovcationEventRule:
Type: 'AWS::Events::Rule' Properties:
Description: Rule to move acceptance tests events to the queue EventPattern:
source:
- aws.cloudformation
Walkthrough: Python detail-type:
- CloudFormation Hook Invocation Progress Targets:
- Arn: !GetAtt
- HooksInvocationEventQueue - Arn
Id: HooksInovcationEventQueue
2. Create a stack to receive hook invocation details and events in EventBridge. The following example specifies the template EventBridgeInfra.yml.
aws cloudformation create-stack \ --stack-name event-bridge-infra \
--template-body file://EventBridgeInfra.yml
3. (Optional) To view EventBridge events, run create-stack and the events will display in your Amazon SQS queue or another EventBridge target. To learn more about additional target types and policy configurations, see Using resource-based policies for Amazon EventBridge.
Managing hooks
Once you've registered a hook, you can manage it through the CloudFormation registry, including versioning and account and region availability.
Updating a hook
Updating a hook allows revisions in the hook to be made available in the CloudFormation registry.
To update a hook, submit your revisions to the CloudFormation registry through the CloudFormation CLI the section called “submit” (p. 170) operation.
cfn submit
To specify the default version of your hook in your account, use the set-type-default-version command and specify the type, type name, and version ID.
aws cloudformation set-type-default-version \ --type HOOK \
--type-name MyCompany::Testing::MyTestHook \ --version-id 00000003
To retrieve information about the versions of a hook, use list-type-versions.
aws cloudformation list-type-versions \ --type HOOK \
--type-name "MyCompany::Testing::MyTestHook"
Deactivating a hook
Deactivating a hook prevents the hook from running your AWS account.
TargetStacks set to NONE turns the hook off in your account, so it doesn't apply to stack operations.
Use the set-type-configuration operation and specify TargetStacks as NONE to deactivate a hook.
The following example specifies the AWS Region and the Amazon Resource Name (ARN) of the hook that's being deactivated.