aws / aws-sdk-js-v3

Modularized AWS SDK for JavaScript.
Apache License 2.0
3.05k stars 573 forks source link

Add Support for Custom `NodeHttpHandler` in RDS Signer Interface #5504

Open MathieuGuillet opened 10 months ago

MathieuGuillet commented 10 months ago

Checkboxes for prior research

Describe the bug

I want to create an IAM token to authenticate to my Postgres DB, using the RDS Signer (AWS SDK v3). But my service is in a pod and has to go through a proxy to join the AWS Signer server.

(I'm using NodeJs, NestJS, TypeORM and Typescript)

I've searched for some way to give a NodeHttpHandler to override the http and https agent with my proxy config, but haven't found anything about this case... The Signer interface and config is too restrictive.

This page gives an example but it is not applicable for my case with Typeorm and Postgresql (unless I missed something...)

Any idea on how to do this ? If not possible yet, can you fix this ?

SDK version number

@aws-sdk/rds-signer: ^3.445.0

Which JavaScript Runtime is this issue in?

Node.js

Details of the browser/Node.js/ReactNative version

v21.1.0

Reproduction Steps

import { DataSource } from 'typeorm';
import { PostgresConnectionOptions } from 'typeorm/driver/postgres/PostgresConnectionOptions';
import { Signer } from '@aws-sdk/rds-signer';
import process from 'process';
import { DataSourceOptions } from 'typeorm';

function getAuthTokenProvider(): () => Promise<string> {

    const signer = new Signer({
      hostname: process.env.DB_HOST!,
      port: Number(process.env.DB_PORT)!,
      username: process.env.DB_USERNAME!,
      // I would like to be able to specify a proxy configuration here !
    });

    return () => signer.getAuthToken(); // This is were the timeout occurs when TypeORM tries to create the DB connection
  }
}

function dataSourceConfiguration(): DataSourceOptions {

  return {
    type: 'postgres',
    applicationName: 'my_app',
    host: process.env.DB_HOST!,
    port: Number(process.env.DB_PORT)!,
    username: process.env.DB_USERNAME!,
    password: getAuthTokenProvider(),
    database: process.env.DB_DATABASE!,
    ssl: { rejectUnauthorized: false,  },
    entities: [`${__dirname}/../**/*.entity.ts`, `${__dirname}/../**/*.entity.js`],
  };
}

new DataSource({
  ...dataSourceConfiguration(),
} as PostgresConnectionOptions);

Observed Behavior

I have a connection timeout when calling AWS RDS to sign the token.

Expected Behavior

I would expect a way to configure a proxy through a requestHandler, as it is the case in the runtime config of client SSO in aws-sdk, for instance.

WDTY ?

Possible Solution

No response

Additional Information/Context

No response

RanVaknin commented 9 months ago

Hi @MathieuGuillet ,

Thanks for reaching out.

From looking at the code for RDS Signer, it doesn't make any actual network requests. Therefore Im not sure what the expected outcome of adding the custom handler would be?

It sounds like from your use case that TypeORM, which actually facilitates the requests is the thing that needs to support the proxy?

It would be great if you can give us some more context on your the desired behavior.

Thanks, Ran~

github-actions[bot] commented 9 months 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.

mupperton commented 9 months ago

From looking at the code for RDS Signer, it doesn't make any actual network requests. Therefore Im not sure what the expected outcome of adding the custom handler would be?

@RanVaknin - Not directly, but if you don't provide your own credentials to the Signer configuration it will fallback to using fromNodeProviderChain() like so: https://github.com/aws/aws-sdk-js-v3/blob/main/packages/rds-signer/src/runtimeConfig.ts#L15

That then eventually creates an STS client which will perform an AssumeRole command to generate the credentials, I assume it is the underlying network request that STS makes that the issue is arising from

See my comment on a similar issue: https://github.com/aws/aws-sdk-js-v3/issues/4235#issuecomment-1856368532

With usage like:

import https from 'https';

const signer = new Signer({
  region: 'eu-west-1',
  // ...other config
  clientConfig: {
    requestHandler: https, // Custom http handler here
  },
});

This doesn't seem unreasonable

mupperton commented 9 months ago

In the meantime, you can do this manually yourself:

import https from 'https';
import { fromNodeProviderChain } from '@aws-sdk/credential-providers';
import { Signer } from '@aws-sdk/rds-signer';

const signer = new Signer({
  region: 'eu-west-1',
  credentials: fromNodeProviderChain({
    clientConfig: {
      requestHandler: https, // Custom http handler here
    },
  }),
});
MathieuGuillet commented 9 months ago

Hey, thank you so much for taking time on my issue. And yes, @mupperton, this is exactly how we resolved it so far! Maybe the official doc can integrate this specific case ? Thanks for your analyze and time 🙏