Skip to content

How to resolve in Elastic Beanstalk: Error: Unable to create a POST object policy without a bucket, region, and credentials at AWSS3Service

0

I have my Node.js application deployed on Elastic Beanstalk, it works correctly except for creating signed urls to upload files to AWS S3:

async buildUploadURL(filePath: FileToSign): Promise<string> {
    let url;

    try {
      const params = {
        Bucket: this.privateBasePath,
        Fields: {
          key: filePath.path,
          'Content-Type': filePath.type
        },
        Expires: this.signedUrlExpirationTime
      };

      url = await this.s3.createPresignedPost(params);
    } catch (error) {
      throw new FileSystemError(error);
    }

    return url;
  }

This code generates a signed URL that is sent to the client side to upload the specific file.

This actually works, but after a few minutes of deploying a new version to Elastic Beanstalk, it would not be a big deal if the service did not terminate and create new EC2 instances under the configurations, causing errors in the client when uploading files.

The solution is actually to wait a few minutes for the server to decide that it can now sign URLs, since the credentials are correctly configured in the environment and without doing anything it works randomly.

I haven't found anything that helps me identify what I'm doing wrong, or what I should do or not do, has this happened to anyone else?

Additionally, to enable the websocket in Elastic Beanstalk I must add the code:

        location /websocket {
            proxy_pass http://172.17.0.2:8000;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "Upgrade";
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_read_timeout 86400s;
            proxy_send_timeout 86400s;
        }

In: /etc/nginx/nginx.conf manually, which is obviously inefficient but I'm not sure where to add that code in .platform in my code as I've tried several ways and it doesn't auto configure.

asked a year ago115 views
1 Answer
0

The issue you're experiencing with signed URLs in Elastic Beanstalk appears to be related to temporary credential availability when new EC2 instances are created. This can cause intermittent failures in generating presigned URLs for S3 uploads.

To resolve this, consider implementing a retry mechanism with exponential backoff in your code. This approach will allow your application to wait and retry if it encounters errors related to missing credentials. Here's an example of how you could modify your code:

async buildUploadURL(filePath: FileToSign): Promise<string> {
let url;
let retries = 5;
let delay = 1000; // Start with 1 second delay

while (retries > 0) {
try {
const params = {
Bucket: this.privateBasePath,
Fields: {
key: filePath.path,
'Content-Type': filePath.type
},
Expires: this.signedUrlExpirationTime
};

url = await this.s3.createPresignedPost(params);
return url;
} catch (error) {
if (retries === 1) {
throw new FileSystemError(error);
}
await new Promise(resolve => setTimeout(resolve, delay));
retries--;
delay *= 2; // Exponential backoff
}
}
}

This modification will attempt to create the presigned URL multiple times, with increasing delays between attempts. This should help mitigate the issue of temporary credential unavailability.

Regarding the websocket configuration in Elastic Beanstalk, you can add the Nginx configuration in your application's .ebextensions directory. Create a file named 01_nginx.config in the .ebextensions folder with the following content:

files:
"/etc/nginx/conf.d/proxy.conf":
mode: "000644"
owner: root
group: root
content: |
location /websocket {
proxy_pass http://172.17.0.2:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
}

container_commands:
01_reload_nginx:
command: "service nginx reload"

This configuration will be applied automatically during deployment, eliminating the need for manual intervention. Make sure to include this .ebextensions directory in your application bundle when deploying to Elastic Beanstalk.

By implementing these changes, you should be able to resolve the issues with signed URL generation and websocket configuration in your Elastic Beanstalk environment.
Sources
Unable to upload to s3 using pre_signed_url generated using IAM roles | AWS re:Post
Having trouble with POST request for uploading S3 objects | AWS re:Post
Setup Elastic Beanstalk with S3 | AWS re:Post

answered a year ago
  • This solution does not work, since nginx does not allow a location block outside the server block.

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.