Introducing AWS CloudFormation Hooks invoked via AWS Cloud Control API (CCAPI)
November 24, 2024Today we are announcing the integration of AWS CloudFormation Hooks with AWS Cloud Control API (CCAPI). This integration enables the use of hooks to validate the configuration of resources being provisioned through CCAPI. In this blog post, we will explore the integration between CloudFormation Hooks and CCAPI by configuring an existing hook to work with CCAPI and then test that hook using the AWS CLI and Terraform.
Understanding CloudFormation Hooks
CloudFormation Hooks integrate seamlessly with your CloudFormation and CCAPI requests to perform validation of your resource configuration during resource create and update operations. You can create hooks using AWS Lambda, AWS CloudFormation Guard rules, or using code and the CloudFormation Command Line Interface (CFN-CLI). A hook can be triggered on change sets, entire stack templates, or by each resource and it will return back any discovered misconfiguration information. Hooks can be configured to warn or fail on the operation allowing you to prevent any misconfigured resources from being deployed in your account. Some key benefits of using CloudFormation Hooks with CCAPI include:
- Enforcing security best practices
- Applying organizational policies to resource deployments
- Optimizing resource configurations for cost and performance
- Standardize validation across different infrastructure as code solutions like CloudFormation, Terraform (Terraform AWS Cloud Control Provider), and Pulumi (AWS Cloud Control)
Prerequisites
For this post we are going to use the new AWS CloudFormation Guard (Guard) hook AWS::Hooks::GuardHook
. Guard is an open-source policy-as-code tool that allows you to validate your infrastructure configurations against company policy guidelines. It provides a domain-specific language (DSL) for writing rules to check both required and prohibited resource configurations. The new AWS::Hooks::GuardHook
allows you to use the Guard DSL inside of a hook so you can easily implement your organizations guidelines. The result is you can use the same Guard rules in our local development environment, continuous integration and continuous deployment pipelines, and at deployment time (using hooks). To learn more about AWS::Hooks::GuardHook
you can look at the blog.
This is what the configuration of the current Guard hook looks like.
This hook has been configured to log the Guard validation report to an Amazon Simple Storage Service (S3) bucket. Additionally, this hook is configured to use a rule from the AWS CloudFormation Guard registry. This rule will validate that an S3 bucket is using versioning. This hook is configured with an alias named My::Hooks::Guard
.
Here is the rule for reference. This rule will validate that the property VersioningConfiguration
is provided and that its value is Enabled
.
Configuring the hook to work with CCAPI
This announcement adds a new hook target that can easily be configured on your existing or new hooks. To configure the hook to work with CCAPI you will edit the configuration to include a new TargetOperations
value of CLOUD_CONTROL
. This hook is only enabled to execute on CREATE
and UPDATE
operations. Additionally HookInvocationStatus
is ENABLED
which will execute the hook and FailureMode
will tell the hook to FAIL
the operation if the resource is not compliant.
By using TargetOperations
of ["RESOURCE", "CLOUD_CONTROL"]
the Guard rules will work the same across CloudFormation resource operations and CCAPI operations.
Testing the hook using AWS CLI
Test your hook using the AWS CLI which allows us to create, update, delete, and list resources.
- Start by creating a S3 bucket using CCAPI. In this example you are providing no properties for creating the S3 bucket. Run the command
aws cloudcontrol create-resource --type-name AWS::S3::Bucket --desired-state {}
Response: - Get the request status by using the
RequestToken
from the response above. Run the commandaws cloudcontrol get-resource-request-status --request-token 2c7b6f5e-4083-4ef8-9a23-5c81472540b1
In the response you will see all hooks that were executed and their response in relation to the request. This response shows that the hook
My::Hooks::Guard
failed because of the ruleS3_BUCKET_VERSIONING_ENABLED
. You are also provided a s3 location for where the full Guard output is stored. - You can get the Guard results file by using the following command. Replace
<path-from-previous-output>
with the path provided in the previous output. Run the commandaws s3 cp s3://<path-from-previous-output> -
Response:
We truncated the output as it can be very verbose.
Testing the hook using Terraform
The Terraform AWS Cloud Control Provider allows you to manage AWS resources using CCAPI and Terraform. By leveraging this provider you get the benefit of using hooks to validate the configuration of Terraform provisioned resources.
- Create a new Terraform configuration file named
main.tf
with the following content: - Run the following commands to initialize Terraform and create an execution plan. Run the command
terraform init
followed byterraform plan
. - Apply the configuration by running. Run the command
terraform apply
- You can get details on the hook invocation by running the command
aws cloudformation list-hook-results --hook-target TargetType=CLOUD_CONTROL,TargetId=d417b05b-9eff-46ef-b164-08c76aec1801
Response:As with the AWS CLI you now know what rule failed and additional you have the S3 bucket location for the Guard log file.
- You can get the Guard results file by running the command
aws s3 cp s3://<path-from-previous-output> -
. Replace<path-from-previous-output>
with the path provided in the previous output.Response:We truncated the output as it can be very verbose.
- Let’s correct our S3 bucket configuration in
main.tf
- Try the deployment again by running
terraform apply
Response:Conclusion
CloudFormation Hooks provide a powerful way to enforce best practices and compliance for your AWS resources. By leveraging CloudFormation Hooks and the Cloud Control API you can create consistent validation of your resources before deployment across many of your infrastructure as code solutions.