Skip to content

Commit

Permalink
feat(config-resolver): use real region in configuration (#2986)
Browse files Browse the repository at this point in the history
  • Loading branch information
trivikr committed Nov 4, 2021
1 parent 41d3762 commit af5b00e
Show file tree
Hide file tree
Showing 17 changed files with 166 additions and 4,280 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,4 @@ export const resolveCustomEndpointsConfig = <T>(
endpoint: normalizeEndpoint(input),
isCustomEndpoint: true,
useDualstackEndpoint: normalizeBoolean(input.useDualstackEndpoint!),
useFipsEndpoint: normalizeBoolean(input.useFipsEndpoint!),
});
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,13 @@ export interface EndpointsInputConfig {
* Enables IPv6/IPv4 dualstack endpoint.
*/
useDualstackEndpoint?: boolean | Provider<boolean>;

/**
* Enables FIPS compatible endpoints.
*/
useFipsEndpoint?: boolean | Provider<boolean>;
}

interface PreviouslyResolved {
regionInfoProvider: RegionInfoProvider;
urlParser: UrlParser;
region: Provider<string>;
useFipsEndpoint: Provider<boolean>;
}

export interface EndpointsResolvedConfig extends Required<EndpointsInputConfig> {
Expand All @@ -48,26 +44,20 @@ export interface EndpointsResolvedConfig extends Required<EndpointsInputConfig>
* Resolved value for input {@link EndpointsInputConfig.useDualstackEndpoint}
*/
useDualstackEndpoint: Provider<boolean>;

/**
* Resolved value for input {@link EndpointsInputConfig.useFipsEndpoint}
*/
useFipsEndpoint: Provider<boolean>;
}

export const resolveEndpointsConfig = <T>(
input: T & EndpointsInputConfig & PreviouslyResolved
): T & EndpointsResolvedConfig => {
const useDualstackEndpoint = normalizeBoolean(input.useDualstackEndpoint!);
const useFipsEndpoint = normalizeBoolean(input.useFipsEndpoint!);
const { endpoint, useFipsEndpoint } = input;
return {
...input,
tls: input.tls ?? true,
endpoint: input.endpoint
? normalizeEndpoint({ ...input, endpoint: input.endpoint })
endpoint: endpoint
? normalizeEndpoint({ ...input, endpoint })
: () => getEndpointFromRegion({ ...input, useDualstackEndpoint, useFipsEndpoint }),
isCustomEndpoint: input.endpoint ? true : false,
isCustomEndpoint: endpoint ? true : false,
useDualstackEndpoint,
useFipsEndpoint,
};
};
36 changes: 36 additions & 0 deletions packages/config-resolver/src/regionConfig/getRealRegion.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { getRealRegion } from "./getRealRegion";
import { isFipsRegion } from "./isFipsRegion";

jest.mock("./isFipsRegion");

describe(getRealRegion.name, () => {
beforeEach(() => {
(isFipsRegion as jest.Mock).mockReturnValue(true);
});

afterEach(() => {
expect(isFipsRegion).toHaveBeenCalledTimes(1);
jest.clearAllMocks();
});

it("returns provided region if it's not FIPS", () => {
const mockRegion = "mockRegion";
(isFipsRegion as jest.Mock).mockReturnValue(false);
expect(getRealRegion(mockRegion)).toStrictEqual(mockRegion);
});

describe("FIPS regions", () => {
it.each(["fips-aws-global", "aws-fips"])(`returns "us-east-1" for "%s"`, (input) => {
expect(getRealRegion(input)).toStrictEqual("us-east-1");
});

it.each([
["us-west-1", "us-west-1-fips"],
["us-west-1", "fips-us-west-1"],
["us-west-1", "fips-dkr-us-west-1"],
["us-west-1", "fips-prod-us-west-1"],
])(`returns "%s" for "%s"`, (output, input) => {
expect(getRealRegion(input)).toStrictEqual(output);
});
});
});
8 changes: 8 additions & 0 deletions packages/config-resolver/src/regionConfig/getRealRegion.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { isFipsRegion } from "./isFipsRegion";

export const getRealRegion = (region: string) =>
isFipsRegion(region)
? ["fips-aws-global", "aws-fips"].includes(region)
? "us-east-1"
: region.replace(/fips-(dkr-|prod-)?|-fips/, "")
: region;
15 changes: 0 additions & 15 deletions packages/config-resolver/src/regionConfig/normalizeRegion.spec.ts

This file was deleted.

9 changes: 0 additions & 9 deletions packages/config-resolver/src/regionConfig/normalizeRegion.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,28 +1,85 @@
import { normalizeRegion } from "./normalizeRegion";
import { getRealRegion } from "./getRealRegion";
import { isFipsRegion } from "./isFipsRegion";
import { resolveRegionConfig } from "./resolveRegionConfig";

jest.mock("./normalizeRegion");
jest.mock("./getRealRegion");
jest.mock("./isFipsRegion");

describe("RegionConfig", () => {
const mockRegionProvider = () => Promise.resolve("mockRegion");
const mockRegion = "mockRegion";
const mockRealRegion = "mockRealRegion";
const mockUseFipsEndpoint = () => Promise.resolve(false);

beforeEach(() => {
(normalizeRegion as jest.Mock).mockReturnValue(mockRegionProvider);
(getRealRegion as jest.Mock).mockReturnValue(mockRealRegion);
(isFipsRegion as jest.Mock).mockReturnValue(false);
});

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

it("assigns value returned by normalizeRegion to region", async () => {
const region = "mockRegion";
expect(resolveRegionConfig({ region }).region).toBe(mockRegionProvider);
expect(normalizeRegion).toHaveBeenCalledTimes(1);
expect(normalizeRegion).toHaveBeenCalledWith(region);
describe("region", () => {
it("return normalized value with real region if passed as a string", async () => {
const resolvedRegionConfig = resolveRegionConfig({ region: mockRegion, useFipsEndpoint: mockUseFipsEndpoint });
const resolvedRegion = await resolvedRegionConfig.region();
expect(resolvedRegion).toBe(mockRealRegion);
expect(getRealRegion).toHaveBeenCalledTimes(1);
expect(getRealRegion).toHaveBeenCalledWith(mockRegion);
});

it("return provider with real region if passed as a Provider", async () => {
const resolvedRegionConfig = resolveRegionConfig({
region: () => Promise.resolve(mockRegion),
useFipsEndpoint: mockUseFipsEndpoint,
});
const resolvedRegion = await resolvedRegionConfig.region();
expect(resolvedRegion).toBe(mockRealRegion);
expect(getRealRegion).toHaveBeenCalledTimes(1);
expect(getRealRegion).toHaveBeenCalledWith(mockRegion);
});

it("throw if region is not supplied", () => {
expect(() => resolveRegionConfig({ useFipsEndpoint: mockUseFipsEndpoint })).toThrow();
});
});

it("throw if region is not supplied", () => {
expect(() => resolveRegionConfig({})).toThrow();
expect(normalizeRegion).not.toHaveBeenCalled();
describe("useFipsEndpoint", () => {
let mockRegionProvider;
let mockUseFipsEndpoint;

beforeEach(() => {
mockRegionProvider = jest.fn().mockResolvedValueOnce(Promise.resolve(mockRegion));
mockUseFipsEndpoint = jest.fn().mockResolvedValueOnce(Promise.resolve(false));
});

afterEach(() => {
expect(isFipsRegion).toHaveBeenCalledTimes(1);
expect(isFipsRegion).toHaveBeenCalledWith(mockRegion);
expect(mockRegionProvider).toHaveBeenCalledTimes(1);
});

it("returns Provider which returns true for FIPS endpoints", async () => {
(isFipsRegion as jest.Mock).mockReturnValue(true);
const resolvedRegionConfig = resolveRegionConfig({
region: mockRegionProvider,
useFipsEndpoint: mockUseFipsEndpoint,
});

const useFipsEndpoint = await resolvedRegionConfig.useFipsEndpoint();
expect(useFipsEndpoint).toStrictEqual(true);
expect(mockUseFipsEndpoint).not.toHaveBeenCalled();
});

it("returns passed Provider if endpoint is not FIPS", async () => {
const resolvedRegionConfig = resolveRegionConfig({
region: mockRegionProvider,
useFipsEndpoint: mockUseFipsEndpoint,
});

const useFipsEndpoint = await resolvedRegionConfig.useFipsEndpoint();
expect(useFipsEndpoint).toStrictEqual(false);
expect(mockUseFipsEndpoint).toHaveBeenCalledTimes(1);
});
});
});
32 changes: 29 additions & 3 deletions packages/config-resolver/src/regionConfig/resolveRegionConfig.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import { Provider } from "@aws-sdk/types";

import { normalizeRegion } from "./normalizeRegion";
import { getRealRegion } from "./getRealRegion";
import { isFipsRegion } from "./isFipsRegion";

export interface RegionInputConfig {
/**
* The AWS region to which this client will send requests
*/
region?: string | Provider<string>;

/**
* Enables FIPS compatible endpoints.
*/
useFipsEndpoint?: boolean | Provider<boolean>;
}

interface PreviouslyResolved {}
Expand All @@ -16,14 +22,34 @@ export interface RegionResolvedConfig {
* Resolved value for input config {@link RegionInputConfig.region}
*/
region: Provider<string>;

/**
* Resolved value for input {@link RegionInputConfig.useFipsEndpoint}
*/
useFipsEndpoint: Provider<boolean>;
}

export const resolveRegionConfig = <T>(input: T & RegionInputConfig & PreviouslyResolved): T & RegionResolvedConfig => {
if (!input.region) {
const { region, useFipsEndpoint } = input;
if (!region) {
throw new Error("Region is missing");
}

return {
...input,
region: normalizeRegion(input.region!),
region: async () => {
if (typeof region === "string") {
return getRealRegion(region);
}
const providedRegion = await region();
return getRealRegion(providedRegion);
},
useFipsEndpoint: async () => {
const providedRegion = typeof region === "string" ? region : await region();
if (isFipsRegion(providedRegion)) {
return true;
}
return typeof useFipsEndpoint === "boolean" ? Promise.resolve(useFipsEndpoint) : useFipsEndpoint!();
},
};
};
12 changes: 6 additions & 6 deletions packages/config-resolver/src/regionInfo/getRegionInfo.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,9 @@ describe(getRegionInfo.name, () => {
partitionHostname: mockPartitionHostname,
});
expect(getResolvedPartition).toHaveBeenCalledWith(mockRegion, mockGetResolvedPartitionOptions);
expect(getResolvedSigningRegion).toHaveBeenCalledWith(mockRegion, {
hostname: mockHostname,
expect(getResolvedSigningRegion).toHaveBeenCalledWith(mockHostname, {
regionRegex: mockRegionRegex,
useFipsEndpoint: false,
});
});
});
Expand Down Expand Up @@ -169,10 +169,10 @@ describe(getRegionInfo.name, () => {
partitionHostname: mockPartitionHostname,
});
expect(getResolvedPartition).toHaveBeenCalledWith(mockRegion, mockGetResolvedPartitionOptions);
expect(getResolvedSigningRegion).toHaveBeenCalledWith(mockRegion, {
hostname: mockHostname,
expect(getResolvedSigningRegion).toHaveBeenCalledWith(mockHostname, {
signingRegion: mockSigningRegion,
regionRegex: mockRegionRegex,
useFipsEndpoint: false,
});
});
});
Expand Down Expand Up @@ -232,9 +232,9 @@ describe(getRegionInfo.name, () => {
partitionHostname: mockPartitionHostname,
});
expect(getResolvedPartition).toHaveBeenCalledWith(mockRegion, mockGetResolvedPartitionOptions);
expect(getResolvedSigningRegion).toHaveBeenCalledWith(mockRegion, {
hostname: mockHostname,
expect(getResolvedSigningRegion).toHaveBeenCalledWith(mockHostname, {
regionRegex: mockRegionRegex,
useFipsEndpoint: false,
});
});
});
Expand Down
4 changes: 2 additions & 2 deletions packages/config-resolver/src/regionInfo/getRegionInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ export const getRegionInfo = (
throw new Error(`Endpoint resolution failed for: ${{ resolvedRegion, useFipsEndpoint, useDualstackEndpoint }}`);
}

const signingRegion = getResolvedSigningRegion(region, {
hostname,
const signingRegion = getResolvedSigningRegion(hostname, {
signingRegion: regionHash[resolvedRegion]?.signingRegion,
regionRegex: partitionHash[partition].regionRegex,
useFipsEndpoint,
});

return {
Expand Down
Loading

0 comments on commit af5b00e

Please sign in to comment.