Skip to content

Commit

Permalink
fix(config-resolver): get signingRegion from regionRegex if not prese…
Browse files Browse the repository at this point in the history
…nt for FIPS (#2936)
  • Loading branch information
trivikr committed Oct 27, 2021
1 parent 4df3162 commit 79bbc43
Show file tree
Hide file tree
Showing 8 changed files with 299 additions and 156 deletions.
19 changes: 18 additions & 1 deletion packages/config-resolver/src/regionInfo/getRegionInfo.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { getRegionInfo } from "./getRegionInfo";
import { getResolvedHostname } from "./getResolvedHostname";
import { getResolvedPartition } from "./getResolvedPartition";
import { getResolvedSigningRegion } from "./getResolvedSigningRegion";
import { PartitionHash } from "./PartitionHash";
import { RegionHash } from "./RegionHash";

jest.mock("./getResolvedHostname");
jest.mock("./getResolvedPartition");
jest.mock("./getResolvedSigningRegion");

describe(getRegionInfo.name, () => {
const mockPartition = "mockPartition";
Expand Down Expand Up @@ -63,6 +65,7 @@ describe(getRegionInfo.name, () => {
beforeEach(() => {
(getResolvedHostname as jest.Mock).mockReturnValue(mockHostname);
(getResolvedPartition as jest.Mock).mockReturnValue(mockPartition);
(getResolvedSigningRegion as jest.Mock).mockReturnValue(undefined);
});

afterEach(() => {
Expand Down Expand Up @@ -92,10 +95,14 @@ describe(getRegionInfo.name, () => {
partitionHostname: mockGetRegionInfoOptions.partitionHash[mockPartition]?.hostname,
});
expect(getResolvedPartition).toHaveBeenCalledWith(mockRegion, mockGetResolvedPartitionOptions);
expect(getResolvedSigningRegion).toHaveBeenCalledWith(mockRegion, {
hostname: mockHostname,
regionRegex: mockRegionRegex,
});
});
});

describe("returns signingRegion if present in regionHash", () => {
describe("returns signingRegion if resolved by getResolvedSigningRegion", () => {
const getMockRegionHashWithSigningRegion = (
regionCase: RegionCase,
mockRegionHash: RegionHash,
Expand All @@ -118,6 +125,7 @@ describe(getRegionInfo.name, () => {

it.each(Object.values(RegionCase))("%s", (regionCase) => {
const mockSigningRegion = "mockSigningRegion";
(getResolvedSigningRegion as jest.Mock).mockReturnValueOnce(mockSigningRegion);
const mockRegionHash = getMockRegionHash(regionCase);
const mockPartitionHash = getMockPartitionHash(regionCase);

Expand Down Expand Up @@ -146,6 +154,11 @@ describe(getRegionInfo.name, () => {
partitionHostname: mockGetRegionInfoOptions.partitionHash[mockPartition]?.hostname,
});
expect(getResolvedPartition).toHaveBeenCalledWith(mockRegion, mockGetResolvedPartitionOptions);
expect(getResolvedSigningRegion).toHaveBeenCalledWith(mockRegion, {
hostname: mockHostname,
signingRegion: mockSigningRegion,
regionRegex: mockRegionRegex,
});
});
});

Expand Down Expand Up @@ -199,6 +212,10 @@ describe(getRegionInfo.name, () => {
partitionHostname: mockGetRegionInfoOptions.partitionHash[mockPartition]?.hostname,
});
expect(getResolvedPartition).toHaveBeenCalledWith(mockRegion, mockGetResolvedPartitionOptions);
expect(getResolvedSigningRegion).toHaveBeenCalledWith(mockRegion, {
hostname: mockHostname,
regionRegex: mockRegionRegex,
});
});
});
});
23 changes: 15 additions & 8 deletions packages/config-resolver/src/regionInfo/getRegionInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { RegionInfo } from "@aws-sdk/types";

import { getResolvedHostname } from "./getResolvedHostname";
import { getResolvedPartition } from "./getResolvedPartition";
import { getResolvedSigningRegion } from "./getResolvedSigningRegion";
import { PartitionHash } from "./PartitionHash";
import { RegionHash } from "./RegionHash";

Expand All @@ -17,17 +18,23 @@ export const getRegionInfo = (
): RegionInfo => {
const partition = getResolvedPartition(region, { partitionHash });
const resolvedRegion = partitionHash[partition]?.endpoint ?? region;

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

return {
partition,
signingService,
hostname: getResolvedHostname(resolvedRegion, {
signingService,
regionHostname: regionHash[resolvedRegion]?.hostname,
partitionHostname: partitionHash[partition]?.hostname,
}),
...(regionHash[resolvedRegion]?.signingRegion && {
signingRegion: regionHash[resolvedRegion].signingRegion,
}),
hostname,
...(signingRegion && { signingRegion }),
...(regionHash[resolvedRegion]?.signingService && {
signingService: regionHash[resolvedRegion].signingService,
}),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { getResolvedSigningRegion } from "./getResolvedSigningRegion";
import { isFipsRegion } from "./isFipsRegion";

jest.mock("./isFipsRegion");

describe(getResolvedSigningRegion.name, () => {
const mockRegion = "mockRegion";
const mockSigningRegion = "mockSigningRegion";
const mockHostname = "mockHostname";
const mockRegionRegex = "mockRegionRegex";

const mockOptions = {
hostname: mockHostname,
regionRegex: mockRegionRegex,
};

beforeEach(() => {
(isFipsRegion as jest.Mock).mockReturnValue(false);
});

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

it("returns signingRegion if passed in options", () => {
expect(getResolvedSigningRegion(mockRegion, { ...mockOptions, signingRegion: mockSigningRegion })).toEqual(
mockSigningRegion
);
expect(isFipsRegion).not.toHaveBeenCalled();
});

describe("returns undefined if signingRegion is not present and", () => {
it("region is not FIPS", () => {
expect(getResolvedSigningRegion(mockRegion, mockOptions)).not.toBeDefined();
expect(isFipsRegion).toHaveBeenCalledTimes(1);
expect(isFipsRegion).toHaveBeenCalledWith(mockRegion);
});

it("regionRegex does not return a match in hostname", () => {
(isFipsRegion as jest.Mock).mockReturnValueOnce(true);
const matchSpy = jest.spyOn(String.prototype, "match").mockReturnValueOnce(null);

expect(getResolvedSigningRegion(mockRegion, mockOptions)).not.toBeDefined();
expect(matchSpy).toHaveBeenCalledTimes(1);
expect(matchSpy).toHaveBeenCalledWith(mockRegionRegex);
expect(isFipsRegion).toHaveBeenCalledTimes(1);
expect(isFipsRegion).toHaveBeenCalledWith(mockRegion);
});

it("region is not present between dots in a hostname", () => {
const regionInHostname = "us-east-1";
(isFipsRegion as jest.Mock).mockReturnValueOnce(true);

expect(
getResolvedSigningRegion(mockRegion, {
...mockOptions,
hostname: `test-${regionInHostname}.amazonaws.com`,
regionRegex: "^(us|eu|ap|sa|ca|me|af)\\-\\w+\\-\\d+$",
})
).not.toBeDefined();
expect(isFipsRegion).toHaveBeenCalledTimes(1);
expect(isFipsRegion).toHaveBeenCalledWith(mockRegion);
});
});

it("returns region from hostname if signingRegion is not present", () => {
const regionInHostname = "us-east-1";
(isFipsRegion as jest.Mock).mockReturnValueOnce(true);

expect(
getResolvedSigningRegion(mockRegion, {
...mockOptions,
hostname: `test.${regionInHostname}.amazonaws.com`,
regionRegex: "^(us|eu|ap|sa|ca|me|af)\\-\\w+\\-\\d+$",
})
).toEqual(regionInHostname);
expect(isFipsRegion).toHaveBeenCalledTimes(1);
expect(isFipsRegion).toHaveBeenCalledWith(mockRegion);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { isFipsRegion } from "./isFipsRegion";

export interface GetResolvedSigningRegionOptions {
hostname: string;
regionRegex: string;
signingRegion?: string;
}

export const getResolvedSigningRegion = (
region: string,
{ hostname, signingRegion, regionRegex }: GetResolvedSigningRegionOptions
) => {
if (signingRegion) {
return signingRegion;
} else if (isFipsRegion(region)) {
const regionRegexJs = regionRegex.replace("\\\\", "\\").replace(/^\^/g, "\\.").replace(/\$$/g, "\\.");
const regionRegexmatchArray = hostname.match(regionRegexJs);
if (regionRegexmatchArray) {
return regionRegexmatchArray[0].slice(1, -1);
}
}
};
15 changes: 15 additions & 0 deletions packages/config-resolver/src/regionInfo/isFipsRegion.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { isFipsRegion } from "./isFipsRegion";

describe(isFipsRegion.name, () => {
it.each([
[true, "fips-us-east-1"],
[true, "us-east-1-fips"],
[false, "us-east-1"],
])(`returns %s for region "%s"`, (output, input) => {
expect(isFipsRegion(input)).toEqual(output);
});

it.each([undefined, null])("returns false for %s", (input) => {
expect(isFipsRegion(input)).toEqual(false);
});
});
2 changes: 2 additions & 0 deletions packages/config-resolver/src/regionInfo/isFipsRegion.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const isFipsRegion = (region: string) =>
typeof region === "string" && (region.startsWith("fips-") || region.endsWith("-fips"));
147 changes: 147 additions & 0 deletions tests/functional/endpoints/fips/test_cases_supported.json
Original file line number Diff line number Diff line change
Expand Up @@ -3925,5 +3925,152 @@
"region": "fips-us-iso-east-1",
"signingRegion": "us-iso-east-1",
"hostname": "elasticfilesystem-fips.us-iso-east-1.c2s.ic.gov"
},
{
"endpointPrefix": "data.iot",
"sdkId": "IoT Data Plane",
"region": "fips-ca-central-1",
"signingRegion": "ca-central-1",
"hostname": "data.iot-fips.ca-central-1.amazonaws.com"
},
{
"endpointPrefix": "data.iot",
"sdkId": "IoT Data Plane",
"region": "fips-us-east-1",
"signingRegion": "us-east-1",
"hostname": "data.iot-fips.us-east-1.amazonaws.com"
},
{
"endpointPrefix": "data.iot",
"sdkId": "IoT Data Plane",
"region": "fips-us-east-2",
"signingRegion": "us-east-2",
"hostname": "data.iot-fips.us-east-2.amazonaws.com"
},
{
"endpointPrefix": "data.iot",
"sdkId": "IoT Data Plane",
"region": "fips-us-west-1",
"signingRegion": "us-west-1",
"hostname": "data.iot-fips.us-west-1.amazonaws.com"
},
{
"endpointPrefix": "data.iot",
"sdkId": "IoT Data Plane",
"region": "fips-us-west-2",
"signingRegion": "us-west-2",
"hostname": "data.iot-fips.us-west-2.amazonaws.com"
},
{
"endpointPrefix": "iot",
"sdkId": "IoT",
"region": "fips-ca-central-1",
"signingRegion": "ca-central-1",
"hostname": "iot-fips.ca-central-1.amazonaws.com"
},
{
"endpointPrefix": "iot",
"sdkId": "IoT",
"region": "fips-us-east-1",
"signingRegion": "us-east-1",
"hostname": "iot-fips.us-east-1.amazonaws.com"
},
{
"endpointPrefix": "iot",
"sdkId": "IoT",
"region": "fips-us-east-2",
"signingRegion": "us-east-2",
"hostname": "iot-fips.us-east-2.amazonaws.com"
},
{
"endpointPrefix": "iot",
"sdkId": "IoT",
"region": "fips-us-west-1",
"signingRegion": "us-west-1",
"hostname": "iot-fips.us-west-1.amazonaws.com"
},
{
"endpointPrefix": "iot",
"sdkId": "IoT",
"region": "fips-us-west-2",
"signingRegion": "us-west-2",
"hostname": "iot-fips.us-west-2.amazonaws.com"
},
{
"endpointPrefix": "s3",
"sdkId": "S3",
"region": "fips-accesspoint-ca-central-1",
"signingRegion": "ca-central-1",
"hostname": "s3-accesspoint-fips.ca-central-1.amazonaws.com"
},
{
"endpointPrefix": "s3",
"sdkId": "S3",
"region": "fips-accesspoint-us-east-1",
"signingRegion": "us-east-1",
"hostname": "s3-accesspoint-fips.us-east-1.amazonaws.com"
},
{
"endpointPrefix": "s3",
"sdkId": "S3",
"region": "fips-accesspoint-us-east-2",
"signingRegion": "us-east-2",
"hostname": "s3-accesspoint-fips.us-east-2.amazonaws.com"
},
{
"endpointPrefix": "s3",
"sdkId": "S3",
"region": "fips-accesspoint-us-west-1",
"signingRegion": "us-west-1",
"hostname": "s3-accesspoint-fips.us-west-1.amazonaws.com"
},
{
"endpointPrefix": "s3",
"sdkId": "S3",
"region": "fips-accesspoint-us-west-2",
"signingRegion": "us-west-2",
"hostname": "s3-accesspoint-fips.us-west-2.amazonaws.com"
},
{
"endpointPrefix": "data.iot",
"sdkId": "IoT Data Plane",
"region": "fips-us-gov-east-1",
"signingRegion": "us-gov-east-1",
"hostname": "data.iot-fips.us-gov-east-1.amazonaws.com"
},
{
"endpointPrefix": "data.iot",
"sdkId": "IoT Data Plane",
"region": "fips-us-gov-west-1",
"signingRegion": "us-gov-west-1",
"hostname": "data.iot-fips.us-gov-west-1.amazonaws.com"
},
{
"endpointPrefix": "iot",
"sdkId": "IoT",
"region": "fips-us-gov-east-1",
"signingRegion": "us-gov-east-1",
"hostname": "iot-fips.us-gov-east-1.amazonaws.com"
},
{
"endpointPrefix": "iot",
"sdkId": "IoT",
"region": "fips-us-gov-west-1",
"signingRegion": "us-gov-west-1",
"hostname": "iot-fips.us-gov-west-1.amazonaws.com"
},
{
"endpointPrefix": "s3",
"sdkId": "S3",
"region": "fips-accesspoint-us-gov-east-1",
"signingRegion": "us-gov-east-1",
"hostname": "s3-accesspoint-fips.us-gov-east-1.amazonaws.com"
},
{
"endpointPrefix": "s3",
"sdkId": "S3",
"region": "fips-accesspoint-us-gov-west-1",
"signingRegion": "us-gov-west-1",
"hostname": "s3-accesspoint-fips.us-gov-west-1.amazonaws.com"
}
]
Loading

0 comments on commit 79bbc43

Please sign in to comment.