Skip to content

Credential Provider Chain Resolution #1366

Closed
@RLovelett

Description

@RLovelett

This is a question about expected behavior.

Let's say I have the following code (Node 7.5.0 because of async/await).

(async function () {
  const govcloudCredential = new CredentialProviderChain([
    () => { return new EnvironmentCredentials('GC_AWS'); },
    () => { return new EnvironmentCredentials('GC_AMAZON'); },
    () => { return new SharedIniFileCredentials({ profile: 'govcloud' }); },
    () => { return new SharedIniFileCredentials({ profile: 'default' }); },
    () => { return new EC2MetadataCredentials(); }
  ]);

  const s3 = new S3({
    region: 'us-gov-west-1',
    credentials: undefined,
    credentialProvider: govcloudCredential
  });

  try {
    const foo = await s3.listObjectsV2({
      Bucket: 'bucket'
    }).promise();
    console.log(foo.KeyCount);
  } catch (error) {
    console.error(error);
  }
})()

And ~/.aws/credentials file:

[default]
aws_access_key_id = valid-for-commercial
aws_secret_access_key = valid-for-commercial

[govcloud]
aws_access_key_id = valid-for-gov-cloud
aws_secret_access_key = valid-for-gov-cloud

[commercial]
aws_access_key_id = valid-for-commercial
aws_secret_access_key = valid-for-commercial

I would expect that the resulting S3 instance would pull from the explicit provider chain. Such that if I ran the code it would pull from the govcloud section and work fine. However, it pulls from default and thus prevents my call from succeeding. Just to be sure I checked by removing the default group. Then the call actually pulls from govcloud.

This behavior, to me, seems counter-intuitive. Can someone help my intuition?

Update

(async function () {
  const govcloudCredential = new CredentialProviderChain([
    () => { return new EnvironmentCredentials('GC_AWS'); },
    () => { return new EnvironmentCredentials('GC_AMAZON'); },
    () => { return new SharedIniFileCredentials({ profile: 'govcloud' }); },
    () => { return new SharedIniFileCredentials({ profile: 'default' }); },
    () => { return new EC2MetadataCredentials(); }
  ]);

  const creds = new Promise<Credentials>((resolve, reject) => {
    govcloudCredential.resolve((error, creds) => {
      if (error) { reject(error); }
      else { resolve(creds); }
    });
  });

  const s3 = new S3({
    region: 'us-gov-west-1',
    credentials: (await creds)
  });

  try {
    const foo = await s3.listObjectsV2({
      Bucket: 'refman-bundler-dev'
    }).promise();
    console.log(foo.KeyCount);
  } catch (error) {
    console.error(error);
  }
})()

This second example code does work as I expect but notice now I have explicitly called resolve and I am awaiting the credentials resolving before creating my S3 object. This does feel like the way the documentation indicates this should work.

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationThis is a problem with documentation.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions