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:
-
Prepare a list of resources that you are planning to provision by using CloudFormation.
-
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.
-
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_buildis the name of the CodeBuild project. -
Deployment-Pipelineis 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
Resourceelement 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, ands3:PutObjectrequire an S3 object resource type, ands3:GetBucketVersioningrequires 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
Principalelement 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
Conditionelement further restricts access to the S3 bucket so that only theDeployfiles_buildCodeBuild project, theDeployment-PipelineCodePipeline 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}/*'