0
votes

I've been trying for several hours to get this to work and not sure what I'm doing wrong. I have a bucket in US-West Oregon (us-west-2). I have an IAM user with full S3 access. I am attempting to store the contents of a string into a file on S3. Here is the code below:

using System.IO;
using Amazon;

namespace XXX.Util
{

    public static class S3
    {

        private static Amazon.S3.Transfer.TransferUtility transferUtility;

        public static void UploadFile(string bucket, string key, string contents)
        {    
            // user "publisher" credentials
            transferUtility = new Amazon.S3.Transfer.TransferUtility("{AccessID}", "{Secret}",RegionEndpoint.USWest2);

            using (Stream s = GenerateStreamFromString(contents))
            {
                using (transferUtility)
                {
                    transferUtility.Upload(s, bucket, key);
                }
            }


        }
        public static Stream GenerateStreamFromString(string s)
        {
            MemoryStream stream = new MemoryStream();
            StreamWriter writer = new StreamWriter(stream);
            writer.Write(s);
            writer.Flush();
            stream.Position = 0;
            return stream;
        }
    }
}

I invoke the method with:

S3.UploadFile("s3-us-west-2.amazonaws.com/{bucket-name}", guid.ToString(),contents);

The error message I get is:

AmazonS3Exception: Access Denied Amazon.Runtime.Internal.HttpErrorResponseExceptionHandler.HandleException(IExecutionContext executionContext, HttpErrorResponseException exception) in HttpErrorResponseExceptionHandler.cs, line 60

My S3 policy:

{ "Version": "2012-10-17", "Id": "Policy1516569218147", "Statement": [ { "Sid": "Stmt1516569211561", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::{iamID}:user/publisher" }, "Action": "s3:*", "Resource": "arn:aws:s3:::{bucket-name}" } ] }

Any ideas?

1
Delete the policy and try again. The S3 policy is not needed when signing requests. However, a broken S3 policy can deny signed requests. Your code looks fine and I do not see an obvious error. I think that your goal is to only allow uploads to "/user/publisher" but your "Principal" should be using AccountNumber and not iamID.John Hanley
I do see one problem with your code. You are specifying a URL for the bucket name. It should just be the bucket name in your call to S3.UploadFile(). You are already setting the region via Amazon.S3.Transfer.TransferUtility()John Hanley
I believe you will need "Resource": [ "arn:aws:s3:::{bucket-name}", "arn:aws:s3:::{bucket-name}/*" ] in your policy. The second form refers to objects, the first one to the bucket itself.Michael - sqlbot
John - your answer did it! I think using the bucket name instead of the full URL did the trick. Thanks, I was pulling my hair out.user301340

1 Answers

0
votes

According to the documentation:

The S3 location matches the format s3://bucket/path. Don't include the endpoint. For example, s3://us-east-1.amazonaws.com/bucket/path results in an "Access Denied" error.