Why can't I load website content uploaded to my Amazon S3 bucket from another AWS account?

Last updated: 2021-01-27

I'm using an Amazon Simple Storage Service (Amazon S3) bucket to store content for my website. A user from another AWS account uploaded an object for the website to my bucket. My bucket policy is correct, but the object won't load on the website. How can I fix this?

Short description

If another AWS account uploads an object to your bucket, then you won't own the object by default. As a result, you might not be able to read the object. The uploading account must explicitly grant you (the bucket owner) permissions to the object.

Additionally, a bucket policy doesn't apply to objects in the bucket that are owned by other accounts. Therefore, the bucket policy that grants read access to your website's users doesn't automatically apply to objects uploaded by another account.

To fix the loading issue, change the object's access control list (ACL) using one of these ways:

  • The object owner grants the object public read access.
  • The object owner grants the bucket owner full control of the object.

Note the following when granting bucket access to another account:

  • Objects uploaded to a bucket by another account won't be readable by the bucket's account by default. The account that uploaded the object must explicitly update the ACL to grant read permissions.
  • Objects uploaded to a bucket by another account won't automatically inherit the permissions defined in the bucket policy. The bucket owner must take ownership of the object for the bucket policy to apply.
  • If you want to allow another account to access your bucket, it's a best practice that you use a bucket policy. A bucket policy is a more centralized and comprehensive way to manage permissions.
  • If you want to allow another account to upload objects to your bucket, create an AWS Identity and Access Management (IAM) role. The IAM role must be created from your AWS account, and configured so that another AWS account can assume the role. When the other account uses the IAM role to upload objects, your account then owns the objects because the role belongs to your account. For an example cross-account configuration using an IAM role, see Bucket owner granting cross-account permission to objects it does not own.

Resolution

The object owner grants the object public read access

The account that uploaded the object can grant the object public read access by running this AWS Command Line Interface (AWS CLI) command:

aws s3api put-object-acl --bucket docexamplebucket --key example.jpg --acl public read

For the value of --bucket, enter the name of the bucket that stores your website content.

Note: If you receive errors when running AWS CLI commands, make sure that you’re using the most recent AWS CLI version.

To restrict traffic to an object, the bucket owner can use a bucket policy that only allows requests coming from certain IP addresses or VPCs.

For example, this bucket policy denies access to objects in docexamplebucket unless the request is from the IP addresses listed as "aws:SourceIp". Or, the request must be from the VPC specified as "aws:sourceVpc":

{
    "Version": "2012-10-17",
    "Id": "Policy1415115909152",
    "Statement": [
        {
            "Sid": "Deny-Access-Except-For-Trusted-IPs-and-VPC",
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::docexamplebucket/*",
            "Condition": {
                "NotIpAddress": {
                    "aws:SourceIp": [
                        "1.1.1.1/32",
                        "2.2.2.2/32",
                        "3.3.3.3/32"
                    ]
                },
                "StringNotEquals": {
                    "aws:sourceVpc": "vpc-12345abc"
                }
            }
        }
    ]
}

The object owner grants the bucket owner full control of the object

Object owners can automatically grant the bucket owner full control of an object by enabling S3 Object Ownership on the destination bucket. This feature grants the bucket owner control when the object owner uploads an object, and includes the bucket-owner-full-control canned ACL.

After the bucket owner configures their S3 Object Ownership to "bucket owner preferred", the bucket owner can add another bucket policy. This additional bucket policy must require all Amazon S3 PUT operations to include the bucket-owner-full-control canned ACL. This ACL grants the bucket owner full control of new objects. For more information, see Controlling ownership of uploaded objects using S3 Object Ownership.

To grant the bucket owner full control of the object, use the following CLI syntax when uploading objects:

aws s3api put-object --bucket docexamplebucket --key example.jpg --acl bucket-owner-full-control

The bucket owner now owns the object, and the object inherits the permissions set on the bucket policy.

For existing objects that were uploaded before enabling S3 Object Ownership, the object owner must grant the bucket owner permissions on the object. Then, the bucket owner must copy over the object itself.

To grant the bucket owner full control of the object, use the following CLI syntax with the account that uploaded the object:

aws s3api put-object-acl --bucket docexamplebucket --key example.jpg --acl bucket-owner-full-control

To inherit object ownership of the object, the bucket owner must copy over the object itself like this:

aws s3 cp s3://docexamplebucket/example.jpg s3://docexamplebucket/example.jpg --acl bucket-owner-full-control

The bucket owner now owns the object, and the object inherits the permissions set on the bucket policy.

Require that cross-account uploads grant the bucket owner full control of the object

To require that all uploads (s3:PutObject) from another account grant the bucket owner full control of the object, use a bucket policy like this:

{
    "Id": "Policy1541018284691",
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "RequireBucketOwnerFullControlOnPuts",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::111122223333:user/iam_user"                ]
            },
            "Action": [
                "s3:PutObject"
            ],
            "Effect": "Allow",
            "Resource": "arn:aws:s3:::docexamplebucket/*",
            "Condition": {
                "StringEquals": {
                    "s3:x-amz-acl": "bucket-owner-full-control"
                }
            }
        }
    ]
}

With this bucket policy, the user from the other account (111122223333) can upload to the bucket only when the object's ACL is specified. The object's ACL must grant the bucket owner full control. The user must then upload objects like this:

aws s3 cp path/to/local/file s3://docexamplebucket --acl bucket-owner-full-control