diff --git a/UPGRADING.md b/UPGRADING.md index 00f21cf6f55f..27021072c146 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -221,33 +221,25 @@ Default credential provider is how SDK resolve the AWS credential if you DO NOT masterCredentials during instantiation, precluding the ability to refresh credentials which require intermediate, temporary credentials. The original [`TemporaryCredentials`](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/TemporaryCredentials.html) - has been **deprecated** in favor of `ChainableTemporaryCredentials` in v2 and `` + has been **deprecated** in favor of `ChainableTemporaryCredentials` in v2. -- **v3**: Partially supported. You can retrieve the temporary credential from STS with the - [role assumer function based on `sts:AssumeRole`](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-sts/globals.html#getdefaultroleassumer). The difference to v2 is that `sts:getSessionToken` is not called - if no `RoleArn` is supplied. Please open a [feature request](https://github.com/aws/aws-sdk-js-v3/issues/new?assignees=&labels=feature-request&template=---feature-request.md&title=) - if you need it. - Here's an example: +- **v3**: [`Temporary Credentials Provider`](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/modules/_aws_sdk_credential_providers.html). + You can call `fromTemporaryCredentials()` from `@aws-sdk/credential-providers` package. Here's an example: ```javascript import { FooClient } from "@aws-sdk/client-foo"; - import { getDefaultRoleAssumer } from "@aws-sdk/client-sts"; // ES6 import + import { fromTemporaryCredentials } from "@aws-sdk/credential-providers"; // ES6 import // const { FooClient } = require("@aws-sdk/client-foo"); - // const { getDefaultRoleAssumer } = require("@aws-sdk/client-sts"); // CommonJS import + // const { fromTemporaryCredentials } = require("@aws-sdk/credential-providers"); // CommonJS import - /* role assumer function that calls sts:AssumeRole API */ - const roleAssumer = getDefaultRoleAssumer(); - const sourceCredential = { - /* A credential can be a credential object or an async function that returns a credential object */ + const sourceCredentials = { + // A credential can be a credential object or an async function that returns a credential object }; - /* A credential can be a credential object or an async function that returns a credential object */ - const derivativeCredentials = () => - roleAssumer(sourceCredentials, { - RoleArn, - RoleSessionName, - }); const client = new FooClient({ - credentials: derivativeCredentials, + credentials: fromTemporaryCredentials({ + masterCredentials: sourceCredentials, + params: { RoleArn }, + }), }); ``` @@ -257,11 +249,11 @@ Load credentials from Cognito Identity service, normally used in browsers. - **v2**: [`CognitoIdentityCredentials`](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/CognitoIdentityCredentials.html) Represents credentials retrieved from STS Web Identity Federation using the Amazon Cognito Identity service. -- **v3**: [`Cognito Identity Credential Provider`](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/modules/_aws_sdk_credential_provider_cognito_identity.html#fromcognitoidentity-1) - The [`@aws/credential-provider-cognito-identity` package](https://www.npmjs.com/package/@aws-sdk/credential-provider-cognito-identity) - provides two credential provider functions, one of which [`fromCognitoIdentity`](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/modules/_aws_sdk_credential_provider_cognito_identity.html#fromcognitoidentity-1) +- **v3**: [`Cognito Identity Credential Provider`](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/modules/_aws_sdk_credential_providers.html) + The [`@aws/credential-providers` package](https://www.npmjs.com/package/@aws-sdk/credential-providers) + provides two credential provider functions, one of which [`fromCognitoIdentity`](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/modules/_aws_sdk_credential_providers.html) takes an identity ID and calls `cognitoIdentity:GetCredentialsForIdentity`, while the other - [`fromCognitoIdentityPool`](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/modules/_aws_sdk_credential_provider_cognito_identity.html#fromcognitoidentitypool-1) + [`fromCognitoIdentityPool`](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/modules/_aws_sdk_credential_providers.html) takes an identity pool ID, calls `cognitoIdentity:GetId` on the first invocation, and then calls`fromCognitoIdentity`. Subsequent invocations of the latter do not re-invoke GetId @@ -272,18 +264,13 @@ Load credentials from Cognito Identity service, normally used in browsers. ```javascript // fromCognitoIdentityPool example - import { fromCognitoIdentityPool } from "@aws-sdk/credential-provider-cognito-identity"; - import { CognitoIdentityClient } from "@aws-sdk/client-cognito-identity"; // ES6 import - // const { fromCognitoIdentityPool } = require("@aws-sdk/credential-provider-cognito-identity"); - // const { CognitoIdentityClient } = require("@aws-sdk/client-cognito-identity"); // CommonJS import + import { fromCognitoIdentityPool } from "@aws-sdk/credential-providers"; // ES6 import + // const { fromCognitoIdentityPool } = require("@aws-sdk/credential-providers"); // CommonJS import const client = new FooClient({ region: "us-east-1", credentials: fromCognitoIdentityPool({ - client: new CognitoIdentityClient({ - // specify Cognito Identity client config here - region: "us-east-1", - }), + clientConfig: cognitoIdentityClientConfig, // Optional identityPoolId: "us-east-1:1699ebc0-7900-4099-b910-2df94f52a030", customRoleArn: "arn:aws:iam::1234567890:role/MYAPP-CognitoIdentity", // Optional logins: { @@ -298,15 +285,13 @@ Load credentials from Cognito Identity service, normally used in browsers. ```javascript // fromCognitoIdentity example - import { fromCognitoIdentity } from "@aws-sdk/credential-provider-cognito-identity"; - import { CognitoIdentityClient } from "@aws-sdk/client-cognito-identity"; // ES6 import + import { fromCognitoIdentity } from "@aws-sdk/credential-providers"; // ES6 import // const { fromCognitoIdentity } = require("@aws-sdk/credential-provider-cognito-identity"); - // const { CognitoIdentityClient } = require("@aws-sdk/client-cognito-identity"); // CommonJS import const client = new FooClient({ region: "us-east-1", credentials: fromCognitoIdentity({ - client: new CognitoIdentityClient({ region: "us-east-1" }), + clientConfig: cognitoIdentityClientConfig, // Optional identityId: "us-east-1:128d0a74-c82f-4553-916d-90053e4a8b0f", customRoleArn: "arn:aws:iam::1234567890:role/MYAPP-CognitoIdentity", // Optional logins: { @@ -324,11 +309,12 @@ Load credentials from Cognito Identity service, normally used in browsers. Represents credentials received from the metadata service on an EC2 instance. - **v2**: [`EC2MetadataCredentials`](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/CognitoIdentityCredentials.html) -- **v3**: [`fromInstanceMetadata`](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/modules/_aws_sdk_credential_provider_imds.html#frominstancemetadata-1): Creates a credential provider that will source credentials from the EC2 Instance Metadata Service. +- **v3**: [`fromInstanceMetadata`](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/modules/_aws_sdk_credential_providers.html): + Creates a credential provider that will source credentials from the EC2 Instance Metadata Service. ```javascript - import { fromInstanceMetadata } from "@aws-sdk/credential-provider-imds"; // ES6 import - // const { fromInstanceMetadata } = require("@aws-sdk/credential-provider-imds"); // CommonJS import + import { fromInstanceMetadata } from "@aws-sdk/credential-providers"; // ES6 import + // const { fromInstanceMetadata } = require("@aws-sdk/credential-providers"); // CommonJS import const client = new FooClient({ credentials: fromInstanceMetadata({ @@ -345,11 +331,11 @@ URI specified by the `AWS_CONTAINER_CREDENTIALS_RELATIVE_URI` or the `AWS_CONTAI variable. - **v2**: `ECSCredentials` or [`RemoteCredentials`](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/RemoteCredentials.html). -- **v3**: [`fromContainerMetadata`](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/modules/_aws_sdk_credential_provider_imds.html#fromcontainermetadata-1) creates a credential provider that will source credentials from the ECS Container Metadata Service. +- **v3**: [`fromContainerMetadata`](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/modules/_aws_sdk_credential_providers.html) + creates a credential provider that will source credentials from the ECS Container Metadata Service. ```javascript - import { fromContainerMetadata } from "@aws-sdk/credential-provider-imds"; // ES6 import - // const { fromContainerMetadata } = require("@aws-sdk/credential-provider-imds"); // CommonJS import + import { fromContainerMetadata } from "@aws-sdk/credential-providers"; // ES6 import const client = new FooClient({ credentials: fromContainerMetadata({ @@ -382,13 +368,11 @@ refer to the [shared config and credentials files document](https://docs.aws.ama for more information. - **v2**: [`SharedIniFileCredentials`](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/SharedIniFileCredentials.html) -- **v3**: [`fromIni`](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/modules/_aws_sdk_credential_provider_ini.html). +- **v3**: [`fromIni`](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/modules/_aws_sdk_credential_providers.html). ```javascript - import { fromIni } from "@aws-sdk/credential-provider-ini"; - import { getDefaultRoleAssumer, getDefaultRoleAssumerWithWebIdentity } from "@aws-sdk/client-sts"; // ES6 import - // const { fromIni } from("@aws-sdk/credential-provider-ini"); - // const { getDefaultRoleAssumer, getDefaultRoleAssumerWithWebIdentity } = require("@aws-sdk/client-sts"); // CommonJS import + import { fromIni } from "@aws-sdk/credential-providers"; + // const { fromIni } from("@aws-sdk/credential-providers"); const client = new FooClient({ credentials: fromIni({ @@ -399,8 +383,7 @@ for more information. return "some_code"; }, // Optional profile: "default", // Optional - roleAssumer: getDefaultRoleAssumer(), // Optional. Required if you specify role to assume - roleAssumerWithWebIdentity: getDefaultRoleAssumerWithWebIdentity(), // Optional. Required if you specify role to assume using `sts:AssumeRoleWithWebIdentity` API + clientConfig: { region }, // Optional }), }); ``` @@ -413,17 +396,18 @@ Retrieves credentials using OIDC token from a file on disk. It's commonly used i - **v3**: [`fromTokenFile`](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/modules/_aws_sdk_credential_provider_web_identity.html#fromtokenfile-1) ```javascript - import { fromTokenFile } from "@aws-sdk/credential-provider-web-identity"; - import { getDefaultRoleAssumerWithWebIdentity } from "@aws-sdk/client-sts"; // ES6 import - // const { fromIni } from("@aws-sdk/credential-provider-ini"); - // const { getDefaultRoleAssumerWithWebIdentity } = require("@aws-sdk/client-sts"); // CommonJS import + import { fromTokenFile } from "@aws-sdk/credential-providers"; // ES6 import + // const { fromIni } from("@aws-sdk/credential-providers"); // CommonJS import const client = new FooClient({ credentials: fromTokenFile({ - roleAssumerWithWebIdentity: getDefaultRoleAssumerWithWebIdentity(), - roleArn: "arn:xxxx" // Optional. Otherwise read from `AWS_ROLE_ARN` environmental variable - roleSessionName: "session:a" // Optional. Otherwise read from `AWS_ROLE_SESSION_NAME` environmental variable - }) + // Optional. If skipped, read from `AWS_ROLE_ARN` environmental variable + roleArn: "arn:xxxx", + // Optional. If skipped, read from `AWS_ROLE_SESSION_NAME` environmental variable + roleSessionName: "session:a", + // Optional. STS client config to make the assume role request. + clientConfig: { region }, + }), }); ``` @@ -435,17 +419,18 @@ Retrieves credentials from STS web identity federation support. - **v3**: [`fromWebToken`](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/modules/_aws_sdk_credential_provider_web_identity.html#fromwebtoken-1) ```javascript - import { fromWebToken } from "@aws-sdk/credential-provider-web-identity"; - import { getDefaultRoleAssumerWithWebIdentity } from "@aws-sdk/client-sts"; // ES6 import - // const { fromWebToken } from("@aws-sdk/credential-provider-web-identity"); - // const { getDefaultRoleAssumerWithWebIdentity } = require("@aws-sdk/client-sts"); // CommonJS import + import { fromWebToken } from "@aws-sdk/credential-providers"; // ES6 import + // const { fromWebToken } from("@aws-sdk/credential-providers"); // CommonJS import const client = new FooClient({ credentials: fromWebToken({ - roleAssumerWithWebIdentity: getDefaultRoleAssumerWithWebIdentity(), - roleArn: "arn:xxxx" // Otherwise read from `AWS_ROLE_ARN` environmental variable - roleSessionName: "session:a" // Otherwise read from `AWS_ROLE_SESSION_NAME` environmental variable - }) + // Optional. If skipped, read from `AWS_ROLE_ARN` environmental variable + roleArn: "arn:xxxx", + // Optional. If skipped, read from `AWS_ROLE_SESSION_NAME` environmental variable + roleSessionName: "session:a", + // Optional. STS client config to make the assume role request. + clientConfig: { region }, + }), }); ``` diff --git a/packages/credential-provider-cognito-identity/README.md b/packages/credential-provider-cognito-identity/README.md index 178b35d9dbfe..7ea2c4070eaf 100644 --- a/packages/credential-provider-cognito-identity/README.md +++ b/packages/credential-provider-cognito-identity/README.md @@ -2,3 +2,10 @@ [![NPM version](https://img.shields.io/npm/v/@aws-sdk/credential-provider-cognito-identity/latest.svg)](https://www.npmjs.com/package/@aws-sdk/credential-provider-cognito-identity) [![NPM downloads](https://img.shields.io/npm/dm/@aws-sdk/credential-provider-cognito-identity.svg)](https://www.npmjs.com/package/@aws-sdk/credential-provider-cognito-identity) + +> An internal package + +## Usage + +You probably shouldn't, at least directly. Please use [@aws-sdk/credential-providers](https://www.npmjs.com/package/@aws-sdk/credential-providers) +instead. diff --git a/packages/credential-provider-env/README.md b/packages/credential-provider-env/README.md index 1f641416b570..61a643614132 100644 --- a/packages/credential-provider-env/README.md +++ b/packages/credential-provider-env/README.md @@ -3,20 +3,9 @@ [![NPM version](https://img.shields.io/npm/v/@aws-sdk/credential-provider-env/latest.svg)](https://www.npmjs.com/package/@aws-sdk/credential-provider-env) [![NPM downloads](https://img.shields.io/npm/dm/@aws-sdk/credential-provider-env.svg)](https://www.npmjs.com/package/@aws-sdk/credential-provider-env) -## AWS Credential Provider for Node.JS - Environment Variables +> An internal package -This module provides a `CredentialProvider` function, `fromEnv`, that reads from -the following environment variables: +## Usage -- `AWS_ACCESS_KEY_ID` - The access key for your AWS account. -- `AWS_SECRET_ACCESS_KEY` - The secret key for your AWS account. -- `AWS_SESSION_TOKEN` - The session key for your AWS account. This is only - needed when you are using temporary credentials. -- `AWS_CREDENTIAL_EXPIRATION` - The expiration time of the credentials contained - in the environment variables described above. This value must be in a format - compatible with the [ISO-8601 standard](https://en.wikipedia.org/wiki/ISO_8601) - and is only needed when you are using temporary credentials. - -If either the `AWS_ACCESS_KEY_ID` or `AWS_SECRET_ACCESS_KEY` environment -variable is not set or contains a falsy value, the promise returned by the -`fromEnv` function will be rejected. +You probably shouldn't, at least directly. Please use [@aws-sdk/credential-providers](https://www.npmjs.com/package/@aws-sdk/credential-providers) +instead. diff --git a/packages/credential-provider-imds/README.md b/packages/credential-provider-imds/README.md index cba1de93f1e4..15039903d432 100644 --- a/packages/credential-provider-imds/README.md +++ b/packages/credential-provider-imds/README.md @@ -3,33 +3,9 @@ [![NPM version](https://img.shields.io/npm/v/@aws-sdk/credential-provider-imds/latest.svg)](https://www.npmjs.com/package/@aws-sdk/credential-provider-imds) [![NPM downloads](https://img.shields.io/npm/dm/@aws-sdk/credential-provider-imds.svg)](https://www.npmjs.com/package/@aws-sdk/credential-provider-imds) -## AWS Credential Provider for Node.JS - Instance and Container Metadata +> An internal package -This module provides two `CredentialProvider` factory functions, -`fromContainerMetadata` and `fromInstanceMetadata`, that will create -`CredentialProvider` functions that read from the ECS container metadata service -and the EC2 instance metadata service, respectively. +## Usage -A `CredentialProvider` function created with `fromContainerMetadata` will return -a promise that will resolve with credentials for the IAM role associated with -containers in an Amazon ECS task. Please see [IAM Roles for Tasks](http://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html) -for more information on using IAM roles with Amazon ECS. - -A `CredentialProvider` function created with `fromInstanceMetadata` will return -a promise that will resolve with credentials for the IAM role associated with -an EC2 instance. -Please see [IAM Roles for Amazon EC2](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html) -for more information on using IAM roles with Amazon EC2. -Both IMDSv1 (a request/response method) and IMDSv2 (a session-oriented method) are supported. -Please see [Configure the instance metadata service](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html) for more information. - -## Supported configuration - -You may customize how credentials are resolved by providing an options hash to -the `fromContainerMetadata` and `fromInstanceMetadata` factory functions. The -following options are supported: - -- `timeout` - The connection timeout (in milliseconds) to apply to any remote - requests. If not specified, a default value of `1000` (one second) is used. -- `maxRetries` - The maximum number of times any HTTP connections should be - retried. If not specified, a default value of `0` will be used. +You probably shouldn't, at least directly. Please use [@aws-sdk/credential-providers](https://www.npmjs.com/package/@aws-sdk/credential-providers) +instead. diff --git a/packages/credential-provider-ini/README.md b/packages/credential-provider-ini/README.md index 37531c657f9a..b4f3af1b9a9b 100644 --- a/packages/credential-provider-ini/README.md +++ b/packages/credential-provider-ini/README.md @@ -3,166 +3,9 @@ [![NPM version](https://img.shields.io/npm/v/@aws-sdk/credential-provider-ini/latest.svg)](https://www.npmjs.com/package/@aws-sdk/credential-provider-ini) [![NPM downloads](https://img.shields.io/npm/dm/@aws-sdk/credential-provider-ini.svg)](https://www.npmjs.com/package/@aws-sdk/credential-provider-ini) -## AWS Credential Provider for Node.JS - Shared Configuration Files +> An internal package -This module provides a function, `fromIni` that will create -`CredentialProvider` functions that read from a shared credentials file at -`~/.aws/credentials` and a shared configuration file at `~/.aws/config`. Both -files are expected to be INI formatted with section names corresponding to -profiles. Sections in the credentials file are treated as profile names, whereas -profile sections in the config file must have the format of`[profile profile-name]`, -except for the default profile. Please see the [sample -files](#sample-files) below for examples of well-formed configuration and -credentials files. +## Usage -Profiles that appear in both files will not be merged, and the version that -appears in the credentials file will be given precedence over the profile found -in the config file. - -## Supported configuration - -You may customize how credentials are resolved by providing an options hash to -the `fromIni` factory function. The following options are supported: - -- `profile` - The configuration profile to use. If not specified, the provider - will use the value in the `AWS_PROFILE` environment variable or a default of - `default`. -- `filepath` - The path to the shared credentials file. If not specified, the - provider will use the value in the `AWS_SHARED_CREDENTIALS_FILE` environment - variable or a default of `~/.aws/credentials`. -- `configFilepath` - The path to the shared config file. If not specified, the - provider will use the value in the `AWS_CONFIG_FILE` environment variable or a - default of `~/.aws/config`. -- `mfaCodeProvider` - A function that returns a a promise fulfilled with an - MFA token code for the provided MFA Serial code. If a profile requires an MFA - code and `mfaCodeProvider` is not a valid function, the credential provider - promise will be rejected. -- `roleAssumer` - A function that assumes a role and returns a promise - fulfilled with credentials for the assumed role. You may call `sts:assumeRole` - API within this function. -- `roleAssumerWithWebIdentity` - A function that assumes a role with web identity - and returns a promise fulfilled with credentials for the assumed role. You may call - `sts:assumeRoleWithWebIdentity` API within this function. - -## Sample files - -### `~/.aws/credentials` - -```ini -[default] -aws_access_key_id=foo -aws_secret_access_key=bar - -[dev] -aws_access_key_id=foo2 -aws_secret_access_key=bar2 - -[prod] -aws_access_key_id=foo3 -aws_secret_access_key=bar3 -``` - -### `~/.aws/config` - -```ini -[default] -aws_access_key_id=foo -aws_secret_access_key=bar - -[profile dev] -aws_access_key_id=foo2 -aws_secret_access_key=bar2 - -[profile prod] -aws_access_key_id=foo3 -aws_secret_access_key=bar3 - -[profile "testing host"] -aws_access_key_id=foo4 -aws_secret_access_key=bar4 -``` - -### profile with source profile - -```ini -[second] -aws_access_key_id=foo -aws_secret_access_key=bar - -[first] -source_profile=second -role_arn=arn:aws:iam::123456789012:role/example-role-arn -``` - -### profile with source provider - -You can supply `credential_source` options to tell the SDK where to source -credentials for the call to `AssumeRole`. The supported credential providers are -listed bellow: - -```ini -[default] -role_arn=arn:aws:iam::123456789012:role/example-role-arn -credential_source = Ec2InstanceMetadata -``` - -```ini -[default] -role_arn=arn:aws:iam::123456789012:role/example-role-arn -credential_source = Environment -``` - -```ini -[default] -role_arn=arn:aws:iam::123456789012:role/example-role-arn -credential_source = EcsContainer -``` - -### profile with web_identity_token_file - -```ini -[default] -web_identity_token_file=/temp/token -role_arn=arn:aws:iam::123456789012:role/example-role-arn -``` - -You can specify another profile(`second`) whose credentials are used to assume -the role by the `role_arn` setting in this profile(`first`). - -```ini -[second] -web_identity_token_file=/temp/token -role_arn=arn:aws:iam::123456789012:role/example-role-2 - -[first] -source_profile=second -role_arn=arn:aws:iam::123456789012:role/example-role -``` - -### profile with sso credentials - -Please refer the the [`sso credential provider package`](https://www.npmjs.com/package/@aws-sdk/credential-provider-sso) -for how to configure the SSO credentials. - -```ini -[default] -sso_account_id = 012345678901 -sso_region = us-east-1 -sso_role_name = SampleRole -sso_start_url = https://d-abc123.awsapps.com/start -``` - -You can specify another profile(`second`) whose credentials derived from SSO -are used to assume the role by the `role_arn` setting in this profile(`first`). - -```ini -[second] -sso_account_id = 012345678901 -sso_region = us-east-1 -sso_role_name = example-role-2 -sso_start_url = https://d-abc123.awsapps.com/start - -[first] -source_profile=second -role_arn=arn:aws:iam::123456789012:role/example-role -``` +You probably shouldn't, at least directly. Please use [@aws-sdk/credential-providers](https://www.npmjs.com/package/@aws-sdk/credential-providers) +instead. diff --git a/packages/credential-provider-process/README.md b/packages/credential-provider-process/README.md index 5b09d5e3bd13..4e9d9bd480ed 100644 --- a/packages/credential-provider-process/README.md +++ b/packages/credential-provider-process/README.md @@ -3,61 +3,9 @@ [![NPM version](https://img.shields.io/npm/v/@aws-sdk/credential-provider-process/latest.svg)](https://www.npmjs.com/package/@aws-sdk/credential-provider-process) [![NPM downloads](https://img.shields.io/npm/dm/@aws-sdk/credential-provider-process.svg)](https://www.npmjs.com/package/@aws-sdk/credential-provider-process) -## AWS Credential Provider for Node.JS - Shared Configuration Files +> An internal package -This module provides a function, `fromSharedConfigFiles` that will create -`CredentialProvider` functions that read from a shared credentials file at -`~/.aws/credentials` and a shared configuration file at `~/.aws/config`. Both -files are expected to be INI formatted with section names corresponding to -profiles. Sections in the credentials file are treated as profile names, whereas -profile sections in the config file must have the format of`[profile profile-name]`, except for the default profile. Please see the [sample -files](#sample-files) below for examples of well-formed configuration and -credentials files. +## Usage -Profiles that appear in both files will not be merged, and the version that -appears in the credentials file will be given precedence over the profile found -in the config file. - -## Supported configuration - -You may customize how credentials are resolved by providing an options hash to -the `fromSharedConfigFiles` factory function. The following options are -supported: - -- `profile` - The configuration profile to use. If not specified, the provider - will use the value in the `AWS_PROFILE` environment variable or a default of - `default`. -- `filepath` - The path to the shared credentials file. If not specified, the - provider will use the value in the `AWS_SHARED_CREDENTIALS_FILE` environment - variable or a default of `~/.aws/credentials`. -- `configFilepath` - The path to the shared config file. If not specified, the - provider will use the value in the `AWS_CONFIG_FILE` environment variable or a - default of `~/.aws/config`. - -## Sample files - -### `~/.aws/credentials` - -```ini -[default] -credential_process = /usr/local/bin/awscreds - -[dev] -credential_process = /usr/local/bin/awscreds dev - -[prod] -credential_process = /usr/local/bin/awscreds prod -``` - -### `~/.aws/config` - -```ini -[default] -credential_process = /usr/local/bin/awscreds - -[profile dev] -credential_process = /usr/local/bin/awscreds dev - -[profile prod] -credential_process = /usr/local/bin/awscreds prod -``` +You probably shouldn't, at least directly. Please use [@aws-sdk/credential-providers](https://www.npmjs.com/package/@aws-sdk/credential-providers) +instead. diff --git a/packages/credential-provider-sso/README.md b/packages/credential-provider-sso/README.md index 995df79d697c..aba3fa8063f2 100644 --- a/packages/credential-provider-sso/README.md +++ b/packages/credential-provider-sso/README.md @@ -3,115 +3,9 @@ [![NPM version](https://img.shields.io/npm/v/@aws-sdk/credential-provider-sso/latest.svg)](https://www.npmjs.com/package/@aws-sdk/credential-provider-sso) [![NPM downloads](https://img.shields.io/npm/dm/@aws-sdk/credential-provider-sso.svg)](https://www.npmjs.com/package/@aws-sdk/credential-provider-sso) -## AWS Credential Provider for Node.js - AWS Single Sign-On (SSO) +> An internal package -This module provides a function, `fromSSO`, that creates -`CredentialProvider` functions that read from the -_resolved_ access token from local disk then requests temporary AWS -credentials. For guidance on the AWS Single Sign-On service, please -refer to [AWS's Single Sign-On documentation](https://aws.amazon.com/single-sign-on/). +## Usage -You can create the `CredentialProvider` functions using the inline SSO -parameters(`ssoStartUrl`, `ssoAccountId`, `ssoRegion`, `ssoRoleName`) or load -them from [AWS SDKs and Tools shared configuration and credentials files](https://docs.aws.amazon.com/credref/latest/refdocs/creds-config-files.html). -Profiles in the `credentials` file are given precedence over -profiles in the `config` file. - -This credential provider is intended for use with the AWS SDK for Node.js. - -This credential provider **ONLY** supports profiles using the SSO credential. If -you have a profile that assumes a role which derived from the SSO credential, -you should use the `@aws-sdk/credential-provider-ini`, or -`@aws-sdk/credential-provider-node` package. - -## Supported configuration - -You may customize how credentials are resolved by providing an options hash to -the `fromSSO` factory function. The following options are supported: - -- `ssoStartUrl`: The URL to the AWS SSO service. Required if any of the `sso*` - options(except for `ssoClient`) is provided. -- `ssoAccountId`: The ID of the AWS account to use for temporary credentials. - Required if any of the `sso*` options(except for `ssoClient`) is provided. -- `ssoRegion`: The AWS region to use for temporary credentials. Required if any - of the `sso*` options(except for `ssoClient`) is provided. -- `ssoRoleName`: The name of the AWS role to assume. Required if any of the - `sso*` options(except for `ssoClient`) is provided. -- `profile` - The configuration profile to use. If not specified, the provider - will use the value in the `AWS_PROFILE` environment variable or `default` by - default. -- `filepath` - The path to the shared credentials file. If not specified, the - provider will use the value in the `AWS_SHARED_CREDENTIALS_FILE` environment - variable or `~/.aws/credentials` by default. -- `configFilepath` - The path to the shared config file. If not specified, the - provider will use the value in the `AWS_CONFIG_FILE` environment variable or - `~/.aws/config` by default. -- `ssoClient` - The SSO Client used to request AWS credentials with the SSO - access token. If not specified, a default SSO client will be created with the - region specified in the profile `sso_region` entry. - -## SSO Login with the AWS CLI - -This credential provider relies on the [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html#sso-configure-profile) -to log into an AWS SSO session. Here's a brief walk-through: - -1. Create a new AWS SSO enabled profile using the AWS CLI. It will ask you to login - to your AWS SSO account and prompt for the name of the profile: - -```console -$ aws configure sso -... -... -CLI profile name [123456789011_ReadOnly]: my-sso-profile -``` - -2. Configure your SDK client with the SSO credential provider: - -```javascript -import { fromSSO } from "@aws-sdk/credential-provider-sso"; // ES6 example -// const { fromSSO } = require(@aws-sdk/credential-provider-sso") // CommonJS example -//... -const client = new FooClient({ credentials: fromSSO({ profile: "my-sso-profile" }); -``` - -Alternatively, the SSO credential provider is supported as a default -Node.js credential provider: - -```javascript -import { defaultProvider } from "@aws-sdk/credential-provider-node"; // ES6 example -// const { defaultProvider } = require(@aws-sdk/credential-provider-node") // CommonJS example -//... -const client = new FooClient({ credentials: defaultProvider({ profile: "my-sso-profile" }); -``` - -3. To log out from the current SSO session, use the AWS CLI: - -```console -$ aws sso logout -Successfully signed out of all SSO profiles. -``` - -## Sample files - -This credential provider is only applicable if the profile specified in shared -configuration and credentials files contain ALL of the following entries: - -### `~/.aws/credentials` - -```ini -[sample-profile] -sso_account_id = 012345678901 -sso_region = us-east-1 -sso_role_name = SampleRole -sso_start_url = https://d-abc123.awsapps.com/start -``` - -### `~/.aws/config` - -```ini -[profile sample-profile] -sso_account_id = 012345678901 -sso_region = us-east-1 -sso_role_name = SampleRole -sso_start_url = https://d-abc123.awsapps.com/start -``` +You probably shouldn't, at least directly. Please use [@aws-sdk/credential-providers](https://www.npmjs.com/package/@aws-sdk/credential-providers) +instead. diff --git a/packages/credential-provider-web-identity/README.md b/packages/credential-provider-web-identity/README.md index ad2078abeb56..e4858a41b1bb 100644 --- a/packages/credential-provider-web-identity/README.md +++ b/packages/credential-provider-web-identity/README.md @@ -3,137 +3,9 @@ [![NPM version](https://img.shields.io/npm/v/@aws-sdk/credential-provider-web-identity/latest.svg)](https://www.npmjs.com/package/@aws-sdk/credential-provider-web-identity) [![NPM downloads](https://img.shields.io/npm/dm/@aws-sdk/credential-provider-web-identity.svg)](https://www.npmjs.com/package/@aws-sdk/credential-provider-web-identity) -## AWS Credential Provider for Node.js - AssumeRole +> An internal package -This module includes functions which get credentials by calling STS assumeRoleWithWebIdentity API. +## Usage -## fromWebToken - -The function `fromWebToken` returns `CredentialProvider` that get credentials calling sts:assumeRoleWithWebIdentity -API via `roleAssumerWithWebIdentity`. - -### Supported configuration - -This configuration supports all the input parameters from -[sts:AssumeWithWebIdentity](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-sts/modules/assumerolewithwebidentityrequest.html) API. The following options are supported: - -- `roleArn` - The Amazon Resource Name (ARN) of the role that the caller is assuming. -- `webIdentityToken` - The OAuth 2.0 access token or OpenID Connect ID token that is provided by the identity provider. -- `roleSessionName` - An identifier for the assumed role session. -- `providerId` - The fully qualified host component of the domain name of the identity provider. Do not specify this - value for OpenID Connect ID tokens. -- `policyArns` - The Amazon Resource Names (ARNs) of the IAM managed policies that you want to use as managed session - policies. -- `policy` - An IAM policy in JSON format that you want to use as an inline session policy. -- `durationSeconds` - The duration, in seconds, of the role session. Default to 3600. -- `roleAssumerWithWebIdentity` - A function that assumes a role with web identity - and returns a promise fulfilled with credentials for the assumed role. You may call - `sts:assumeRoleWithWebIdentity` API within this function. - -### Examples - -You can directly configure individual identity providers to access AWS resources using web identity federation. AWS -currently supports authenticating users using web identity federation through several identity providers: - -- [Login with Amazon](https://login.amazon.com/) - -- [Facebook Login](https://developers.facebook.com/docs/facebook-login/web/) - -- [Google Sign-in](https://developers.google.com/identity/) - -You must first register your application with the providers that your application supports. Next, create an IAM role and -set up permissions for it. The IAM role you create is then used to grant the permissions you configured for it through -the respective identity provider. For example, you can set up a role that allows users who logged in through Facebook -to have read access to a specific Amazon S3 bucket you control. - -After you have both an IAM role with configured privileges and an application registered with your chosen identity -providers, you can set up the SDK to get credentials for the IAM role using helper code, as follows: - -```javascript -import { DynamoDBClient } from "@aws-sdk/client-dynamodb"; -import { getDefaultRoleAssumerWithWebIdentity } from "@aws-sdk/client-sts"; -import { fromWebToken } from "@aws-sdk/credential-provider-web-identity"; - -const dynamodb = new DynamoDBClient({ - region, - credentials: fromWebToken({ - roleArn: 'arn:aws:iam::/:role/', - providerId: 'graph.facebook.com|www.amazon.com', // this is null for Google - webIdentityToken: ACCESS_TOKEN // from OpenID token identity provider - roleAssumerWithWebIdentity: getDefaultRoleAssumerWithWebIdentity(), - }) -}); - -``` - -The value in the ProviderId parameter depends on the specified identity provider. The value in the WebIdentityToken -parameter is the access token retrieved from a successful login with the identity provider. For more information on how -to configure and retrieve access tokens for each identity provider, see the documentation for the identity provider. - -## fromTokenFile - -The function `fromTokenFile` returns `CredentialProvider` that reads credentials as follows: - -- Reads file location of where the OIDC token is stored from either provided option `webIdentityTokenFile` or environment variable `AWS_WEB_IDENTITY_TOKEN_FILE`. -- Reads IAM role wanting to be assumed from either provided option `roleArn` or environment variable `AWS_ROLE_ARN`. -- Reads optional role session name to be used to distinguish sessions from provided option `roleSessionName` or environment variable `AWS_ROLE_SESSION_NAME`. - If session name is not defined, it comes up with a role session name. -- Reads OIDC token from file on disk. -- Calls sts:AssumeRoleWithWebIdentity via `roleAssumerWithWebIdentity` option to get credentials. - -| **Configuration Key** | **Environment Variable** | **Required** | **Description** | -| --------------------- | --------------------------- | ------------ | ------------------------------------------------- | -| webIdentityTokenFile | AWS_WEB_IDENTITY_TOKEN_FILE | true | File location of where the `OIDC` token is stored | -| roleArn | AWS_IAM_ROLE_ARN | true | The IAM role wanting to be assumed | -| roleSessionName | AWS_IAM_ROLE_SESSION_NAME | false | The IAM session name used to distinguish sessions | - -### Supported configuration - -The following options are supported: - -- `roleAssumerWithWebIdentity` - A function that assumes a role with web identity - and returns a promise fulfilled with credentials for the assumed role. You may call - `sts:assumeRoleWithWebIdentity` API within this function. - -### Examples - -A basic example of using fromTokenFile: - -```js -import { getDefaultRoleAssumerWithWebIdentity } from "@aws-sdk/client-sts"; -import { fromTokenFile } from "@aws-sdk/credential-provider-web-identity"; - -const client = new FooClient({ - credentials: fromTokenFile({ - roleAssumerWithWebIdentity: getDefaultRoleAssumerWithWebIdentity() - }); -}); -``` - -#### Values in environment variables - -The values can be defined in environment variables as follows: - -```console -$ node -> Object.fromEntries(Object.entries(process.env).filter(([key, value]) => key.startsWith("AWS_"))); -{ - AWS_WEB_IDENTITY_TOKEN_FILE: '/temp/token', - AWS_ROLE_ARN: 'arn:aws:iam::123456789012:role/example-role-arn' -} -``` - -#### Values in configuration keys - -The values can be defined in configuration keys as follows: - -```js -... -const client = new FooClient({ - credentials: fromTokenFile({ - webIdentityTokenFile: "/temp/token", - roleArn: "arn:aws:iam::123456789012:role/example-role-arn", - roleAssumerWithWebIdentity: getDefaultRoleAssumerWithWebIdentity() - }); -}); -``` +You probably shouldn't, at least directly. Please use [@aws-sdk/credential-providers](https://www.npmjs.com/package/@aws-sdk/credential-providers) +instead. diff --git a/packages/credential-providers/LICENSE b/packages/credential-providers/LICENSE new file mode 100644 index 000000000000..7b6491ba7876 --- /dev/null +++ b/packages/credential-providers/LICENSE @@ -0,0 +1,201 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2018-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/packages/credential-providers/README.md b/packages/credential-providers/README.md new file mode 100644 index 000000000000..b08157d35fb4 --- /dev/null +++ b/packages/credential-providers/README.md @@ -0,0 +1,628 @@ +# @aws-sdk/credential-providers + +[![NPM version](https://img.shields.io/npm/v/@aws-sdk/credential-providers/latest.svg)](https://www.npmjs.com/package/@aws-sdk/credential-providers) +[![NPM downloads](https://img.shields.io/npm/dm/@aws-sdk/credential-providers.svg)](https://www.npmjs.com/package/@aws-sdk/credential-providers) + +A collection of all credential providers, with default clients. + +# Table of Contents + +1. [From Cognito Identity](#fromcognitoidentity) +1. [From Cognito Identity Pool](#fromcognitoidentitypool) +1. [From Temporary Credentials](#fromtemporarycredentials) +1. [From Web Token](#fromwebtoken) + 1. [Examples](#examples) +1. [From Token File](#fromtokenfile) +1. [From Instance and Container Metadata Service](#fromcontainermetadata-and-frominstancemetadata) +1. [From Shared INI files](#fromini) + 1. [Sample Files](#sample-files) +1. [From Environmental Variables](#fromenv) +1. [From Credential Process](#fromprocess) + 1. [Sample files](#sample-files-1) +1. [From Single Sign-On Service](#fromsso) + 1. [Supported Configuration](#supported-configuration) + 1. [SSO login with AWS CLI](#sso-login-with-the-aws-cli) + 1. [Sample Files](#sample-files-2) + +## `fromCognitoIdentity()` + +The function `fromCognitoIdentity()` returns `CredentialsProvider` that retrieves credentials for +the provided identity ID. See [GetCredentialsForIdentity API][getcredentialsforidentity_api] +for more information. + +```javascript +import { fromCognitoIdentity } from "@aws-sdk/credential-providers"; // ES6 import +// const { fromCognitoIdentity } = require("@aws-sdk/credential-providers"); // CommonJS import + +const client = new FooClient({ + region, + credentials: fromCognitoIdentity({ + // Required. The unique identifier for the identity against which credentials + // will be issued. + identityId: "us-east-1:128d0a74-c82f-4553-916d-90053example", + // Optional. The ARN of the role to be assumed when multiple roles were received in the token + // from the identity provider. + customRoleArn: "arn:aws:iam::1234567890:role/MYAPP-CognitoIdentity", + // Optional. A set of name-value pairs that map provider names to provider tokens. + // Required when using identities associated with external identity providers such as Facebook. + logins: { + "graph.facebook.com": "FBTOKEN", + "www.amazon.com": "AMAZONTOKEN", + "accounts.google.com": "GOOGLETOKEN", + "api.twitter.com": "TWITTERTOKEN'", + "www.digits.com": "DIGITSTOKEN", + }, + // Optional. Custom client config if you need overwrite default Cognito Identity client + // configuration. + clientConfig: { region }, + }), +}); +``` + +## `fromCognitoIdentityPool()` + +The function `fromCognitoIdentityPool()` returns `CredentialProvider` that calls [GetId API][getid_api] +to obtain an `identityId`, then generates temporary AWS credentials with +[GetCredentialsForIdentity API][getcredentialsforidentity_api], see +[`fromCognitoIdentity()`](#fromcognitoidentity). + +Results from `GetId` are cached internally, but results from `GetCredentialsForIdentity` are not. + +```javascript +import { fromCognitoIdentityPool } from "@aws-sdk/credential-providers"; // ES6 import +// const { fromCognitoIdentityPool } = require("@aws-sdk/credential-providers"); // CommonJS import + +const client = new FooClient({ + region, + credentials: fromCognitoIdentityPool({ + // Required. The unique identifier for the identity pool from which an identity should be + // retrieved or generated. + identityPoolId: "us-east-1:1699ebc0-7900-4099-b910-2df94f52a030", + // Optional. A standard AWS account ID (9+ digits) + accountId: "123456789", + // Optional. A cache in which to store resolved Cognito IdentityIds. + cache: custom_storage, + // Optional. A unique identifier for the user used to cache Cognito IdentityIds on a per-user + // basis. + userIdentifier: "user_0", + // Optional. The ARN of the role to be assumed when multiple roles were received in the token + // from the identity provider. + customRoleArn: "arn:aws:iam::1234567890:role/MYAPP-CognitoIdentity", + // Optional. A set of name-value pairs that map provider names to provider tokens. + // Required when using identities associated with external identity providers such as Facebook. + logins: { + "graph.facebook.com": "FBTOKEN", + "www.amazon.com": "AMAZONTOKEN", + "accounts.google.com": "GOOGLETOKEN", + "api.twitter.com": "TWITTERTOKEN", + "www.digits.com": "DIGITSTOKEN", + }, + // Optional. Custom client config if you need overwrite default Cognito Identity client + // configuration. + clientConfig: { region }, + }), +}); +``` + +## `fromTemporaryCredentials()` + +The function `fromTemporaryCredentials` returns `CredentialProvider` that retrieves temporary +credentials from [STS AssumeRole API][assumerole_api]. + +```javascript +import { fromTemporaryCredentials } from "@aws-sdk/credential-providers"; // ES6 import +// const { fromTemporaryCredentials } = require("@aws-sdk/credential-providers"); // CommonJS import + +const client = new FooClient({ + region, + credentials: fromTemporaryCredentials( + // Optional. The master credentials used to get and refresh temporary credentials from AWS STS. + // If skipped, it uses the default credential resolved by internal STS client. + masterCredentials: fromTemporaryCredentials({ + params: { RoleArn: "arn:aws:iam::1234567890:role/RoleA" } + }), + // Required. Options passed to STS AssumeRole operation. + params: { + // Required. ARN of role to assume. + RoleArn: "arn:aws:iam::1234567890:role/RoleB", + // Optional. An identifier for the assumed role session. If skipped, it generates a random + // session name with prefix of 'aws-sdk-js-'. + RoleSessionName: "aws-sdk-js-123", + // Optional. The duration, in seconds, of the role session. + DurationSeconds: 3600 + // ... For more options see https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html + }, + // Optional. Custom STS client configurations overriding the default ones. + clientConfig: { region }, + // Optional. A function that returns a promise fulfilled with an MFA token code for the provided + // MFA Serial code. Required if `params` has `SerialNumber` config. + mfaCodeProvider: async mfaSerial => { + return "token" + } + ), +}); +``` + +## `fromWebToken()` + +The function `fromWebToken` returns `CredentialProvider` that gets credentials calling +[STS AssumeRoleWithWebIdentity API][assumerolewithwebidentity_api] + +```javascript +import { fromWebToken } from "@aws-sdk/credential-providers"; // ES6 import +// const { fromWebToken } = require("@aws-sdk/credential-providers"); // CommonJS import + +const client = new FooClient({ + region, + credentials: fromWebToken({ + // Required. ARN of the role that the caller is assuming. + roleArn: "arn:aws:iam::1234567890:role/RoleA", + // Required. The OAuth 2.0 access token or OpenID Connect ID token that is provided by the + // identity provider. + webIdentityToken: await openIdProvider(), + // Optional. Custom STS client configurations overriding the default ones. + clientConfig: { region }, + // Optional. A function that assumes a role with web identity and returns a promise fulfilled + // with credentials for the assumed role. + roleAssumerWithWebIdentity, + // Optional. An identifier for the assumed role session. + roleSessionName: "session_123", + // Optional. The fully qualified host component of the domain name of the identity provider. + providerId: "graph.facebook.com", + // Optional. ARNs of the IAM managed policies that you want to use as managed session. + policyArns: [{ arn: "arn:aws:iam::1234567890:policy/SomePolicy" }], + // Optional. An IAM policy in JSON format that you want to use as an inline session policy. + policy: "JSON_STRING", + // Optional. The duration, in seconds, of the role session. Default to 3600. + durationSeconds: 7200, + }), +}); +``` + +### Examples + +You can directly configure individual identity providers to access AWS resources using web identity +federation. AWS currently supports authenticating users using web identity federation through +several identity providers: + +- [Login with Amazon](https://login.amazon.com/) + +- [Facebook Login](https://developers.facebook.com/docs/facebook-login/web/) + +- [Google Sign-in](https://developers.google.com/identity/) + +You must first register your application with the providers that your application supports. Next, +create an IAM role and set up permissions for it. The IAM role you create is then used to grant the +permissions you configured for it through the respective identity provider. For example, you can set +up a role that allows users who logged in through Facebook to have read access to a specific Amazon +S3 bucket you control. + +After you have both an IAM role with configured privileges and an application registered with your +chosen identity providers, you can set up the SDK to get credentials for the IAM role using helper +code, as follows: + +The value in the ProviderId parameter depends on the specified identity provider. The value in the +WebIdentityToken parameter is the access token retrieved from a successful login with the identity +provider. For more information on how to configure and retrieve access tokens for each identity +provider, see the documentation for the identity provider. + +## `fromContainerMetadata()` and `fromInstanceMetadata()` + +`fromContainerMetadata` and `fromInstanceMetadata` will create `CredentialProvider` functions that +read from the ECS container metadata service and the EC2 instance metadata service, respectively. + +```javascript +import { fromInstanceMetadata } from "@aws-sdk/credential-providers"; // ES6 import +// const { fromInstanceMetadata } = require("@aws-sdk/credential-providers"); // CommonJS import + +const client = new FooClient({ + credentials: fromInstanceMetadata({ + // Optional. The connection timeout (in milliseconds) to apply to any remote requests. + // If not specified, a default value of `1000` (one second) is used. + timeout: 1000, + // Optional. The maximum number of times any HTTP connections should be retried. If not + // specified, a default value of `0` will be used. + maxRetries: 0, + }), +}); +``` + +```javascript +import { fromContainerMetadata } from "@aws-sdk/credential-providers"; // ES6 import +// const { fromContainerMetadata } = require("@aws-sdk/credential-providers"); // CommonJS import + +const client = new FooClient({ + credentials: fromContainerMetadata({ + // Optional. The connection timeout (in milliseconds) to apply to any remote requests. + // If not specified, a default value of `1000` (one second) is used. + timeout: 1000, + // Optional. The maximum number of times any HTTP connections should be retried. If not + // specified, a default value of `0` will be used. + maxRetries: 0, + }), +}); +``` + +A `CredentialProvider` function created with `fromContainerMetadata` will return a promise that will +resolve with credentials for the IAM role associated with containers in an Amazon ECS task. Please +see [IAM Roles for Tasks][iam_roles_for_tasks] for more information on using IAM roles with Amazon +ECS. + +A `CredentialProvider` function created with `fromInstanceMetadata` will return a promise that will +resolve with credentials for the IAM role associated with an EC2 instance. +Please see [IAM Roles for Amazon EC2][iam_roles_for_ec2] for more information on using IAM roles +with Amazon EC2. Both IMDSv1 (a request/response method) and IMDSv2 (a session-oriented method) are +supported. + +Please see [Configure the instance metadata service][config_instance_metadata] for more information. + +## `fromIni()` + +`fromIni` creates `CredentialProvider` functions that read from a shared credentials file at +`~/.aws/credentials` and a shared configuration file at `~/.aws/config`. Both files are expected to +be INI formatted with section names corresponding to profiles. Sections in the credentials file are +treated as profile names, whereas profile sections in the config file must have the format of +`[profile profile-name]`, except for the default profile. Please see the +[sample files](#sample-files) below for examples of well-formed configuration and credentials files. + +Profiles that appear in both files will not be merged, and the version that appears in the +credentials file will be given precedence over the profile found in the config file. + +```javascript +import { fromIni } from "@aws-sdk/credential-providers"; // ES6 import +// const { fromIni } = require("@aws-sdk/credential-providers"); // CommonJS import + +const client = new FooClient({ + credentials: fromIni({ + // Optional. The configuration profile to use. If not specified, the provider will use the value + // in the `AWS_PROFILE` environment variable or a default of `default`. + profile: "profile", + // Optional. The path to the shared credentials file. If not specified, the provider will use + // the value in the `AWS_SHARED_CREDENTIALS_FILE` environment variable or a default of + // `~/.aws/credentials`. + filepath: "~/.aws/credentials", + // Optional. The path to the shared config file. If not specified, the provider will use the + // value in the `AWS_CONFIG_FILE` environment variable or a default of `~/.aws/config`. + configFilepath: "~/.aws/config", + // Optional. A function that returns a a promise fulfilled with an MFA token code for the + // provided MFA Serial code. If a profile requires an MFA code and `mfaCodeProvider` is not a + // valid function, the credential provider promise will be rejected. + mfaCodeProvider: async (mfaSerial) => { + return "token"; + }, + // Optional. Custom STS client configurations overriding the default ones. + clientConfig: { region }, + }), +}); +``` + +### Sample files + +#### `~/.aws/credentials` + +```ini +[default] +aws_access_key_id=foo +aws_secret_access_key=bar + +[dev] +aws_access_key_id=foo2 +aws_secret_access_key=bar2 +``` + +#### `~/.aws/config` + +```ini +[default] +aws_access_key_id=foo +aws_secret_access_key=bar + +[profile dev] +aws_access_key_id=foo2 +aws_secret_access_key=bar2 +``` + +#### profile with source profile + +```ini +[second] +aws_access_key_id=foo +aws_secret_access_key=bar + +[first] +source_profile=second +role_arn=arn:aws:iam::123456789012:role/example-role-arn +``` + +#### profile with source provider + +You can supply `credential_source` options to tell the SDK where to source credentials for the call +to `AssumeRole`. The supported credential providers are listed below: + +```ini +[default] +role_arn=arn:aws:iam::123456789012:role/example-role-arn +credential_source = Ec2InstanceMetadata +``` + +```ini +[default] +role_arn=arn:aws:iam::123456789012:role/example-role-arn +credential_source = Environment +``` + +```ini +[default] +role_arn=arn:aws:iam::123456789012:role/example-role-arn +credential_source = EcsContainer +``` + +#### profile with web_identity_token_file + +```ini +[default] +web_identity_token_file=/temp/token +role_arn=arn:aws:iam::123456789012:role/example-role-arn +``` + +You can specify another profile(`second`) whose credentials are used to assume the role by the +`role_arn` setting in this profile(`first`). + +```ini +[second] +web_identity_token_file=/temp/token +role_arn=arn:aws:iam::123456789012:role/example-role-2 + +[first] +source_profile=second +role_arn=arn:aws:iam::123456789012:role/example-role +``` + +#### profile with sso credentials + +See [`fromSSO()`](#fromsso) fro more information + +## `fromEnv()` + +```javascript +import { fromEnv } from "@aws-sdk/credential-providers"; // ES6 import +// const { fromEnv } = require("@aws-sdk/credential-providers"); // CommonJS import + +const client = new FooClient({ + credentials: fromEnv(), +}); +``` + +`fromEnv` returns a `CredentialProvider` function, that reads credentials from the following +environment variables: + +- `AWS_ACCESS_KEY_ID` - The access key for your AWS account. +- `AWS_SECRET_ACCESS_KEY` - The secret key for your AWS account. +- `AWS_SESSION_TOKEN` - The session key for your AWS account. This is only needed when you are using + temporarycredentials. +- `AWS_CREDENTIAL_EXPIRATION` - The expiration time of the credentials contained in the environment + variables described above. This value must be in a format compatible with the + [ISO-8601 standard][iso8601_standard] and is only needed when you are using temporary credentials. + +If either the `AWS_ACCESS_KEY_ID` or `AWS_SECRET_ACCESS_KEY` environment variable is not set or +contains a falsy value, the promise returned by the `fromEnv` function will be rejected. + +## `fromProcess()` + +```javascript +import { fromProcess } from "@aws-sdk/credential-providers"; // ES6 import +// const { fromProcess } = require("@aws-sdk/credential-providers"); // CommonJS import + +const client = new FooClient({ + credentials: fromProcess({ + // Optional. The configuration profile to use. If not specified, the provider will use the value + // in the `AWS_PROFILE` environment variable or a default of `default`. + profile: "profile", + // Optional. The path to the shared credentials file. If not specified, the provider will use + // the value in the `AWS_SHARED_CREDENTIALS_FILE` environment variable or a default of + // `~/.aws/credentials`. + filepath: "~/.aws/credentials", + // Optional. The path to the shared config file. If not specified, the provider will use the + // value in the `AWS_CONFIG_FILE` environment variable or a default of `~/.aws/config`. + configFilepath: "~/.aws/config", + }), +}); +``` + +`fromSharedConfigFiles` creates a `CredentialProvider` functions that executes a given process and +attempt to read its standard output to receive a JSON payload containing the credentials. The +process command is read from a shared credentials file at `~/.aws/credentials` and a shared +configuration file at `~/.aws/config`. Both files are expected to be INI formatted with section +names corresponding to profiles. Sections in the credentials file are treated as profile names, +whereas profile sections in the config file must have the format of`[profile profile-name]`, except +for the default profile. Please see the [sample files](#sample-files-1) below for examples of +well-formed configuration and credentials files. + +Profiles that appear in both files will not be merged, and the version that appears in the +credentials file will be given precedence over the profile found in the config file. + +### Sample files + +#### `~/.aws/credentials` + +```ini +[default] +credential_process = /usr/local/bin/awscreds + +[dev] +credential_process = /usr/local/bin/awscreds dev +``` + +#### `~/.aws/config` + +```ini +[default] +credential_process = /usr/local/bin/awscreds + +[profile dev] +credential_process = /usr/local/bin/awscreds dev +``` + +## `fromTokenFile()` + +The function `fromTokenFile` returns `CredentialProvider` that reads credentials as follows: + +- Reads file location of where the OIDC token is stored from either provided option + `webIdentityTokenFile` or environment variable `AWS_WEB_IDENTITY_TOKEN_FILE`. +- Reads IAM role wanting to be assumed from either provided option `roleArn` or environment + variable `AWS_ROLE_ARN`. +- Reads optional role session name to be used to distinguish sessions from provided option + `roleSessionName` or environment variable `AWS_ROLE_SESSION_NAME`. If session name is not defined, + it comes up with a role session name. +- Reads OIDC token from file on disk. +- Calls sts:AssumeRoleWithWebIdentity via `roleAssumerWithWebIdentity` option to get credentials. + +| **Configuration Key** | **Environment Variable** | **Required** | **Description** | +| --------------------- | --------------------------- | ------------ | ------------------------------------------------- | +| webIdentityTokenFile | AWS_WEB_IDENTITY_TOKEN_FILE | true | File location of where the `OIDC` token is stored | +| roleArn | AWS_IAM_ROLE_ARN | true | The IAM role wanting to be assumed | +| roleSessionName | AWS_IAM_ROLE_SESSION_NAME | false | The IAM session name used to distinguish sessions | + +```javascript +import { fromTokenFile } from "@aws-sdk/credential-providers"; // ES6 import +// const { fromTokenFile } = require("@aws-sdk/credential-providers"); // CommonJS import + +const client = new FooClient({ + credentials: fromTokenFile({ + // Optional. STS client config to make the assume role request. + clientConfig: { region } + }); +}); +``` + +## `fromSSO()` + +> This credential provider **ONLY** supports profiles using the SSO credential. If you have a +> profile that assumes a role which derived from the SSO credential, you should use the +> [`fromIni()`](#fromini), or `@aws-sdk/credential-provider-node` package. + +`fromSSO`, that creates `CredentialProvider` functions that read from the _resolved_ access token +from local disk then requests temporary AWS credentials. For guidance on the AWS Single Sign-On +service, please refer to [AWS's Single Sign-On documentation][sso_api]. + +You can create the `CredentialProvider` functions using the inline SSO parameters(`ssoStartUrl`, +`ssoAccountId`, `ssoRegion`, `ssoRoleName`) or load them from +[AWS SDKs and Tools shared configuration and credentials files][shared_config_files]. +Profiles in the `credentials` file are given precedence over profiles in the `config` file. + +This credential provider is intended for use with the AWS SDK for Node.js. + +### Supported configuration + +You may customize how credentials are resolved by providing an options hash to the `fromSSO` factory +function. You can either load the SSO config from shared INI credential files, or specify the +`ssoStartUrl`, `ssoAccountId`, `ssoRegion`, and `ssoRoleName` directly from the code. + +```javascript +import { fromSSO } from "@aws-sdk/credential-providers"; // ES6 import +// const { fromSSO } = require(@aws-sdk/credential-providers") // CommonJS import + +const client = new FooClient({ + credentials: fromSSO({ + // Optional. The configuration profile to use. If not specified, the provider will use the value + // in the `AWS_PROFILE` environment variable or `default` by default. + profile: "my-sso-profile", + // Optional. The path to the shared credentials file. If not specified, the provider will use + // the value in the `AWS_SHARED_CREDENTIALS_FILE` environment variable or a default of + // `~/.aws/credentials`. + filepath: "~/.aws/credentials", + // Optional. The path to the shared config file. If not specified, the provider will use the + // value in the `AWS_CONFIG_FILE` environment variable or a default of `~/.aws/config`. + configFilepath: "~/.aws/config", + // Optional. The URL to the AWS SSO service. Required if any of the `sso*` options(except for + // `ssoClient`) is provided. + ssoStartUrl: "https://d-abc123.awsapps.com/start", + // Optional. The ID of the AWS account to use for temporary credentials. Required if any of the + // `sso*` options(except for `ssoClient`) is provided. + ssoAccountId: "1234567890", + // Optional. The AWS region to use for temporary credentials. Required if any of the `sso*` + // options(except for `ssoClient`) is provided. + ssoRegion: "us-east-1", + // Optional. The name of the AWS role to assume. Required if any of the `sso*` options(except + // for `ssoClient`) is provided. + ssoRoleName: "SampleRole", + // Optional. Overwrite the configuration used construct the SSO service client. If not + // specified, a default SSO client will be created with the region specified in the profile + // `sso_region` entry. + clientConfig: { region }, + }), +}); +``` + +### SSO Login with the AWS CLI + +This credential provider relies on the [AWS CLI][cli_sso] to log into an AWS SSO session. Here's a +brief walk-through: + +1. Create a new AWS SSO enabled profile using the AWS CLI. It will ask you to login to your AWS SSO + account and prompt for the name of the profile: + +```console +$ aws configure sso +... +... +CLI profile name [123456789011_ReadOnly]: my-sso-profile +``` + +2. Configure your SDK client with the SSO credential provider: + +```javascript +//... +const client = new FooClient({ credentials: fromSSO({ profile: "my-sso-profile" }); +``` + +Alternatively, the SSO credential provider is supported in shared INI credentials provider + +```javascript +//... +const client = new FooClient({ credentials: fromIni({ profile: "my-sso-profile" }); +``` + +3. To log out from the current SSO session, use the AWS CLI: + +```console +$ aws sso logout +Successfully signed out of all SSO profiles. +``` + +### Sample files + +This credential provider is only applicable if the profile specified in shared configuration and +credentials files contain ALL of the following entries: + +#### `~/.aws/credentials` + +```ini +[sample-profile] +sso_account_id = 012345678901 +sso_region = us-east-1 +sso_role_name = SampleRole +sso_start_url = https://d-abc123.awsapps.com/start +``` + +#### `~/.aws/config` + +```ini +[profile sample-profile] +sso_account_id = 012345678901 +sso_region = us-east-1 +sso_role_name = SampleRole +sso_start_url = https://d-abc123.awsapps.com/start +``` + +[getcredentialsforidentity_api]: https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetCredentialsForIdentity.html +[getid_api]: https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetId.html +[assumerole_api]: https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html +[assumerolewithwebidentity_api]: https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html +[iam_roles_for_tasks]: http://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html +[iam_roles_for_ec2]: http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html +[config_instance_metadata]: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html +[iso8601_standard]: https://en.wikipedia.org/wiki/ISO_8601 +[sso_api]: https://aws.amazon.com/single-sign-on/ +[shared_config_files]: https://docs.aws.amazon.com/credref/latest/refdocs/creds-config-files.html +[cli_sso]: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html#sso-configure-profile diff --git a/packages/credential-providers/jest.config.js b/packages/credential-providers/jest.config.js new file mode 100644 index 000000000000..a8d1c2e49912 --- /dev/null +++ b/packages/credential-providers/jest.config.js @@ -0,0 +1,5 @@ +const base = require("../../jest.config.base.js"); + +module.exports = { + ...base, +}; diff --git a/packages/credential-providers/package.json b/packages/credential-providers/package.json new file mode 100644 index 000000000000..9bf3b83a171c --- /dev/null +++ b/packages/credential-providers/package.json @@ -0,0 +1,78 @@ +{ + "name": "@aws-sdk/credential-providers", + "version": "3.0.0", + "description": "A collection of credential providers, without requiring service clients like STS, Cognito", + "main": "./dist/cjs/index.js", + "module": "./dist/es/index.js", + "browser": { + "@aws-sdk/credential-provider-env": false, + "@aws-sdk/credential-provider-imds": false, + "./fromIni": false, + "@aws-sdk/credential-provider-process": false, + "./fromTokenFile": false + }, + "react-native": { + "@aws-sdk/credential-provider-env": false, + "@aws-sdk/credential-provider-imds": false, + "./fromIni": false, + "@aws-sdk/credential-provider-process": false, + "./fromTokenFile": false + }, + "sideEffects": false, + "scripts": { + "build:cjs": "tsc -p tsconfig.cjs.json", + "build:es": "tsc -p tsconfig.es.json", + "build": "yarn build:es && yarn build:cjs", + "downlevel-dts": "downlevel-dts dist/types dist/types/ts3.4", + "test": "jest" + }, + "keywords": [ + "aws", + "credentials" + ], + "author": { + "name": "AWS SDK for JavaScript Team", + "url": "https://aws.amazon.com/javascript/" + }, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/credential-provider-cognito-identity": "3.25.0", + "@aws-sdk/credential-provider-env": "3.25.0", + "@aws-sdk/credential-provider-imds": "3.25.0", + "@aws-sdk/credential-provider-ini": "3.25.0", + "@aws-sdk/credential-provider-process": "3.25.0", + "@aws-sdk/credential-provider-sso": "3.25.0", + "@aws-sdk/credential-provider-web-identity": "3.25.0", + "@aws-sdk/client-sts": "3.25.0", + "@aws-sdk/client-cognito-identity": "3.25.0", + "@aws-sdk/client-sso": "3.25.0", + "@aws-sdk/property-provider": "3.25.0", + "@aws-sdk/shared-ini-file-loader": "3.23.0", + "@aws-sdk/types": "3.25.0", + "@aws-sdk/util-credentials": "3.23.0", + "tslib": "^2.3.0" + }, + "devDependencies": { + "@types/jest": "^26.0.4", + "@types/node": "^10.0.0", + "jest": "^26.1.0", + "typescript": "~4.3.2" + }, + "types": "./dist/types/index.d.ts", + "engines": { + "node": ">= 10.0.0" + }, + "typesVersions": { + "<4.0": { + "dist/types/*": [ + "dist/types/ts3.4/*" + ] + } + }, + "homepage": "https://github.com/aws/aws-sdk-js-v3/tree/main/packages/credential-provider-ini", + "repository": { + "type": "git", + "url": "https://github.com/aws/aws-sdk-js-v3.git", + "directory": "packages/credential-provider-ini" + } +} diff --git a/packages/credential-providers/src/fromCognitoIdentity.spec.ts b/packages/credential-providers/src/fromCognitoIdentity.spec.ts new file mode 100644 index 000000000000..3282121b6561 --- /dev/null +++ b/packages/credential-providers/src/fromCognitoIdentity.spec.ts @@ -0,0 +1,42 @@ +jest.mock("@aws-sdk/client-cognito-identity", () => ({ + CognitoIdentityClient: jest.fn().mockImplementation(function () { + return "COGNITO_IDENTITY_CLIENT"; + }), +})); + +import { CognitoIdentityClient } from "@aws-sdk/client-cognito-identity"; +import { fromCognitoIdentity as coreProvider } from "@aws-sdk/credential-provider-cognito-identity"; + +import { fromCognitoIdentity } from "./fromCognitoIdentity"; + +jest.mock("@aws-sdk/credential-provider-cognito-identity", () => ({ + fromCognitoIdentity: jest.fn(), +})); + +describe("fromCognitoIdentity", () => { + const identityId = "IDENTITY_ID"; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it("should inject default client", () => { + fromCognitoIdentity({ + identityId, + }); + expect((coreProvider as jest.Mock).mock.calls[0][0]?.identityId).toBe(identityId); + expect((coreProvider as jest.Mock).mock.calls[0][0]?.client).toBeInstanceOf(CognitoIdentityClient); + expect(CognitoIdentityClient).toBeCalled(); + }); + + it("should use client config if supplied", () => { + const clientConfig = "CLIENT" as any; + fromCognitoIdentity({ + identityId, + clientConfig, + }); + expect((coreProvider as jest.Mock).mock.calls[0][0]?.identityId).toBe(identityId); + expect((coreProvider as jest.Mock).mock.calls[0][0]?.client).toBeInstanceOf(CognitoIdentityClient); + expect(CognitoIdentityClient).toBeCalledWith(clientConfig); + }); +}); diff --git a/packages/credential-providers/src/fromCognitoIdentity.ts b/packages/credential-providers/src/fromCognitoIdentity.ts new file mode 100644 index 000000000000..32c8d582cdf6 --- /dev/null +++ b/packages/credential-providers/src/fromCognitoIdentity.ts @@ -0,0 +1,56 @@ +import { CognitoIdentityClient, CognitoIdentityClientConfig } from "@aws-sdk/client-cognito-identity"; +import { + CognitoIdentityCredentialProvider as _CognitoIdentityCredentialProvider, + fromCognitoIdentity as _fromCognitoIdentity, + FromCognitoIdentityParameters as _FromCognitoIdentityParameters, +} from "@aws-sdk/credential-provider-cognito-identity"; + +export interface FromCognitoIdentityParameters extends Omit<_FromCognitoIdentityParameters, "client"> { + /** + * Custom client configuration if you need overwrite default Cognito Identity client configuration. + */ + clientConfig?: CognitoIdentityClientConfig; +} + +export type CognitoIdentityCredentialProvider = _CognitoIdentityCredentialProvider; + +/** + * Creates a credential provider function that reetrieves temporary AWS credentials using Amazon Cognito's + * `GetCredentialsForIdentity` operation. + * + * Results from this function call are not cached internally. + * + * ```javascript + * import { fromCognitoIdentity } from "@aws-sdk/credential-providers"; // ES6 import + * // const { fromCognitoIdentity } = require("@aws-sdk/credential-providers"); // CommonJS import + * + * const client = new FooClient({ + * region, + * credentials: fromCognitoIdentity({ + * // Required. The unique identifier for the identity against which credentials + * // will be issued. + * identityId: "us-east-1:128d0a74-c82f-4553-916d-90053e4a8b0f" + * // optional. The ARN of the role to be assumed when multiple roles were + * // received in the token from the identity provider. + * customRoleArn: "arn:aws:iam::1234567890:role/MYAPP-CognitoIdentity" + * // Optional. A set of name-value pairs that map provider names to provider + * // tokens. Required when using identities associated with external identity + * // providers such as Facebook. + * logins: { + * "graph.facebook.com": "FBTOKEN", + * "www.amazon.com": "AMAZONTOKEN", + * "accounts.google.com": "GOOGLETOKEN", + * "api.twitter.com": "TWITTERTOKEN'", + * "www.digits.com": "DIGITSTOKEN" + * }, + * // Optional. Custom client configuration if you need overwrite default Cognito Identity client configuration. + * clientConfig: { region } + * }), + * }); + * ``` + */ +export const fromCognitoIdentity = (options: FromCognitoIdentityParameters): CognitoIdentityCredentialProvider => + _fromCognitoIdentity({ + ...options, + client: new CognitoIdentityClient(options.clientConfig ?? {}), + }); diff --git a/packages/credential-providers/src/fromCognitoIdentityPool.spec.ts b/packages/credential-providers/src/fromCognitoIdentityPool.spec.ts new file mode 100644 index 000000000000..27d3aa923776 --- /dev/null +++ b/packages/credential-providers/src/fromCognitoIdentityPool.spec.ts @@ -0,0 +1,47 @@ +jest.mock("@aws-sdk/client-cognito-identity", () => ({ + CognitoIdentityClient: jest.fn().mockImplementation(function () { + return "COGNITO_IDENTITY_CLIENT"; + }), +})); + +import { CognitoIdentityClient } from "@aws-sdk/client-cognito-identity"; +import { fromCognitoIdentityPool as coreProvider } from "@aws-sdk/credential-provider-cognito-identity"; + +import { fromCognitoIdentityPool } from "./fromCognitoIdentityPool"; + +jest.mock("@aws-sdk/credential-provider-cognito-identity", () => ({ + fromCognitoIdentityPool: jest.fn(), +})); + +describe("fromCognitoIdentityPool", () => { + const identityPoolId = "IDENTITY_POOL_ID"; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it("should inject default client", () => { + fromCognitoIdentityPool({ + identityPoolId, + }); + expect(coreProvider).toBeCalledWith( + expect.objectContaining({ + identityPoolId, + }) + ); + expect((coreProvider as jest.Mock).mock.calls[0][0]?.identityPoolId).toBe(identityPoolId); + expect((coreProvider as jest.Mock).mock.calls[0][0]?.client).toBeInstanceOf(CognitoIdentityClient); + expect(CognitoIdentityClient).toBeCalledWith({}); + }); + + it("should use client config if supplied", () => { + const clientConfig = "CLIENT" as any; + fromCognitoIdentityPool({ + identityPoolId, + clientConfig, + }); + expect((coreProvider as jest.Mock).mock.calls[0][0]?.identityPoolId).toBe(identityPoolId); + expect((coreProvider as jest.Mock).mock.calls[0][0]?.client).toBeInstanceOf(CognitoIdentityClient); + expect(CognitoIdentityClient).toBeCalledWith(clientConfig); + }); +}); diff --git a/packages/credential-providers/src/fromCognitoIdentityPool.ts b/packages/credential-providers/src/fromCognitoIdentityPool.ts new file mode 100644 index 000000000000..ebc2bafee830 --- /dev/null +++ b/packages/credential-providers/src/fromCognitoIdentityPool.ts @@ -0,0 +1,58 @@ +import { CognitoIdentityClient, CognitoIdentityClientConfig } from "@aws-sdk/client-cognito-identity"; +import { + CognitoIdentityCredentialProvider, + fromCognitoIdentityPool as _fromCognitoIdentityPool, + FromCognitoIdentityPoolParameters as _FromCognitoIdentityPoolParameters, +} from "@aws-sdk/credential-provider-cognito-identity"; + +export interface FromCognitoIdentityPoolParameters extends Omit<_FromCognitoIdentityPoolParameters, "client"> { + clientConfig?: CognitoIdentityClientConfig; +} + +/** + * Creates a credential provider function that retrieves or generates a unique identifier using Amazon Cognito's `GetId` + * operation, then generates temporary AWS credentials using Amazon Cognito's `GetCredentialsForIdentity` operation. + * + * Results from `GetId` are cached internally, but results from `GetCredentialsForIdentity` are not. + * + * ```javascript + * import { fromCognitoIdentityPool } from "@aws-sdk/credential-providers"; // ES6 import + * // const { fromCognitoIdentityPool } = require("@aws-sdk/credential-providers"); // CommonJS import + * + * const client = new FooClient({ + * region, + * credentials: fromCognitoIdentityPool({ + * // Required. The unique identifier for the identity pool from which an identity should be retrieved or generated. + * identityPoolId: "us-east-1:1699ebc0-7900-4099-b910-2df94f52a030"; + * // Optional. A standard AWS account ID (9+ digits) + * accountId: "123456789", + * // Optional. A cache in which to store resolved Cognito IdentityIds. + * cache: custom_storage, + * // Optional. A unique identifier for the user used to cache Cognito IdentityIds on a per-user basis. + * userIdentifier: "user_0", + * // optional. The ARN of the role to be assumed when multiple roles were + * // received in the token from the identity provider. + * customRoleArn: "arn:aws:iam::1234567890:role/MYAPP-CognitoIdentity" + * // Optional. A set of name-value pairs that map provider names to provider + * // tokens. Required when using identities associated with external identity + * // providers such as Facebook. + * logins: { + * 'graph.facebook.com': 'FBTOKEN', + * 'www.amazon.com': 'AMAZONTOKEN', + * 'accounts.google.com': 'GOOGLETOKEN', + * 'api.twitter.com': 'TWITTERTOKEN', + * 'www.digits.com': 'DIGITSTOKEN' + * }, + * // Optional. Custom client configuration if you need overwrite default Cognito Identity client configuration. + * client: new CognitoIdentityClient({ region }) + * }), + * }); + * ``` + */ +export const fromCognitoIdentityPool = ( + options: FromCognitoIdentityPoolParameters +): CognitoIdentityCredentialProvider => + _fromCognitoIdentityPool({ + ...options, + client: new CognitoIdentityClient(options.clientConfig ?? {}), + }); diff --git a/packages/credential-providers/src/fromContainerMetadata.ts b/packages/credential-providers/src/fromContainerMetadata.ts new file mode 100644 index 000000000000..88d6d5dc2482 --- /dev/null +++ b/packages/credential-providers/src/fromContainerMetadata.ts @@ -0,0 +1,28 @@ +import { + fromContainerMetadata as _fromContainerMetadata, + RemoteProviderInit as _RemoteProviderInit, +} from "@aws-sdk/credential-provider-imds"; +import { CredentialProvider } from "@aws-sdk/types"; + +export interface RemoteProviderInit extends _RemoteProviderInit {} + +/** + * Create a credential provider function that reads from ECS container metadata service. + * + * ```javascript + * import { fromContainerMetadata } from "@aws-sdk/credential-providers"; // ES6 import + * // const { fromContainerMetadata } = require("@aws-sdk/credential-providers"); // CommonJS import + * + * const foo = new FooClient({ + * credentials: fromInstanceMetadata({ + * // Optional. The connection timeout (in milliseconds) to apply to any remote requests. If not specified, a default value + * // of`1000` (one second) is used. + * timeout: 1000, + * // Optional. The maximum number of times any HTTP connections should be retried. If not specified, a default value of `0` + * // will be used. + * maxRetries: 0, + * }), + * }); + * ``` + */ +export const fromContainerMetadata = (init?: RemoteProviderInit): CredentialProvider => _fromContainerMetadata(init); diff --git a/packages/credential-providers/src/fromEnv.ts b/packages/credential-providers/src/fromEnv.ts new file mode 100644 index 000000000000..d980d386c454 --- /dev/null +++ b/packages/credential-providers/src/fromEnv.ts @@ -0,0 +1,28 @@ +import { fromEnv as _fromEnv } from "@aws-sdk/credential-provider-env"; +import { CredentialProvider } from "@aws-sdk/types"; + +/** + * Create a credential provider that reads credentials from the following environment variables: + * + * - `AWS_ACCESS_KEY_ID` - The access key for your AWS account. + * - `AWS_SECRET_ACCESS_KEY` - The secret key for your AWS account. + * - `AWS_SESSION_TOKEN` - The session key for your AWS account. This is only + * needed when you are using temporary credentials. + * - `AWS_CREDENTIAL_EXPIRATION` - The expiration time of the credentials contained + * in the environment variables described above. This value must be in a format + * compatible with the [ISO-8601 standard](https://en.wikipedia.org/wiki/ISO_8601) + * and is only needed when you are using temporary credentials. + * + * If either the `AWS_ACCESS_KEY_ID` or `AWS_SECRET_ACCESS_KEY` environment variable is not set or contains a falsy + * value, the promise returned by the `fromEnv` function will be rejected. + * + * ```javascript + * import { fromEnv } from "@aws-sdk/credential-providers"; // ES6 import + * // const { fromEnv } = require("@aws-sdk/credential-providers"); // CommonJS import + * + * const client = new DynamoDBClient({ + * credentials: fromEnv(), + * }); + * ``` + */ +export const fromEnv = (): CredentialProvider => _fromEnv(); diff --git a/packages/credential-providers/src/fromIni.spec.ts b/packages/credential-providers/src/fromIni.spec.ts new file mode 100644 index 000000000000..ba0346ca3afc --- /dev/null +++ b/packages/credential-providers/src/fromIni.spec.ts @@ -0,0 +1,58 @@ +const ROLE_ASSUMER = "ROLE_ASSUMER"; +const ROLE_ASSUMER_WITH_WEB_IDENTITY = "ROLE_ASSUMER_WITH_WEB_IDENTITY"; + +jest.mock("@aws-sdk/client-sts", () => ({ + getDefaultRoleAssumer: jest.fn().mockReturnValue(ROLE_ASSUMER), + getDefaultRoleAssumerWithWebIdentity: jest.fn().mockReturnValue(ROLE_ASSUMER_WITH_WEB_IDENTITY), +})); + +import { getDefaultRoleAssumer, getDefaultRoleAssumerWithWebIdentity } from "@aws-sdk/client-sts"; +import { fromIni as coreProvider } from "@aws-sdk/credential-provider-ini"; + +import { fromIni } from "./fromIni"; + +jest.mock("@aws-sdk/credential-provider-ini", () => ({ + fromIni: jest.fn(), +})); + +describe("fromIni", () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it("should inject default role assumers", () => { + const profile = "profile"; + fromIni({ profile }); + expect(coreProvider).toBeCalledWith({ + profile, + roleAssumer: ROLE_ASSUMER, + roleAssumerWithWebIdentity: ROLE_ASSUMER_WITH_WEB_IDENTITY, + }); + expect(getDefaultRoleAssumer).toBeCalled(); + expect(getDefaultRoleAssumerWithWebIdentity).toBeCalled(); + }); + + it("should use supplied role assumers", () => { + const profile = "profile"; + const roleAssumer = jest.fn(); + const roleAssumerWithWebIdentity = jest.fn(); + fromIni({ profile, roleAssumer, roleAssumerWithWebIdentity }); + expect(coreProvider).toBeCalledWith({ + profile, + roleAssumer, + roleAssumerWithWebIdentity, + }); + expect(getDefaultRoleAssumer).not.toBeCalled(); + expect(getDefaultRoleAssumerWithWebIdentity).not.toBeCalled(); + }); + + it("should use supplied sts options", () => { + const profile = "profile"; + const clientConfig = { + region: "US_BAR_1", + }; + fromIni({ profile, clientConfig }); + expect(getDefaultRoleAssumer).toBeCalledWith(clientConfig); + expect(getDefaultRoleAssumerWithWebIdentity).toBeCalledWith(clientConfig); + }); +}); diff --git a/packages/credential-providers/src/fromIni.ts b/packages/credential-providers/src/fromIni.ts new file mode 100644 index 000000000000..5b68319b56cd --- /dev/null +++ b/packages/credential-providers/src/fromIni.ts @@ -0,0 +1,51 @@ +import { getDefaultRoleAssumer, getDefaultRoleAssumerWithWebIdentity, STSClientConfig } from "@aws-sdk/client-sts"; +import { fromIni as _fromIni, FromIniInit as _FromIniInit } from "@aws-sdk/credential-provider-ini"; +import { CredentialProvider } from "@aws-sdk/types"; + +export interface FromIniInit extends _FromIniInit { + clientConfig?: STSClientConfig; +} + +/** + * Creates a credential provider function that reads from a shared credentials file at `~/.aws/credentials` and a + * shared configuration file at `~/.aws/config`. Both files are expected to be INI formatted with section names + * corresponding to profiles. Sections in the credentials file are treated as profile names, whereas profile sections in + * the config file must have the format of`[profile profile-name]`, except for the default profile. + * + * Profiles that appear in both files will not be merged, and the version that appears in the credentials file will be + * given precedence over the profile found in the config file. + * + * ```javascript + * import { fromIni } from "@aws-sdk/credential-providers"; // ES6 import + * // const { fromIni } = require("@aws-sdk/credential-providers"); // CommonJS import + * + * const client = new FooClient({ + * credentials: fromIni({ + * // Optional. The configuration profile to use. If not specified, the provider will use the value in the + * // `AWS_PROFILE` environment variable or a default of `default`. + * profile: "profile", + * // Optional. The path to the shared credentials file. If not specified, the provider will use the value in the + * // `AWS_SHARED_CREDENTIALS_FILE` environment variable or a default of `~/.aws/credentials`. + * filepath: "~/.aws/credentials", + * // Optional. The path to the shared config file. If not specified, the provider will use the value in the + * // `AWS_CONFIG_FILE` environment variable or a default of `~/.aws/config`. + * configFilepath: "~/.aws/config", + * // Optional. A function that returns a a promise fulfilled with an MFA token code for the provided MFA Serial + * // code. If a profile requires an MFA code and `mfaCodeProvider` is not a valid function, the credential provider + * // promise will be rejected. + * mfaCodeProvider: async (mfaSerial) => { + * return "token"; + * }, + * // Optional. Custom STS client configurations overriding the default ones. + * clientConfig: { region }, + * }), + * }); + * ``` + */ +export const fromIni = (init: FromIniInit = {}): CredentialProvider => + _fromIni({ + ...init, + roleAssumer: init.roleAssumer ?? getDefaultRoleAssumer(init.clientConfig), + roleAssumerWithWebIdentity: + init.roleAssumerWithWebIdentity ?? getDefaultRoleAssumerWithWebIdentity(init.clientConfig), + }); diff --git a/packages/credential-providers/src/fromInstanceMetadata.ts b/packages/credential-providers/src/fromInstanceMetadata.ts new file mode 100644 index 000000000000..ec8ee1bddb71 --- /dev/null +++ b/packages/credential-providers/src/fromInstanceMetadata.ts @@ -0,0 +1,26 @@ +import { + fromInstanceMetadata as _fromInstanceMetadata, + RemoteProviderConfig as _RemoteProviderInit, +} from "@aws-sdk/credential-provider-imds"; +import { CredentialProvider } from "@aws-sdk/types"; + +/** + * Creates a credential provider function that reads from the EC2 instance metadata service. + * + * ```javascript + * import { fromInstanceMetadata } from "@aws-sdk/credential-providers"; // ES6 import + * // const { fromInstanceMetadata } = require("@aws-sdk/credential-providers"); // CommonJS import + * + * const client = new DynamoDBClient({ + * credentials: fromInstanceMetadata({ + * // Optional. The connection timeout (in milliseconds) to apply to any remote requests. If not specified, a + * // default value of`1000` (one second) is used. + * timeout: 1000, + * // Optional. The maximum number of times any HTTP connections should be retried. If not specified, a default + * // value of `0` will be used. + * maxRetries: 0, + * }), + * }); + * ``` + */ +export const fromInstanceMetadata = (init?: _RemoteProviderInit): CredentialProvider => _fromInstanceMetadata(init); diff --git a/packages/credential-providers/src/fromProcess.ts b/packages/credential-providers/src/fromProcess.ts new file mode 100644 index 000000000000..0010c0c0d9cd --- /dev/null +++ b/packages/credential-providers/src/fromProcess.ts @@ -0,0 +1,29 @@ +import { fromProcess as _fromProcess, FromProcessInit as _FromProcessInit } from "@aws-sdk/credential-provider-process"; +import { CredentialProvider } from "@aws-sdk/types"; + +export interface FromProcessInit extends _FromProcessInit {} + +/** + * Creates a credential provider function that executes a given process and attempt to read its standard output to + * receive a JSON payload containing the credentials. + * + * ```javascript + * import { fromProcess } from "@aws-sdk/credential-providers"; // ES6 import + * // const { fromProcess } = require("@aws-sdk/credential-providers"); // CommonJS import + * + * const client = new FooClient({ + * credentials: fromProcess({ + * // Optional. The configuration profile to use. If not specified, the provider will use the value in the + * // `AWS_PROFILE` environment variable or a default of `default`. + * profile: "profile", + * // Optional. The path to the shared credentials file. If not specified, the provider will use the value in the + * // `AWS_SHARED_CREDENTIALS_FILE` environment variable or a default of `~/.aws/credentials`. + * filepath: "~/.aws/credentials", + * // Optional. The path to the shared config file. If not specified, the provider will use the value in the + * // `AWS_CONFIG_FILE` environment variable or a default of `~/.aws/config`. + * configFilepath: "~/.aws/config", + * }), + * }); + * ``` + */ +export const fromProcess = (init?: FromProcessInit): CredentialProvider => _fromProcess(init); diff --git a/packages/credential-providers/src/fromSSO.spec.ts b/packages/credential-providers/src/fromSSO.spec.ts new file mode 100644 index 000000000000..0179c62f3272 --- /dev/null +++ b/packages/credential-providers/src/fromSSO.spec.ts @@ -0,0 +1,26 @@ +import { SSOClient } from "@aws-sdk/client-sso"; + +import { fromSSO } from "./fromSSO"; + +jest.mock("@aws-sdk/client-sso", () => ({ + SSOClient: jest.fn().mockImplementation(function () { + return "SSO_CLIENT"; + }), +})); + +describe("fromSSO", () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it("should not inject SSO client if no client config supplied", async () => { + fromSSO(); + expect(SSOClient as jest.Mock).not.toBeCalled(); + }); + + it("should inject SSO client if client config is supplied", async () => { + const region = "us-foo-1"; + fromSSO({ clientConfig: { region } }); + expect(SSOClient as jest.Mock).toBeCalledWith({ region }); + }); +}); diff --git a/packages/credential-providers/src/fromSSO.ts b/packages/credential-providers/src/fromSSO.ts new file mode 100644 index 000000000000..10508f075c7c --- /dev/null +++ b/packages/credential-providers/src/fromSSO.ts @@ -0,0 +1,51 @@ +import { SSOClient, SSOClientConfig } from "@aws-sdk/client-sso"; +import { fromSSO as _fromSSO, FromSSOInit as _FromSSOInit } from "@aws-sdk/credential-provider-sso"; +import { CredentialProvider } from "@aws-sdk/types"; + +export interface FromSSOInit extends Omit<_FromSSOInit, "client"> { + clientConfig?: SSOClientConfig; +} + +/** + * Creates a credential provider function that reads from the _resolved_ access token from local disk then requests + * temporary AWS credentials. + * + * You can create the `CredentialProvider` functions using the inline SSO parameters(`ssoStartUrl`, `ssoAccountId`, + * `ssoRegion`, `ssoRoleName`) or load them from [AWS SDKs and Tools shared configuration and credentials files](https://docs.aws.amazon.com/credref/latest/refdocs/creds-config-files.html). + * Profiles in the `credentials` file are given precedence over profiles in the `config` file. + * + * ```javascript + * import { fromSSO } from "@aws-sdk/credential-providers"; // ES6 import + * // const { fromSSO } = require(@aws-sdk/credential-providers") // CommonJS import + * + * const client = new FooClient({ + * credentials: fromSSO({ + * // Optional. The configuration profile to use. If not specified, the provider will use the value in the + * // `AWS_PROFILE` environment variable or `default` by default. + * profile: "my-sso-profile", + * // Optional. The path to the shared credentials file. If not specified, the provider will use the value in the + * // `AWS_SHARED_CREDENTIALS_FILE` environment variable or a default of `~/.aws/credentials`. + * filepath: "~/.aws/credentials", + * // Optional. The path to the shared config file. If not specified, the provider will use the value in the + * // `AWS_CONFIG_FILE` environment variable or a default of `~/.aws/config`. + * configFilepath: "~/.aws/config", + * // Optional. The URL to the AWS SSO service. Required if any of the `sso*` options(except for `ssoClient`) is + * // provided. + * ssoStartUrl: "https://d-abc123.awsapps.com/start", + * // Optional. The ID of the AWS account to use for temporary credentials. Required if any of the `sso*` + * // options(except for `ssoClient`) is provided. + * ssoAccountId: "1234567890", + * // Optional. The AWS region to use for temporary credentials. Required if any of the `sso*` options(except for + * // `ssoClient`) is provided. + * ssoRegion: "us-east-1", + * // Optional. The name of the AWS role to assume. Required if any of the `sso*` options(except for `ssoClient`) is + * // provided. + * ssoRoleName: "SampleRole", + * // Optional. Overwrite the configuration used construct the SSO service client. + * clientConfig: { region }, + * }), + * }); + * ``` + */ +export const fromSSO = (init: FromSSOInit = {}): CredentialProvider => + _fromSSO({ ...{ ssoClient: init.clientConfig ? new SSOClient(init.clientConfig) : undefined }, ...init }); diff --git a/packages/credential-providers/src/fromTemporaryCredentials.spec.ts b/packages/credential-providers/src/fromTemporaryCredentials.spec.ts new file mode 100644 index 000000000000..d5d653678ef9 --- /dev/null +++ b/packages/credential-providers/src/fromTemporaryCredentials.spec.ts @@ -0,0 +1,199 @@ +const sendMock = jest.fn(); +jest.mock("@aws-sdk/client-sts", () => ({ + STSClient: jest.fn().mockImplementation(function (config) { + this.config = config; + this.send = jest.fn().mockImplementation(async function (command) { + // Mock resolving client credentials provider at send() + if (typeof this.config.credentials === "function") this.config.credentials = await this.config.credentials(); + return await sendMock(command); + }); + return this; + }), + AssumeRoleCommand: jest.fn().mockImplementation(function (params) { + // Return the input so we can assert the input parameters in client's send() + return { + input: params, + command: "ASSUME_ROLE", + }; + }), +})); + +import { AssumeRoleCommand, STSClient } from "@aws-sdk/client-sts"; + +import { fromTemporaryCredentials } from "./fromTemporaryCredentials"; + +describe("fromTemporaryCredentials", () => { + const RoleArn = "ROLE_ARN"; + const RoleSessionName = "ROLE_SESSION_NAME"; + const masterCredentials = { + accessKeyId: "ACCESS_KEY_ID", + secretAccessKey: "SECRET_ACCESS_KEY", + }; + const region = "US_BAR_1"; + + beforeEach(() => { + jest.clearAllMocks(); + sendMock.mockResolvedValueOnce({ + Credentials: { + AccessKeyId: "ACCESS_KEY_ID", + SecretAccessKey: "SECRET_ACCESS_KEY", + SessionToken: "SESSION_TOKEN", + }, + }); + }); + + it("should call STS::AssumeRole API with master credentials", async () => { + const options = { + params: { + RoleArn, + RoleSessionName, + }, + masterCredentials, + clientConfig: { region }, + }; + const provider = fromTemporaryCredentials(options); + const credential = await provider(); + expect(credential).toEqual({ + accessKeyId: "ACCESS_KEY_ID", + secretAccessKey: "SECRET_ACCESS_KEY", + sessionToken: "SESSION_TOKEN", + }); + expect(STSClient as jest.Mock).toBeCalledWith({ + credentials: masterCredentials, + region, + }); + expect(AssumeRoleCommand as jest.Mock).toBeCalledWith({ + RoleArn, + RoleSessionName, + }); + expect(sendMock as jest.Mock).toBeCalledWith({ command: "ASSUME_ROLE", input: options.params }); + }); + + it("should create STS client if not supplied", async () => { + const provider = fromTemporaryCredentials({ + params: { + RoleArn, + RoleSessionName, + }, + masterCredentials, + }); + await provider(); + expect(STSClient as jest.Mock).toBeCalledWith({ + credentials: masterCredentials, + }); + }); + + it("should resolve default credentials if master credential is not supplied", async () => { + const provider = fromTemporaryCredentials({ + params: { + RoleArn, + RoleSessionName, + }, + }); + await provider(); + expect(STSClient as jest.Mock).toBeCalledWith({}); + }); + + it("should create a role session name if none provided", async () => { + const provider = fromTemporaryCredentials({ + params: { RoleArn }, + }); + await provider(); + expect(AssumeRoleCommand as jest.Mock).toBeCalledWith({ + RoleArn, + RoleSessionName: expect.stringMatching(/^aws-sdk-js-/), + }); + }); + + it("should allow assume roles assuming roles assuming roles ad infinitum", async () => { + const roleArnOf = (id: string) => `arn:aws:iam::123456789:role/${id}`; + const idOf = (roleArn: string) => roleArn.split("/")?.[1] ?? "UNKNOWN"; + const provider = fromTemporaryCredentials({ + params: { RoleArn: roleArnOf("third") }, + masterCredentials: fromTemporaryCredentials({ + params: { RoleArn: roleArnOf("second") }, + masterCredentials: fromTemporaryCredentials({ + params: { RoleArn: roleArnOf("first") }, + }), + }), + }); + sendMock.mockReset().mockImplementation((mockCommand) => ({ + Credentials: { + AccessKeyId: `access_id_from_${idOf(mockCommand.input.RoleArn)}`, + SecretAccessKey: "SECRET_ACCESS_KEY", + SessionToken: "SESSION_TOKEN", + }, + })); + const credentials = await provider(); + expect(sendMock.mock.calls.length).toBe(3); + expect((AssumeRoleCommand as jest.Mock).mock.calls.length).toBe(3); + expect(credentials.accessKeyId).toBe("access_id_from_third"); + // Creates STS Client with right master credentials and assume role with + // expected role arn. + expect((STSClient as jest.Mock).mock.results.length).toBe(3); + const outmostClient = (STSClient as jest.Mock).mock.results[0].value; + expect(outmostClient.config.credentials).toEqual(expect.objectContaining({ accessKeyId: "access_id_from_second" })); + expect((outmostClient.send as jest.Mock).mock.calls.length).toBe(1); + expect((outmostClient.send as jest.Mock).mock.calls[0][0].input).toEqual( + expect.objectContaining({ RoleArn: roleArnOf("third") }) + ); + + const middleClient = (STSClient as jest.Mock).mock.results[1].value; + expect(middleClient.config.credentials).toEqual(expect.objectContaining({ accessKeyId: "access_id_from_first" })); + expect((middleClient.send as jest.Mock).mock.calls.length).toBe(1); + expect((middleClient.send as jest.Mock).mock.calls[0][0].input).toEqual( + expect.objectContaining({ RoleArn: roleArnOf("second") }) + ); + + const innermostClient = (STSClient as jest.Mock).mock.results[2].value; + expect(innermostClient.config.credentials).toEqual(undefined); + expect((innermostClient.send as jest.Mock).mock.calls.length).toBe(1); + expect((innermostClient.send as jest.Mock).mock.calls[0][0].input).toEqual( + expect.objectContaining({ RoleArn: roleArnOf("first") }) + ); + + // Call assume role API with expected chronological order + expect(sendMock.mock.calls[0][0].input).toEqual(expect.objectContaining({ RoleArn: roleArnOf("first") })); + expect(sendMock.mock.calls[1][0].input).toEqual(expect.objectContaining({ RoleArn: roleArnOf("second") })); + expect(sendMock.mock.calls[2][0].input).toEqual(expect.objectContaining({ RoleArn: roleArnOf("third") })); + + // Should not create extra clients if credentials is still valid + await provider(); + expect((STSClient as jest.Mock).mock.results.length).toBe(3); + }); + + it("should support assuming a role with multi-factor authentication", async () => { + const SerialNumber = "SERIAL_NUMBER"; + const mfaCode = "MFA_CODE"; + const mfaCodeProvider = jest.fn().mockResolvedValue(mfaCode); + const provider = fromTemporaryCredentials({ + params: { RoleArn, SerialNumber, RoleSessionName }, + mfaCodeProvider, + }); + await provider(); + expect(mfaCodeProvider).toBeCalledWith(SerialNumber); + expect(sendMock).toBeCalledWith( + expect.objectContaining({ + input: { + RoleArn, + RoleSessionName, + SerialNumber, + TokenCode: mfaCode, + }, + }) + ); + }); + + it("should reject the promise with a terminal error if a MFA serial presents but mfaCodeProvider is missing", async () => { + const SerialNumber = "SERIAL_NUMBER"; + try { + await fromTemporaryCredentials({ + params: { RoleArn, SerialNumber, RoleSessionName }, + })(); + fail("this test must fail"); + } catch (e) { + expect(e.message).toEqual(expect.stringContaining("Temporary credential requires multi-factor authentication")); + expect(e.tryNextLink).toBe(false); + } + }); +}); diff --git a/packages/credential-providers/src/fromTemporaryCredentials.ts b/packages/credential-providers/src/fromTemporaryCredentials.ts new file mode 100644 index 000000000000..b0dedf0bb29e --- /dev/null +++ b/packages/credential-providers/src/fromTemporaryCredentials.ts @@ -0,0 +1,74 @@ +import { AssumeRoleCommand, AssumeRoleCommandInput, STSClient, STSClientConfig } from "@aws-sdk/client-sts"; +import { CredentialsProviderError } from "@aws-sdk/property-provider"; +import { CredentialProvider, Credentials } from "@aws-sdk/types"; + +export interface FromTemporaryCredentialsOptions { + params: Omit & { RoleSessionName?: string }; + masterCredentials?: Credentials | CredentialProvider; + clientConfig?: STSClientConfig; + mfaCodeProvider?: (mfaSerial: string) => Promise; +} + +/** + * Creates a credential provider function that retrieves temporary credentials from STS AssumeRole API. + * + * ```javascript + * import { fromTemporaryCredentials } from "@aws-sdk/credential-providers"; // ES6 import + * // const { fromTemporaryCredentials } = require("@aws-sdk/credential-providers"); // CommonJS import + * + * const client = new FooClient({ + * region, + * credentials: fromTemporaryCredentials( + * // Optional. The master credentials used to get and refresh temporary credentials from AWS STS. If skipped, it uses + * // the default credential resolved by internal STS client. + * masterCredentials: fromTemporaryCredentials({ + * params: { RoleArn: "arn:aws:iam::1234567890:role/RoleA" } + * }), + * // Required. Options passed to STS AssumeRole operation. + * params: { + * // Required. ARN of role to assume. + * RoleArn: "arn:aws:iam::1234567890:role/RoleB", + * // Optional. An identifier for the assumed role session. If skipped, it generates a random session name with + * // prefix of 'aws-sdk-js-'. + * RoleSessionName: "aws-sdk-js-123", + * // Optional. The duration, in seconds, of the role session. + * DurationSeconds: 3600 + * //... For more options see https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html + * }, + * // Optional. Custom STS client configurations overriding the default ones. + * clientConfig: { region }, + * // Optional. A function that returns a promise fulfilled with an MFA token code for the provided MFA Serial code. + * // Required if `params` has `SerialNumber` config. + * mfaCodeProvider: async mfaSerial => { + * return "token" + * } + * ), + * }); + * ``` + */ +export const fromTemporaryCredentials = (options: FromTemporaryCredentialsOptions): CredentialProvider => { + let stsClient: STSClient; + return async (): Promise => { + const params = { ...options.params, RoleSessionName: options.params.RoleSessionName ?? "aws-sdk-js-" + Date.now() }; + if (params?.SerialNumber) { + if (!options.mfaCodeProvider) { + throw new CredentialsProviderError( + `Temporary credential requires multi-factor authentication,` + ` but no MFA code callback was provided.`, + false + ); + } + params.TokenCode = await options.mfaCodeProvider(params?.SerialNumber); + } + if (!stsClient) stsClient = new STSClient({ ...options.clientConfig, credentials: options.masterCredentials }); + const { Credentials } = await stsClient.send(new AssumeRoleCommand(params)); + if (!Credentials || !Credentials.AccessKeyId || !Credentials.SecretAccessKey) { + throw new CredentialsProviderError(`Invalid response from STS.assumeRole call with role ${params.RoleArn}`); + } + return { + accessKeyId: Credentials.AccessKeyId, + secretAccessKey: Credentials.SecretAccessKey, + sessionToken: Credentials.SessionToken, + expiration: Credentials.Expiration, + }; + }; +}; diff --git a/packages/credential-providers/src/fromTokenFile.spec.ts b/packages/credential-providers/src/fromTokenFile.spec.ts new file mode 100644 index 000000000000..f68bb2551f0f --- /dev/null +++ b/packages/credential-providers/src/fromTokenFile.spec.ts @@ -0,0 +1,41 @@ +const ROLE_ASSUMER_WITH_WEB_IDENTITY = "ROLE_ASSUMER_WITH_WEB_IDENTITY"; + +jest.mock("@aws-sdk/client-sts", () => ({ + getDefaultRoleAssumerWithWebIdentity: jest.fn().mockReturnValue(ROLE_ASSUMER_WITH_WEB_IDENTITY), +})); + +import { getDefaultRoleAssumerWithWebIdentity } from "@aws-sdk/client-sts"; +import { fromTokenFile as coreProvider } from "@aws-sdk/credential-provider-web-identity"; + +import { fromTokenFile } from "./fromTokenFile"; + +jest.mock("@aws-sdk/credential-provider-web-identity", () => ({ + fromTokenFile: jest.fn(), +})); + +describe("fromTokenFile", () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it("should inject default role assumer", () => { + fromTokenFile(); + expect(coreProvider).toBeCalledWith({ + roleAssumerWithWebIdentity: ROLE_ASSUMER_WITH_WEB_IDENTITY, + }); + expect(getDefaultRoleAssumerWithWebIdentity).toBeCalled(); + }); + + it("should supply sts config to role assumer", () => { + const clientConfig = { + region: "US_FOO_0", + }; + fromTokenFile({ + clientConfig, + }); + expect((coreProvider as jest.Mock).mock.calls[0][0]).toMatchObject({ + roleAssumerWithWebIdentity: ROLE_ASSUMER_WITH_WEB_IDENTITY, + }); + expect(getDefaultRoleAssumerWithWebIdentity).toBeCalledWith(clientConfig); + }); +}); diff --git a/packages/credential-providers/src/fromTokenFile.ts b/packages/credential-providers/src/fromTokenFile.ts new file mode 100644 index 000000000000..762464d94e2f --- /dev/null +++ b/packages/credential-providers/src/fromTokenFile.ts @@ -0,0 +1,42 @@ +import { getDefaultRoleAssumerWithWebIdentity, STSClientConfig } from "@aws-sdk/client-sts"; +import { + fromTokenFile as _fromTokenFile, + FromTokenFileInit as _FromTokenFileInit, +} from "@aws-sdk/credential-provider-web-identity"; +import { CredentialProvider } from "@aws-sdk/types"; + +export interface FromTokenFileInit extends _FromTokenFileInit { + clientConfig?: STSClientConfig; +} + +/** + * Creates a credential provider function that reads OIDC token from given file, then call STS.AssumeRoleWithWebIdentity + * API. The configurations must be specified in environmental variables: + * + * - Reads file location of where the OIDC token is stored from either provided option `webIdentityTokenFile` or + * environment variable `AWS_WEB_IDENTITY_TOKEN_FILE`. + * - Reads IAM role wanting to be assumed from either provided option `roleArn` or environment variable `AWS_ROLE_ARN`. + * - Reads optional role session name to be used to distinguish sessions from provided option `roleSessionName` or + * environment variable `AWS_ROLE_SESSION_NAME`. + * If session name is not defined, it comes up with a role session name. + * - Reads OIDC token from file on disk. + * - Calls sts:AssumeRoleWithWebIdentity via `roleAssumerWithWebIdentity` option to get credentials. + * + * ```javascript + * import { fromTokenFile } from "@aws-sdk/credential-providers"; // ES6 import + * // const { fromTokenFile } = require("@aws-sdk/credential-providers"); // CommonJS import + * + * const client = new FooClient({ + * credentials: fromTokenFile({ + * // Optional. STS client config to make the assume role request. + * clientConfig: { region } + * }); + * }); + * ``` + */ +export const fromTokenFile = (init: FromTokenFileInit = {}): CredentialProvider => + _fromTokenFile({ + ...init, + roleAssumerWithWebIdentity: + init.roleAssumerWithWebIdentity ?? getDefaultRoleAssumerWithWebIdentity(init.clientConfig), + }); diff --git a/packages/credential-providers/src/fromWebToken.spec.ts b/packages/credential-providers/src/fromWebToken.spec.ts new file mode 100644 index 000000000000..3cb12338991c --- /dev/null +++ b/packages/credential-providers/src/fromWebToken.spec.ts @@ -0,0 +1,51 @@ +const ROLE_ASSUMER_WITH_WEB_IDENTITY = "ROLE_ASSUMER_WITH_WEB_IDENTITY"; + +jest.mock("@aws-sdk/client-sts", () => ({ + getDefaultRoleAssumerWithWebIdentity: jest.fn().mockReturnValue(ROLE_ASSUMER_WITH_WEB_IDENTITY), +})); + +import { getDefaultRoleAssumerWithWebIdentity } from "@aws-sdk/client-sts"; +import { fromWebToken as coreProvider } from "@aws-sdk/credential-provider-web-identity"; + +import { fromWebToken } from "./fromWebToken"; + +jest.mock("@aws-sdk/credential-provider-web-identity", () => ({ + fromWebToken: jest.fn(), +})); + +describe("fromWebToken", () => { + const roleArn = "ROLE_ARN"; + const webIdentityToken = "WEB_IDENTITY_TOKEN"; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it("should inject default role assumer", () => { + fromWebToken({ + roleArn, + webIdentityToken, + }); + expect(coreProvider).toBeCalledWith({ + roleArn, + webIdentityToken, + roleAssumerWithWebIdentity: ROLE_ASSUMER_WITH_WEB_IDENTITY, + }); + expect(getDefaultRoleAssumerWithWebIdentity).toBeCalled(); + }); + + it("should supply sts config to role assumer", () => { + const clientConfig = { + region: "US_FOO_0", + }; + fromWebToken({ + roleArn, + webIdentityToken, + clientConfig, + }); + expect((coreProvider as jest.Mock).mock.calls[0][0]).toMatchObject({ + roleAssumerWithWebIdentity: ROLE_ASSUMER_WITH_WEB_IDENTITY, + }); + expect(getDefaultRoleAssumerWithWebIdentity).toBeCalledWith(clientConfig); + }); +}); diff --git a/packages/credential-providers/src/fromWebToken.ts b/packages/credential-providers/src/fromWebToken.ts new file mode 100644 index 000000000000..042caf8ceac3 --- /dev/null +++ b/packages/credential-providers/src/fromWebToken.ts @@ -0,0 +1,51 @@ +import { getDefaultRoleAssumerWithWebIdentity, STSClientConfig } from "@aws-sdk/client-sts"; +import { + fromWebToken as _fromWebToken, + FromWebTokenInit as _FromWebTokenInit, +} from "@aws-sdk/credential-provider-web-identity"; +import { CredentialProvider } from "@aws-sdk/types"; + +export interface FromWebTokenInit extends _FromWebTokenInit { + clientConfig?: STSClientConfig; +} + +/** + * Creates a credential provider function that gets credentials calling STS + * AssumeRoleWithWebIdentity API. + * + * ```javascript + * import { fromWebToken } from "@aws-sdk/credential-providers"; // ES6 import + * // const { fromWebToken } = require("@aws-sdk/credential-providers"); // CommonJS import + * + * const dynamodb = new DynamoDBClient({ + * region, + * credentials: fromWebToken({ + * // Required. ARN of the role that the caller is assuming. + * roleArn: "arn:aws:iam::1234567890:role/RoleA", + * // Required. The OAuth 2.0 access token or OpenID Connect ID token that is provided by the identity provider. + * webIdentityToken: await openIdProvider() + * // Optional. Custom STS client configurations overriding the default ones. + * clientConfig: { region } + * // Optional. A function that assumes a role with web identity and returns a promise fulfilled with credentials for + * // the assumed role. + * roleAssumerWithWebIdentity, + * // Optional. An identifier for the assumed role session. + * roleSessionName: "session_123", + * // Optional. The fully qualified host component of the domain name of the identity provider. + * providerId: "graph.facebook.com", + * // Optional. ARNs of the IAM managed policies that you want to use as managed session. + * policyArns: [{arn: "arn:aws:iam::1234567890:policy/SomePolicy"}], + * // Optional. An IAM policy in JSON format that you want to use as an inline session policy. + * policy: "JSON_STRING", + * // Optional. The duration, in seconds, of the role session. Default to 3600. + * durationSeconds: 7200 + * }), + * }); + * ``` + */ +export const fromWebToken = (init: FromWebTokenInit): CredentialProvider => + _fromWebToken({ + ...init, + roleAssumerWithWebIdentity: + init.roleAssumerWithWebIdentity ?? getDefaultRoleAssumerWithWebIdentity(init.clientConfig), + }); diff --git a/packages/credential-providers/src/index.ts b/packages/credential-providers/src/index.ts new file mode 100644 index 000000000000..edde0870f755 --- /dev/null +++ b/packages/credential-providers/src/index.ts @@ -0,0 +1,11 @@ +export * from "./fromCognitoIdentity"; +export * from "./fromCognitoIdentityPool"; +export * from "./fromEnv"; +export * from "./fromContainerMetadata"; +export * from "./fromInstanceMetadata"; +export * from "./fromIni"; +export * from "./fromProcess"; +export * from "./fromSSO"; +export * from "./fromTokenFile"; +export * from "./fromWebToken"; +export * from "./fromTemporaryCredentials"; diff --git a/packages/credential-providers/tsconfig.cjs.json b/packages/credential-providers/tsconfig.cjs.json new file mode 100644 index 000000000000..67f09ddd4138 --- /dev/null +++ b/packages/credential-providers/tsconfig.cjs.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "declarationDir": "./dist/types", + "rootDir": "./src", + "outDir": "./dist/cjs", + "baseUrl": "." + }, + "extends": "../../tsconfig.cjs.json", + "include": ["src/"] +} diff --git a/packages/credential-providers/tsconfig.es.json b/packages/credential-providers/tsconfig.es.json new file mode 100644 index 000000000000..a6e910d7020a --- /dev/null +++ b/packages/credential-providers/tsconfig.es.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "lib": ["es5", "es2015.promise", "es2015.collection"], + "declarationDir": "./dist/types", + "rootDir": "./src", + "outDir": "./dist/es", + "baseUrl": "." + }, + "extends": "../../tsconfig.es.json", + "include": ["src/"] +} diff --git a/scripts/generate-clients/index.js b/scripts/generate-clients/index.js index 128df68ddaf9..ef3fb695a166 100644 --- a/scripts/generate-clients/index.js +++ b/scripts/generate-clients/index.js @@ -48,7 +48,7 @@ const { await prettifyCode(CODE_GEN_PROTOCOL_TESTS_OUTPUT_DIR); await copyServerTests(CODE_GEN_PROTOCOL_TESTS_OUTPUT_DIR, PROTOCOL_TESTS_CLIENTS_DIR); - // emptyDirSync(CODE_GEN_PROTOCOL_TESTS_OUTPUT_DIR); + emptyDirSync(CODE_GEN_PROTOCOL_TESTS_OUTPUT_DIR); emptyDirSync(TEMP_CODE_GEN_INPUT_DIR); rmdirSync(TEMP_CODE_GEN_INPUT_DIR);