S3 upload from iOS Swift - AWSS3TransferUtility not uploading

2.1k views Asked by At

Fellow devs,

I have a requirement to upload in S3 in a cognito-unauthenticated + cognito authenticated state.

(the upload should disregard cognito credentials, but can happen during both states)

I have a cognito identity pool with unauthorized role created for it. I have a cognito user pool too.

I have a special bucket dedicated for it. After several attempts at swift code + S3 policy + role policy, it does not work.

Swift:

    class func uploadfile(fileURL: URL, s3Key: String)
    {
        let credentialsProvider = AWSStaticCredentialsProvider(accessKey: awsAccessKey, secretKey: awsSecretKey)
        //let credentialsProvider = AWSCognitoCredentialsProvider(regionType:.EUCentral1, identityPoolId:"cognito_identity_pool_id")
        
        let configuration = AWSServiceConfiguration(region:.EUCentral1, credentialsProvider:credentialsProvider)
        AWSServiceManager.default().defaultServiceConfiguration = configuration
        
        let tuConf = AWSS3TransferUtilityConfiguration()
        tuConf.isAccelerateModeEnabled = false
        
        AWSS3TransferUtility.register(
            with: configuration!,
            transferUtilityConfiguration: tuConf,
            forKey: "utility-key"
        )
        
        guard let transferUtility = AWSS3TransferUtility.s3TransferUtility(forKey: "utility-key")
        else
        {
            return
        }

        let expression = AWSS3TransferUtilityUploadExpression()
        expression.progressBlock = {(task, progress) in
            print("progress \(progress.fractionCompleted)")
        }
        
        var completionHandler: AWSS3TransferUtilityUploadCompletionHandlerBlock?
        completionHandler = { (task, error) -> Void in
            print("task finished")
        }
        
        let bucketName = "bucket name (not ARN)"
        guard let data = try? Data.init(contentsOf: fileURL)
        else
        {
            return
        }
    
        transferUtility.uploadData(data as Data, bucket: bucketName, key: s3Key, contentType: "text/plain", expression: expression,
        completionHandler: completionHandler).continueWith
        {
            (task) -> AnyObject? in
            if let error = task.error {
                print("Error: \(error.localizedDescription)")
            }
            
            if let _ = task.result {
                print ("upload successful.")
            }
            
            return nil
        }
    }

Here is bucket policy:

{
    "Version": "2012-10-17",
    "Id": "PolicyID",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "ARN for Cognito Identity pool unauthorized role"
            },
            "Action": "s3:*",
            "Resource": "ARN for bucket to upload"
        }
    ]
}

Here is the role policy for Cognito Identity pool unauthorized role (mentioned in bucket policy above):

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:*",
            "Resource": "*"
        }
    ]
}

Note: I want to restrict the above role policy (because this is guest unauthorized upload) instead of full access but even with full access uploading is not successful.

What I have tried already:

  • The Swift code above has comments that I have tried and failed already
  • Upon repeated calls to uploadfile(), I only get "upload successful." but not "task finished" or "progress" message. The first time, I get all 3 messages.
  • I have cleared cache of Keychain DB (for simulator) - just to refresh credentials after AWS side changes. No result.

Thank you for your time!

1

There are 1 answers

0
Nirav Bhatt On

I resolved it with following solution:

Bucket policy:

{
    "Version": "2012-10-17",
    "Id": "PolicyID",
    "Statement": [
        {
            "Sid": "StatementID",
            "Effect": "Allow",
            "Principal": {
                "AWS": "bucket_arn"
            },
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": "bucket_arn/*"
        }
    ]
}

Policy attached with the unauthenticated Cognito role:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "s3:PutObject",
            "Resource": "bucket_arn"
        }
    ]
}

iOS code changes made (following statement is added):

tuConf.bucket = "bucket_name (not ARN, not full bucket URL, just name)"