amazon-web-servicesamazon-s3aws-cloudformationamazon-cloudfronttroposphere

How to add OriginAccessIdentity to AWS S3 Bucket Policy using troposphere


I have a AWS Cloudformation stack, created in Python using Troposphere. I need to add OriginAccessIdentity to the S3 bucket access policy.

Amongst other things, I am importing the following:

from awacs.aws import (
    Allow,
    Policy,
    AWSPrincipal,
    Statement
)

Part of the stack creates a Cloudfront distribution, added a S3 Origin with just one associated cacheBehavior. This works fine, the Origin an behavior are created and can be seen in the AWS Cloudfront console.

I have used the following code to create an OriginAccessIdentity:

cloudfrontOriginAccessIdentity = t.add_resource(CloudFrontOriginAccessIdentity(
   "cloudfrontOriginAccessIdentity",
      CloudFrontOriginAccessIdentityConfig=CloudFrontOriginAccessIdentityConfig(
        Comment = "React-Pattern-Origin-Access-Identity" 
      )
 ))

Again, this works fine and the OriginAccessIdentity is created and can be seen in the AWS Cloudfront console, and is associated with the Origin.

I am using the following code to create a S3BucketPolicy:

t.add_resource(s3.BucketPolicy(
  "reactBucketPolicy",
    Bucket=Ref("ParamS3BucketName"),
    PolicyDocument=dict(
      Statement=[dict(
        Sid="reactBucketPolicyStatement01",
        Effect="Allow",
        Action=[
          "s3:GetObject"
        ],
        Principal=AWSPrincipal(["*"]),
        Resource=[Join("", ["arn:aws:s3:::", Ref("ParamS3BucketName"), "/*"])],
      )],
    )
)) 

This too works fine, with the policy being generated and attached to the bucket - can be seen in the AWS S3 console. The issue I am having is trying to replace
Principal=AWSPrincipal(["*"])
with
Principal=AWSPrincipal([<the_origin_access_identity>])

I have tried
Principal=AWSPrincipal([Join("", ["origin-access-identity/cloudfront/", "Ref(cloudfrontoriginaccessidentity)"])])
and
Principal=AWSPrincipal([Ref(cloudfrontoriginaccessidentity)])

but Cloudformation rejects the update, saying that the Principal is invalid. What do I need to replace the * with in order to get Cloudformation to add my OriginAccessIdentity as the principal to the policy?


Solution

  • Replace this:

    Principal=AWSPrincipal(["*"]),
    

    with this:

    Principal=Principal(
        "CanonicalUser", 
        GetAtt(cloudfrontOriginAccessIdentity, "S3CanonicalUserId"),
    ),
    

    Replace this:

    from awacs.aws import (
        Allow,
        Policy,
        AWSPrincipal,
        Statement
    )
    

    with this:

    from awacs.aws import (
        Allow,
        Policy,
        Principal,
        Statement
    )