Skip to content

Commit e5dd3e9

Browse files
committed
modifying test to ensure credential chain resolves in intended order
1 parent 85b716b commit e5dd3e9

File tree

2 files changed

+150
-24
lines changed

2 files changed

+150
-24
lines changed

packages/credential-providers/src/fromAwsCliV2CompatibleProviderChain.spec.ts

Lines changed: 148 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -63,17 +63,40 @@ describe("fromAwsCliV2CompatibleProviderChain", () => {
6363
accessKeyId: "PROFILE_ACCESS_KEY",
6464
secretAccessKey: "PROFILE_SECRET_KEY",
6565
});
66+
expect(mockFromIni).toHaveBeenCalled();
6667
expect(mockLogger.debug).toHaveBeenCalledWith(expect.stringContaining("Using fromIni with profile:test-profile"));
6768
});
6869

69-
it("should try credential chain when no static credentials or profile", async () => {
70+
it("should merge caller client config with init options", async () => {
71+
// Initial credentials
72+
const credentials = {
73+
accessKeyId: "TEST_ACCESS_KEY",
74+
secretAccessKey: "TEST_SECRET_KEY",
75+
};
76+
77+
const provider = fromAwsCliV2CompatibleProviderChain(credentials);
78+
const callerConfig = {
79+
profile: "caller-profile",
80+
logger: mockLogger,
81+
region: mockRegion,
82+
};
83+
84+
const result = await provider({ callerClientConfig: callerConfig });
85+
86+
expect(result).toEqual(credentials);
87+
expect(mockLogger.debug).toHaveBeenCalled();
88+
});
89+
90+
it("should fall back to environment variables if no profile is provided", async () => {
7091
const mockEnvCredentials = {
7192
accessKeyId: "ENV_ACCESS_KEY",
7293
secretAccessKey: "ENV_SECRET_KEY",
7394
};
7495

96+
const mockFromEnv = vi.fn(() => vi.fn(async () => mockEnvCredentials));
97+
7598
vi.mock("@aws-sdk/credential-provider-env", () => ({
76-
fromEnv: () => () => Promise.resolve(mockEnvCredentials),
99+
fromEnv: mockFromEnv,
77100
}));
78101

79102
const provider = fromAwsCliV2CompatibleProviderChain({
@@ -83,11 +106,98 @@ describe("fromAwsCliV2CompatibleProviderChain", () => {
83106
const result = await provider();
84107

85108
expect(result).toEqual(mockEnvCredentials);
109+
expect(mockFromEnv).toHaveBeenCalled();
86110
expect(mockLogger.debug).toHaveBeenCalledWith(expect.stringContaining("Using from custom credential chain"));
87111
});
88112

89-
it("should throw error when no credentials are found", async () => {
90-
// Mock all providers to fail
113+
it("should fall back to web identity credentials when environment variables are unavailable", async () => {
114+
vi.mock("@aws-sdk/credential-provider-env", () => ({
115+
fromEnv: () => () => Promise.reject(new Error("No env credentials")),
116+
}));
117+
118+
const mockTokenFileCredentials = {
119+
accessKeyId: "TOKEN_ACCESS_KEY",
120+
secretAccessKey: "TOKEN_SECRET_KEY",
121+
};
122+
123+
const mockFromTokenFile = vi.fn(() => vi.fn(async () => mockTokenFileCredentials));
124+
125+
vi.mock("@aws-sdk/credential-provider-web-identity", () => ({
126+
fromTokenFile: mockFromTokenFile,
127+
}));
128+
129+
const provider = fromAwsCliV2CompatibleProviderChain({
130+
logger: mockLogger,
131+
});
132+
133+
const result = await provider();
134+
135+
expect(result).toEqual(mockTokenFileCredentials);
136+
expect(mockFromTokenFile).toHaveBeenCalled();
137+
});
138+
139+
it("should fall back to SSO credentials when web identity is unavailable", async () => {
140+
vi.mock("@aws-sdk/credential-provider-env", () => ({
141+
fromEnv: () => () => Promise.reject(new Error("No env credentials")),
142+
}));
143+
vi.mock("@aws-sdk/credential-provider-web-identity", () => ({
144+
fromTokenFile: () => () => Promise.reject(new Error("No token file")),
145+
}));
146+
147+
const mockSSOCredentials = {
148+
accessKeyId: "SSO_ACCESS_KEY",
149+
secretAccessKey: "SSO_SECRET_KEY",
150+
};
151+
152+
const mockFromSSO = vi.fn(() => vi.fn(async () => mockSSOCredentials));
153+
154+
vi.mock("@aws-sdk/credential-provider-sso", () => ({
155+
fromSSO: mockFromSSO,
156+
}));
157+
158+
const provider = fromAwsCliV2CompatibleProviderChain({
159+
logger: mockLogger,
160+
});
161+
162+
const result = await provider();
163+
164+
expect(result).toEqual(mockSSOCredentials);
165+
expect(mockFromSSO).toHaveBeenCalled();
166+
});
167+
168+
it("should fall back to process credentials when SSO is unavailable", async () => {
169+
vi.mock("@aws-sdk/credential-provider-env", () => ({
170+
fromEnv: () => () => Promise.reject(new Error("No env credentials")),
171+
}));
172+
vi.mock("@aws-sdk/credential-provider-web-identity", () => ({
173+
fromTokenFile: () => () => Promise.reject(new Error("No token file")),
174+
}));
175+
vi.mock("@aws-sdk/credential-provider-sso", () => ({
176+
fromSSO: () => () => Promise.reject(new Error("No SSO credentials")),
177+
}));
178+
179+
const mockProcessCredentials = {
180+
accessKeyId: "PROCESS_ACCESS_KEY",
181+
secretAccessKey: "PROCESS_SECRET_KEY",
182+
};
183+
184+
const mockFromProcess = vi.fn(() => vi.fn(async () => mockProcessCredentials));
185+
186+
vi.mock("@aws-sdk/credential-provider-process", () => ({
187+
fromProcess: mockFromProcess,
188+
}));
189+
190+
const provider = fromAwsCliV2CompatibleProviderChain({
191+
logger: mockLogger,
192+
});
193+
194+
const result = await provider();
195+
196+
expect(result).toEqual(mockProcessCredentials);
197+
expect(mockFromProcess).toHaveBeenCalled();
198+
});
199+
200+
it("should fall back to remote credentials when process credentials are unavailable", async () => {
91201
vi.mock("@aws-sdk/credential-provider-env", () => ({
92202
fromEnv: () => () => Promise.reject(new Error("No env credentials")),
93203
}));
@@ -100,35 +210,51 @@ describe("fromAwsCliV2CompatibleProviderChain", () => {
100210
vi.mock("@aws-sdk/credential-provider-process", () => ({
101211
fromProcess: () => () => Promise.reject(new Error("No process credentials")),
102212
}));
213+
214+
const mockRemoteCredentials = {
215+
accessKeyId: "REMOTE_ACCESS_KEY",
216+
secretAccessKey: "REMOTE_SECRET_KEY",
217+
};
218+
219+
const mockRemoteProvider = vi.fn(() => vi.fn(async () => mockRemoteCredentials));
220+
103221
vi.mock("@aws-sdk/credential-provider-node/src/remoteProvider", () => ({
104-
remoteProvider: () => () => Promise.reject(new Error("No remote credentials")),
222+
remoteProvider: mockRemoteProvider,
105223
}));
106224

107225
const provider = fromAwsCliV2CompatibleProviderChain({
108226
logger: mockLogger,
109227
});
110228

111-
await expect(provider()).rejects.toThrow(CredentialsProviderError);
112-
await expect(provider()).rejects.toThrow("Could not load credentials from any providers");
229+
const result = await provider();
230+
231+
expect(result).toEqual(mockRemoteCredentials);
232+
expect(mockRemoteProvider).toHaveBeenCalled();
113233
});
114234

115-
it("should merge caller client config with init options", async () => {
116-
// Initial credentials
117-
const credentials = {
118-
accessKeyId: "TEST_ACCESS_KEY",
119-
secretAccessKey: "TEST_SECRET_KEY",
120-
};
235+
it("should throw error when no credentials are found", async () => {
236+
// Mock all providers to fail
237+
vi.mock("@aws-sdk/credential-provider-env", () => ({
238+
fromEnv: () => () => Promise.reject(new Error("No env credentials")),
239+
}));
240+
vi.mock("@aws-sdk/credential-provider-web-identity", () => ({
241+
fromTokenFile: () => () => Promise.reject(new Error("No token file")),
242+
}));
243+
vi.mock("@aws-sdk/credential-provider-sso", () => ({
244+
fromSSO: () => () => Promise.reject(new Error("No SSO credentials")),
245+
}));
246+
vi.mock("@aws-sdk/credential-provider-process", () => ({
247+
fromProcess: () => () => Promise.reject(new Error("No process credentials")),
248+
}));
249+
vi.mock("@aws-sdk/credential-provider-node/src/remoteProvider", () => ({
250+
remoteProvider: () => () => Promise.reject(new Error("No remote credentials")),
251+
}));
121252

122-
const provider = fromAwsCliV2CompatibleProviderChain(credentials);
123-
const callerConfig = {
124-
profile: "caller-profile",
253+
const provider = fromAwsCliV2CompatibleProviderChain({
125254
logger: mockLogger,
126-
region: mockRegion,
127-
};
128-
129-
const result = await provider({ callerClientConfig: callerConfig });
255+
});
130256

131-
expect(result).toEqual(credentials);
132-
expect(mockLogger.debug).toHaveBeenCalled();
257+
await expect(provider()).rejects.toThrow(CredentialsProviderError);
258+
await expect(provider()).rejects.toThrow("Could not load credentials from any providers");
133259
});
134260
});

packages/credential-providers/src/resolveAwsCliV2Region.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ vi.mock("@smithy/shared-ini-file-loader", () => ({
1212

1313
describe("AWS Region Resolution", () => {
1414
// Store original environment variables to restore them later
15-
const originalEnv = process.env;
15+
const originalEnv = { ...process.env };
1616

1717
beforeEach(() => {
1818
// Reset environment variables before each test
@@ -23,7 +23,7 @@ describe("AWS Region Resolution", () => {
2323

2424
afterEach(() => {
2525
// Restore environment variables after each test
26-
process.env = originalEnv;
26+
process.env = { ...originalEnv };
2727
});
2828

2929
describe("resolveAwsCliV2Region", () => {

0 commit comments

Comments
 (0)