I'm unable to generate an Amazon S3 Inventory Report. Why is this happening?

Last updated: 2021-11-19

I've configured the Amazon Simple Storage Service (Amazon S3) Inventory Report, but it's not being delivered and I'm getting an Access Denied error. Why won't my Inventory Report configuration generate the reports, and how do I resolve this?

Short description

If you created the Amazon S3 Inventory configuration, you must have the correct bucket policies and permissions in place to avoid receiving an Access Denied error:

Access denied Inventory export for 2021-02-19 failed because S3 doesn’t have access to the destination bucket or KMS key. Ask the owner of the destination bucket or KMS key to grant the necessary access and then try again.

To generate an Amazon S3 Inventory Report, the following requirements must be met:

  • Your destination bucket must allow the source bucket to upload the Amazon S3 Inventory Report to the destination bucket.
  • Your destination bucket must be in the same AWS Region as the source bucket (where you've set up the Amazon S3 Inventory).
  • Your destination bucket policy must grant access to the AWS KMS key that's been used to encrypt the Inventory Report file.

Note: It can take up to 48 hours to deliver the first Inventory Report.

Resolution

Allowing the source bucket to upload the Amazon S3 Inventory Report to the destination bucket

To generate and upload the Inventory Report to the destination bucket, your bucket policy must allow the source bucket to upload to the destination bucket.

For example:

{
  "Version": "2012-10-17",
  "Id": "S3PolicyId",
  "Statement": [
    {
      "Sid":"InventoryAndAnalyticsExamplePolicy",
      "Effect":"Allow",
      "Principal": {"Service": "s3.amazonaws.com"},
      "Action":"s3:PutObject",
      "Resource":["arn:aws:s3:::destinationbucket/*"],
      "Condition": {
          "ArnLike": {
              "aws:SourceArn": "arn:aws:s3:::sourcebucket"
           },
         "StringEquals": {
             "aws:SourceAccount": "123456789012",
             "s3:x-amz-acl": "bucket-owner-full-control"
          }
       }
    }
  ]
}

Therefore, review your destination bucket policy for any Deny statements. The bucket can't include any Deny statements that prevent Amazon S3 (s3.amazonaws.com) from performing a PutObject in the destination bucket. An explicit deny takes precedence over any Allow statements. Exclude the Amazon S3 service (s3.amazonaws.com) from every Deny statement that might affect a PutObject action.

Here's an example bucket policy that denies access to Amazon S3 (s3.amazonaws.com) and only allows access to a specified IP range:

{
  "Version": "2012-10-17",
  "Id": "S3PolicyId",
  "Statement": [
    {
      "Sid": "IPAllow",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": [
	       "arn:aws:s3:::destinationbucket",
               "arn:aws:s3:::destinationbucket/*"
      ],
      "Condition": {
	 "NotIpAddress": {"aws:SourceIp": "54.240.143.0/24"}
      }
    }
  ]
}

To correct the previous bucket policy, update your policy like this:

{
"Version": "2012-10-17",  "Id": "S3PolicyId",
 "Statement": [
    {
      "Sid": "IPAllow",
      "Action": "s3:*",
      "Effect": "Deny",
      "Resource": [
        "arn:aws:s3:::destinationbucket",
        "arn:aws:s3:::destinationbucket/*"
      ],
      "Condition": {
        "NotIpAddress": {
          "aws:SourceIp": "54.240.143.0/24"
        },
        "ArnNotLike": {
          "aws:SourceArn": "arn:aws:s3:::sourcebucket"
        }
      },
      "Principal": "*"
    },
    {
      "Sid": "InventoryAndAnalyticsExamplePolicy",
      "Action": [
        "s3:PutObject"
      ],
      "Effect": "Allow",
      "Resource": [
        "arn:aws:s3:::destinationbucket/*"
      ],
      "Condition": {
        "ArnLike": {
          "aws:SourceArn": "arn:aws:s3:::sourcebucket"
        },
        "StringEquals": {
          "aws:SourceAccount": "123456789012",
          "s3:x-amz-acl": "bucket-owner-full-control"
        }
      },
      "Principal": {
        "AWS": [
          "s3.amazonaws.com"
        ]
      }
    }
  ]
}

Confirming that your destination bucket is in the same AWS Region as the source bucket

To verify that your destination bucket is in the same AWS Region as your source bucket, perform the following steps:

1.    Sign in to the AWS Management Console.

2.    Open the Amazon S3 console.

3.    Review the AWS Region column in your bucket list to confirm that your destination bucket is in the same AWS Region as the source bucket. (The source bucket is where you set up the Amazon S3 Inventory.)

4.    (Optional) If your source and destination bucket are in different Regions, then create or choose a new bucket. This is because the source bucket and destination bucket must be in the same AWS Region.

Note: Amazon S3 creates buckets in specific Regions. After a bucket is created in a specific Region, any objects that belong to the bucket never leave that Region (unless they're explicitly transferred). For more information about using Amazon S3 buckets and AWS Regions, see Buckets overview.

Granting access to the AWS KMS key that's been used to encrypt the Inventory Report file

If you encrypted your Amazon S3 bucket with an AWS KMS key, then make sure to give Amazon S3 access to your KMS key.

To grant permissions for encryption using your AWS KMS key, perform the following steps:

1.    Sign into the AWS Management Console.

Note: Make sure to sign in using the AWS account that owns the AWS KMS key.

2.    Open the AWS KMS console.

3.    In the left navigation pane, choose Customer managed keys.

4.    Under Customer managed keys, select the AWS KMS key that you want to use to encrypt the Inventory Report file.

5.    Under Key policy, choose Switch to policy view.

6 To update the key policy, choose Edit.

7.    Under Edit key policy, add the following key policy to the existing key policy.

{
    "Sid": "Allow Amazon S3 use of the KMS key",
    "Effect": "Allow",
    "Principal": {
        "Service": "s3.amazonaws.com"
    },
    "Action": [
        "kms:GenerateDataKey"
    ],
    "Resource": "*",
    "Condition":{
      "StringEquals":{
         "aws:SourceAccount":"source-account-id"
     },
      "ArnLike":{
        "aws:SourceARN": "arn:aws:s3:::source-bucket-name"
     }
   }
}

8.    Choose Save changes.

Reviewing your server access logs and CloudTrail History

Review your server access logs to see if any changes were made to your bucket policies during the time that your Inventory Report stopped being delivered. The Amazon S3 server access log format looks like the following:

79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be awsexamplebucket1 [06/Feb/2019:00:00:38 +0000] 192.0.2.3 79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be 891CE47D2EXAMPLE REST.PUT.BUCKETPOLICY - "GET /awsexamplebucket1?logging HTTP/1.1" 200 - 242 - 11 - "-" "S3Console/0.4" - 9vKBE6vMhrNiWHZmb2L0mXOcqPGzQOI5XLnCtZNPxev+Hf+7tpT6sxDwDty4LHBUOZJG96N1234= SigV2 ECDHE-RSA-AES128-GCM-SHA256 AuthHeader awsexamplebucket1.s3.us-west-1.amazonaws.com TLSV1.1

Look for any of the following entries, which indicate that changes were made to your bucket policy:

REST.PUT.BUCKETPOLICY

You can also search for the PutBucketPolicy action in your AWS CloudTrail Event history to confirm whether any recent changes were made. Note that CloudTrail Event history provides only a 90-day window. If the PutBucketPolicy action was performed more than 90 days ago, then you must query the CloudTrail logs directly in Amazon S3. For information about the Amazon S3 API calls that are captured by CloudTrail, see Amazon S3 information in CloudTrail on the AWS Docs GitHub website.