Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to use a locally defined ~/.aws/credentials profile if it specifies a source_profile in v3 SDK #2087

Closed
3 tasks done
cpitchford opened this issue Feb 23, 2021 · 4 comments · Fixed by #2221
Closed
3 tasks done
Assignees
Labels
guidance General information and guidance, answers to FAQs, or recommended best practices/resources. needs-triage This issue or PR still needs to be triaged.

Comments

@cpitchford
Copy link

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

Describe the bug
When attempting to use a profile defined in ~/.aws/credentials that refers to a role_arn and another source_profile, v3 of the SDK fails to assume the role where-as v2 of the SDK successfully assumes the role.

roleAssumer is missing from the STS client options and therefore the assume role never happens and a failure is returned.

This seems counter to:

https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/modules/_aws_sdk_credential_provider_node.html

roleAssumer - A function that assumes a role and returns a promise fulfilled with credentials for the assumed role. If not specified, the SDK will create an STS client and call its assumeRole method.

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

If on Node.js, are you running this on AWS Lambda?
Running on laptop/MacOS

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

SDK version number
aws-sdk@2.746.0
@aws-sdk/client-sts@3.6.1

To Reproduce (observed behavior)
~/.aws/credentials:

# Two profiles defined. One using keys, another using the first as the source when assuming a role:
[mycreds]
aws_access_key_id= <mykey>
aws_secret_access_key=<mykey></mykey>

[adminrole]
role_arn = arn:aws:iam::<myaccount>:role/<rolename>
role_session_name=testing-v3-sdk
source_profile=mycreds

Check that the profiles work using was-cli:

aws --profile mycreds sts get-caller-identity
aws --profile adminrole sts get-caller-identity

Test node script to check sts:GetCallerIdentity using the v2 and v3 SDK:

async function runTests() {
 
  console.log("Checking SDK v2");

  try {
    const AWS = require('aws-sdk');
    const v2client = new AWS.STS();
    let v2result = await v2client.getCallerIdentity({}).promise();
    console.log("V2 test completed");
  } catch (err) {
    console.log("V2 test failed");
    console.log(err);
  }

  console.log("====================");
  console.log("Checking SDK v3");
  

  try {
    const {STSClient, GetCallerIdentityCommand}  = require('@aws-sdk/client-sts');
    let v3client = new STSClient();
    let v3result = await v3client.send(new GetCallerIdentityCommand({}));
    console.log("V3 test completed");
  } catch (err) {
    console.log("V3 test failed");
    console.log(err);
  }
}

runTests().then(x=>1);

Running test $AWS_PROFILE=mycreds (profile contains keys only)

AWS_PROFILE=mycreds node test.js
Checking SDK v2
V2 test completed
====================
Checking SDK v3
V3 test completed

Running test with $AWS_PROFILE=adminrole (profile has role_arn and source_profile)

AWS_PROFILE=adminrole node test.js
Checking SDK v2
V2 test completed
====================
Checking SDK v3
V3 test failed
ProviderError: Profile adminrole requires a role to be assumed, but no role assumption callback was provided.
    at resolveProfileData (/Users/home/node_modules/@aws-sdk/credential-provider-ini/dist/cjs/index.js:62:19)
    at /Users/home/node_modules/@aws-sdk/credential-provider-ini/dist/cjs/index.js:26:12
    at async SignatureV4.credentialProvider (/Users/home/node_modules/@aws-sdk/property-provider/dist/cjs/memoize.js:26:26)
    at async SignatureV4.signRequest (/Users/home/node_modules/@aws-sdk/signature-v4/dist/cjs/SignatureV4.js:84:29)
    at async /Users/home/node_modules/@aws-sdk/middleware-signing/dist/cjs/middleware.js:14:22
    at async StandardRetryStrategy.retry (/Users/home/node_modules/@aws-sdk/middleware-retry/dist/cjs/defaultStrategy.js:56:46)
    at async /Users/home/node_modules/@aws-sdk/middleware-logger/dist/cjs/loggerMiddleware.js:6:22
    at async runTests (/Users/home/lab/src/test-sdk/t.js:26:20) {
  tryNextLink: false,
  '$metadata': { attempts: 1, totalRetryDelay: 0 }
}

Expected behavior
The credential provider should be able to assume the profile role_arn using the credentials in the source_profile since role assumer is defined as optional, the default should achieve this?

Additional context
The outcome is the same regardless of $AWS_SDK_LOAD_CONFIG being defined

Excluding v2 of the SDK from the test does not affect the v3 outcome

@cpitchford
Copy link
Author

Writing an assumer function such as this seems to resolve the issue:

async function myRoleAssumer(credentials, role) {
    const {STSClient, AssumeRoleCommand}  = require('@aws-sdk/client-sts');
    const client = new STSClient({credentials});
    let result = await client.send(new AssumeRoleCommand(role));
    return {
      secretAccessKey: result.Credentials.SecretAccessKey,
      accessKeyId:     result.Credentials.AccessKeyId,
      sessionToken:    result.Credentials.SessionToken,
      expiration:      result.Credentials.Expiration
    }
}

let client = STSClient({roleAssumer: myRoleAssumer});

Note sure if there is a downside to making this the default?

@ajredniwja ajredniwja transferred this issue from aws/aws-sdk-js Feb 25, 2021
@ajredniwja ajredniwja added guidance General information and guidance, answers to FAQs, or recommended best practices/resources. needs-triage This issue or PR still needs to be triaged. labels Feb 25, 2021
@ajredniwja ajredniwja self-assigned this Feb 25, 2021
@gdamjan
Copy link

gdamjan commented Mar 31, 2021

How do I use V4 signature, like the example here https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-request-signing.html#es-request-signing-node when using this kind of setup?

@mark-bixler
Copy link

Writing an assumer function such as this seems to resolve the issue:

async function myRoleAssumer(credentials, role) {
    const {STSClient, AssumeRoleCommand}  = require('@aws-sdk/client-sts');
    const client = new STSClient({credentials});
    let result = await client.send(new AssumeRoleCommand(role));
    return {
      secretAccessKey: result.Credentials.SecretAccessKey,
      accessKeyId:     result.Credentials.AccessKeyId,
      sessionToken:    result.Credentials.SessionToken,
      expiration:      result.Credentials.Expiration
    }
}

let client = STSClient({roleAssumer: myRoleAssumer});

Note sure if there is a downside to making this the default?

Do you have a full working example of using your assumer function, for those of us less intelligent folk?

@github-actions
Copy link

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs and link to relevant comments in this thread.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 24, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
guidance General information and guidance, answers to FAQs, or recommended best practices/resources. needs-triage This issue or PR still needs to be triaged.
Projects
None yet
4 participants