aws / aws-sdk-js-v3

Modularized AWS SDK for JavaScript.
Apache License 2.0
3.01k stars 565 forks source link

Cannot use SSO Session auth when use fromIni for setting profile. #5158

Open Reasonably opened 11 months ago

Reasonably commented 11 months ago

Checkboxes for prior research

Describe the bug

[sso-session abc]
sso_region = ap-northeast-2
sso_start_url = aaa
sso_registration_scopes = sso:account:access

[profile sample]
sso_session = abc
sso_account_id = aaa
sso_role_name = aaa
region = ap-northeast-2

I've set my ~/.aws/config like above. And I tried to make s3 client like below.

        const s3Config: S3ClientConfig = {
          region,
          credentials: fromIni({ profile: 'sample' }),
        };
        const client = new S3Client(s3Config);

It show error when I request some s3 command

error: CredentialsProviderError: Profile is configured with invalid SSO credentials. Required parameters "sso_account_id", "sso_region", "sso_role_name", "sso_start_url". Got sso_session, sso_account_id, sso_role_name, region
Reference: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html

And It is in https://github.com/aws/aws-sdk-js-v3/blob/main/packages/credential-provider-sso/src/validateSsoProfile.ts#L11

It called from fromSSO (It's not problem).
And called from resolveSsoCredentials (It's the problem).

When I use fromIni, it validate my sso config before sso session data fetched yet.
I think validateSsoProfile already called in fromSSO.ts. It doesn`t have to check before call fromSSO on fromIni function.

When I used default provider chain, it just call fromSSO directly so it worked well.

SDK version number

@aws-sdk/credential-provider@latest, @aws-sdk/s3-client@latest

Which JavaScript Runtime is this issue in?

Node.js

Details of the browser/Node.js/ReactNative version

v18.16.1

Reproduction Steps

set ~/.aws/config

[sso-session abc]
sso_region = ap-northeast-2
sso_start_url = aaa
sso_registration_scopes = sso:account:access

[profile sample]
sso_session = abc
sso_account_id = aaa
sso_role_name = aaa
region = ap-northeast-2

set s3 client config

        const s3Config: S3ClientConfig = {
          region,
          credentials: fromIni({ profile: 'sample' }),
        };
        const client = new S3Client(s3Config);

call command.

Observed Behavior

error: CredentialsProviderError: Profile is configured with invalid SSO credentials. Required parameters "sso_account_id", "sso_region", "sso_role_name", "sso_start_url". Got sso_session, sso_account_id, sso_role_name, region
Reference: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html

Expected Behavior

work well if I have permission

Possible Solution

Remove validateSsoProfile from https://github.com/aws/aws-sdk-js-v3/blob/main/packages/credential-provider-ini/src/resolveSsoCredentials.ts#L13

Additional Information/Context

If I use default chain, it work

Reasonably commented 11 months ago

I think this also have to be changed.
When a fromIni call with partially resolved sso params fromSSO, It show error because thease params not complete. https://github.com/aws/aws-sdk-js-v3/blob/736212e25faa1e013f87f8906cc6df5d437aacf2/packages/credential-provider-sso/src/fromSSO.ts#L85
I think If there is sso_session, it has to load sso_session info before validate params.

yenfryherrerafeliz commented 11 months ago

Hi @Reasonably, I can confirm the reported behavior and I also agree with this comment. I will mark this issue with a needs-review label so we can further deep into this, however, is there a specific reason why you use fromIni and not fromSSO provider?

Please let me know.

Thanks!

Reasonably commented 11 months ago

I just wanted to change profile using config not env, and searched "aws javascript sdk v3 change profile" to google, it shows this guide.
My app is running on k8s and it use IRSA, I've change my code like below now.

        const s3Config: S3ClientConfig = {
          region,
          credentials: defaultProvider({ profile }),
        };
        const client = new S3Client(s3Config);

There is shared profile name used in my team using sso, and k8s app will use web token auth.

I think if I use fromSSO directly, it use only sso auth not auth chain. Is it right?

yenfryherrerafeliz commented 11 months ago

@Reasonably, the default chain will try to resolve a list of defined credential providers until one of them works, but if you know which credential provider you want to use is also correct to explicitly set it when instancing the client. So, in your case do you want to always use fromSSO?

Please let me know.

Thanks!

Reasonably commented 11 months ago

@Reasonably, the default chain will try to resolve a list of defined credential providers until one of them works, but if you know which credential provider you want to use is also correct to explicitly set it when instancing the client. So, in your case do you want to always use fromSSO?

Please let me know.

Thanks!

I want to use sso auth(local env) and web identity token auth(production env). And I also want to set profile for not using default profile(I don't want to set AWS_PROFILE because I intent to set profile by a config file).
So I've tried to use fromIni at first for setting profile, I found there is some bug I mentioned at this issue. I've changed my s3 client to use defaultProvider now - it work well.

tpickett66 commented 4 weeks ago

This is labeled as workaround-available but when I switch my use of fromIni() to fromSSO() I'm greeted with CredentialsProviderError: Profile dev was not found. Which appears to be coming from here. There are two weird things about this. First, that profile does exist. Second, reproducing the lookup code in fromSSO doesn't exhibit the same issue.

Sample INI file:

[profile dev]
sso_session = my-sso
sso_account_id = 123456789012
sso_role_name = super-duper-role
region = us-west-2
output = json

[sso-session my-sso]
sso_start_url = https://my-sso.awsapps.com/start
sso_region = us-west-2
sso_registration_scopes = sso:account:access

Code that is failing:

const { fromSSO } = require('@aws-sdk/credential-providers');
const pino = require("pino");

const logger = pino({
        level: 'trace',
});

const init = {
    logger: logger,
    profile: 'dev',

    clientConfig: {
        region: "us-west-2",
        logger: logger,
    }
}

console.log(fromSSO(init)().then((c) => {
    console.log(c)
}, (err) => {
    console.log(err)
}))

Code extracted from fromSSO that should reproduce the error but works:

const { getProfileName, parseKnownFiles } =require("@smithy/shared-ini-file-loader");
const pino = require('pino');

const logger = pino({
        level: 'trace',
});

const init = {
    logger: logger,
    profile: 'dev',

    clientConfig: {
        region: "us-west-2",
        logger: logger,
    }
}

const profileName = getProfileName(init)
console.log(profileName);
parseKnownFiles(init).then((profiles) => {
    // console.log(profiles);
    const profile = profiles[profileName];
    console.log(profile);
});