从 AWS S3 下载文件访问被拒绝

Download File from AWS S3 Access Denied

嗨,我正在尝试使用亚马逊网络服务为我的 iOS 应用程序存储文件。

这是我用来下载存储在 aws S3 上的文件的代码

我将以下内容添加到 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;

然后在我的 class 中,我使用以下方法下载对象。请注意,没有对对象应用加密,并且对存储桶的所有权限都已解锁

- (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(), ^{
        
        });
    }];
}

虽然我已经把所有的权限都允许了。阻止所有 public 访问已关闭,我不断收到以下错误:

    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=}

我已应用此视频中的所有建议: Why am I getting an Access Denied error from the Amazon S3 console while I modify a bucket policy? - YouTube

在云端尝试以下命令 shell 没有显示任何错误:

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

如果需要任何进一步的代码或信息,请告诉我。

首先,让我们排除编码。尝试使用 AWS CLI 本机访问该文件。直接向上 aws s3 cp s3://<bucket name>/<key> /tmp/localfile

如果这有效,则说明您遇到了代码问题,我们会继续检查。如果它不起作用,您可能有权限问题。

要检查的第二件事 - 您是否使用加密?有可能(根据我的经验)虽然您可能有权访问 S3 存储桶,但您可能无权访问加密密钥,因此您获得的访问被拒绝实际上来自 KMS。您可能需要授予解密 KMS 密钥的权限。

您似乎正在使用 Cognito 作为凭据提供程序。据我了解,即使对于 public 个存储桶,如果您通过 API 访问,您也需要设置适当的 IAM 角色和权限。这意味着为 IAM 角色 分配对 身份池 身份池 内的 已验证身份 的 S3 访问权限18=]认知.

或者,您必须通过no-sign-request。至少在 CLI 中你必须这样做。 https://docs.aws.amazon.com/cli/latest/reference/.

但如果您使用 URL 访问,使用 public 个存储桶,您将能够获取对象。

在 cognito 身份池中,您可以指定两个 IAM 角色(甚至更多,但让我们关注默认的两个):

  • 未经身份验证的角色 - 分配给未登录身份提供者的用户的角色
  • 经过身份验证的角色 - 分配给经过身份验证的用户的角色

Cognito 创建的默认角色不提供对 S3 存储桶的访问权限 - 您必须修改策略并添加缺少的权限(即 s3:PutObject、s3:GetObject、s3:ListBucket)

如果您的存储桶使用 KMS 密钥加密,您的角色策略或密钥策略必须允许 kms 操作(即 kms.Encrypt、kms:Decrypt、kms:generateKeyData)

尝试在您的应用程序中调用 sts getCallerIdentity 操作并检查 returned 身份,它应该 return 经过身份验证的角色 ARN。 如果是这样,请将缺少的访问 S3 存储桶和 KMS 密钥的权限添加到 returned 角色策略。