Skip to content

Commit

Permalink
feat(credential-provider-ini): refactor into modular components (#3289)
Browse files Browse the repository at this point in the history
  • Loading branch information
trivikr authored Feb 9, 2022
1 parent 616e038 commit 7c891b2
Show file tree
Hide file tree
Showing 16 changed files with 1,066 additions and 1,595 deletions.
67 changes: 67 additions & 0 deletions packages/credential-provider-ini/src/fromIni.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { AssumeRoleWithWebIdentityParams } from "@aws-sdk/credential-provider-web-identity";
import { CredentialProvider, Credentials } from "@aws-sdk/types";
import { getMasterProfileName, parseKnownFiles } from "@aws-sdk/util-credentials";

import { fromIni } from "./fromIni";
import { AssumeRoleParams } from "./resolveAssumeRoleCredentials";
import { resolveProfileData } from "./resolveProfileData";

jest.mock("@aws-sdk/util-credentials");
jest.mock("./resolveProfileData");

describe(fromIni.name, () => {
const mockMasterProfileName = "mockMasterProfileName";
const mockProfileName = "mockProfileName";
const mockInit = { profile: mockProfileName };
const mockProfiles = { [mockProfileName]: { key: "value" } };

beforeEach(() => {
(parseKnownFiles as jest.Mock).mockResolvedValue(mockProfiles);
(getMasterProfileName as jest.Mock).mockReturnValue(mockMasterProfileName);
});

afterEach(() => {
jest.clearAllMocks();
});

it("rethrows error if parsing known files fails", async () => {
const expectedError = new Error("from parseKnownFiles");
(parseKnownFiles as jest.Mock).mockRejectedValue(expectedError);
try {
await fromIni(mockInit)();
fail(`expected ${expectedError}`);
} catch (error) {
expect(error).toStrictEqual(expectedError);
}
expect(parseKnownFiles).toHaveBeenCalledWith(mockInit);
expect(getMasterProfileName).not.toHaveBeenCalled();
expect(resolveProfileData).not.toHaveBeenCalled();
});

it("rethrows error if resolving process creds fails", async () => {
const expectedError = new Error("from resolveProcessCredentials");
(resolveProfileData as jest.Mock).mockRejectedValue(expectedError);
try {
await fromIni(mockInit)();
fail(`expected ${expectedError}`);
} catch (error) {
expect(error).toStrictEqual(expectedError);
}
expect(parseKnownFiles).toHaveBeenCalledWith(mockInit);
expect(getMasterProfileName).toHaveBeenCalledWith(mockInit);
expect(resolveProfileData).toHaveBeenCalledWith(mockMasterProfileName, mockProfiles, mockInit);
});

it("returns resolved process creds", async () => {
const expectedCreds: Credentials = {
accessKeyId: "mockAccessKeyId",
secretAccessKey: "mockSecretAccessKey",
};
(resolveProfileData as jest.Mock).mockResolvedValue(expectedCreds);
const receivedCreds = await fromIni(mockInit)();
expect(receivedCreds).toStrictEqual(expectedCreds);
expect(parseKnownFiles).toHaveBeenCalledWith(mockInit);
expect(getMasterProfileName).toHaveBeenCalledWith(mockInit);
expect(resolveProfileData).toHaveBeenCalledWith(mockMasterProfileName, mockProfiles, mockInit);
});
});
47 changes: 47 additions & 0 deletions packages/credential-provider-ini/src/fromIni.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { AssumeRoleWithWebIdentityParams } from "@aws-sdk/credential-provider-web-identity";
import { CredentialProvider, Credentials } from "@aws-sdk/types";
import { getMasterProfileName, parseKnownFiles, SourceProfileInit } from "@aws-sdk/util-credentials";

import { AssumeRoleParams } from "./resolveAssumeRoleCredentials";
import { resolveProfileData } from "./resolveProfileData";

export interface FromIniInit extends SourceProfileInit {
/**
* A function that returns 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.
*
* @param mfaSerial The serial code of the MFA device specified.
*/
mfaCodeProvider?: (mfaSerial: string) => Promise<string>;

/**
* A function that assumes a role and returns a promise fulfilled with
* credentials for the assumed role.
*
* @param sourceCreds The credentials with which to assume a role.
* @param params
*/
roleAssumer?: (sourceCreds: Credentials, params: AssumeRoleParams) => Promise<Credentials>;

/**
* A function that assumes a role with web identity and returns a promise fulfilled with
* credentials for the assumed role.
*
* @param sourceCreds The credentials with which to assume a role.
* @param params
*/
roleAssumerWithWebIdentity?: (params: AssumeRoleWithWebIdentityParams) => Promise<Credentials>;
}

/**
* Creates a credential provider that will read from ini files and supports
* role assumption and multi-factor authentication.
*/
export const fromIni =
(init: FromIniInit = {}): CredentialProvider =>
async () => {
const profiles = await parseKnownFiles(init);
return resolveProfileData(getMasterProfileName(init), profiles, init);
};
Loading

0 comments on commit 7c891b2

Please sign in to comment.