aws / aws-sdk-js

AWS SDK for JavaScript in the browser and Node.js
https://aws.amazon.com/developer/language/javascript/
Apache License 2.0
7.59k stars 1.55k forks source link

S3 Signing key using ECS Credentials is undefined #3931

Closed AlexMog closed 2 years ago

AlexMog commented 2 years ago

Confirm by changing [ ] to [x] below to ensure that it's a bug:

Describe the bug When using ECS credentials on an ECS instance (with RemoteCredentials or ECSCredentials as AWS.config.credentials) and trying to use s3.createPresignedPost, the following error is thrown:

TypeError [ERR_INVALID_ARG_TYPE]: The "key" argument must be of type string or an instance of Buffer, TypedArray, DataView, or KeyObject. Received undefined
--
  | 2021-10-27T15:54:36.724+02:00 | at new NodeError (internal/errors.js:322:7)
  | 2021-10-27T15:54:36.724+02:00 | at prepareSecretKey (internal/crypto/keys.js:322:11)
  | 2021-10-27T15:54:36.724+02:00 | at new Hmac (internal/crypto/hash.js:111:9)
  | 2021-10-27T15:54:36.724+02:00 | at Object.createHmac (crypto.js:148:10)
  | 2021-10-27T15:54:36.724+02:00 | at Object.hmac (/app/node_modules/aws-sdk/lib/util.js:428:30)
  | 2021-10-27T15:54:36.724+02:00Copy    at Object.getSigningKey (/app/node_modules/aws-sdk/lib/signers/v4_credentials.js:62:8) | at Object.getSigningKey (/app/node_modules/aws-sdk/lib/signers/v4_credentials.js:62:8)
  | 2021-10-27T15:54:36.724+02:00 | at features.constructor.preparePostFields (/app/node_modules/aws-sdk/lib/services/s3.js:1139:21)
  | 2021-10-27T15:54:36.724+02:00 | at finalizePost (/app/node_modules/aws-sdk/lib/services/s3.js:1066:22)
  | 2021-10-27T15:54:36.724+02:00 | at features.constructor.createPresignedPost (/app/node_modules/aws-sdk/lib/services/s3.js:1090:14)
  | 2021-10-27T15:54:36.724+02:00 | at MeasuresService.generateUploadSignedUrl (/app/dist/apps/measures/main.js:6616:51)
  | 2021-10-27T15:54:36.724+02:00 | at MeasuresService.createUploadTask (/app/dist/apps/measures/main.js:6644:41)
  | 2021-10-27T15:54:36.724+02:00 | at MeasuresController.createUploadTask (/app/dist/apps/measures/main.js:6472:37)
  | 2021-10-27T15:54:36.724+02:00 | at /app/node_modules/@nestjs/microservices/context/rpc-context-creator.js:44:33
  | 2021-10-27T15:54:36.724+02:00 | at processTicksAndRejections (internal/process/task_queues.js:95:5)

Is the issue in the browser/Node.js? Node.js

If on Node.js, are you running this on AWS Lambda? No, running in an ECS container

Details of the browser/Node.js version Node v14.17.4

SDK version number Example: 2.1015.0

To Reproduce (observed behavior) The following code should be executed on an ECS container instance using the node image node:14-alpine:

import * as AWS from 'aws-sdk';

AWS.config.credentials =  new AWS.RemoteCredentials();
const S3 = new AWS.S3({
    credentials: AWS.config.credentials,
    useAccelerateEndpoint: true,
  });
S3.createPresignedPost({
      Bucket: <test_bucket>,
      Fields: {
        key: <test_key>,
      },
      Expires: 3600,
    });

Expected behavior Should return presigned url data, instead it throws an exception.

Additional context This exact code was working yesterday. So it seems to be related to this new release of the SDK.

AlexMog commented 2 years ago

After further tests, I can confirm that it is related to the SDK version.
It works fine using 2.1014.0 but not with 2.1015.0.

vudh1 commented 2 years ago

Hi @AlexMog thanks for reaching out. I'm not able to reproduce this problem. Can you give more details non how your params formats are for createPresignedPost?

S3.createPresignedPost({params});
github-actions[bot] commented 2 years ago

This issue has not received a response in 1 week. If you still think there is a problem, please leave a comment to avoid the issue from automatically closing.

AlexMog commented 2 years ago

Sorry for the delayed response.
I haven't been able to reproduce it since then, but I may have encountred a problem that can be related:
My AWS Client is not able to automatically discover the configuration in an ECS Container.
I have to use the following code to allow it to link the ECS Task credentials:

import { Injectable, Logger } from '@nestjs/common';
import * as AWS from 'aws-sdk';

@Injectable()
export class AwsClientService {
  constructor() {
    if (!process.env.LOCAL_DEV) {
      console.log('Using AWS Remote Credentials');
      (async () => {
        try {
          const credentials = new AWS.RemoteCredentials({
            maxRetries: 10,
            httpOptions: {
              timeout: 10000,
            },
          });
          AWS.config.credentials = credentials;
          await credentials.getPromise();
          // Trying to force the refresh every 15 minutes, does not work. No errors thrown either.
          setTimeout(async () => {
            await credentials.getPromise();
            await credentials.refreshPromise();
          }, 60_000 * 15);
        } catch (e) {
          Logger.error('AWS Credentials error', e);
        }
      })();
    } else {
      Logger.warn('WARNING: Using LOCAL configuration');
      AWS.config.credentials = {
        accessKeyId: process.env.AWS_ACCESS_KEY_ID,
        secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
      };
    }
  }

  getAws() {
    return AWS;
  }
}

This code works partially, the RemoteCredentials is able to retrieve the AWS credentials linked to the ECS Task, but it is not able to refresh the token. Even when I force the refresh myself each 15 minutes.
Because of that, I am getting ExpiredToken errors when I try to upload to S3 when using Presigned Post URL, the S3 client is configured as following:

    this.S3 = new (awsClient.getAws().S3)({
      signatureVersion: 'v4',
      useAccelerateEndpoint: true,
    });

The Policy payload seems correct, it is the token that is expired and is never refreshed.

It's been three weeks since the tokens are not refreshing anymore, I have no idea why and I've tryed everything.
My last hope would be to pass to the v3 SDK, but it is missing the createPresignedPost method, so I will need to change my current file upload workflow for it to work correctly...

If you need any informations for more clarifications, I can provide them.

In advance, thanks for the help.

Alex