Configuring least-privilege permissions for resources provisioned through CloudFormation - AWS Prescriptive Guidance

Configuring least-privilege permissions for resources provisioned through CloudFormation

AWS CloudFormation allows you to provision many different types of AWS resources. Provisioned resources require their own set of permissions to function as intended and to configure who has access to those resources. The previous chapter reviewed options for configuring permissions to access and use the CloudFormation service. This chapter reviews how you can apply the principle of least privilege to resources provisioned through CloudFormation.

In this guide, it would be practically impossible to review the security recommendations and best practices for every type of AWS resource that can be provisioned through CloudFormation. If you have questions related to a specific service, we recommend that you review the documentation for that service. Most AWS service documents contain a security section and information about the permissions required to use that service. For a complete list of AWS service documentation, see AWS Documentation.

The following are high-level, service-agnostic steps you can take to create CloudFormation templates that adhere to the principle of least privilege:

  1. Prepare a list of resources that you are planning to provision by using CloudFormation.

  2. See the AWS Documentation for the corresponding services and review the sections about security and access management. This helps you understand the service-specific requirements and recommendations.

  3. Use the information you gathered in the previous steps to design CloudFormation templates and associated policies that allow only the required permissions and deny all others.

Next, this guide reviews an example of how you can apply the principle of least privilege in CloudFormation templates, using a real-world use case.

Example: Amazon S3 bucket for storing pipeline artifacts

This example creates an Amazon Simple Storage Service (Amazon S3) bucket that is used to store AWS CodeBuild project artifacts. AWS CodePipeline uses these stored artifacts. You can allow CodeBuild and CodePipeline to access this S3 bucket through service roles, and you control that access by using an Amazon S3 bucket policy. The following are the resource names used in this example:

  • Deployfiles_build is the name of the CodeBuild project.

  • Deployment-Pipeline is the name of the pipeline in CodePipeline.

Define the Amazon S3 bucket

First, you define the S3 bucket in the CloudFormation template, which is a YAML-formatted text file.

amzn-s3-demo-bucket: Type: AWS::S3::Bucket Properties: PublicAccessBlockConfiguration: BlockPublicAcls: true BlockPublicPolicy: true IgnorePublicAcls: true RestrictPublicBuckets: true

Define the Amazon S3 bucket policy

Next, in the CloudFormation template, you create a bucket policy that allows only the Deployfiles_build project and the Deployment-Pipeline pipeline to access the bucket.

MyBucketPolicy: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref amzn-s3-demo-bucket PolicyDocument: Version: "2012-10-17" Statement: - Sid: "S3ArtifactRepoAccess" Effect: Allow Action: - ‘s3:GetObject' - ‘s3:GetObjectVersion' - ‘s3:PutObject' - ‘s3:GetBucketVersioning' Resource: - !Sub ‘arn:aws:s3:::${amzn-s3-demo-bucket}' - !Sub ‘arn:aws:s3:::${amzn-s3-demo-bucket}/*' Principal: Service: - codebuild.amazonaws.com - codepipeline.amazonaws.com Condition: StringLike: ‘aws:SourceArn': - !Sub ‘arn:aws:codebuild:${AWS::Region}:${AWS::AccountId}:project/Deployfiles_build' - !Sub ‘arn:aws:codepipeline:${AWS::Region}:${AWS::AccountId}:Deployment-Pipeline' - !Sub ‘arn:aws:codepipeline:${AWS::Region}:${AWS::AccountId}:Deployment-Pipeline/*'

Note the following about this bucket policy:

  • The Resource element lists two different types of resources that use the following Amazon Resource Name (ARN) formats:

    • The ARN format of an S3 object is arn:$<Partition>:s3:::$<BucketName>/$<ObjectName>.

    • The ARN format of an S3 bucket is arn:$<Partition>:s3:::$<BucketName>.

    s3:GetObject, s3:GetObjectVersion, and s3:PutObject require an S3 object resource type, and s3:GetBucketVersioning requires an S3 bucket resource type. For more information about the required resource types for each action, see Actions, resources, and condition keys for Amazon S3.

  • The Principal element lists the entities that are allowed to perform the Amazon S3 actions defined in the statement. In this case, only CodeBuild and CodePipeline are allowed to perform these actions.

  • The Condition element further restricts access to the S3 bucket so that only the Deployfiles_build CodeBuild project, the Deployment-Pipeline CodePipeline pipeline, and the pipeline actions can access the bucket.

Create the service roles

Although the bucket policy controls access to the bucket, it doesn't grant permissions to CodeBuild and CodePipeline to access it. To grant access, you need to create a service role for each service and add the following statement to each. The services roles for CodeBuild and CodePipeline allow the services to access the S3 bucket and its objects.

Sid: "ViewAccessToS3ArtifactRepo" Effect: Allow Action: - ‘s3:GetObject' - ‘s3:GetObjectVersion' - ‘s3:PutObject' - ‘s3:GetBucketVersioning' Resource: - !Sub ‘arn:aws:s3:::${BuildArtifactsBucket}' - !Sub ‘arn:aws:s3:::${BuildArtifactsBucket}/*'