【问题标题】:Download File from AWS S3 Access Denied从 AWS S3 下载文件访问被拒绝
【发布时间】:2022-01-27 17:42:36
【问题描述】:

嗨,我正在尝试使用 Amazon 网络服务来存储我的 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;

然后在我的课堂上,我使用以下内容下载对象。请注意,该对象未应用任何加密,并且该存储桶的所有权限均已解锁

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

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

    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

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

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

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

【问题讨论】:

  • 您表示您在修改存储桶策略时应用了与拒绝访问相关的 YouTube 视频建议,但这似乎与您的问题完全无关。除非您真的知道自己在这里做什么,否则您不应该进行任何这些更改。
  • @jarmod 感谢您的评论,确实 aws 环境是全新的,我不确定我是否走在正确的轨道上,因此非常欢迎任何建议。

标签: ios objective-c amazon-web-services amazon-s3


【解决方案1】:

首先,让我们排除编码。尝试使用 AWS CLI 以本机方式访问该文件。直接上aws s3 cp s3://&lt;bucket name&gt;/&lt;key&gt; /tmp/localfile

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

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

【讨论】:

  • 首先感谢您的建议,我没有使用任何类型的加密,所以我们可以排除这种情况,其次,我想尝试 cloud shell 命令但得到以下结果:CloudShell is not在中东(巴林)有售。请选择其他地区。
  • 你认为区域可能是拒绝访问的原因,我选择了我所在的区域,我应该选择不同的吗?知道我希望该文件可以在全球范围内访问。
  • 将您的区域切换到 us-east-1,然后再次尝试 CloudShell。 CloudShell 在巴林不可用的事实不应该成为问题。在我自己的系统上,我安装了 AWS CLI,因此无需使用 CloudShell。不过要小心 - 当您使用 CloudShell 时,它将继承您登录时使用的权限,而不一定是您假设从应用程序中使用的权限。因此,当您设法启动 Cloud Shell 时,您应该更新您的访问密钥,使其与您尝试在应用中使用的密钥相似。
  • 我不熟悉巴林地区,但我知道需要启用它(因为默认情况下未启用)。该区域可能是一个问题,因此请尝试在您的代码中强制该区域(我熟悉python中的boto3,您可以指定该区域)。另一种可能性是巴林的端点可能未启用。查看docs.aws.amazon.com/general/latest/gr/rande-manage.html
  • 我已启用该区域,但从您之前的回复中我注意到必须使用访问密钥,我非常了解 aws 环境您认为您可以发送显示的文档如何设置它。我在我的应用程序中使用了这个 gitHub 项目,并认为它可能就足够了:github.com/dimitardanailov/objc-aws-playground
【解决方案2】:

您似乎正在使用 Cognito 作为凭据提供程序。据我了解,即使对于公共存储桶,如果您通过 API 访问,则需要设置适当的 IAM 角色和权限。这意味着分配具有 S3 访问权限的 IAM 角色,以访问 Cognito 中的身份池内的经过身份验证的身份。。 p>

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

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

【讨论】:

  • 确实我的错误是我为 IAM 用户分配了所有权限,而我应该为 IAM 角色这样做。感谢您的善意建议。
【解决方案3】:

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

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

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

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

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

【讨论】:

  • 谢谢您,您的回答很有启发性,我相信对其他人非常有用,我希望我可以给它不止一票,但实际上是针对我的问题的另一个答案完全正确。
猜你喜欢
  • 2019-05-09
  • 2020-09-30
  • 1970-01-01
  • 1970-01-01
  • 2015-09-22
  • 2016-04-28
  • 1970-01-01
  • 1970-01-01
  • 2019-02-03
相关资源
最近更新 更多