eetee
eetee

Reputation: 125

aws-sdk upload with STS credentials - 403 error

I've been trying to set up Amazon's STS (Security Token Service) to create temporary credentials for client side uploads to S3.

I can get the code working fine with an access key generated from the IAM user, but when I swap out the access key/secret key and then add the session token I am getting a 403 Forbidden. S3 access logs do not log the attempt.

On the STS side I am generating the credentials via the aws-sdk for node.js, using the same IAM user as above, the SDK generates the STS credentials happily:

let sts = new AWS.STS({apiVersion: '2011-06-15'});
sts.assumeRole({
  RoleArn: 'arn:aws:iam::[REMOVED]:role/[REMOVED]',
  RoleSessionName: [REMOVED (generated by concatenating a few ids)]
  DurationSeconds: 60 * 20,
}, (err, data)=>{
  //callback handling
});

Upload test code:

var AWS = require('aws-sdk');

// Load the stream
var fs = require('fs');
var body = fs.createReadStream('./helloworld.txt');

AWS.config.update({
  region: 'ap-southeast-2',
  accessKeyId: '[REMOVED]',
  secretAccessKey: '[REMOVED]',
  sessionToken: '[REMOVED]'
});

// Upload the stream
var s3 = new AWS.S3();

s3.putObject({
  Body: body,
  Bucket: '[REMOVED]',
  Key: 'helloworld.txt'
}, function(err, data) {
  if (err) console.log(err, err.stack); // an error occurred
  else     console.log(data);           // successful response
});

aws-sdk version: 2.4.8 node.js: 4.2.3

I've tested the role policy that it assumes using the IAM simulator which says it's fine. Tried on both browser side and server side uploading using the sdk.

I opened up the S3 CORS (for debugging) to make sure nothing weird was going on there:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>PUT</AllowedMethod>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
        <MaxAgeSeconds>0</MaxAgeSeconds>
        <ExposeHeader>ETag</ExposeHeader>
        <ExposeHeader>x-amz-server-side-encryption</ExposeHeader>
        <ExposeHeader>x-amz-request-id</ExposeHeader>
        <ExposeHeader>x-amz-id-2</ExposeHeader>
        <AllowedHeader>*</AllowedHeader>
        <AllowedHeader>x-amz-acl</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

S3 policy I've opened up (again for debugging):

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

Any ideas?

Upvotes: 8

Views: 3481

Answers (1)

eetee
eetee

Reputation: 125

Turns out the missing configuration was the ACL on the bucket itself, the original ACL allowed my root account to make all changes, I'm guessing the IAM account where the code worked was inheriting some sort of permission.

Adding this extra line for upload/delete worked.

Screenshot of the configuration change

Upvotes: 0

Related Questions