Question: Why can't I generate an Amazon S3 Inventory Report?

I configured the Amazon Simple Storage Service (Amazon S3) Inventory Report, but it's not being delivered and I'm getting an Access Denied error.

Short descriptionIf you created the Amazon S3 Inventory configuration, then you must have the correct bucket policies and permissions in place to avoid getting this 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.

ResolutionAllow the source bucket to upload the Amazon S3 Inventory Report to the destination bucketTo 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"          }       }    }  ]}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 of a 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"        ]      }    }  ]}Confirm 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, do the following: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.Grant access to the AWS KMS key that was used to encrypt the inventory report fileIf you encrypted your Amazon S3 bucket with an AWS KMS key, then make sure to give Amazon S3 access to your AWS KMS key.To grant permissions for encryption using your AWS KMS key, do the following:1.    Sign in to 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.Note: Check the Last export column under Inventory configurations in the Amazon S3 console. If this column is empty, then Amazon S3 received a 403 AccessDenied response from querying the inventory status of the destination bucket. An empty Last export column doesn't always indicate that the report wasn't delivered. It's possible that the inventory report was successfully delivered. In this case, you can find the inventory report in the specified path within the destination bucket.Review your server access logs and CloudTrail HistoryReview your server access logs. Check if any changes were made to your bucket policies when 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.1Look for any of the following entries that indicate that changes were made to your bucket policy:REST.PUT.BUCKETPOLICYYou can also search for the PutBucketPolicy action in your AWS CloudTrail Event history to confirm if 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.

Related informationEnabling CloudTrail event logging for S3 buckets and objectsGranting permissions for Amazon S3 Inventory and Amazon S3 analyticsHow can I copy all objects from one Amazon S3 bucket to another bucket?