aws-sdk-js: s3.createPresignedPost not working with ec2 role - The AWS Access Key Id you provided does not exist in our records.

I created ec2 role and assigned it to the ec2.

Using this role I am able to do s3 getobject and other actions without error.

To do POST upload I used s3.createPresignedPost, which generates the url without error using temporary aws key. Now when trying to upload using this url it gives below error.

<Error><Code>InvalidAccessKeyId</Code><Message>The AWS Access Key Id you provided does not exist in our records.</Message><AWSAccessKeyId>ASIAXXXXXXXXXXX</AWSAccessKeyId><RequestId>EADQD0E6FAPZDYWW</RequestId><HostId>xJemQGRc9sfwefwefy6x3No4VlgSRg1/nWCasdfdsfdfYNX9anh/l/QkKS/Pl2sdvsdfsvD4uc=</HostId></Error>

It seems S3 does not recognize the access key. It does not recognize even after inserting the role as principle in bucket policy.

Can someone help?

About this issue

  • Original URL
  • State: open
  • Created 3 years ago
  • Comments: 17 (2 by maintainers)

Most upvoted comments

@ajredniwja thank you for looking into the issue.

I followed every possible aws doc to solve the issue but have been unsuccessful. As mentioned above I am using EC2 instance role with required permissions to upload files to S3 using POST request.

The credentials are derived automatically by aws sdk and i am not using session token explicitly in my code. Hence using the credentials I am able to to s3 gets without issue. I am using same role for all other services like sqs, sns and they are all working. The issue is coming only for the s3 POST using presigned url created by createPresignedPost() function.

So i created a new user with only s3 put permission and used this user’s credential to create presigned post url. This worked without issue. So the issue is due to the ec2 instance role credentials which are automatically retrieved by aws sdk for this specific function only.

Steps to recreate the issue:

  1. Create IAM EC2 role having S3 PUT permission
  2. Use aws sdk and create presigned url using createPresignedPost(). instance role credentials are handled by aws sdk itself.
  3. Try to upload using this presigned url and error occurs.
  4. Create get signed url using getSignedUrl()
  5. Try to view the file using this url and it works.

Exact same issue. Not sure it’s related to the AWS SDK code but maybe more on how AWS is working on this point ?

An example code to reproduce

  • Create a bucket
  • Create an EC2 instance
  • Create a new role that have full access to the bucket
  • Assign the role to the EC2 instance
  • Install the aws sdk and node js to the instance
  • Run the script
const { S3 } = require('aws-sdk');

const s3 = new S3({
  region: 'eu-west-1',
  endpoint: 'https://s3.eu-west-1.amazonaws.com',
  s3ForcePathStyle: false,
});

const options = {
  Bucket: '<bucket name>',
  Fields: {
    key: 'test/test.json',
    acl: 'private',
  },
  Expires: 60,
  Conditions: [],
};

const response = s3.createPresignedPost(options);

console.log(response);

You have the error. Now if you update the code with:

  • Create a new user with the policy associated to the role to have full acvess to the s3 bucket
const s3 = new S3({
  region: 'eu-west-1',
  endpoint: 'https://s3.eu-west-1.amazonaws.com',
  s3ForcePathStyle: false,
  accessKeyId: <access key>,
  secretAccessKey: <secret key>,
});

you don’t have the error.