What might cause an "Access Denied" error when creating a cloudfront s3 Origin using cloudformation?

0

I have a bucket in account A. This bucket is configured to block all public access, and to allow GetObject to requests from cloudfront with "aws:ResourceOrgID" matching my orgId.

In Account B (inside my organisation) I can create an OriginAccessControl, and using this and the console, i can manually add the url bucketname.s3.region.amazonaws.com as an s3 origin, and using this OriginAccessControl, I can access the files from cloudformation. (I have also verified that this is not possible form an account outside my org, I believe my bucket policy is ok)

Trying to configure the exact same origin using cloudformation leads to the following error:

Resource handler returned message: "Access denied for operation 'Access Denied. (Service: CloudFront, Status Code: 403, Request ID: ....

I assume, that cloudformation is either trying to verify that the bucket is accessbile in the background, or is trying to change the bucket permissions.

Unfortunately changing the bucket policy action to * for resources BucketName, BUcketname/* doesnt help.

What could cloudformation be doing that the console doesnt which causes this failure?

  • In the CloudFormation template, what is the value for Distribution.Properties.DistributionConfig.Origins.DomainName?

5 Answers
0
Accepted Answer

Turns out there was no problem at all, the issue was with my bucket name being misformed!

James
answered a year ago
0

Hi Gary, I promise you that the following does appear to work, but only if i add the origin through the console, not when using cloudformation. The problem is using cloudformation to do the same. Also, I cannot add the distribution ID at this point to the bucket policy as it is unknown, and this bucket is not part of this stack.

    {
        "Effect": "Allow",
        "Principal": {
            "Service": "cloudfront.amazonaws.com"
        },
        "Action": "s3:GetObject",
        "Resource": "arn:aws:s3:::MyBucketName/*",
        "Condition": {
            "StringEquals": {
                "aws:ResourceOrgID": "myOrgId"
            }
        }
    },

It's really stumped me

James
answered a year ago
0

Hey James,

So I stand true with my statement still. Your policy "Condition" isnt allowing allowing access from your ORG, its allowing access from CloudFront to your Bucket In your Org. The Condition ResourceOrgID is the resource being accessed not the source account/service.

aws:ResourceOrgID = AWS organization ID of the resource being accessed

This means anycloud Distribution can access your bucket. PrincipalOrgID would be the condition you would need to only allow access from a Role/Account in your Org but that as I said isnt supported.

The table here explains what your condition is https://aws.amazon.com/blogs/security/how-to-control-access-to-aws-resources-based-on-aws-account-ou-or-organization/

Your policy is only backing up your defined resource being that the bucket is in your org which is going to be because thats the where the bucket lives. So that condition doesnt actually do anything.

Anyway that wasnt the issue you had but one to review if security is a concern..

We use terraform where that issue you have with cat and mouse isnt a problem..

Gary

profile picture
EXPERT
answered a year ago
  • Hi Gary, You're absolutely right actually, thanks for taking the time to look into it! I thought I'd tested it, but I just set up a cloudfront distribution in an account outside the organisation and it worked, so all I was actually testing for was a signed request from any cloudfront as you said! To resolve this, without having to add each distributionId indiviudally to the bucket policy, I've tested the following bucket policy which does seem to work (requires the Referer header to be set as a custom header in the origin)

    { "Effect": "Allow", "Principal": { "Service": "cloudfront.amazonaws.com" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::MyBucketName/*", "Condition": { "StringEquals": { "aws:Referer": "someSecretString" } } },

    It's not absolutely essential that nobody can access the bucket directly as it's a public website, and I think that restricting it to only cloudfront distributions that "know" the secret header should be sufficent?

    The problem I was orignally having has disappeared (turns out the problem was me).

  • Hey James,

    That policy i think without specifying the ARN is the best your going to get. Good idea using a referer! Unless someone knows both the bucket name and header your good to go buddy..

    Thanks for the update.. Its good to know

    Gary

0

Hey there,

You can NOT reference an ResourceOrgID on Principals originating from AWS Services. The AWS Services i.e. Cloudfront does NOT reside in your ORG. You will need to reference the CloudFront ARN of the account its setup in than the ORG

Correct your bucket policy which should fix the issue as an example. Update the Bucket name and sourceARN :-

{
    "Version": "2012-10-17",
    "Statement": {
        "Sid": "AllowCloudFrontServicePrincipalReadOnly",
        "Effect": "Allow",
        "Principal": {
            "Service": "cloudfront.amazonaws.com"
        },
        "Action": "s3:GetObject",
        "Resource": "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*",
        "Condition": {
            "StringEquals": {
                "AWS:SourceArn": "arn:aws:cloudfront::111122223333:distribution/EDFDVBD6EXAMPLE"
            }
        }
    }
}

If you are using KMS encryption you may need to also adjust your KMS policy also.

If this answers your question, please accept this so it helps others and me.

profile picture
EXPERT
answered a year ago
0

I think I ran into a similar problem once and it was caused by not using the region as part of the DomainName when referencing an S3 bucket.

profile pictureAWS
EXPERT
kentrad
answered a year 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.

Guidelines for Answering Questions