Skip to content

Commit 1788e95

Browse files
committed
test(credential-providers): more tests
1 parent 444d7bd commit 1788e95

19 files changed

+620
-232
lines changed

packages/credential-provider-node/src/runtime/memoize-chain.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ describe("memoize runtime config aware AWS credential chain", () => {
88
let staticCredentials!: RuntimeConfigAwsCredentialIdentityProvider;
99
let expiringCredentials!: RuntimeConfigAwsCredentialIdentityProvider;
1010

11-
const expiration = new Date();
11+
const expiration = new Date(Date.now() + 5_000);
1212

1313
beforeEach(() => {
1414
vi.resetAllMocks();

packages/credential-provider-node/src/runtime/memoize-chain.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ export function memoizeChain(
3434
if (options?.forceRefresh) {
3535
return await chain(options);
3636
}
37+
if (credentials?.expiration) {
38+
if (credentials?.expiration?.getTime() < Date.now()) {
39+
credentials = undefined;
40+
}
41+
}
3742
if (activeLock) {
3843
await activeLock;
3944
} else if (!credentials || treatAsExpired?.(credentials!)) {

packages/credential-provider-node/tests/credential-provider-node.integ.spec.ts

Lines changed: 1 addition & 179 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@ import {
44
fromCognitoIdentity,
55
fromCognitoIdentityPool,
66
fromIni,
7-
fromNodeProviderChain,
87
fromTokenFile,
98
fromWebToken,
109
} from "@aws-sdk/credential-providers";
11-
import { MockNodeHttpHandler, assumeRoleArns } from "@aws-sdk/credential-providers/tests/_test-lib.spec";
10+
import { assumeRoleArns, MockNodeHttpHandler } from "@aws-sdk/credential-providers/tests/_test-lib.spec";
1211
import { NodeHttpHandler } from "@smithy/node-http-handler";
1312
import { externalDataInterceptor } from "@smithy/shared-ini-file-loader";
1413
import type { HttpRequest, MiddlewareStack, ParsedIniData } from "@smithy/types";
@@ -19,7 +18,6 @@ import { homedir } from "node:os";
1918
import { join } from "node:path";
2019
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test as it, vi } from "vitest";
2120

22-
// eslint-disable-next-line no-restricted-imports
2321
import { defaultProvider } from "../src/defaultProvider";
2422

2523
describe("credential-provider-node integration test", () => {
@@ -1510,181 +1508,5 @@ describe("credential-provider-node integration test", () => {
15101508
});
15111509
});
15121510
});
1513-
1514-
describe("STS region logic", () => {
1515-
type Parameters = {
1516-
// has caller context client
1517-
withCaller: boolean;
1518-
// has region specified on the caller client
1519-
codeRegion: boolean;
1520-
// AWS_REGION is set
1521-
envRegion: boolean;
1522-
// profile regions are set
1523-
profileRegion: boolean;
1524-
// provider itself has a clientConfig.region
1525-
providerRegion: boolean;
1526-
// profile name
1527-
profile: string | undefined;
1528-
};
1529-
1530-
function serializeParams(params: Parameters) {
1531-
let buffer = "";
1532-
for (const [key, value] of Object.entries(params)) {
1533-
if (typeof value === "boolean") {
1534-
if (value) {
1535-
buffer += ` ${key},`;
1536-
}
1537-
} else {
1538-
buffer += ` ${key} = ${value},`;
1539-
}
1540-
}
1541-
return buffer;
1542-
}
1543-
1544-
for (const withCaller of [true, false]) {
1545-
for (const codeRegion of [true, false]) {
1546-
for (const envRegion of [true, false]) {
1547-
for (const profileRegion of [true, false]) {
1548-
for (const providerRegion of [true, false]) {
1549-
for (const profile of ["default", "alt", undefined]) {
1550-
if (!codeRegion && !profileRegion && !envRegion) {
1551-
continue;
1552-
}
1553-
1554-
const params = {
1555-
withCaller,
1556-
codeRegion,
1557-
envRegion,
1558-
profileRegion,
1559-
providerRegion,
1560-
profile,
1561-
};
1562-
1563-
it(`${serializeParams(params)}`, async () => {
1564-
const region = await resolveStsRegion(params);
1565-
1566-
if (providerRegion) {
1567-
expect(region).toBe("provider-region");
1568-
return;
1569-
}
1570-
1571-
if (profileRegion) {
1572-
expect(region).toBe(`${profile ?? "default"}-profile-region`);
1573-
return;
1574-
}
1575-
1576-
if (codeRegion && withCaller) {
1577-
expect(region).toBe("code-region");
1578-
return;
1579-
}
1580-
1581-
if (envRegion) {
1582-
expect(region).toBe("env-region");
1583-
return;
1584-
}
1585-
1586-
expect(region).toBe("us-east-1");
1587-
});
1588-
}
1589-
}
1590-
}
1591-
}
1592-
}
1593-
}
1594-
1595-
async function resolveStsRegion({
1596-
withCaller,
1597-
envRegion,
1598-
profile,
1599-
profileRegion,
1600-
codeRegion,
1601-
providerRegion,
1602-
}: Parameters) {
1603-
if (envRegion) {
1604-
process.env.AWS_REGION = "env-region";
1605-
} else {
1606-
delete process.env.AWS_REGION;
1607-
}
1608-
1609-
if (profileRegion) {
1610-
iniProfileData = {
1611-
default: {
1612-
region: "default-profile-region",
1613-
role_arn: "ROLE_ARN",
1614-
role_session_name: "ROLE_SESSION_NAME",
1615-
external_id: "EXTERNAL_ID",
1616-
source_profile: "assume",
1617-
},
1618-
assume: {
1619-
region: "assume-profile-region",
1620-
aws_access_key_id: "ASSUME_STATIC_ACCESS_KEY",
1621-
aws_secret_access_key: "ASSUME_STATIC_SECRET_KEY",
1622-
},
1623-
alt: {
1624-
region: "alt-profile-region",
1625-
role_arn: "ROLE_ARN",
1626-
role_session_name: "ROLE_SESSION_NAME",
1627-
external_id: "EXTERNAL_ID",
1628-
source_profile: "assume2",
1629-
},
1630-
assume2: {
1631-
region: "assume2-profile-region",
1632-
aws_access_key_id: "ASSUME_STATIC_ACCESS_KEY",
1633-
aws_secret_access_key: "ASSUME_STATIC_SECRET_KEY",
1634-
},
1635-
};
1636-
} else {
1637-
iniProfileData = {
1638-
default: {
1639-
role_arn: "ROLE_ARN",
1640-
role_session_name: "ROLE_SESSION_NAME",
1641-
external_id: "EXTERNAL_ID",
1642-
source_profile: "assume",
1643-
},
1644-
assume: {
1645-
aws_access_key_id: "ASSUME_STATIC_ACCESS_KEY",
1646-
aws_secret_access_key: "ASSUME_STATIC_SECRET_KEY",
1647-
},
1648-
alt: {
1649-
role_arn: "ROLE_ARN",
1650-
role_session_name: "ROLE_SESSION_NAME",
1651-
external_id: "EXTERNAL_ID",
1652-
source_profile: "assume2",
1653-
},
1654-
assume2: {
1655-
aws_access_key_id: "ASSUME_STATIC_ACCESS_KEY",
1656-
aws_secret_access_key: "ASSUME_STATIC_SECRET_KEY",
1657-
},
1658-
};
1659-
}
1660-
setIniProfileData(iniProfileData);
1661-
1662-
if (withCaller) {
1663-
const sts = new STS({
1664-
profile,
1665-
region: codeRegion ? "code-region" : undefined,
1666-
credentials: fromNodeProviderChain({
1667-
clientConfig: {
1668-
region: providerRegion ? "provider-region" : undefined,
1669-
},
1670-
}),
1671-
});
1672-
1673-
await sts.getCallerIdentity({});
1674-
const credentials = await sts.config.credentials();
1675-
return credentials.sessionToken!.replace("STS_AR_SESSION_TOKEN_", "");
1676-
}
1677-
1678-
const provider = fromNodeProviderChain({
1679-
profile,
1680-
clientConfig: {
1681-
region: providerRegion ? "provider-region" : undefined,
1682-
},
1683-
});
1684-
1685-
const credentials = await provider();
1686-
return credentials.sessionToken!.replace("STS_AR_SESSION_TOKEN_", "");
1687-
}
1688-
});
16891511
});
16901512
});

packages/credential-providers/src/fromSSO.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,6 @@ import { AwsCredentialIdentityProvider } from "@smithy/types";
4444
*
4545
* @public
4646
*/
47-
export const fromSSO = (init: FromSSOInit = {}): AwsCredentialIdentityProvider => {
47+
export const fromSSO = (init: Parameters<typeof _fromSSO>[0] = {}): AwsCredentialIdentityProvider => {
4848
return _fromSSO({ ...init });
4949
};

packages/credential-providers/tests/_test-lib.spec.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { S3 } from "@aws-sdk/client-s3";
2+
import { fromSSO } from "@aws-sdk/credential-providers";
3+
import { warning } from "@aws-sdk/region-config-resolver";
24
import { ParsedIniData, RuntimeConfigAwsCredentialIdentityProvider } from "@aws-sdk/types";
35
import { NodeHttpHandler } from "@smithy/node-http-handler";
46
import { HttpResponse } from "@smithy/protocol-http";
@@ -9,14 +11,10 @@ import { createHash } from "node:crypto";
911
import { homedir } from "node:os";
1012
import { join } from "node:path";
1113
import { PassThrough } from "node:stream";
12-
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, test as it } from "vitest";
13-
import { fromSSO } from "@aws-sdk/credential-providers";
14-
15-
describe("placeholder for testing lib", () => {
16-
it("", () => {});
17-
});
14+
import { afterAll, afterEach, beforeAll, beforeEach, expect, test as it } from "vitest";
1815

1916
export const assumeRoleArns: string[] = [];
17+
warning.silence = true;
2018
let iniProfileData: ParsedIniData = null as any;
2119

2220
export type CredentialTestParameters = {
@@ -52,13 +50,13 @@ export class CTest<P extends (init?: any) => RuntimeConfigAwsCredentialIdentityP
5250
fallbackRegion,
5351
}: {
5452
credentialProvider: P;
55-
providerParams: (testParams: CredentialTestParameters) => Parameters<P>[0];
53+
providerParams?: (testParams: CredentialTestParameters) => Parameters<P>[0];
5654
profileCredentials?: boolean;
5755
filter?: (testParams: CredentialTestParameters) => boolean;
5856
fallbackRegion?: string;
5957
}) {
6058
this.credentialProvider = credentialProvider;
61-
this.providerParams = providerParams;
59+
this.providerParams = providerParams ?? CTest.defaultRegionConfigProvider;
6260
this.profileCredentials = !!profileCredentials;
6361
this.filter = filter ?? (() => true);
6462
this.fallbackRegion = fallbackRegion ?? "unresolved";
@@ -354,7 +352,7 @@ export class MockNodeHttpHandler {
354352

355353
const region = (request.hostname.match(/(sts|cognito-identity|portal\.sso)\.(.*?)\./) || [, , "unknown"])[2];
356354

357-
if (request.headers.Authorization === "container-authorization") {
355+
if (request.headers.Authorization === "container-authorization" || request.hostname === "169.254.170.23") {
358356
body.write(
359357
JSON.stringify({
360358
AccessKeyId: "CONTAINER_ACCESS_KEY",
@@ -446,6 +444,7 @@ export class MockNodeHttpHandler {
446444
console.log(request);
447445
throw new Error("request not supported.");
448446
}
447+
449448
body.end();
450449
return {
451450
response: new HttpResponse({

packages/credential-providers/tests/fromCognitoIdentity.integ.spec.ts

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
import { S3 } from "@aws-sdk/client-s3";
12
import { fromCognitoIdentity } from "@aws-sdk/credential-providers";
2-
import { describe } from "vitest";
3+
import { describe, expect, test as it } from "vitest";
34

45
import { CTest } from "./_test-lib.spec";
56

@@ -17,4 +18,38 @@ describe(fromCognitoIdentity.name, () => {
1718
});
1819

1920
ctest.testRegion();
21+
22+
describe("configure from env", () => {
23+
it("is not configurable from env", async () => {
24+
expect("ok").toBeTruthy();
25+
});
26+
});
27+
28+
describe("configure from profile", () => {
29+
it("is not configurable from profile", async () => {
30+
expect("ok").toBeTruthy();
31+
});
32+
});
33+
34+
describe("configure from code", () => {
35+
it("should be configurable from code", async () => {
36+
const s3 = new S3({
37+
region: "us-east-2",
38+
credentials: fromCognitoIdentity({
39+
identityId: "us-east-2:128d0a74-c82f-4553-916d-90053example",
40+
}),
41+
});
42+
await s3.listBuckets();
43+
expect(await s3.config.credentials()).toEqual({
44+
$source: {
45+
CREDENTIALS_CODE: "e",
46+
},
47+
accessKeyId: "COGNITO_ACCESS_KEY_ID",
48+
expiration: new Date("3000-01-01T00:00:00.000Z"),
49+
identityId: "us-east-2:128d0a74-c82f-4553-916d-90053example",
50+
secretAccessKey: "COGNITO_SECRET_KEY",
51+
sessionToken: "COGNITO_SESSION_TOKEN_us-east-2",
52+
});
53+
});
54+
});
2055
});

packages/credential-providers/tests/fromCognitoIdentityPool.integ.spec.ts

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
import { S3 } from "@aws-sdk/client-s3";
12
import { fromCognitoIdentityPool } from "@aws-sdk/credential-providers";
2-
import { describe } from "vitest";
3+
import { describe, expect, test as it } from "vitest";
34

45
import { CTest } from "./_test-lib.spec";
56

@@ -17,4 +18,38 @@ describe(fromCognitoIdentityPool.name, () => {
1718
});
1819

1920
ctest.testRegion();
21+
22+
describe("configure from env", () => {
23+
it("is not configurable from env", async () => {
24+
expect("ok").toBeTruthy();
25+
});
26+
});
27+
28+
describe("configure from profile", () => {
29+
it("is not configurable from profile", async () => {
30+
expect("ok").toBeTruthy();
31+
});
32+
});
33+
34+
describe("configure from code", () => {
35+
it("should be configurable from code", async () => {
36+
const s3 = new S3({
37+
region: "us-east-2",
38+
credentials: fromCognitoIdentityPool({
39+
identityPoolId: "us-east-2:COGNITO_IDENTITY_ID",
40+
}),
41+
});
42+
await s3.listBuckets();
43+
expect(await s3.config.credentials()).toEqual({
44+
$source: {
45+
CREDENTIALS_CODE: "e",
46+
},
47+
accessKeyId: "COGNITO_ACCESS_KEY_ID",
48+
expiration: new Date("3000-01-01T00:00:00.000Z"),
49+
identityId: "us-east-2:COGNITO_IDENTITY_ID",
50+
secretAccessKey: "COGNITO_SECRET_KEY",
51+
sessionToken: "COGNITO_SESSION_TOKEN_us-east-2",
52+
});
53+
});
54+
});
2055
});

0 commit comments

Comments
 (0)