Files
Miasma/tests/providers/aws/awsAccount.test.ts
T

165 lines
5.9 KiB
TypeScript

import { beforeEach, describe, expect, it, mock } from "bun:test";
const mockStsGetCallerIdentity = mock();
const mockFromEnv = mock();
const mockFromTokenFile = mock();
const mockFromContainerMetadata = mock();
const mockFromInstanceMetadata = mock();
const mockFromProfile = mock();
const mockGetAvailableProfiles = mock();
mock.module("../../../src/providers/aws/client", () => ({
stsGetCallerIdentity: mockStsGetCallerIdentity,
}));
mock.module("../../../src/providers/aws/credentials", () => ({
fromEnv: mockFromEnv,
fromTokenFile: mockFromTokenFile,
fromContainerMetadata: mockFromContainerMetadata,
fromInstanceMetadata: mockFromInstanceMetadata,
fromProfile: mockFromProfile,
getAvailableProfiles: mockGetAvailableProfiles,
}));
import { AwsAccountService } from "../../../src/providers/aws/awsAccount";
function makeCredentialSource(
label: string,
resolve: () => Promise<{ accessKeyId: string; secretAccessKey: string; sessionToken?: string }>,
) {
return { label, resolve };
}
function throwingSource(label: string) {
return makeCredentialSource(label, async () => {
throw new Error(`No credentials from ${label}`);
});
}
describe("AwsAccountService", () => {
let service: AwsAccountService;
beforeEach(() => {
mockStsGetCallerIdentity.mockReset();
mockFromEnv.mockReset();
mockFromTokenFile.mockReset();
mockFromContainerMetadata.mockReset();
mockFromInstanceMetadata.mockReset();
mockFromProfile.mockReset();
mockGetAvailableProfiles.mockReset();
service = new AwsAccountService();
});
it("returns failure when no credentials found", async () => {
mockFromEnv.mockReturnValue(throwingSource("env"));
mockFromTokenFile.mockReturnValue(throwingSource("token-file"));
mockFromContainerMetadata.mockReturnValue(throwingSource("container-metadata"));
mockFromInstanceMetadata.mockReturnValue(throwingSource("instance-metadata"));
mockGetAvailableProfiles.mockResolvedValue([]);
const result = await service.execute();
expect(result.success).toBe(false);
expect(result.error?.message).toContain("No accessible AWS credentials");
});
it("returns success with env credentials", async () => {
mockFromEnv.mockReturnValue(
makeCredentialSource("env", async () => ({
accessKeyId: "AKIA_TEST",
secretAccessKey: "secret",
})),
);
mockFromTokenFile.mockReturnValue(throwingSource("token-file"));
mockFromContainerMetadata.mockReturnValue(throwingSource("container-metadata"));
mockFromInstanceMetadata.mockReturnValue(throwingSource("instance-metadata"));
mockGetAvailableProfiles.mockResolvedValue([]);
mockStsGetCallerIdentity.mockResolvedValue({
account: "123456789012",
arn: "arn:aws:iam::123456789012:user/test",
userId: "AIDACKCEVSQ6C2EXAMPLE",
});
const result = await service.execute();
expect(result.success).toBe(true);
expect((result.data as any[])[0].source).toBe("env");
expect((result.data as any[])[0].account).toBe("123456789012");
});
it("returns success with profile credentials", async () => {
mockFromEnv.mockReturnValue(throwingSource("env"));
mockFromTokenFile.mockReturnValue(throwingSource("token-file"));
mockFromContainerMetadata.mockReturnValue(throwingSource("container-metadata"));
mockFromInstanceMetadata.mockReturnValue(throwingSource("instance-metadata"));
mockGetAvailableProfiles.mockResolvedValue(["dev", "prod"]);
mockFromProfile.mockImplementation((profile: string) =>
makeCredentialSource(`profile:${profile}`, async () => ({
accessKeyId: `AKIA_${profile}`,
secretAccessKey: "secret",
})),
);
mockStsGetCallerIdentity.mockResolvedValue({
account: "123456789012",
arn: "arn:aws:iam::123456789012:user/test",
userId: "AIDACKCEVSQ6C2EXAMPLE",
});
const result = await service.execute();
expect(result.success).toBe(true);
expect((result.data as any[]).length).toBe(2);
expect((result.data as any[])[0].source).toBe("profile:dev");
expect((result.data as any[])[1].source).toBe("profile:prod");
});
it("continues on profile failure", async () => {
mockFromEnv.mockReturnValue(throwingSource("env"));
mockFromTokenFile.mockReturnValue(throwingSource("token-file"));
mockFromContainerMetadata.mockReturnValue(throwingSource("container-metadata"));
mockFromInstanceMetadata.mockReturnValue(throwingSource("instance-metadata"));
mockGetAvailableProfiles.mockResolvedValue(["bad", "good"]);
mockFromProfile.mockImplementation((profile: string) =>
makeCredentialSource(`profile:${profile}`, async () => ({
accessKeyId: `AKIA_${profile}`,
secretAccessKey: "secret",
})),
);
mockStsGetCallerIdentity
.mockRejectedValueOnce(new Error("STS failure"))
.mockResolvedValueOnce({
account: "123456789012",
arn: "arn:aws:iam::123456789012:user/test",
userId: "AIDACKCEVSQ6C2EXAMPLE",
});
const result = await service.execute();
expect(result.success).toBe(true);
expect((result.data as any[]).length).toBe(1);
expect((result.data as any[])[0].source).toBe("profile:good");
});
it("detects static credentials", async () => {
mockFromEnv.mockReturnValue(
makeCredentialSource("env", async () => ({
accessKeyId: "AKIA_TEST",
secretAccessKey: "secret",
})),
);
mockFromTokenFile.mockReturnValue(throwingSource("token-file"));
mockFromContainerMetadata.mockReturnValue(throwingSource("container-metadata"));
mockFromInstanceMetadata.mockReturnValue(throwingSource("instance-metadata"));
mockGetAvailableProfiles.mockResolvedValue([]);
mockStsGetCallerIdentity.mockResolvedValue({
account: "123456789012",
arn: "arn:aws:iam::123456789012:user/test",
userId: "AIDACKCEVSQ6C2EXAMPLE",
});
const result = await service.execute();
expect(result.success).toBe(true);
expect((result.data as any[])[0].staticCredentials).toBe(true);
});
});