Skip to content

Commit 8b307aa

Browse files
committed
chore(credential-provider-web-identity): update unit tests
1 parent 52de007 commit 8b307aa

File tree

4 files changed

+147
-126
lines changed

4 files changed

+147
-126
lines changed
Lines changed: 60 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import { ProviderError } from "@aws-sdk/property-provider";
21
import { readFileSync } from "fs";
3-
4-
import { fromTokenFile, FromTokenFileInit } from "./fromTokenFile";
5-
import { AssumeRoleWithWebIdentityParams } from "./index";
2+
jest.mock("./fromWebToken", () => ({
3+
fromWebToken: jest.fn().mockReturnValue(() => Promise.resolve(MOCK_CREDS)),
4+
}));
5+
import { fromTokenFile } from "./fromTokenFile";
6+
import { fromWebToken } from "./fromWebToken";
67

78
const ENV_TOKEN_FILE = "AWS_WEB_IDENTITY_TOKEN_FILE";
89
const ENV_ROLE_ARN = "AWS_ROLE_ARN";
@@ -31,57 +32,6 @@ describe(fromTokenFile.name, () => {
3132
jest.restoreAllMocks();
3233
});
3334

34-
const testRoleAssumerWithWebIdentityNotDefined = async (init: FromTokenFileInit, roleArn: string) => {
35-
try {
36-
// @ts-ignore An argument for 'init' was not provided.
37-
await fromTokenFile(init)();
38-
fail(`Expected error to be thrown`);
39-
} catch (error) {
40-
expect(error).toEqual(
41-
new ProviderError(
42-
`Role Arn '${roleArn}' needs to be assumed with web identity, but no role assumption callback was provided.`,
43-
false
44-
)
45-
);
46-
}
47-
};
48-
49-
const testReadFileSyncError = async (init: FromTokenFileInit) => {
50-
const readFileSyncError = new Error("readFileSyncError");
51-
(readFileSync as jest.Mock).mockImplementation(() => {
52-
throw readFileSyncError;
53-
});
54-
try {
55-
await fromTokenFile(init)();
56-
fail(`Expected error to be thrown`);
57-
} catch (error) {
58-
expect(error).toEqual(readFileSyncError);
59-
}
60-
expect(readFileSync).toHaveBeenCalledTimes(1);
61-
};
62-
63-
const testRoleAssumerWithWebIdentitySuccess = async (init: FromTokenFileInit) => {
64-
const creds = await fromTokenFile(init)();
65-
expect(creds).toEqual(MOCK_CREDS);
66-
expect(readFileSync).toHaveBeenCalledTimes(1);
67-
expect(readFileSync).toHaveBeenCalledWith(mockTokenFile, { encoding: "ascii" });
68-
};
69-
70-
const testRandomValueForRoleSessionName = async (init: FromTokenFileInit) => {
71-
const mockDateNow = Date.now();
72-
const spyDateNow = jest.spyOn(Date, "now").mockReturnValueOnce(mockDateNow);
73-
74-
const creds = await fromTokenFile({
75-
...init,
76-
roleAssumerWithWebIdentity: async (params: AssumeRoleWithWebIdentityParams) => {
77-
expect(params.RoleSessionName).toEqual(`aws-sdk-js-session-${mockDateNow}`);
78-
return MOCK_CREDS;
79-
},
80-
})();
81-
expect(creds).toEqual(MOCK_CREDS);
82-
expect(spyDateNow).toHaveBeenCalledTimes(1);
83-
};
84-
8535
describe("reads config from env", () => {
8636
const original_ENV_TOKEN_FILE = process.env[ENV_TOKEN_FILE];
8737
const original_ENV_ROLE_ARN = process.env[ENV_ROLE_ARN];
@@ -99,83 +49,70 @@ describe(fromTokenFile.name, () => {
9949
process.env[ENV_ROLE_SESSION_NAME] = original_ENV_ROLE_SESSION_NAME;
10050
});
10151

102-
it("throws if roleAssumerWithWebIdentity is not defined", async () => {
103-
return testRoleAssumerWithWebIdentityNotDefined({}, process.env[ENV_ROLE_ARN]);
52+
it(`passes values to ${fromWebToken.name}`, async () => {
53+
const roleAssumerWithWebIdentity = jest.fn();
54+
const creds = await fromTokenFile({
55+
roleAssumerWithWebIdentity,
56+
})();
57+
expect(creds).toEqual(MOCK_CREDS);
58+
expect(fromWebToken as jest.Mock).toBeCalledTimes(1);
59+
const webTokenInit = (fromWebToken as jest.Mock).mock.calls[0][0];
60+
expect(webTokenInit.webIdentityToken).toBe(mockTokenValue);
61+
expect(webTokenInit.roleSessionName).toBe(mockRoleSessionName);
62+
expect(webTokenInit.roleArn).toBe(mockRoleArn);
63+
expect(webTokenInit.roleAssumerWithWebIdentity).toBe(roleAssumerWithWebIdentity);
10464
});
10565

106-
it("throws if ENV_TOKEN_FILE read from disk failed", async () => {
107-
return testReadFileSyncError({
108-
roleAssumerWithWebIdentity: async (params: AssumeRoleWithWebIdentityParams) => {
109-
return MOCK_CREDS;
110-
},
111-
});
66+
it("prefers init parameters over environmental variables", async () => {
67+
const roleAssumerWithWebIdentity = jest.fn();
68+
const init = {
69+
webIdentityTokenFile: "anotherTokenFile",
70+
roleArn: "anotherRoleArn",
71+
roleSessionName: "anotherRoleSessionName",
72+
roleAssumerWithWebIdentity,
73+
};
74+
const creds = await fromTokenFile(init)();
75+
expect(creds).toEqual(MOCK_CREDS);
76+
expect(fromWebToken as jest.Mock).toBeCalledTimes(1);
77+
const webTokenInit = (fromWebToken as jest.Mock).mock.calls[0][0];
78+
expect(webTokenInit.roleSessionName).toBe(init.roleSessionName);
79+
expect(webTokenInit.roleArn).toBe(init.roleArn);
80+
expect(webTokenInit.roleAssumerWithWebIdentity).toBe(roleAssumerWithWebIdentity);
81+
expect(readFileSync as jest.Mock).toBeCalledTimes(1);
82+
expect((readFileSync as jest.Mock).mock.calls[0][0]).toBe(init.webIdentityTokenFile);
11283
});
11384

114-
it("passes values to roleAssumerWithWebIdentity", async () => {
115-
return testRoleAssumerWithWebIdentitySuccess({
116-
roleAssumerWithWebIdentity: async (params: AssumeRoleWithWebIdentityParams) => {
117-
expect(params.WebIdentityToken).toEqual(mockTokenValue);
118-
expect(params.RoleArn).toEqual(mockRoleArn);
119-
expect(params.RoleSessionName).toEqual(mockRoleSessionName);
120-
return MOCK_CREDS;
121-
},
85+
it("throws if ENV_TOKEN_FILE read from disk failed", async () => {
86+
const readFileSyncError = new Error("readFileSyncError");
87+
(readFileSync as jest.Mock).mockImplementation(() => {
88+
throw readFileSyncError;
12289
});
123-
});
124-
125-
it("generates a random value for RoleSessionName if not available", async () => {
126-
delete process.env[ENV_ROLE_SESSION_NAME];
127-
return testRandomValueForRoleSessionName({});
128-
});
129-
});
130-
131-
describe("reads config from configuration keys", () => {
132-
const original_ENV_TOKEN_FILE = process.env[ENV_TOKEN_FILE];
133-
const original_ENV_ROLE_ARN = process.env[ENV_ROLE_ARN];
134-
const original_ENV_ROLE_SESSION_NAME = process.env[ENV_ROLE_SESSION_NAME];
135-
136-
beforeAll(() => {
137-
delete process.env[ENV_TOKEN_FILE];
138-
delete process.env[ENV_ROLE_ARN];
139-
delete process.env[ENV_ROLE_SESSION_NAME];
140-
});
141-
142-
afterAll(() => {
143-
process.env[ENV_TOKEN_FILE] = original_ENV_TOKEN_FILE;
144-
process.env[ENV_ROLE_ARN] = original_ENV_ROLE_ARN;
145-
process.env[ENV_ROLE_SESSION_NAME] = original_ENV_ROLE_SESSION_NAME;
146-
});
147-
148-
it("throws if roleAssumerWithWebIdentity is not defined", async () => {
149-
return testRoleAssumerWithWebIdentityNotDefined({ roleArn: mockRoleArn }, mockRoleArn);
90+
try {
91+
await fromTokenFile({ roleAssumerWithWebIdentity: jest.fn() })();
92+
fail(`Expected error to be thrown`);
93+
} catch (error) {
94+
expect(error).toEqual(readFileSyncError);
95+
}
96+
expect(readFileSync).toHaveBeenCalledTimes(1);
15097
});
15198

15299
it("throws if web_identity_token_file read from disk failed", async () => {
153-
return testReadFileSyncError({
154-
webIdentityTokenFile: mockTokenFile,
155-
roleArn: mockRoleArn,
156-
roleSessionName: mockRoleSessionName,
157-
roleAssumerWithWebIdentity: async (params: AssumeRoleWithWebIdentityParams) => {
158-
return MOCK_CREDS;
159-
},
160-
});
161-
});
162-
163-
it("passes values to roleAssumerWithWebIdentity", async () => {
164-
return testRoleAssumerWithWebIdentitySuccess({
165-
webIdentityTokenFile: mockTokenFile,
166-
roleArn: mockRoleArn,
167-
roleSessionName: mockRoleSessionName,
168-
roleAssumerWithWebIdentity: async (params: AssumeRoleWithWebIdentityParams) => {
169-
expect(params.WebIdentityToken).toEqual(mockTokenValue);
170-
expect(params.RoleArn).toEqual(mockRoleArn);
171-
expect(params.RoleSessionName).toEqual(mockRoleSessionName);
172-
return MOCK_CREDS;
173-
},
100+
const readFileSyncError = new Error("readFileSyncError");
101+
(readFileSync as jest.Mock).mockImplementation(() => {
102+
throw readFileSyncError;
174103
});
175-
});
176-
177-
it("generates a random value for RoleSessionName if not available", async () => {
178-
return testRandomValueForRoleSessionName({ webIdentityTokenFile: mockTokenFile, roleArn: mockRoleArn });
104+
try {
105+
await fromTokenFile({
106+
webIdentityTokenFile: mockTokenFile,
107+
roleArn: mockRoleArn,
108+
roleSessionName: mockRoleSessionName,
109+
roleAssumerWithWebIdentity: jest.fn(),
110+
})();
111+
fail(`Expected error to be thrown`);
112+
} catch (error) {
113+
expect(error).toEqual(readFileSyncError);
114+
}
115+
expect(readFileSync).toHaveBeenCalledTimes(1);
179116
});
180117
});
181118
});

packages/credential-provider-web-identity/src/fromTokenFile.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const ENV_TOKEN_FILE = "AWS_WEB_IDENTITY_TOKEN_FILE";
77
const ENV_ROLE_ARN = "AWS_ROLE_ARN";
88
const ENV_ROLE_SESSION_NAME = "AWS_ROLE_SESSION_NAME";
99

10-
export interface FromTokenFileInit extends Partial<FromWebTokenInit> {
10+
export interface FromTokenFileInit extends Partial<Omit<FromWebTokenInit, "webIdentityToken">> {
1111
/**
1212
* File location of where the `OIDC` token is stored.
1313
*/
@@ -24,6 +24,6 @@ export const fromTokenFile = (init: FromTokenFileInit): CredentialProvider => {
2424
...init,
2525
webIdentityToken: readFileSync(webIdentityTokenFile ?? process.env[ENV_TOKEN_FILE]!, { encoding: "ascii" }),
2626
roleArn: roleArn ?? process.env[ENV_ROLE_ARN]!,
27-
roleSessionName: roleSessionName ?? process.env[ENV_ROLE_SESSION_NAME] ?? `aws-sdk-js-session-${Date.now()}`,
27+
roleSessionName: roleSessionName ?? process.env[ENV_ROLE_SESSION_NAME],
2828
});
2929
};
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import { ProviderError } from "@aws-sdk/property-provider";
2+
3+
import { fromWebToken } from "./fromWebToken";
4+
5+
const mockToken = "exampletoken";
6+
const mockRoleArn = "mockRoleArn";
7+
const mockRoleSessionName = "mockRoleSessionName";
8+
const mockPolicy = "mockPolicy";
9+
const mockPolicyArns = [{ arn: "policyArn" }];
10+
const mockProviderId = "mockProviderId";
11+
const mockDurationSeconds = 7200;
12+
const MOCK_CREDS = {
13+
accessKeyId: "accessKeyId",
14+
secretAccessKey: "secretAccessKey",
15+
sessionToken: "sessionToken",
16+
};
17+
18+
describe("fromWebToken", () => {
19+
afterEach(() => {
20+
jest.clearAllMocks();
21+
jest.restoreAllMocks();
22+
});
23+
it("throws if roleAssumerWithWebIdentity is not defined", async () => {
24+
try {
25+
await fromWebToken({
26+
webIdentityToken: mockToken,
27+
roleArn: mockRoleArn,
28+
})();
29+
fail(`Expected error to be thrown`);
30+
} catch (error) {
31+
expect(error).toEqual(
32+
new ProviderError(
33+
`Role Arn '${mockRoleArn}' needs to be assumed with web identity, but no role assumption callback was provided.`,
34+
false
35+
)
36+
);
37+
}
38+
});
39+
40+
it("passes values to roleAssumerWithWebIdentity", async () => {
41+
expect.assertions(2);
42+
const init = {
43+
webIdentityToken: mockToken,
44+
roleArn: mockRoleArn,
45+
roleSessionName: mockRoleSessionName,
46+
providerId: mockProviderId,
47+
policyArns: mockPolicyArns,
48+
policy: mockPolicy,
49+
durationSeconds: mockDurationSeconds,
50+
};
51+
const creds = await fromWebToken({
52+
...init,
53+
roleAssumerWithWebIdentity: async (params) => {
54+
expect(params).toMatchObject({
55+
WebIdentityToken: mockToken,
56+
RoleArn: mockRoleArn,
57+
RoleSessionName: mockRoleSessionName,
58+
ProviderId: mockProviderId,
59+
PolicyArns: mockPolicyArns,
60+
Policy: mockPolicy,
61+
DurationSeconds: mockDurationSeconds,
62+
});
63+
return MOCK_CREDS;
64+
},
65+
})();
66+
expect(creds).toEqual(MOCK_CREDS);
67+
});
68+
69+
it("generates a random value for RoleSessionName if not available", async () => {
70+
const mockDateNow = Date.now();
71+
const spyDateNow = jest.spyOn(Date, "now").mockReturnValueOnce(mockDateNow);
72+
73+
const creds = await fromWebToken({
74+
webIdentityToken: mockToken,
75+
roleArn: mockRoleArn,
76+
roleAssumerWithWebIdentity: async (params) => {
77+
expect(params.RoleSessionName).toEqual(`aws-sdk-js-session-${mockDateNow}`);
78+
return MOCK_CREDS;
79+
},
80+
})();
81+
expect(creds).toEqual(MOCK_CREDS);
82+
expect(spyDateNow).toHaveBeenCalledTimes(1);
83+
});
84+
});

packages/credential-provider-web-identity/src/fromWebToken.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ export const fromWebToken = (init: FromWebTokenInit): CredentialProvider => () =
148148

149149
return roleAssumerWithWebIdentity({
150150
RoleArn: roleArn,
151-
RoleSessionName: roleSessionName ?? "web-identity",
151+
RoleSessionName: roleSessionName ?? `aws-sdk-js-session-${Date.now()}`,
152152
WebIdentityToken: webIdentityToken,
153153
ProviderId: providerId,
154154
PolicyArns: policyArns,

0 commit comments

Comments
 (0)