AWS CloudFormation Security: 8 Best Practices

Tony Loehr
Developer Advocate

AWS CloudFormation gives organizations the ability to easily manage a collection of AWS resources by automating the initialization, provisioning, and deletion of infrastructure, services, and applications. This tool is easy to use–users simply describe a technology stack using Amazon’s template language and may use a single CreateStack function call to build their environment. With such a powerful tool at hand, developers need to be aware of AWS CloudFormation security best practices to help mitigate the cyber security risk.

CloudFormation may be broken down into two parts, templates and stacks. A template is a file that defines which resources are required to run your application. For example, the template may specify that an application requires three Elastic Cloud Compute (EC2) servers and a particular Identify and Access Management (IAM) Policy. Once the template is uploaded, CloudFormation automatically launches the required resources and builds a stack that matches the template. 

Improving the Security of AWS CloudFormation

In order to secure this tool, security best practices for AWS CloudFormation should be adhered to as misconfigurations are amplified within IaC environments. We recommend the following to help mitigate risk:

1. Ensure consistent governance through AWS CloudFormation Stack policies

A stack policy is a JSON document that describes what update actions can be performed on designated resources; this can help protect critical stack resources from unintentional updates, also helping mitigate risks including environmental drift. To use stack policies, specify a stack policy when creating stacks containing critical resources. For example, say we have a production database with resource name ProductionDatabase. The corresponding stack policy could be declared as such:

{
    "Statement" : [
        {
            "Effect" : "Deny",
            "Action" : "Update:*",
            "Principal": "*",
            "Resource" : "CycodeSampleApplication/ProductionDatabase"
        }
    ]
}

When calling a stack update on stacks containing protected resources, the protected resources must be explicitly specified or else the intended changes will not occur–this functionality helps protect critical stack resources from unintended changes.

Attributes may be added to a Cloudformation resource to control certain behaviors and relationships. Utilizing DeletionPolicy attributes can help preserve and backup resources when its stack is deleted.

2. Control access with IAM 

IAM is an AWS service used to manage users and their permissions within AWS. Within AWS CloudFormation, this service may define the actions that each user is permitted to perform such actions include viewing stack templates, creating stacks, or deleting stacks.

Separating user roles from service roles within IAM also helps separate permissions between a user and the AWS CloudFormation service, furthering the auditability of the system. This also helps to enforce a well-established best practice of adhering to principles of least privilege. An IAM role is an IAM identity that has specific permissions within an account, and this role is intended to be usable by any user, application, or service that needs temporary security credentials. 

To declare a new IAM role in an AWS CloudFormation template, use following JSON syntax:

{
    "Type" : "AWS::IAM::Role",
    "Properties" : {
           "AssumeRolePolicyDocument" : Json,
           "Description" : String,
           "ManagedPolicyArns" : [ String, ... ],
           "MaxSessionDuration" : Integer,
           "Path" : String,
           "PermissionsBoundary" : String,
           "Policies" : [ Policy, ... ],
           "RoleName" : String,
           "Tags" : [ Tag, ... ]
    }
}

An issue plaguing mobile development is the fact that there are scenarios where it may seem that embedding credentials is the only way forward. One such case includes the scenario where mobile applications need to use AWS resources–the naive and common approach is to include AWS keys within the app, but this makes keys difficult to rotate and provides attackers a route to extract them. Rather than embedding these sensitive keys, an IAM role may be used to delegate access to the needed resources and attach the policy to the user. Further explanation for this may be found within the AWS Amplify documentation, which contains technology-specific explanations.

3. Avoid hard coding secrets in AWS CloudFormation stack template

As previously stated in our guidelines for IaC security best practices, hard coding secrets within IaC often results in security vulnerabilities. The same care should be taken to not embed credentials in AWS CloudFormation stack templates. The recommendation by CloudFormation for embedding sensitive information in stack templates is to use dynamic references. When a dynamic reference is used, CloudFormation retrieves the value of the specified reference when necessary during stack and change set operations, and passes the value to the appropriate resource. However, CloudFormation never stores the actual reference value. 

Dynamic references allow for external values stored in services such as AWS Systems Manager Parameter Store or AWS Secrets Manager to be used. AWS Secrets Manager helps to securely encrypt, store, and retrieve credentials for affiliated databases and other services. The AWS Systems Manager Parameter Store provides secure, hierarchical storage for configuration data management. 

4. Enable AWS CloudFormation Stack Notifications

Monitoring stack events within AWS CloudFormation enables an organization to act fast to actions, unauthorized or otherwise negatively impacting, that could alter the AWS environment. To receive notifications when an event occurs, Amazon recommends using Simple Notification Service, frequently abbreviated as AWS SNS. 

One of the best approaches for setting notifications up is to use a Lambda function as an intermediary between AWS CloudFormation and SNS. Publishing CloudFormation stack events directly to an email SNS topic runs the risk of bombarding the chosen email inbox with irrelevant notifications, thus reducing the effectiveness by increasing the noise. A template for this CloudFormation template containing these 3 main components is as follows:

Resources:
    # SNS topic to send emails to users (used inside Lambda function)
    SNSTopicEmail:
       Type: "AWS::SNS::Topic"
       Properties:
           Subscription:
               - Endpoint: "my-real-email-address@example.com"
                   Protocol: "email"
               - Endpoint: "sivuca@jazz.com.br"
                   Protocol: "email"
    # SNS topic and inline subscription to forward events to Lambda function
    SNSTopicCloudFormation:
       Type: "AWS::SNS::Topic"
       Properties:
           Subscription:
               - Endpoint: !GetAtt "LambdaFunction.Arn"
                   Protocol: "lambda"
       DependsOn: "LambdaFunction"
   # Lambda function to catch CloudFormation events (forwarded by SNS) and create new SNS notifications from them
    LambdaFunction:
       Type: "AWS::Lambda::Function"
       Properties:
           FunctionName: "cloudformation-notifications-lambda"
           Description: "Forward CloudFormation notifications to SNS topic"
           Handler: "index.handler"
           Role: !GetAtt "LambdaRole.Arn"
           Environment:
               Variables:
                   SNS_TOPIC_ARN: !Ref "SNSTopicEmail"
                   NOTIFICATION_TYPES: "CREATE_COMPLETE,UPDATE_COMPLETE,ROLLBACK_IN_PROGRESS"
           Code:
               ZipFile:
                   # omitted ZipFile details for brevity
           Runtime: "python3.6"
           Timeout: "90"
           TracingConfig:
               Mode: "Active"

SNSTopicCloudFormation is an SNS topic that listens to CloudFormation events and forwards them to a Lambda function. LambdaFunction is a Lambda function capable of sending email messages through SNS–this function works like an input filter, as described below. SNSTopicEmail is an SNS topic that sends email messages to users; this topic is called from the Lambda function above. This CloudFormation template supports sending SNS notifications to users during CloudFormation stack creation, update, deletion but is customizable in that only the listed events CREATE_COMPLETE, UPDATE_COMPLETE, and ROLLBACK_IN_PROGRESS are notified.

5. Secure CloudFormation by detecting and correcting environmental drift

Environmental drift is a common problem for IaC broadly, and AWS CloudFormation is no exception. Stack drift occurs within AWS CloudFormation when the actual configurations of infrastructure resources differ from the expected configurations. The most common way environmental drift happens is when a user modifies resources directly rather than making changes through the service which created the resource. The best practices for managing stack resources through AWS CloudFormation include using the CloudFormation console, the CloudFormation API, or the AWS CLI to update resources on launched stacks. If using the AWS Management Console, the Update Stack wizard may be used once logged into the AWS CloudFormation dashboard; if using the CLI, the command

 aws cloudformation update-stack

may be used to update the application. The Amazon documentation contains a comprehensive explanation on properly updating stacks to update upstream resources; an important note is that organizations should take steps to avoid manual changes as this type of procedure is not good practice. The best practice to ensure AWS CloudFormation security is to execute the CLI command within the CI/CD process as this allows auditing, ensures repeatability, and helps make suspicious deployments easier to identify.

One option for correcting environmental drift is to utilize the drift detection feature within AWS to detect unmanaged configuration changes to stacks and resources. When enabled, AWS CloudFormation analyses the current specifications of resources in a stack against the specifications defined in the stack template. 

Environmental drift poses risk to sensitive resources such as IAM roles, S3 bucket policies, and security groups–in the pursuit of ensuring best security practices for AWS CloudFormation, these particular resources should have measures employed to prevent accidental modification. The practice of monitoring code to ensure that it only changes when intended is known as critical code monitoring. This practice is particularly suited for the aforementioned AWS resources because these resources do not change often relative to feature code, and any changes made to sensitive resources should be highly visible.

6. Log AWS CloudFormation API calls with AWS CloudTrail

AWS CloudTrail may be utilized to track actors who make AWS CloudFormation API calls in an AWS account. Enabling logging allows for audits to be performed; this can make nefarious actions such as code tampering easier to identify and helps improve the security of AWS CloudFormation implementations. 

To log AWS CloudFormation API calls, logging must be enabled and an S3 bucket to store these logs should be specified. However, it is imperative that this S3 bucket is configured securely as insecure configurations can result in a code leak of the logs–this can be devastating to an organization’s security posture.

7. Regularly scan for code leaks

A common S3 bucket misconfiguration that used to plague AWS customers involved the fact that S3 buckets had public access by default. This has since been remedied by AWS; S3 buckets are blocked from public access by default. Should they wish to create a public S3 bucket, users receive a warning message that they must acknowledge to proceed, shown below:

Block Public access settings page for AWS S3 buckets - Cycode

The recommendations for preventing S3 bucket leaks that could expose logging info include selecting “Block all public access” when creating this bucket–using policies to enforce this setting helps prevent mistakes from persisting. In addition, AWS Config and Lambda should be utilized to detect and remediate if S3 buckets are publicly accessible. Beyond all else, it is imperative to regularly scan for code leaks to ensure that configuration details are not posted elsewhere–dedicated tools for detecting code leaks are recommended to further protect AWS CloudFormation code.

8. Update Amazon EC2 Linux instances regularly

Security updates for Amazon EC2 Linux instances should be run regularly to help patch vulnerabilities and retrieve the latest bug fixes. The command is:

[ec2-user ~]$ sudo yum update

To only apply security updates, a security flag may be appended as such:

[ec2-user ~]$ sudo yum update –security

To update a single package and its dependencies without updating the entire system:

[ec2-user ~]$ sudo yum update single-package-name

Running these commands all serve to update the RPM package and helps to mitigate the risks within Amazon EC2 Linux instances that may exist in a CloudFormation ecosystem.

Conclusion

AWS CloudFormation is a powerful tool for managing infrastructure. As an organization’s infrastructure grows and the quantity of CloudFormation stacks and templates increases, it’s important to secure that infrastructure from development to production. Learning these and other best practices will help an organization get the most out of AWS CloudFormation.

With local or CI/CD scanning of your AWS CloudFormation code, it’s possible to receive instant feedback on stacks and templates. But because of the complexity inherent to AWS’s suite of tools and CloudFormation’s dependency-driven nature, particularly when using cross-stack references, it’s possible to miss important components. In order to get a holistic view into what is actually being provisioned or changed, including variables being called, you may need to scan the AWS CloudFormation resource outputs.

How Cycode Can Help With AWS CloudFormation Security

Cycode provides complete visibility into enterprise DevOps tools and infrastructure. Cycode’s Infrastructure as Code capabilities include comprehensive security scanning and preventing escaped secrets, environmental drift, code leaks, and other common issues, all within flexible developer-friendly workflows. Cycode also supports critical code monitoring as a means of helping ensure CloudFormation security best practices are adhered to. Once integrated into developer workflows, each commit and PR is scanned for issues including hard-coded secrets or potential IaC misconfigurations, and alerts are issued appropriately. Remediation is available both through a GUI and within the PR.

Cycode helps establish strong governance overall points of the IaC lifecycle by providing a cross-SCM inventory of all users, contributors, teams, organizations, and repositories in your organization; this governance extends into providing more oversight into changes made to code as a means of further protecting key code. Cycode also helps you automatically audit access privileges to identify and reduce excessive, unused privileges, and implement separation of duties. Furthermore, Cycode helps ensure that strong authentication and secure development practices are in place. This helps apply security best practices for IaC code when using Terraform, Kubernetes, YAML, ARM, and CloudFormation.

Want To Learn More?

A great place to start is with a free assessment of the security of your DevOps pipeline