aws-sdk-js icon indicating copy to clipboard operation
aws-sdk-js copied to clipboard

Issues with SSO-based source_profile

Open gilesvessey opened this issue 3 years ago • 6 comments

Describe the bug

I have a somewhat complex IAM assume-role configuration that should work using the SDK and does work using the CLI.

  • You have a SSO-based AWS profile set up in ~/.aws/config. It is functional and active.
[profile mysso]
sso_start_url = ...
sso_region = us-east-1
sso_account_name = ...
sso_account_id = ...
sso_role_name = ...
region = us-east-1
credential_process = aws-sso-util credential-process --profile ...
sso_auto_populated = true 
  • You create a profile that uses the aforementioned profile to assume_role into another account.
[profile usesmysso]
source_profile = mysso
role_arn = arn:aws:iam::...:role/i-want-to-be-this-role
external_id = ...
region = us-east-1

Expected Behavior

THE ONLY AWS_ ENVIRONMENT VARIABLE SET IS AWS_SDK_LOAD_CONFIG=1

gvessey@lap-gvessey  ➤  env | grep AWS
AWS_SDK_LOAD_CONFIG=1

This works great:

aws sts get-caller-identity --profile usesmysso

Therefore, using the AWS SDK, the following should work as well:

    const aws = require('aws-sdk')
    const opts = { region: 'us-east-1', credentials: new aws.SharedIniFileCredentials({ profile: 'usesmysso' }), }
    const sts = new aws.STS(opts)
    return sts.getCallerIdentity({}).promise()

Current Behavior

CLI OUTPUT (working):

{
    "UserId": "AROAVIZUEM43GSDSGGNMO:botocore-session-1671218894",
    "Account": "[REDACTED]",
    "Arn": "arn:aws:sts::[REDACTED]:assumed-role/[REDACTED]/botocore-session-1671218894"
}

SDK OUTPUT (issues):

Missing credentials in config, if using AWS_CONFIG_FILE, set AWS_SDK_LOAD_CONFIG=1
Error [CredentialsError]: Missing credentials in config, if using AWS_CONFIG_FILE, set AWS_SDK_LOAD_CONFIG=1
    at SharedIniFileCredentials.load (/Users/gvessey/src/devops/docker/patch-driver/node_modules/aws-sdk/lib/credentials/shared_ini_file_credentials.js:146:11)
    at SharedIniFileCredentials.coalesceRefresh (/Users/gvessey/src/devops/docker/patch-driver/node_modules/aws-sdk/lib/credentials.js:205:12)
    at SharedIniFileCredentials.refresh (/Users/gvessey/src/devops/docker/patch-driver/node_modules/aws-sdk/lib/credentials/shared_ini_file_credentials.js:170:10)
    at SharedIniFileCredentials.get (/Users/gvessey/src/devops/docker/patch-driver/node_modules/aws-sdk/lib/credentials.js:122:12)
    at getAsyncCredentials (/Users/gvessey/src/devops/docker/patch-driver/node_modules/aws-sdk/lib/config.js:408:24)
    at Config.getCredentials (/Users/gvessey/src/devops/docker/patch-driver/node_modules/aws-sdk/lib/config.js:428:9)
    at Request.VALIDATE_CREDENTIALS (/Users/gvessey/src/devops/docker/patch-driver/node_modules/aws-sdk/lib/event_listeners.js:111:28)
    at Request.callListeners (/Users/gvessey/src/devops/docker/patch-driver/node_modules/aws-sdk/lib/sequential_executor.js:102:18)
    at Request.emit (/Users/gvessey/src/devops/docker/patch-driver/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
    at Request.emit (/Users/gvessey/src/devops/docker/patch-driver/node_modules/aws-sdk/lib/request.js:686:14) {
  code: 'CredentialsError',
  time: 2022-12-16T19:29:51.624Z,
  originalError: {
    message: 'Could not load credentials from SharedIniFileCredentials',
    code: 'CredentialsError',
    time: 2022-12-16T19:29:51.624Z,
    originalError: {
      message: 'Missing credentials in config, if using AWS_CONFIG_FILE, set AWS_SDK_LOAD_CONFIG=1',
      code: 'CredentialsError',
      time: 2022-12-16T19:29:51.619Z,
      originalError: [Object]
    }
  }
}

Reproduction Steps

  1. Create a SSO based AWS profile in ~/.aws/config
  2. Create another profile that has the above profile in source_profile, as well as role_arn set to the IAM role you want to use the SSO profile to assume
  3. unset all aws environment variables
  4. export AWS_SDK_LOAD_CONFIG=1
  5. aws sts get-caller-identity --profile << the profile you made in step 2 >>
  6. Note success
  7. Execute the following code
    const aws = require('aws-sdk')
    const opts = { region: 'us-east-1', credentials: new aws.SharedIniFileCredentials({ profile: 'usesmysso' }), }
    const sts = new aws.STS(opts)
    sts.getCallerIdentity({}).promise() 
  1. Note failure

Possible Solution

No response

Additional Information/Context

No response

SDK version used

2.1276.0

Environment details (OS name and version, etc.)

MacOS Catalina 10.15.6, AWS CLI 2.6.2, Node 16.17.1

gilesvessey avatar Dec 16 '22 19:12 gilesvessey

Any updates?

matan129 avatar Dec 29 '22 13:12 matan129

Any updates?

None from my end. I managed to get around this in a bit of a painful way - I used the sdk to sts.assumeRole() from the SSO based profile, then took the temporary credentials returned and wrote those to a new profile in ~/.aws/config.

If only there was a way for this to be handled automatically ;)

gilesvessey avatar Jan 03 '23 20:01 gilesvessey

So I was actually able to work around this for now using aws2-wrap (here).

This is the setup in ~/.aws/config:

[profile sso]
sso_start_url = https://...
sso_region = us-east-1
sso_account_id = ...
sso_role_name = ... [sso role]
role_session_name = ...

[profile main]
source_profile = sso
role_arn = ... [a role the the SSO role has permissions to assume]
role_session_name = ...

[profile main-wrapped]
credential_process = aws2-wrap --process --profile main

Then, when working with my node app, I set AWS_PROFILE=main-wrapped and AWS_SDK_LOAD_CONFIG=1 env vars.

The credential_process thing is just a simple application that spews out the correct AWS credentials (access key ID, secret, and session token) after assuming the main profile.

matan129 avatar Jan 03 '23 23:01 matan129

I just ran into this as well. From what I can gather, the current SSO code (v2.1330.0) does not support using the source_profile attribute to delegate SSO configuration to another profile.

Here is the relevant ~/.aws/config:

[default]
sso_start_url = https://acme.awsapps.com/start
sso_region = us-east-1
sso_account_id = 987654321
sso_role_name = MyPrincipal
region = us-east-1
output = json

[profile sandbox]
role_arn = arn:aws:iam::123456789:role/MyRole
source_profile = default

In my testing I would be dropped into the following error block, as there are no sso_* attributes defined on my sandbox profile:

      } else {
        if (!profile.sso_start_url || !profile.sso_account_id || !profile.sso_region || !profile.sso_role_name) {
          throw AWS.util.error(
            new Error('Profile ' + this.profile + ' does not have valid SSO credentials. Required parameters "sso_account_id", "sso_region", ' +
            '"sso_role_name", "sso_start_url". Reference: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html'),
            { code: self.errorCode }
          );
        }
      }

This does work with aws-cli:

$ aws --profile sandbox sts get-caller-identity | jq -r '.UserId[0:6]'
AROAY7

richid avatar Mar 08 '23 18:03 richid

Hi there,

Thank you for bringing this to our attention through your internal ticket. I have assigned it to our development queue.

All the best, Ran~

RanVaknin avatar Mar 19 '24 21:03 RanVaknin

@RanVaknin any updates on this, OR a workaround that your team suggests?

novito avatar May 17 '24 20:05 novito

Hi everyone. As part of our plan to move AWS SDK for JavaScript v2 into maintenance mode, we aren't going to be merging in any major changes to the SDK. Please refer to the workarounds posted in this issue, or migrate to AWS SDK for JavaScript v3, which does not use the environment variable.

kellertk avatar Sep 04 '24 20:09 kellertk