CulturalMe / meteor-slingshot

Upload files directly to AWS S3, Google Cloud Storage and others in meteor
MIT License
594 stars 104 forks source link

what IAM Permissions are required? Unable to work around 403 error #148

Open thatjuan opened 8 years ago

thatjuan commented 8 years ago

Hello,

I am trying to set up an upload form with s3. I'm using the following config:

Slingshot.createDirective( "newDocumentForm", Slingshot.S3Storage, {

    bucket: "my-bucket-name",

    acl: "public-read",

    region: "us-west-2",

    AWSAccessKeyId: "MY-ACCESS-KEY",

    AWSSecretAccessKey: "MY-SECRET",

    authorize: function () {
        if (!this.userId) {
            var message = "Please login before posting files";
            throw new Meteor.Error("Login Required", message);
        }

        return true;
    },

    key: function (file) {
        return file.name;
    }

});

On the IAM side, I have:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::my-bucket-name"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::my-bucket-name",
                "arn:aws:s3:::my-bucket-name/*"
            ]
        }
    ]
}

And when I try to upload, i get a 403 from the POST request. (the OPTIONS call succeeds)

<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>xxDC3CExxE0D7A59</RequestId><HostId>xxx3u+T0s7qiP7ir8alVf6mebwMYdNyqxI=</HostId></Error>

Any clues? thanks!

thomasmery commented 8 years ago

Hi,

I trie also to use an IAM user credentials but got same error

upload worked fine with aws root credentials

wondering if someone with more insight might help here

thanks

spawn-guy commented 8 years ago

this is sufficient(but not squeezed down to min) to upload to bucketname. i use this Policy as EC2-Role. and read them from AWS.EC2MetadataCredentials()

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AppBucketAccess",
            "Action": [
                "s3:Get*",
                "s3:List*",
                "s3:HeadObject*",
                "s3:PutObject*",
                "s3:DeleteObject"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:s3:::bucketname",
                "arn:aws:s3:::bucketname/*"
            ]
        }
    ]
}
gkrizek commented 8 years ago

I was battling this for a while because I really wanted to restrict this user to only be able to upload to the bucket. This is what I came up with for minimum privileges for uploading:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "uploadS3",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject*"
            ],
            "Resource": [
                "arn:aws:s3:::bucket_name",
                "arn:aws:s3:::bucket_name/*"
            ]
        }
    ]
}
MichaelJCole commented 7 years ago

Together with @gkrizek 's AWS policy, I had to remove the acl setting in createDirective

Slingshot.createDirective('myFileUploads', Slingshot.S3Storage, {
  bucket: 'uptestload',

  //acl: 'public-read',

  authorize() {
    //Deny uploads if user is not logged in.
    if (!this.userId) {
      var message = 'Please login before posting files';
      throw new Meteor.Error('Login Required', message);
    }

    return true;
  },

  key(file) {
    //Store file into a directory by the user's username.
    var user = Meteor.users.findOne(this.userId);
    return user._id + '.' + file.name + '.' + Date.now();
  }
});

Here's what I did:

Created a user - got keys. Created a group. Added an inline policy to the group Keys -> settings.json, followed the rest of the readme.