Article Summary
Amazon S3 Permission Denied – This guide provides a complete technical reference for diagnosing and resolving Amazon S3 Access Denied (403 Forbidden) and Permission Denied errors that prevent Amazon Connect administrators and agents from accessing call recordings. Drawing on official AWS documentation, AWS re:Post community knowledge, and AWS Contact Center best practices, this article covers:
• Root causes: IAM policies, bucket policies, KMS encryption, ACLs, SCPs, RCPs, VPC endpoints
• Step-by-step troubleshooting for each root cause with console navigation guidance
• Policy examples (IAM, S3 bucket, KMS key policies) you can adapt immediately
• Validation and testing procedures post-remediation
• Security best practices to prevent recurrence
1. Introduction
Amazon Connect is AWS’s cloud-based contact center service, used by thousands of organizations to manage customer interactions at scale. One of its most operationally critical features is call recording — the automatic capture and storage of agent-customer conversations. These recordings serve compliance, quality assurance, training, and dispute resolution purposes.
Amazon Connect stores call recordings directly in Amazon Simple Storage Service (Amazon S3). When an administrator configures an Amazon Connect instance, a dedicated S3 bucket is created or designated to hold recordings under a structured path, such as:
| connect-{instance-id}/connect/{instance-alias}/CallRecordings/YYYY/MM/DD/{contact-id}.wav |
For call recordings to be stored and later retrieved — whether through the Amazon Connect interface, a custom application, or direct S3 access — a precise set of AWS Identity and Access Management (IAM) permissions must be in place. When any permission in this chain is missing, misconfigured, or overridden by a higher-priority policy, Amazon S3 returns a 403 Access Denied or Permission Denied error.
These errors are notoriously opaque. The S3 API returns a 403 response without explaining which specific permission is missing. The root cause could be an IAM policy, bucket policy, bucket ACL, object ACL, AWS KMS encryption key policy, VPC endpoint policy, Service Control Policy (SCP), or Resource Control Policy (RCP). Without a structured approach, administrators can spend hours chasing the wrong configuration.
This guide eliminates that guesswork. It provides a methodical, expert-level walkthrough of every common and uncommon cause, complete with policy examples, console navigation steps, and validation procedures.
1.1 Amazon Connect Recording Architecture
Understanding the recording storage architecture is essential before troubleshooting. The following components are involved:
- Amazon Connect Instance: The contact center environment where calls are processed.
- Contact Flows: The routing logic that controls call behavior. Recording must be explicitly enabled in a Contact Flow using the Set Recording Behavior block. Without this step, no recordings are written to S3.
- Amazon Connect Service Role: An IAM role that Amazon Connect assumes to write recordings to S3.
- Amazon S3 Bucket: The destination storage bucket, typically named with a prefix of connect-.
- AWS KMS (optional): Used to encrypt recordings at rest when SSE-KMS is configured.
- IAM Users/Roles: The identities of administrators or agents who retrieve recordings.
| Important: Recording must be enabled in Contact Flows. If the Set Recording Behavior block is absent or set to |
| None, Amazon Connect creates the S3 bucket but writes no recording objects. The bucket will appear empty, |
| which is often mistaken for a permissions error. |
2. Understanding the Error: Amazon S3 Permission Denied
An HTTP 403 Forbidden (Access Denied) error from Amazon S3 occurs under two distinct conditions:
- Explicit Denial: A policy contains a Deny statement for the specific AWS action being performed. Explicit Deny always wins — it overrides any Allow statement from any other policy.
- Implicit Denial: There is no applicable Deny statement, but also no applicable Allow statement. Because IAM implicitly denies all actions by default, a missing Allow is effectively a denial.
2.1 Common Error Messages and Their Meanings
| Error / Code | Likely Root Cause |
| AccessDenied: Access Denied | IAM policy missing, bucket policy block, or wrong credentials |
| 403 Forbidden | Bucket policy or ACL restriction; most common S3 error |
| AllAccessDisabled | S3 Block Public Access settings active |
| NoCredentialProviders | AWS credentials not configured or not found |
| InvalidAccessKeyId | Incorrect or mistyped Access Key ID |
| SignatureDoesNotMatch | Incorrect Secret Access Key |
| AccountProblem | AWS account issue such as billing suspension |
| KMS.InvalidKeyUsageException | KMS key policy missing kms:Decrypt or kms:GenerateDataKey |
2.2 Impact on Amazon Connect Operations
When S3 Access Denied errors affect Amazon Connect, the operational impact is significant:
- Agents cannot play back call recordings from the Amazon Connect Contact Control Panel (CCP).
- Contact search in Amazon Connect returns contacts, but the recording playback link is broken or absent.
- Administrators cannot retrieve recordings for compliance audits or quality reviews.
- Custom applications using the Amazon Connect API or direct S3 access fail with 403 errors.
- New recordings may silently fail to write to S3, resulting in compliance gaps.
2.3 Enhanced Error Messages
Amazon S3 now includes additional context in access denied errors for requests within the same AWS account or same AWS Organization. Error messages follow this format:
| User: arn:aws:iam::123456789012:user/Admin is not authorized to perform: |
| s3:GetObject on resource: “arn:aws:s3:::connect-bucket/CallRecordings/…” |
| because no identity-based policy allows the s3:GetObject action |
The context field after because identifies the policy type responsible, making diagnosis significantly faster. Note that cross-account requests outside the same AWS Organization return only a generic Access Denied message.
3. Root Cause Analysis
The following table summarizes all documented root causes of S3 Access Denied errors in Amazon Connect environments. Each cause is addressed in detail in Section 4 (Troubleshooting) and Section 5 (Resolution).
| Root Cause | Frequency | Impact Scope |
| Missing IAM permissions | Very High | Individual user/role |
| Restrictive S3 bucket policy | High | All users accessing bucket |
| S3 Block Public Access | High | All public-facing access |
| Connect service role misconfigured | High | Recording write failure |
| KMS key policy missing kms:Decrypt | Medium | Encrypted object retrieval |
| Object ownership/ACL conflict | Medium | Cross-account objects |
| Recording not enabled in Contact Flow | Medium | No recordings created |
| AWS Organizations SCP restriction | Medium | Entire account/OU |
| Resource Control Policy (RCP) | Medium | Cross-org access |
| VPC endpoint policy restriction | Low-Medium | VPC-routed access |
| IAM permissions boundary | Low-Medium | Bounded IAM identities |
| Temporary credential session policy | Low | Assumed-role sessions |
| Incorrect AWS region/endpoint | Low | Misconfigured clients |
| Object Lock / MFA Delete | Low | Delete operations only |
| Requester Pays misconfiguration | Low | Cross-account access |
3.1 IAM Permission Issues
IAM policies are the first and most common cause of S3 Access Denied errors. An IAM user or role accessing call recordings must have explicit Allow statements for all required S3 actions. The default implicit deny means that any missing permission results in a 403 error, even if the bucket policy allows access.
For same-account access, at least one policy (either the IAM policy or the bucket policy) must contain an Allow statement. For cross-account access, both the bucket policy and the requester’s IAM policy must contain Allow statements.
3.2 S3 Bucket Policy Restrictions
The S3 bucket policy is evaluated alongside IAM policies. A bucket policy Deny statement overrides any IAM Allow. Common mistakes include:
- A catch-all Deny statement that accidentally covers the Amazon Connect service role or administrator IAM users.
- VPC endpoint conditions that block requests from outside a specific VPC.
- IP address conditions that restrict access to certain CIDR ranges.
- Secure transport conditions (aws:SecureTransport) that may conflict with certain SDK configurations.
3.3 Amazon Connect Service Role Configuration
Amazon Connect uses an IAM service role to write call recordings to S3. If this role is missing required permissions — or if the bucket policy explicitly denies the service role — recordings will not be written to S3. For instances created after October 17, 2018, Amazon Connect uses Service-Linked Roles, which are managed by AWS. For older instances, a custom IAM role was created at instance setup time.
The service role must have, at minimum, s3:PutObject and s3:GetObject permissions on the recording bucket, and if KMS encryption is used, kms:GenerateDataKey and kms:Decrypt permissions on the KMS key.
3.4 AWS KMS Encryption Issues
When Amazon Connect recordings are encrypted using AWS Key Management Service (SSE-KMS), accessing those recordings requires the calling identity to have kms:Decrypt permission on the relevant KMS key. This is in addition to the standard S3 permissions. For cross-account scenarios, the KMS key policy must explicitly allow the external account.
The three S3 encryption types have different permission requirements:
- SSE-S3 (AWS managed keys): No additional permissions required.
- SSE-KMS with customer managed key: Requires kms:GenerateDataKey (upload) and kms:Decrypt (download) on the KMS key.
- SSE-KMS with AWS managed key (aws/s3): Requester must be in the same account that owns the key.
- SSE-C (customer-provided key): No additional permissions, but the key must be supplied with each request.
3.5 Object Ownership and ACL Conflicts
By default, an S3 object is owned by the AWS account that uploads it. If a third-party application or a different AWS account uploads recordings to the bucket, the object owner may not be the bucket owner. In this case, the bucket policy and IAM policies may Allow access, but the actual object ACL controls access — and the bucket owner may lack permissions.
AWS recommends using Bucket owner enforced (Object Ownership setting) to disable ACLs entirely and ensure the bucket owner controls all objects. This is now the default setting for new buckets.
3.6 AWS Organizations SCPs and RCPs
If the AWS account is a member of an AWS Organization, Service Control Policies (SCPs) and Resource Control Policies (RCPs) can restrict S3 access at the organization level. SCPs define the maximum permissions for member accounts. RCPs set the maximum available permissions on resources in member accounts. Both can contain Deny statements that override even valid IAM and bucket policies.
An SCP or RCP Deny for s3:* or s3:GetObject will block access regardless of what the bucket policy or IAM policy allows. The management account of the organization is not affected by RCPs.
3.7 VPC Endpoint Policy Restrictions
When Amazon Connect or administrative tools access S3 through a VPC endpoint (private connection), the VPC endpoint policy controls which S3 actions are permitted. A restrictive VPC endpoint policy — one that limits access to specific buckets, actions, or principals — can cause Access Denied errors even when IAM and bucket policies are correct.
4. Step-by-Step Troubleshooting Guide
4.1 Preliminary: Verify Recording Is Enabled in Contact Flow
Before investigating permissions, confirm that recording is enabled in the relevant Contact Flow. This is the most overlooked root cause — Amazon Connect creates the S3 bucket at instance setup but never writes recordings unless recording is explicitly enabled in the flow.
- In the Amazon Connect console, navigate to Routing > Contact Flows.
- Open the contact flow used by the queue where calls are not being recorded.
- Locate the Set call recording behavior block under the Set category in the block palette.
- Verify that the block is present and that the recording mode is set to Agent and Customer (or the appropriate mode for your use case) — not None.
- Save and publish the contact flow if you make any changes.
| Note: The ‘folder structure’ in S3 (year/month/day paths) is created as part of the object key name. |
| If the bucket appears empty, no recordings have been processed through a flow with recording enabled. |
| This is not a permissions error — it is a configuration gap. |
4.2 Check IAM Permissions for the Accessing Identity
Why: If the IAM user or role retrieving recordings lacks required S3 permissions, every access attempt will result in a 403 error, even if the bucket policy grants access.
- Navigate to the IAM console at https://console.aws.amazon.com/iam/
- Select Users or Roles from the left navigation pane.
- Find the IAM identity that is experiencing the Access Denied error.
- Choose the Permissions tab and review all attached policies (both managed and inline).
- Verify that at least one policy grants the following actions on the recording bucket ARN:
| { |
| “Version”: “2012-10-17”, |
| “Statement”: [{ |
| “Effect”: “Allow”, |
| “Action”: [ |
| “s3:ListBucket”, |
| “s3:GetBucketLocation”, |
| “s3:GetObject”, |
| “s3:PutObject”, |
| “s3:GetObjectAcl”, |
| “s3:PutObjectAcl” |
| ], |
| “Resource”: [ |
| “arn:aws:s3:::your-connect-bucket-name”, |
| “arn:aws:s3:::your-connect-bucket-name/*” |
| ] |
| }] |
| } |
- Use the IAM Policy Simulator to test the identity’s effective permissions: https://policysim.aws.amazon.com/
- Verify the IAM identity in use with the AWS CLI:
| aws sts get-caller-identity |
Common mistake: Specifying s3:ListAllMyBuckets on Resource: “*” is required for bucket listing, but the main object permissions must reference the specific bucket and object ARNs. An IAM policy with a space in the ARN (e.g., arn:aws:s3::: DOC-EXAMPLE-BUCKET/*) evaluates to an incorrect ARN and results in Access Denied.
4.3 Review the S3 Bucket Policy
Why: A bucket policy Deny statement overrides any Allow from any IAM policy. Even a correctly configured IAM policy will fail if the bucket policy explicitly denies the requesting identity.
- In the S3 console, navigate to your Amazon Connect recording bucket.
- Choose the Permissions tab.
- Scroll to the Bucket Policy section and choose Edit to view the full policy JSON.
- Review every Statement for Effect: Deny. Check each Deny statement’s Condition block for:
- MFA requirements (aws:MultiFactorAuthPresent)
- VPC or VPC endpoint restrictions (aws:SourceVpce)
- IP address restrictions (aws:SourceIp)
- Specific principal exclusions (StringNotLike on aws:userId)
- Secure transport requirements (aws:SecureTransport)
- Verify that the Amazon Connect service role ARN is not caught by any Deny statement.
- Use the AWS CLI to retrieve the bucket policy programmatically:
| aws s3api get-bucket-policy –bucket your-connect-bucket-name |
| Example: The following bucket policy restricts the bucket to a specific VPC endpoint. |
| Any request from outside vpce-1a2b3c4d will be denied — even for IAM users with Allow policies: |
| { “Effect”: “Deny”, “Principal”: “*”, “Action”: “s3:GetObject”, |
| “Condition”: { “StringNotEquals”: { “aws:SourceVpce”: “vpce-1a2b3c4d” } } } |
4.4 Verify the Amazon Connect Service Role
Why: If the Amazon Connect service role cannot write to S3, recordings will never be created. This also manifests as ‘recordings not found’ errors during playback, because the objects were never stored.
- In the Amazon Connect console, navigate to your instance > Data storage > Call recordings.
- Note the S3 bucket and path configured for recording storage.
- Open the IAM console and locate the IAM role associated with your Amazon Connect instance.
- If your instance was created after 10/17/2018, Amazon Connect uses a Service-Linked Role (SLR) named AWSServiceRoleForAmazonConnect. Verify this role exists and is healthy.
- Expand the attached policies and confirm the role has permissions to the recording bucket:
| # To find the role ID for the Connect service role: |
| aws iam get-role –role-name connect-access-role-{instance-id} |
| # Verify the role can access the bucket by reviewing its attached policies |
- Confirm the S3 bucket listed in the IAM role’s policies matches the bucket in the Connect Data Storage settings.
4.5 Check S3 Block Public Access Settings
Why: S3 Block Public Access settings can override bucket policies and ACLs that would otherwise allow access. If your recording retrieval relies on any form of public or ACL-based access, these settings will block it.
- In the S3 console, open your Connect recording bucket.
- Choose the Permissions tab.
- Review the Block Public Access settings section.
- The four settings and their effects:
- BlockPublicAcls: Blocks PUT requests with public ACLs.
- IgnorePublicAcls: Ignores all public ACLs — any permission granted only by a public ACL is effectively revoked.
- BlockPublicPolicy: Rejects bucket policies that allow public access.
- RestrictPublicBuckets: Restricts bucket access to AWS service principals and authorized users within the account only.
For Amazon Connect recordings accessed only by authenticated IAM users or service roles, Block Public Access settings should not interfere. However, if a custom application relies on object ACLs for access, enable Bucket owner enforced (Object Ownership) instead.
4.6 Investigate KMS Encryption Settings
Why: If recordings are encrypted with SSE-KMS and the requesting identity lacks kms:Decrypt permission, S3 returns a 403 error even if all S3 permissions are correct.
- In the S3 console, navigate to the recording object, then choose its Properties tab.
- Scroll to the Server-side encryption settings section to confirm whether SSE-KMS is in use and note the KMS Key ARN.
- In the AWS KMS console (https://console.aws.amazon.com/kms/), open the relevant key.
- Review the Key Policy to confirm the requesting identity has:
- kms:Decrypt — required to download/play back recordings
- kms:GenerateDataKey — required to upload recordings (for the Connect service role)
- If the IAM user is in a different account than the KMS key, both the key policy and the IAM policy must grant access:
| # In the KMS key policy (cross-account access): |
| { |
| “Effect”: “Allow”, |
| “Principal”: { “AWS”: “arn:aws:iam::EXTERNAL_ACCOUNT_ID:root” }, |
| “Action”: [“kms:Decrypt”, “kms:DescribeKey”], |
| “Resource”: “*” |
| } |
| # In the IAM policy of the external account user: |
| { |
| “Effect”: “Allow”, |
| “Action”: [“kms:Decrypt”, “kms:DescribeKey”], |
| “Resource”: “arn:aws:kms:region:ACCOUNT_ID:key/KEY_ID” |
| } |
4.7 Check Object Ownership and ACLs
Why: If objects were uploaded by a different AWS account, the bucket owner may not have access even with correct bucket policies.
- Use the AWS CLI to compare the canonical ID of the bucket owner with the object owner:
| # Get bucket owner canonical ID: |
| aws s3api list-buckets –query “Owner.ID” |
| # Get object owner canonical ID: |
| aws s3api list-objects –bucket your-connect-bucket –prefix CallRecordings/ |
| # If canonical IDs differ, grant bucket owner full control: |
| aws s3api put-object-acl –bucket your-connect-bucket \ |
| –key CallRecordings/path/to/recording.wav \ |
| –acl bucket-owner-full-control |
- Recommended resolution: Set Object Ownership to Bucket owner enforced to disable ACLs entirely and consolidate ownership. This is the AWS-recommended default for new buckets.
4.8 Review AWS Organizations SCPs and RCPs
Why: SCPs and RCPs define the maximum permissions for an entire account or organization unit. An SCP or RCP Deny overrides all Allow statements from bucket policies and IAM policies.
- Open the AWS Organizations console.
- In the navigation pane, choose Policies.
- Choose Service Control Policies and review all SCPs attached to your account, OU, or organization root.
- Then choose Resource Control Policies and repeat the review.
- Look for any Deny statements on s3:* or s3:GetObject actions.
| # Example SCP that blocks all S3 access (would cause 403 on all S3 operations): |
| { |
| “Version”: “2012-10-17”, |
| “Statement”: [{ |
| “Effect”: “Deny”, |
| “Action”: “s3:*”, |
| “Resource”: “*” |
| }] |
| } |
| Note: The management account of the AWS Organization is not affected by RCPs. |
| Cross-account principals outside the organization receive a generic Access Denied error |
| even if the bucket policy grants them access when an RCP restricts external access. |
4.9 Check VPC Endpoint Policies
Why: If requests to S3 are routed through a VPC endpoint, the endpoint’s policy controls what is allowed. Missing Allow statements or explicit Deny statements in the VPC endpoint policy result in 403 errors.
- In the VPC console, navigate to Endpoints.
- Find the S3 gateway endpoint associated with your VPC.
- Review the Policy tab for the endpoint.
- Verify that the policy allows the required S3 actions on the Amazon Connect recording bucket:
| { |
| “Statement”: [{ |
| “Effect”: “Allow”, |
| “Principal”: “*”, |
| “Action”: [“s3:GetObject”, “s3:PutObject”, “s3:ListBucket”], |
| “Resource”: [ |
| “arn:aws:s3:::your-connect-bucket”, |
| “arn:aws:s3:::your-connect-bucket/*” |
| ] |
| }] |
| } |
4.10 Verify Temporary Credentials and Session Policies
Why: When administrators assume IAM roles or use temporary credentials, a session policy may further restrict permissions. Session policies cannot grant more permissions than the role’s identity-based policies allow.
- Use AWS CloudTrail to find AssumeRole events in the time frame matching the failed access attempts.
- In the CloudTrail event, check the requestParameters field for policy or policyArns fields that indicate session policies were attached.
- Verify that the session policy grants s3:GetObject on the recording bucket ARN.
4.11 Confirm AWS Region and Endpoint Configuration
Why: Accessing an S3 bucket in us-west-2 through the us-east-1 endpoint can return Access Denied errors in some configurations.
- Confirm the region of the Amazon Connect recording bucket:
| aws s3api get-bucket-location –bucket your-connect-bucket-name |
- Ensure that all SDK clients, CLI configurations, and custom applications specify the correct region explicitly.
- For CLI access, use the –region flag: aws s3 ls s3://your-bucket –region us-east-1
4.12 Use the AWS Systems Manager Automation Document
For public bucket access issues, AWS provides an automated diagnostic tool:
- In the AWS Systems Manager console, navigate to Automation.
- Search for and run the AWSSupport-TroubleshootS3PublicRead automation document.
- This tool systematically checks bucket and object ownership, policies, ACLs, and Block Public Access settings.
5. Resolution Methods
5.1 Correcting IAM Policy Permissions
Attach the following policy to the IAM user or role that requires access to Amazon Connect recordings. Replace your-connect-bucket-name with your actual bucket name:
| { |
| “Version”: “2012-10-17”, |
| “Statement”: [ |
| { |
| “Sid”: “ConnectRecordingListBucket”, |
| “Effect”: “Allow”, |
| “Action”: [ |
| “s3:ListBucket”, |
| “s3:GetBucketLocation” |
| ], |
| “Resource”: “arn:aws:s3:::your-connect-bucket-name” |
| }, |
| { |
| “Sid”: “ConnectRecordingObjectAccess”, |
| “Effect”: “Allow”, |
| “Action”: [ |
| “s3:GetObject”, |
| “s3:PutObject”, |
| “s3:GetObjectAcl”, |
| “s3:PutObjectAcl” |
| ], |
| “Resource”: “arn:aws:s3:::your-connect-bucket-name/*” |
| }, |
| { |
| “Sid”: “ListAllBuckets”, |
| “Effect”: “Allow”, |
| “Action”: “s3:ListAllMyBuckets”, |
| “Resource”: “*” |
| } |
| ] |
| } |
5.2 Correcting S3 Bucket Policy
The following bucket policy locks the Amazon Connect recording bucket to only the Amazon Connect service role and an administrative IAM role, using the aws:userId condition with role IDs. This approach is more secure than using ARNs because role IDs remain valid even if the role is renamed.
| { |
| “Version”: “2012-10-17”, |
| “Statement”: [{ |
| “Sid”: “RestrictToConnectAndAdmin”, |
| “Effect”: “Deny”, |
| “Principal”: “*”, |
| “Action”: “s3:*”, |
| “Resource”: [ |
| “arn:aws:s3:::your-connect-bucket”, |
| “arn:aws:s3:::your-connect-bucket/*” |
| ], |
| “Condition”: { |
| “StringNotLike”: { |
| “aws:userId”: [ |
| “CONNECT_SERVICE_ROLE_ID:*”, |
| “ADMIN_ROLE_ID:*” |
| ] |
| } |
| } |
| }] |
| } |
| # Find Role IDs with: |
| # aws iam get-role –role-name YOUR_ROLE_NAME –query ‘Role.RoleId’ |
| Warning: Apply this policy to a test bucket first. A misconfigured Deny policy can lock |
| all users — including administrators — out of the bucket. If locked out, use the |
| AWS root account credentials to remove the bucket policy. |
5.3 Enabling Recordings in Contact Flow
If recordings are not being written to S3 (bucket exists but is empty), enable recording in the Contact Flow:
- In the Amazon Connect console, navigate to Routing > Contact Flows.
- Open the target Contact Flow in the editor.
- In the block palette, under the Set section, drag a Set call recording behavior block onto the canvas.
- Connect the block in the flow before the call reaches the queue.
- Configure the block: set Record to Agent and Customer (or Agent only / Customer only as required).
- Save and Publish the Contact Flow.
5.4 Resolving KMS Permission Issues
Add the following statement to your KMS key policy to allow an IAM user or role to decrypt recordings:
| { |
| “Sid”: “AllowConnectRecordingAccess”, |
| “Effect”: “Allow”, |
| “Principal”: { |
| “AWS”: [ |
| “arn:aws:iam::ACCOUNT_ID:role/YourAdminRole”, |
| “arn:aws:iam::ACCOUNT_ID:role/AWSServiceRoleForAmazonConnect” |
| ] |
| }, |
| “Action”: [ |
| “kms:Decrypt”, |
| “kms:DescribeKey”, |
| “kms:GenerateDataKey” |
| ], |
| “Resource”: “*” |
| } |
5.5 Resolving Object Ownership Issues
To resolve cross-account object ownership conflicts:
- Enable Bucket owner enforced mode to disable ACLs and auto-assign ownership to the bucket owner:
| aws s3api put-bucket-ownership-controls \ |
| –bucket your-connect-bucket \ |
| –ownership-controls=’Rules=[{ObjectOwnership=BucketOwnerEnforced}]’ |
- For existing objects not owned by the bucket owner, grant bucket owner full control:
| aws s3api put-object-acl \ |
| –bucket your-connect-bucket \ |
| –key CallRecordings/path/to/recording.wav \ |
| –acl bucket-owner-full-control |
- Alternatively, copy the object back to itself from the bucket owner’s account to transfer ownership:
| aws s3 cp s3://your-bucket/path/recording.wav s3://your-bucket/path/recording.wav |
5.6 Fixing SCP and RCP Restrictions
If an SCP or RCP is blocking S3 access:
- Identify the specific Deny statement (explicit or implicit) causing the block.
- For an implicit denial (missing Allow), add an Allow statement for the required S3 actions in the SCP.
- For an explicit denial, modify the Deny statement to exclude the required principal using a condition:
| # Exclude specific accounts from a Deny statement using PrincipalAccount: |
| “Condition”: { |
| “StringNotEquals”: { |
| “aws:PrincipalAccount”: “ACCOUNT_ID_TO_ALLOW” |
| } |
| } |
6. Validation and Testing
6.1 Verify Access to the S3 Bucket
After making configuration changes, validate access using the following CLI commands:
| # List objects in the recording bucket: |
| aws s3 ls s3://your-connect-bucket/connect/INSTANCE_ALIAS/CallRecordings/ –recursive |
| # Verify a specific object is accessible: |
| aws s3api head-object –bucket your-connect-bucket –key path/to/recording.wav |
| # Download a recording to test GetObject: |
| aws s3 cp s3://your-connect-bucket/path/to/recording.wav /tmp/test-recording.wav |
6.2 Test Recording Playback in Amazon Connect
- In Amazon Connect, navigate to Contact search (Metrics and quality > Contact search).
- Search for a recent contact that had an active call flow with recording enabled.
- Open the contact record and attempt to play the call recording.
- Successful playback confirms that both the S3 permissions and KMS permissions (if applicable) are correctly configured.
6.3 Use AWS CloudTrail for Access Audit
Enable CloudTrail S3 data event logging to trace all S3 access attempts and identify the exact action and principal causing failures:
| # Enable S3 data event logging in CloudTrail: |
| aws cloudtrail put-event-selectors \ |
| –trail-name your-trail-name \ |
| –event-selectors ‘[{ |
| “ReadWriteType”: “All”, |
| “IncludeManagementEvents”: true, |
| “DataResources”: [{ |
| “Type”: “AWS::S3::Object”, |
| “Values”: [“arn:aws:s3:::your-connect-bucket/”] |
| }] |
| }]’ |
Review CloudTrail logs in CloudWatch Logs or S3 to find Access Denied events. Look for the errorCode field set to AccessDenied and the requestParameters field to identify which action failed.
6.4 IAM Policy Simulator
Use the IAM Policy Simulator to test a user or role’s effective permissions without making actual API calls:
- Navigate to https://policysim.aws.amazon.com/
- Select the IAM user or role to test.
- Choose Amazon S3 as the service and select the actions you want to test (e.g., s3:GetObject).
- Enter the resource ARN (e.g., arn:aws:s3:::your-connect-bucket/path/to/recording.wav).
- Review the simulation result — Allowed or Denied — and the policy responsible for the decision.
7. Best Practices for Secure Amazon Connect Recording Storage
7.1 Least-Privilege IAM Access
- Grant only the S3 actions required by each role. Agents accessing recordings typically only need s3:GetObject; the Connect service role needs s3:PutObject and s3:GetObject.
- Use resource-level permissions: scope all policies to the specific recording bucket and path prefix, not s3:*.
- Prefer IAM roles over IAM users for all programmatic access. Roles support automatic credential rotation.
- Regularly audit IAM policies with AWS IAM Access Analyzer to detect overly permissive configurations.
7.2 S3 Bucket Security Hardening
- Enable Bucket owner enforced (Object Ownership) to disable ACLs and ensure the bucket owner controls all objects.
- Enable S3 Versioning on the recording bucket to protect against accidental deletion and support compliance retention.
- Enable S3 Object Lock in Compliance mode for highly regulated industries where recordings must be immutable.
- Use an S3 bucket policy that restricts access to only the Amazon Connect service role and authorized administrator roles, as shown in Section 5.2.
- Enforce HTTPS-only access with an aws:SecureTransport condition in the bucket policy.
- Enable S3 server access logging or CloudTrail S3 data events to maintain an audit trail.
7.3 KMS Key Management
- Use a customer managed KMS key (CMK) for Amazon Connect recordings. This gives you full control over the key policy and rotation schedule.
- Enable automatic key rotation (annual) for the recording encryption key.
- Scope KMS key policy statements to the minimum required principals: the Connect service role and authorized administrator roles.
- Monitor KMS key usage with AWS CloudTrail and set alarms for unexpected kms:Decrypt calls.
7.4 Monitoring and Auditing
- Enable AWS CloudTrail in all regions and configure S3 data event logging for the recording bucket.
- Set up Amazon CloudWatch Alarms for 4xx error rate on the recording bucket.
- Use Amazon Macie to automatically discover and classify recording data for compliance.
- Use AWS Config rules (s3-bucket-policy-not-more-permissive, s3-bucket-ssl-requests-only) to enforce continuous compliance.
7.5 Operational Governance
- Document the Amazon Connect service role ARN and all IAM roles that require recording access. Maintain this in an internal runbook.
- Test policy changes on a non-production bucket before applying to the production recording bucket.
- Use AWS Service Control Policies to prevent the recording bucket from being made publicly accessible at the organization level.
- Implement tagging on the recording bucket (e.g., Environment: Production, Owner: ContactCenter) to support cost allocation and access governance.
- Review bucket policies and IAM policies quarterly or after any team personnel changes.
8. Key Takeaways
| Takeaway | Detail |
| Deny always wins | An explicit Deny in any policy (SCP, RCP, bucket policy, IAM, VPC endpoint) overrides all Allow statements. |
| Check recording enablement first | Empty S3 bucket is often a Contact Flow misconfiguration, not a permissions error. |
| IAM + Bucket policy for cross-account | Cross-account access requires Allow in both the bucket policy AND the requester’s IAM policy. |
| KMS is a separate permission layer | SSE-KMS encrypted recordings require kms:Decrypt on the KMS key in addition to all S3 permissions. |
| SCPs and RCPs are organization-wide | These policies can silently block all S3 access regardless of IAM or bucket policy configuration. |
| Object Ownership matters | If objects are owned by a different account, only object ACLs control access — bucket policies do not apply. |
| Use IAM Policy Simulator | Test effective permissions before chasing configuration issues across multiple services. |
| Enable CloudTrail data events | S3 data event logging reveals exactly which action, principal, and resource triggered the 403 error. |
9. Frequently Asked Questions (FAQ) for Amazon S3 Permission Denied
Q1: My Amazon Connect recording bucket exists but it is empty. Is this a permissions error?
Not necessarily. If no recordings have been processed through a Contact Flow that has the Set Recording Behavior block configured, no objects will exist in the bucket. First confirm that recording is enabled in the Contact Flow. If the flow has recording enabled and contacts are being handled but no recordings appear, then investigate service role permissions to S3.
Q2: I have s3:GetObject in my IAM policy but still get a 403 error. Why?
Multiple policies contribute to the final access decision. The most likely causes are: (1) the S3 bucket policy has an explicit Deny statement that applies to your identity; (2) an SCP or RCP at the organization level is blocking S3 access; (3) the object is encrypted with SSE-KMS and you lack kms:Decrypt permission; (4) the object is owned by a different account and object ACLs do not grant your identity access.
Q3: How do I allow my Amazon Connect agents to play back recordings without granting them full S3 access?
Create a least-privilege IAM policy granting only s3:GetObject on the specific recording path prefix (e.g., arn:aws:s3:::your-bucket/connect/INSTANCE_ALIAS/CallRecordings/*). Attach this policy to an IAM role assumed by the agent management application. If recordings are KMS-encrypted, also grant kms:Decrypt on the specific key ARN. Agents accessing recordings through the Amazon Connect CCP do not require direct S3 permissions — they access recordings through the Connect service, which uses its own service role.
Q4: We use AWS Organizations. How do I check whether an SCP is blocking our S3 access?
Open the AWS Organizations console, navigate to Policies > Service Control Policies, and review all SCPs attached to your account, organizational unit (OU), and organization root. Look for Deny statements on s3:* or specific S3 actions. Also check Resource Control Policies (RCPs) under Policies > Resource Control Policies for Deny statements that apply to S3 resources. If an SCP or RCP contains a Deny for S3, it will block access even if the bucket policy and IAM policy allow it.
Q5: What is the difference between an explicit deny and an implicit deny in S3 access control?
An explicit deny occurs when a policy statement has Effect: Deny for the specific action. An explicit deny always overrides any Allow statement from any other policy. An implicit deny occurs when no policy grants an Allow for the action — since IAM denies all actions by default, the absence of an Allow is effectively a denial. The distinction matters because only explicit denials appear in enhanced error messages (with the phrase ‘with an explicit deny in a [policy type] policy’).
Q6: My recordings are encrypted with KMS. How do I identify the correct KMS key ARN?
In the S3 console, open the recording object and navigate to its Properties tab. Scroll to the Server-side encryption settings section, which displays the KMS Key ARN if SSE-KMS is in use. You can also use the AWS CLI: aws s3api head-object –bucket your-bucket –key path/to/recording.wav to retrieve the x-amz-server-side-encryption-aws-kms-key-id header.
Q7: How do I prevent future permission errors from locking us out of recordings?
Implement the following preventive measures: (1) Use IAM Access Analyzer to continuously monitor for overly permissive or restrictive policies; (2) Enable CloudTrail S3 data event logging and set up CloudWatch Alarms for 4xx errors on the recording bucket; (3) Test all bucket policy changes on a non-production bucket first; (4) Document the Amazon Connect service role ARN and test recording access as part of any AWS configuration change review process; (5) Use AWS Config rules to enforce bucket policy compliance.
Q8: We have multiple Amazon Connect instances. How do we identify which S3 bucket belongs to which instance?
In the Amazon Connect console, navigate to each instance’s Data storage settings. The call recording bucket name is displayed under Call recordings. Alternatively, in the IAM console, find the IAM role associated with each instance — the role’s attached policy will reference the specific S3 bucket ARN in its Resource field. The bucket name typically follows the pattern connect-{random-id}.
Q9: How do I test my fix without making an actual call?
Use the IAM Policy Simulator (https://policysim.aws.amazon.com/) to test the effective permissions for the IAM user or role without making real AWS API calls. Additionally, use the AWS CLI to attempt an s3api get-object or s3 ls command with the corrected credentials — this validates S3 permissions independently of Amazon Connect.
Q10: Can I use AWS Trusted Advisor to identify S3 permission issues?
Yes. AWS Trusted Advisor includes security checks that can identify S3 buckets with potentially insecure configurations, such as buckets with public access enabled or without logging configured. Navigate to the Trusted Advisor console under the Security category and review the Amazon S3 Bucket Permissions check. For more detailed analysis, use AWS IAM Access Analyzer, which can identify both internal and external access to your S3 resources.
10. Conclusion for Amazon S3 Permission Denied
Amazon S3 Permission Denied and Access Denied errors in Amazon Connect environments are always the result of configuration issues — never bugs. The 403 Forbidden error code is deliberately opaque, masking the specific permission gap to prevent information disclosure. This makes a structured, systematic approach essential.
The recommended troubleshooting sequence for Amazon S3 Permission Denied is:
- Confirm recording is enabled in the Contact Flow (Set Recording Behavior block).
- Verify IAM permissions for the accessing identity using the Policy Simulator.
- Review the S3 bucket policy for explicit Deny statements.
- Check AWS KMS key policy for kms:Decrypt and kms:GenerateDataKey permissions.
- Validate S3 Block Public Access settings if public-facing access is required.
- Review object ownership settings and resolve cross-account ACL conflicts.
- Check AWS Organizations SCPs and RCPs for organization-wide restrictions.
- Verify VPC endpoint policies if access is routed through a VPC.
The most common root causes, in order of frequency, are: missing IAM permissions, restrictive S3 bucket policies, KMS key policy gaps, and SCP/RCP restrictions at the organization level.
The most effective preventive measure is enabling AWS CloudTrail S3 data event logging from day one. This single action transforms opaque 403 errors into attributable, actionable events with full context — who accessed what, from where, and why it was denied.
With the configurations, policy examples, and validation procedures in this guide, AWS administrators and Amazon Connect architects can resolve the full spectrum of S3 permission issues affecting call recording access — and build an environment where such errors become the exception rather than the norm.
Internal Links
- How to Fix “Failed to Get Email Message” in Amazon Connect (S3 CORS Policy)
- How to Perform an AWS ME-CENTRAL-1 Recovery: Restoring S3 and DynamoDB after the March 2026 Outage
- How to Fix AWS Lambda Timeout Errors Triggered by Amazon Connect | Complete Guide 2026
- Amazon Connect API Throttling: A Complete Guide to Fixing 429 RateExceeded Errors
- Troubleshooting AWS IAM SAML Authentication Errors for Amazon Connect: The Complete 2026 Guide
Documentation References
- Troubleshoot access denied (403 Forbidden) errors in Amazon S3 — https://docs.aws.amazon.com/AmazonS3/latest/userguide/troubleshoot-403-errors.html
- Amazon Connect Data Storage — https://docs.aws.amazon.com/connect/latest/adminguide/amazon-connect-instances.html#get-started-data-storage
- Required permissions for Amazon S3 API operations — https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-with-s3-policy-actions.html
- Restrict Access to your Amazon Connect S3 Bucket — https://aws.amazon.com/blogs/contact-center/restrict-access-to-your-amazon-connect-s3-bucket/
People also search for
- Access Denied (Service: Amazon S3; Status Code: 403; Error Code: AccessDenied)
- How to fix 403 Forbidden
- S3 access denied 403
- How to fix 403 Forbidden error on Google Chrome
- An error occurred (403) when calling the HeadObject operation: Forbidden
- An error occurred 403 when calling the headobject operation forbidden s3
- 403 forbidden aws
- 403 forbidden s3 static website
This article was authored by an AWS Solutions Architect specializing in Amazon Connect and AWS cloud security. All policy examples are provided for reference and must be validated against your specific environment before production use.