Skip to content

Has anyone managed to deploy with CloudFormation S3 Multi-Region Access Points?

0

I have created 2 stacks in 2 different regions:

  • 1 bucket as a secondary
  • 1 bucket is primary

I try configuring the policy and access point in the primary stack. Still, I find it impossible because it requires references that create circular dependency or the creation of a third bucket

AWSTemplateFormatVersion: '2010-09-09'

Parameters:
  StageName:
    Type: String
  S3IrlName:
    Type: String
  S3IrlArn:
    Type: String

Resources:
#########################################################################
#  S3
##########################################################################
  PrimaryBucket:
    Type: AWS::S3::Bucket
    Properties:
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
      VersioningConfiguration: 
        Status: Enabled      
     ReplicationConfiguration:   -> This EMIT circular dependency
        Role: !GetAtt ReplicationRole.Arn
        Rules:
          - Id: ReplicationRule
            Status: Enabled
            Prefix: ''
            Destination:
              Bucket: !Ref S3IrlArn
              StorageClass: STANDARD

  ReplicationRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: s3.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: S3ReplicationPolicy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - s3:GetObjectVersionForReplication
                  - s3:GetObjectVersionAcl
                  - s3:GetObjectVersionTagging
                Resource:
                  - !Sub "arn:aws:s3:::${PrimaryBucket}/*"
              - Effect: Allow
                Action:
                  - s3:ReplicateObject
                  - s3:ReplicateDelete
                  - s3:ReplicateTags
                Resource:
                  - !Sub "arn:aws:s3:::${S3IrlName}/*"
      Tags:
        - Key: Name
          Value: !Sub s3-ReplicationRole-${StageName}
        - Key: Environment
          Value: !Sub ${StageName}

  PrimaryBucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref PrimaryBucket
      PolicyDocument:
        Statement:
          - Sid: AllowCloudFrontServicePrincipalReadOnly
            Effect: Allow
            Action:
              - "s3:GetObject"
            Principal: 
              Service: "cloudfront.amazonaws.com"
            Resource:
              - !Sub ${PrimaryBucket.Arn}/*
          - Sid: RequireEncryptionInTransit
            Action: s3:*
            Effect: Deny
            Principal: "*"
            Resource:
              - !GetAtt PrimaryBucket.Arn
              - !Sub ${PrimaryBucket.Arn}/*
            Condition:
              Bool:
                aws:SecureTransport: false
          - Sid: ReplicationPrimary
            Effect: Allow
            Action: s3:ReplicateObject
            Principal:
              AWS: !GetAtt ReplicationRole.Arn
            Resource: arn:aws:s3:::!Ref PrimaryBucket/*
          - Sid: ReplicationSecondary
            Effect: Allow
            Action: s3:ReplicateObject
            Principal:
              AWS: !Ref S3IrlArn
            Resource:
              - !Sub "arn:aws:s3:::${S3IrlName}/*"

####THIS IS WRONG
  ReplicationConfiguration:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Ref PrimaryBucket -> THIS IS WRONG EMIT Bucket already exists
      ReplicationConfiguration: 
        Role: !GetAtt ReplicationRole.Arn
        Rules:
          - Id: ReplicationRule
            Status: Enabled
            Prefix: ''
            Destination:
              Bucket: !Ref S3IrlArn
              StorageClass: STANDARD
####----THIS IS WRONG

  MultiRegionAccessPoint:
    Type: AWS::S3::MultiRegionAccessPoint
    Properties:
      Regions:
        - Bucket: !Ref PrimaryBucket
        - Bucket: !Ref S3IrlName
          
Outputs:
  MultiRegionAccessPointAlias:
    Description: Alias of the Multi-Region Access Point
    Value: !GetAtt MultiRegionAccessPoint.Alias
    Export:
      Name: !Sub ${AWS::StackName}-MultiRegionAccessPointAlias

Does anyone know what is the correct way?

3 Answers
0
Accepted Answer

Your template has an S3 bucket called PrimaryBucket and an IAM role called ReplicationRole that depend on each other.

PrimaryBucket's replication configuration needs the name of the role. ReplicationRole's policies need the name of the bucket.

Each resource uses a !Ref (implicit via a !Sub) to get the name of the other resource.

The PrimaryBucket doesn't set a BucketName, and the ReplicationRole doesn't set a RoleName. Normally in each case CloudFormation will generate an automatic name.

But because of the circular references, CloudFormation can't decide which one to create first, and so it fails with a circular dependency.

To solve this I would set either the name of the bucket or the role via a stack parameter.

For example, I would add a PrimaryBucketName parameter and refer to that parameter in all places where you need the bucket name.

Your template might look like this:

Parameters:
  PrimaryBucketName:
    Type: String

Resources:
  PrimaryBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Ref PrimaryBucketName

  ReplicationRole:
    Type: AWS::IAM::Role
    Properties:
      Policies:
        - PolicyDocument:
            Statement:
              - Resource: !Sub "arn:aws:s3:::${PrimaryBucketName}/*"

answered 2 years ago

EXPERT

reviewed a year ago

0

Deploying S3 Multi-Region Access Points with CloudFormation can indeed be challenging due to the complexities involved. Based on your current setup and the issues you're facing, here are some suggestions to help you configure the Multi-Region Access Point correctly:

  1. Separate the bucket creation and the Multi-Region Access Point configuration into different stacks. This approach can help avoid circular dependencies.

  2. For the ReplicationConfiguration, instead of creating a new bucket, you should modify the existing PrimaryBucket resource. Add the ReplicationConfiguration as a property of the PrimaryBucket:

    PrimaryBucket:
      Type: AWS::S3::Bucket
      Properties:
        # ... other properties ...
        ReplicationConfiguration:
          Role: !GetAtt ReplicationRole.Arn
          Rules:
            - Id: ReplicationRule
              Status: Enabled
              Prefix: ''
              Destination:
                Bucket: !Ref S3IrlArn
                StorageClass: STANDARD
  3. For the Multi-Region Access Point, ensure you're using the correct bucket names or ARNs. If the secondary bucket is in a different account, you'll need to specify the BucketAccountId:

    MultiRegionAccessPoint:
      Type: AWS::S3::MultiRegionAccessPoint
      Properties:
        Regions:
          - Bucket: !Ref PrimaryBucket
          - Bucket: !Ref S3IrlName
            BucketAccountId: '123456789012'  # If in a different account
  4. Consider creating a separate AWS::S3::MultiRegionAccessPointPolicy resource to manage the access policy for your Multi-Region Access Point:

    MultiRegionAccessPointPolicy:
      Type: AWS::S3::MultiRegionAccessPointPolicy
      Properties:
        MrapName: !Ref MultiRegionAccessPoint
        Policy:
          # Your policy document here
  5. Ensure that your IAM roles and policies have the necessary permissions for cross-region and cross-account access if applicable.

Remember that Multi-Region Access Points have some limitations and specific requirements. For example, all buckets associated with a Multi-Region Access Point must have versioning enabled, and they must be in different regions.

Also, keep in mind that some operations related to Multi-Region Access Points might not be immediately consistent across all regions, so you may need to implement appropriate wait conditions or use AWS CLI commands to check the status of your resources after deployment.

By separating your resources into different stacks and ensuring correct references between them, you should be able to successfully deploy your S3 Multi-Region Access Point configuration using CloudFormation.
Sources
AWS::S3::MultiRegionAccessPoint Region - AWS CloudFormation
AWS::S3::MultiRegionAccessPoint - AWS CloudFormation
AWS::S3::MultiRegionAccessPointPolicy - AWS CloudFormation

answered 2 years ago

EXPERT

reviewed 2 years ago

0

Thank you Adeleke

If I move the ReplicationConfiguration into PrimaryBucket I get the circular dependency with ReplicationRole

It is because it is creating the bucket, and the solution is to pass a fixed name for BucketName

BucketName
A name for the bucket. If you don't specify a name, AWS CloudFormation generates a unique ID and uses that ID for the bucket name. The bucket name must contain only lowercase letters, numbers, periods (.), and dashes (-) and must follow Amazon S3 bucket restrictions and limitations. For more information, see Rules for naming Amazon S3 buckets in the Amazon S3 User Guide.

Important
If you specify a name, you can't perform updates that require replacement of this resource. You can perform updates that require no or some interruption. If you need to replace the resource, specify a new name.

Required: No

Type: String

Update requires: Replacement

Setting up a BucketName it works by moving the ReplicationConfiguration into PrimaryBucket

answered 2 years ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.