'Download File from AWS S3 Access Denied

Hy, I am trying to use Amazon web service to store files for my iOS App.

Here's the code I am using to download the file stored on aws S3

I added the following to the appDelegate

AWSCognitoCredentialsProvider *credentialsProvider = [[AWSCognitoCredentialsProvider alloc]
   initWithRegionType:AWSRegionUSEast2
   identityPoolId:@"us-east-2:3764e0f9-khu97-4844-b9f7-57defdfjv8b8b"];

AWSServiceConfiguration *configuration = [[AWSServiceConfiguration alloc] initWithRegion:AWSRegionUSEast2 credentialsProvider:credentialsProvider];

[AWSServiceManager defaultServiceManager].defaultServiceConfiguration = configuration;

Then in my class I used the following to download the object. Kindly note that no encryption is applied to the object and all permissions are unblocked for the bucket

- (void)downloadImageToAWS{

// AWS Configurations
    AWSS3DownloadHelper *aws = [[AWSS3DownloadHelper alloc] init];
    aws.bucket = @"my-sample-bucket-002";
    aws.key = @"photo-sam-002.jpg";

    // AWS progress block
    aws.progressBlock = ^(AWSS3TransferUtilityTask *task, NSProgress *progress) {
    dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"progress.fractionCompleted %f", progress.fractionCompleted);
        });
    };

        // AWS completionHandler
        [self addAWSDownloadComplitionHandler:aws];

    // Update UI if job / task can upload a file on AWS S3
    [self successfulDownloadOfAWSS3ByCompletionHandler:aws.completionHandler withProgressBlock:aws.progressBlock];

    [aws downloadAWSFile];
}

- (void) addAWSDownloadComplitionHandler:(AWSS3DownloadHelper *)aws {
    // Create instance to View Controller
    NSLog(@"addAWSDownloadComplitionHandler");
    aws.completionHandler = ^(AWSS3TransferUtilityDownloadTask *task, NSURL *location, NSData *data, NSError *error) {
    dispatch_async(dispatch_get_main_queue(), ^{
        if (error) {
            NSLog(@"Unsuccessfully downloaded error %li", (long)[error code]);
            NSLog(@"Unsuccessfully downloaded error %@", [error description]);
        }
         else if (data) {
            NSLog(@"data %@", data);
            }
        });
    };   
}


- (void) successfulDownloadOfAWSS3ByCompletionHandler:(AWSS3TransferUtilityDownloadCompletionHandlerBlock)completionHandler withProgressBlock:(AWSS3TransferUtilityProgressBlock)progressBlock {
NSLog(@"successfulDownloadOfAWSS3ByCompletionHandler");
AWSS3TransferUtility *transferUtility = [AWSS3TransferUtility defaultS3TransferUtility];
[transferUtility enumerateToAssignBlocksForUploadTask:nil downloadTask:^(AWSS3TransferUtilityDownloadTask * _Nonnull downloadTask, AWSS3TransferUtilityProgressBlock  _Nullable __autoreleasing * _Nullable downloadProgressBlockReference, AWSS3TransferUtilityDownloadCompletionHandlerBlock  _Nullable __autoreleasing * _Nullable completionHandlerReference) {
    NSLog(@"taskIdentifier %lu", (unsigned long)downloadTask.taskIdentifier);
    
    *downloadProgressBlockReference = progressBlock;
    *completionHandlerReference = completionHandler;
    
    dispatch_async(dispatch_get_main_queue(), ^{
        
        });
    }];
}

Although I have put all permissions to allow. Block all public access is turned off, I keep getting the following error:

    Domain=com.amazonaws.AWSS3TransferUtilityErrorDomain Code=2 "(null)" UserInfo={Server=AmazonS3, Error={
    Code = AccessDenied;
    HostId = "SJABFLSKBtprmLRaHLjjockzjfubejlakhipjaKDNSAFJLB4ViE=";//Changed
    Message = "Access Denied";
    RequestId = jabduw2dhC6WCT;//changed
}, Transfer-Encoding=Identity, Content-Type=application/xml, Date=Wed, 29 Dec 2021 09:33:06 GMT, x-amz-request-id=2TJSHCJ2ASTC6WCT, x-amz-id-2=Fbg2cDXwU5wLgQLHbGtprmLRaHLjjocvZzCcUNfMrSpT5Oiwl3LjEkpPQ2OBzLmBrKXnrwq4ViE=}

I have applied all suggestions in this video: Why am I getting an Access Denied error from the Amazon S3 console while I modify a bucket policy? - YouTube

Trying the following command on the cloud shell didn't show any error:

aws s3 cp s3://<bucket name>/<key> /tmp/localfile

If any further code or info is needed kindly let me know.



Solution 1:[1]

Firstly, let's rule out coding. Try to access the file natively using the AWS CLI. Just a straight up aws s3 cp s3://<bucket name>/<key> /tmp/localfile

If this works, you've got a code issue, and we continue checking. If it does not work, you may have a permissions issue.

The 2nd thing to check - are you using encryption? Chances are (from my experience) that while you may have permissions to access the S3 bucket, you may not have permissions to access the encryption key, so the access denied you're getting is actually coming from KMS. You may need to allow the right to decrypt the KMS key.

Solution 2:[2]

In cognito Identity pool you can specify two IAM Roles (even more, but lets focus on default two):

  • Unauthenticated role - the role assigned to user which is not logged in to Identity Provider
  • Authenticated role - the role assigned to authenticated user

Default roles created by Cognito don't provide access to S3 buckets - you have to modify policy and add missing permissions (i.e. s3:PutObject, s3:GetObject, s3:ListBucket)

If your bucket is encrypted with KMS key, your role policy or key polisy must allow kms actions (i.e. kms.Encrypt, kms:Decrypt, kms:generateKeyData)

Try to invoke sts getCallerIdentity action in your app and check returned identity, it should return Authenticated role ARN. If so, add missing permissions to access S3 bucket and KMS key to returned role policy.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Phil Massyn
Solution 2 Tomasz Bre?