Skip to content

Commit 0debb4f

Browse files
committed
test: more scenarios
1 parent 97849bc commit 0debb4f

File tree

1 file changed

+244
-46
lines changed

1 file changed

+244
-46
lines changed

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

Lines changed: 244 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,121 @@ import type { SourceProfileInit } from "@smithy/shared-ini-file-loader";
44
import type { HttpRequest, NodeHttpHandlerOptions, ParsedIniData } from "@smithy/types";
55
import { Readable } from "stream";
66

7+
import { defaultProvider } from "./defaultProvider";
8+
9+
jest.mock("fs", () => {
10+
const actual = jest.requireActual("fs");
11+
return {
12+
...actual,
13+
readFileSync(file: string, ...options: any[]) {
14+
if (file === "token-filepath") {
15+
return "token-contents";
16+
}
17+
return actual.readFileSync(file, ...options);
18+
},
19+
};
20+
});
21+
722
let iniProfileData: ParsedIniData = null as any;
823
jest.mock("@smithy/shared-ini-file-loader", () => {
9-
const smithySharedIniFileLoader = jest.requireActual("@smithy/shared-ini-file-loader");
24+
const actual = jest.requireActual("@smithy/shared-ini-file-loader");
1025
return {
11-
...smithySharedIniFileLoader,
12-
parseKnownFiles: async (init: SourceProfileInit): Promise<ParsedIniData> => {
26+
...actual,
27+
async loadSsoSessionData() {
28+
return Object.entries(iniProfileData)
29+
.filter(([key]) => key.startsWith("sso-session."))
30+
.reduce(
31+
(acc, [key, value]) => ({
32+
...acc,
33+
[key.split("sso-session.")[1]]: value,
34+
}),
35+
{}
36+
);
37+
},
38+
async parseKnownFiles(init: SourceProfileInit): Promise<ParsedIniData> {
1339
return iniProfileData;
1440
},
41+
async getSSOTokenFromFile() {
42+
return {
43+
accessToken: "mock_sso_token",
44+
expiresAt: new Date("3000/1/1").toISOString(),
45+
};
46+
},
47+
};
48+
});
49+
50+
jest.mock("@aws-sdk/client-sso", () => {
51+
const actual = jest.requireActual("@aws-sdk/client-sso");
52+
return {
53+
...actual,
54+
SSOClient: class {
55+
async send() {
56+
return {
57+
roleCredentials: {
58+
accessKeyId: "SSO_ACCESS_KEY_ID",
59+
secretAccessKey: "SSO_SECRET_ACCESS_KEY",
60+
sessionToken: "SSO_SESSION_TOKEN",
61+
expiration: new Date("3000/1/1"),
62+
credentialScope: "us-sso-1",
63+
},
64+
};
65+
}
66+
},
67+
};
68+
});
69+
70+
jest.mock("@aws-sdk/client-sts", () => {
71+
const actual = jest.requireActual("@aws-sdk/client-sts");
72+
return {
73+
...actual,
74+
getDefaultRoleAssumer() {
75+
return async () => {
76+
return {
77+
accessKeyId: "STS_AR_ACCESS_KEY_ID",
78+
secretAccessKey: "STS_AR_SECRET_ACCESS_KEY",
79+
sessionToken: "STS_AR_SESSION_TOKEN",
80+
expiration: new Date("3000/1/1"),
81+
credentialScope: "us-stsar-1",
82+
};
83+
};
84+
},
85+
getDefaultRoleAssumerWithWebIdentity() {
86+
return async () => {
87+
return {
88+
accessKeyId: "STS_ARWI_ACCESS_KEY_ID",
89+
secretAccessKey: "STS_ARWI_SECRET_ACCESS_KEY",
90+
sessionToken: "STS_ARWI_SESSION_TOKEN",
91+
expiration: new Date("3000/1/1"),
92+
credentialScope: "us-stsarwi-1",
93+
};
94+
};
95+
},
96+
STSClient: class {
97+
async send(command: any) {
98+
if (command.constructor.name === "AssumeRoleCommand") {
99+
return {
100+
Credentials: {
101+
AccessKeyId: "STS_AR_ACCESS_KEY_ID",
102+
SecretAccessKey: "STS_AR_SECRET_ACCESS_KEY",
103+
SessionToken: "STS_AR_SESSION_TOKEN",
104+
Expiration: new Date("3000/1/1"),
105+
CredentialScope: "us-stsar-1",
106+
},
107+
};
108+
}
109+
if (command.constructor.name === "AssumeRoleWithWebIdentityCommand") {
110+
return {
111+
Credentials: {
112+
AccessKeyId: "STS_ARWI_ACCESS_KEY_ID",
113+
SecretAccessKey: "STS_ARWI_SECRET_ACCESS_KEY",
114+
SessionToken: "STS_ARWI_SESSION_TOKEN",
115+
Expiration: new Date("3000/1/1"),
116+
CredentialScope: "us-stsarwi-1",
117+
},
118+
};
119+
}
120+
}
121+
},
15122
};
16123
});
17124

@@ -34,41 +141,43 @@ describe("credential-provider-node integration test", () => {
34141
return JSON.parse(JSON.stringify(data));
35142
}
36143

144+
const mockRequestHandler = new (class {
145+
async handle(request: HttpRequest, ignored?: any) {
146+
const body = new Readable();
147+
body.push(`
148+
<GetCallerIdentityResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
149+
<GetCallerIdentityResult>
150+
<Arn>arn:aws:iam::123456789012:user/Alice</Arn>
151+
<UserId>AIDACKCEVSQ6C2EXAMPLE</UserId>
152+
<Account>123456789012</Account>
153+
</GetCallerIdentityResult>
154+
<ResponseMetadata>
155+
<RequestId>01234567-89ab-cdef-0123-456789abcdef</RequestId>
156+
</ResponseMetadata>
157+
</GetCallerIdentityResponse>
158+
`);
159+
body.push(null);
160+
return {
161+
response: new HttpResponse({
162+
statusCode: 200,
163+
headers: {},
164+
body,
165+
}),
166+
};
167+
}
168+
updateHttpClientConfig(key: keyof NodeHttpHandlerOptions, value: NodeHttpHandlerOptions[typeof key]): void {}
169+
httpHandlerConfigs(): NodeHttpHandlerOptions {
170+
return null as any;
171+
}
172+
})();
173+
37174
beforeAll(async () => {
38175
processSnapshot = copy(process.env);
39176
});
40177

41178
beforeEach(async () => {
42179
sts = new STS({
43-
requestHandler: new (class {
44-
async handle(request: HttpRequest, ignored?: any) {
45-
const body = new Readable();
46-
body.push(`
47-
<GetCallerIdentityResponse xmlns="https://sts.amazonaws.com/doc/2011-06-15/">
48-
<GetCallerIdentityResult>
49-
<Arn>arn:aws:iam::123456789012:user/Alice</Arn>
50-
<UserId>AIDACKCEVSQ6C2EXAMPLE</UserId>
51-
<Account>123456789012</Account>
52-
</GetCallerIdentityResult>
53-
<ResponseMetadata>
54-
<RequestId>01234567-89ab-cdef-0123-456789abcdef</RequestId>
55-
</ResponseMetadata>
56-
</GetCallerIdentityResponse>
57-
`);
58-
body.push(null);
59-
return {
60-
response: new HttpResponse({
61-
statusCode: 200,
62-
headers: {},
63-
body,
64-
}),
65-
};
66-
}
67-
updateHttpClientConfig(key: keyof NodeHttpHandlerOptions, value: NodeHttpHandlerOptions[typeof key]): void {}
68-
httpHandlerConfigs(): NodeHttpHandlerOptions {
69-
return null as any;
70-
}
71-
})(),
180+
requestHandler: mockRequestHandler,
72181
});
73182
for (const variable in RESERVED_ENVIRONMENT_VARIABLES) {
74183
delete process.env[variable];
@@ -98,17 +207,54 @@ describe("credential-provider-node integration test", () => {
98207

99208
describe("fromEnv", () => {
100209
it("should load static credentials from environment variables", async () => {
101-
// TODO
210+
process.env.AWS_ACCESS_KEY_ID = "ENV_ACCESS_KEY";
211+
process.env.AWS_SECRET_ACCESS_KEY = "ENV_SECRET_KEY";
212+
await sts.getCallerIdentity({});
213+
const credentials = await sts.config.credentials();
214+
expect(credentials).toEqual({
215+
accessKeyId: "ENV_ACCESS_KEY",
216+
secretAccessKey: "ENV_SECRET_KEY",
217+
});
102218
});
103219

104220
it("should optionally use session token, expiration, and credential scope", async () => {
105-
// TODO
221+
process.env.AWS_ACCESS_KEY_ID = "ENV_ACCESS_KEY";
222+
process.env.AWS_SECRET_ACCESS_KEY = "ENV_SECRET_KEY";
223+
process.env.AWS_SESSION_TOKEN = "ENV_SESSION_TOKEN";
224+
process.env.AWS_CREDENTIAL_EXPIRATION = "2000-01-01T00:00:00.000Z";
225+
process.env.AWS_CREDENTIAL_SCOPE = "us-env-1";
226+
await sts.getCallerIdentity({});
227+
const credentials = await sts.config.credentials();
228+
expect(credentials).toEqual({
229+
accessKeyId: "ENV_ACCESS_KEY",
230+
secretAccessKey: "ENV_SECRET_KEY",
231+
expiration: new Date("2000-01-01T00:00:00.000Z"),
232+
sessionToken: "ENV_SESSION_TOKEN",
233+
credentialScope: "us-env-1",
234+
});
106235
});
107236
});
108237

109238
describe("fromSSO", () => {
110-
it("should resolve SSO credentials if the profile is an SSO profile", async () => {
111-
// TODO
239+
it("should resolve SSO credentials if legacy SSO parameters are supplied directly", async () => {
240+
sts = new STS({
241+
credentials: defaultProvider({
242+
ssoStartUrl: "SSO_START_URL",
243+
ssoAccountId: "1234",
244+
ssoRegion: "us-sso-1",
245+
ssoRoleName: "sso-role",
246+
}),
247+
requestHandler: mockRequestHandler,
248+
});
249+
await sts.getCallerIdentity({});
250+
const credentials = await sts.config.credentials();
251+
expect(credentials).toEqual({
252+
accessKeyId: "SSO_ACCESS_KEY_ID",
253+
secretAccessKey: "SSO_SECRET_ACCESS_KEY",
254+
sessionToken: "SSO_SESSION_TOKEN",
255+
expiration: new Date("3000/1/1"),
256+
credentialScope: "us-sso-1",
257+
});
112258
});
113259
});
114260

@@ -127,48 +273,100 @@ describe("credential-provider-node integration test", () => {
127273
});
128274

129275
it("should resolve assumeRole credentials", async () => {
130-
// TODO
276+
iniProfileData.assume = {
277+
region: "us-stsar-1",
278+
aws_access_key_id: "ASSUME_STATIC_ACCESS_KEY",
279+
aws_secret_access_key: "ASSUME_STATIC_SECRET_KEY",
280+
};
281+
Object.assign(iniProfileData.default, {
282+
region: "us-stsar-1",
283+
role_arn: "ROLE_ARN",
284+
role_session_name: "ROLE_SESSION_NAME",
285+
external_id: "EXTERNAL_ID",
286+
source_profile: "assume",
287+
});
288+
await sts.getCallerIdentity({});
289+
const credentials = await sts.config.credentials();
290+
expect(credentials).toEqual({
291+
accessKeyId: "STS_AR_ACCESS_KEY_ID",
292+
secretAccessKey: "STS_AR_SECRET_ACCESS_KEY",
293+
sessionToken: "STS_AR_SESSION_TOKEN",
294+
expiration: new Date("3000/1/1"),
295+
credentialScope: "us-stsar-1",
296+
});
131297
});
132298

133-
it("should prefer static credentials over role assumption metadata only if the profile is not the first one visited", async () => {
299+
xit("should prefer static credentials over role assumption metadata only if the profile is not the first one visited", async () => {
134300
// TODO
135301
});
136302

137303
it("should resolve credentials from STS assumeRoleWithWebIdentity if the ini profile is configured for web identity", async () => {
138-
// TODO
304+
Object.assign(iniProfileData.default, {
305+
web_identity_token_file: "token-filepath",
306+
role_arn: "ROLE_ARN",
307+
});
308+
await sts.getCallerIdentity({});
309+
const credentials = await sts.config.credentials();
310+
expect(credentials).toEqual({
311+
accessKeyId: "STS_ARWI_ACCESS_KEY_ID",
312+
secretAccessKey: "STS_ARWI_SECRET_ACCESS_KEY",
313+
sessionToken: "STS_ARWI_SESSION_TOKEN",
314+
expiration: new Date("3000/1/1"),
315+
credentialScope: "us-stsarwi-1",
316+
});
139317
});
140318

141-
it("should resolve credentials from STS assumeRoleWithWebIdentity if the ini profile is configured for web identity and the client region is not the default AWS partition", async () => {
319+
xit("should resolve credentials from STS assumeRoleWithWebIdentity if the ini profile is configured for web identity and the client region is not the default AWS partition", async () => {
142320
// TODO
321+
// this is difficult to do when getDefaultRoleAssumerWithWebIdentity is mocked.
143322
});
144323

145-
it("should resolve process credentials if the profile is a process profile", async () => {
324+
xit("should resolve process credentials if the profile is a process profile", async () => {
146325
// TODO
147326
});
148327

149328
it("should resolve SSO credentials if the profile is an SSO profile", async () => {
150-
// TODO
329+
iniProfileData["sso-session.ssoNew"] = {
330+
sso_region: "us-sso-1",
331+
sso_start_url: "SSO_START_URL",
332+
sso_registration_scopes: "sso:account:access",
333+
};
334+
Object.assign(iniProfileData.default, {
335+
sso_region: "us-sso-1",
336+
sso_session: "ssoNew",
337+
sso_account_id: "1234",
338+
sso_role_name: "integration-test",
339+
});
340+
await sts.getCallerIdentity({});
341+
const credentials = await sts.config.credentials();
342+
expect(credentials).toEqual({
343+
accessKeyId: "SSO_ACCESS_KEY_ID",
344+
secretAccessKey: "SSO_SECRET_ACCESS_KEY",
345+
sessionToken: "SSO_SESSION_TOKEN",
346+
expiration: new Date("3000/1/1"),
347+
credentialScope: "us-sso-1",
348+
});
151349
});
152350
});
153351

154352
describe("fromProcess", () => {
155-
it("should resolve process credentials if the profile is a process profile", async () => {
353+
xit("should resolve process credentials if the profile is a process profile", async () => {
156354
// TODO
157355
});
158356
});
159357

160358
describe("fromTokenFile", () => {
161-
it("should resolve credentials with STS assumeRoleWithWebIdentity using a token", async () => {
359+
xit("should resolve credentials with STS assumeRoleWithWebIdentity using a token", async () => {
162360
// TODO
163361
});
164362
});
165363

166364
describe("remoteProvider", () => {
167-
it("should use container metadata if AWS_CONTAINER_CREDENTIALS_FULL_URI is set", async () => {
365+
xit("should use container metadata if AWS_CONTAINER_CREDENTIALS_FULL_URI is set", async () => {
168366
// TODO
169367
});
170368

171-
it("should use instance metadata unless IMDS is disabled", async () => {
369+
xit("should use instance metadata unless IMDS is disabled", async () => {
172370
// TODO
173371
});
174372
});

0 commit comments

Comments
 (0)