Skip to content

Commit d12c98a

Browse files
authored
chore(middleware): replace isFipsRegion checks with useFipsEndpoint config (#2988)
1 parent af5b00e commit d12c98a

File tree

8 files changed

+71
-46
lines changed

8 files changed

+71
-46
lines changed

packages/middleware-bucket-endpoint/src/bucketEndpointMiddleware.spec.ts

+3
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ describe("bucketEndpointMiddleware", () => {
6767
baseHostname: requestInput.hostname,
6868
clientRegion: mockRegion,
6969
accelerateEndpoint: false,
70+
fipsEndpoint: false,
7071
dualstackEndpoint: false,
7172
pathStyleEndpoint: false,
7273
tlsCompatible: true,
@@ -95,6 +96,7 @@ describe("bucketEndpointMiddleware", () => {
9596
clientRegion: mockRegion,
9697
accelerateEndpoint: true,
9798
dualstackEndpoint: true,
99+
fipsEndpoint: false,
98100
pathStyleEndpoint: true,
99101
tlsCompatible: false,
100102
isCustomEndpoint: true,
@@ -129,6 +131,7 @@ describe("bucketEndpointMiddleware", () => {
129131
baseHostname: requestInput.hostname,
130132
clientRegion: mockRegion,
131133
accelerateEndpoint: false,
134+
fipsEndpoint: false,
132135
dualstackEndpoint: false,
133136
pathStyleEndpoint: false,
134137
tlsCompatible: true,

packages/middleware-bucket-endpoint/src/bucketEndpointMiddleware.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import {
1212
import { parse as parseArn, validate as validateArn } from "@aws-sdk/util-arn-parser";
1313

1414
import { bucketHostname } from "./bucketHostname";
15-
import { getPseudoRegion } from "./bucketHostnameUtils";
1615
import { BucketEndpointResolvedConfig } from "./configurations";
1716

1817
export const bucketEndpointMiddleware =
@@ -30,7 +29,7 @@ export const bucketEndpointMiddleware =
3029
request.hostname = bucketName;
3130
} else if (validateArn(bucketName)) {
3231
const bucketArn = parseArn(bucketName);
33-
const clientRegion = getPseudoRegion(await options.region());
32+
const clientRegion = await options.region();
3433
const useDualstackEndpoint = await options.useDualstackEndpoint();
3534
const useFipsEndpoint = await options.useFipsEndpoint();
3635
const { partition, signingRegion = clientRegion } =
@@ -46,6 +45,7 @@ export const bucketEndpointMiddleware =
4645
baseHostname: request.hostname,
4746
accelerateEndpoint: options.useAccelerateEndpoint,
4847
dualstackEndpoint: useDualstackEndpoint,
48+
fipsEndpoint: useFipsEndpoint,
4949
pathStyleEndpoint: options.forcePathStyle,
5050
tlsCompatible: request.protocol === "https:",
5151
useArnRegion,
@@ -68,14 +68,16 @@ export const bucketEndpointMiddleware =
6868
request.hostname = hostname;
6969
replaceBucketInPath = bucketEndpoint;
7070
} else {
71-
const clientRegion = getPseudoRegion(await options.region());
71+
const clientRegion = await options.region();
7272
const dualstackEndpoint = await options.useDualstackEndpoint();
73+
const fipsEndpoint = await options.useFipsEndpoint();
7374
const { hostname, bucketEndpoint } = bucketHostname({
7475
bucketName,
7576
clientRegion,
7677
baseHostname: request.hostname,
7778
accelerateEndpoint: options.useAccelerateEndpoint,
7879
dualstackEndpoint,
80+
fipsEndpoint,
7981
pathStyleEndpoint: options.forcePathStyle,
8082
tlsCompatible: request.protocol === "https:",
8183
isCustomEndpoint: options.isCustomEndpoint,

packages/middleware-bucket-endpoint/src/bucketHostname.spec.ts

+16-7
Original file line numberDiff line numberDiff line change
@@ -324,9 +324,9 @@ describe("bucketHostname", () => {
324324
});
325325
});
326326

327-
describe("allows fips client region", () => {
327+
describe("allows client region with fipsEndpoint", () => {
328328
const bucketArn = parseArn("arn:aws-us-gov:s3:us-gov-east-1:123456789012:accesspoint:myendpoint");
329-
const clientRegion = "fips-us-gov-east-1";
329+
const clientRegion = "us-gov-east-1";
330330
const clientPartition = "aws-us-gov";
331331
it("should use client region", () => {
332332
const { bucketEndpoint, hostname } = bucketHostname({
@@ -335,6 +335,7 @@ describe("bucketHostname", () => {
335335
isCustomEndpoint: false,
336336
clientRegion,
337337
clientPartition,
338+
fipsEndpoint: true,
338339
});
339340
expect(bucketEndpoint).toBe(true);
340341
expect(hostname).toBe("myendpoint-123456789012.s3-accesspoint-fips.us-gov-east-1.amazonaws.com");
@@ -348,6 +349,7 @@ describe("bucketHostname", () => {
348349
clientRegion,
349350
clientPartition,
350351
useArnRegion: true,
352+
fipsEndpoint: true,
351353
});
352354
expect(bucketEndpoint).toBe(true);
353355
expect(hostname).toBe("myendpoint-123456789012.s3-accesspoint-fips.us-gov-east-1.amazonaws.com");
@@ -362,15 +364,16 @@ describe("bucketHostname", () => {
362364
clientPartition,
363365
useArnRegion: true,
364366
dualstackEndpoint: true,
367+
fipsEndpoint: true,
365368
});
366369
expect(bucketEndpoint).toBe(true);
367370
expect(hostname).toBe("myendpoint-123456789012.s3-accesspoint-fips.dualstack.us-gov-east-1.amazonaws.com");
368371
});
369372
});
370373

371-
describe("validates FIPS client region matching ARN region", () => {
374+
describe("validates client region with fips endpoint matching ARN region", () => {
372375
const bucketArn = parseArn("arn:aws-us-gov:s3:us-gov-west-1:123456789012:accesspoint:myendpoint");
373-
const clientRegion = "fips-us-gov-east-1";
376+
const clientRegion = "us-gov-east-1";
374377
const clientPartition = "aws-us-gov";
375378
it("should throw client region doesn't match arn region", () => {
376379
expect(() =>
@@ -380,6 +383,7 @@ describe("bucketHostname", () => {
380383
isCustomEndpoint: false,
381384
clientRegion,
382385
clientPartition,
386+
fipsEndpoint: true,
383387
})
384388
).toThrowError();
385389
});
@@ -393,6 +397,7 @@ describe("bucketHostname", () => {
393397
clientRegion,
394398
clientPartition,
395399
useArnRegion: true,
400+
fipsEndpoint: true,
396401
})
397402
).toThrowError();
398403
});
@@ -693,7 +698,7 @@ describe("bucketHostname", () => {
693698

694699
describe("fips region", () => {
695700
it("should throw if client is using fips region", () => {
696-
const clientRegion = "fips-us-gov-east-1";
701+
const clientRegion = "us-gov-east-1";
697702
const clientPartition = "aws-us-gov";
698703
expect.assertions(2);
699704
expect(() => {
@@ -705,6 +710,7 @@ describe("bucketHostname", () => {
705710
isCustomEndpoint: false,
706711
clientRegion,
707712
clientPartition,
713+
fipsEndpoint: true,
708714
});
709715
}).toThrow("FIPS region is not supported");
710716

@@ -718,6 +724,7 @@ describe("bucketHostname", () => {
718724
clientRegion,
719725
clientPartition,
720726
useArnRegion: true,
727+
fipsEndpoint: true,
721728
});
722729
}).toThrow("FIPS region is not supported");
723730
});
@@ -962,9 +969,10 @@ describe("bucketHostname", () => {
962969
bucketName: parseArn(arn),
963970
baseHostname: `s3.${region}.amazonaws.com`,
964971
isCustomEndpoint: false,
965-
clientRegion,
972+
clientRegion: clientRegion.startsWith("fips-") ? clientRegion.replace(/fips-/, "") : clientRegion,
966973
useArnRegion,
967974
clientPartition,
975+
fipsEndpoint: clientRegion.startsWith("fips-"),
968976
});
969977
expect(bucketEndpoint).toBe(true);
970978
expect(hostname).toBe(expectedEndpoint);
@@ -1080,8 +1088,9 @@ describe("bucketHostname", () => {
10801088
baseHostname: `s3.${region}.amazonaws.com`,
10811089
isCustomEndpoint: false,
10821090
useArnRegion,
1083-
clientRegion,
1091+
clientRegion: clientRegion.startsWith("fips-") ? clientRegion.replace(/fips-/, "") : clientRegion,
10841092
clientPartition,
1093+
fipsEndpoint: clientRegion.startsWith("fips-"),
10851094
});
10861095
// should never get here
10871096
fail();

packages/middleware-bucket-endpoint/src/bucketHostname.ts

+23-12
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,10 @@ import {
55
BucketHostnameParams,
66
DOT_PATTERN,
77
getArnResources,
8-
getPseudoRegion,
98
getSuffix,
109
getSuffixForArnEndpoint,
1110
isBucketNameOptions,
1211
isDnsCompatibleBucketName,
13-
isFipsRegion,
1412
validateAccountId,
1513
validateArnEndpointOptions,
1614
validateCustomEndpoint,
@@ -48,6 +46,7 @@ const getEndpointFromBucketName = ({
4846
baseHostname,
4947
bucketName,
5048
dualstackEndpoint = false,
49+
fipsEndpoint = false,
5150
pathStyleEndpoint = false,
5251
tlsCompatible = true,
5352
isCustomEndpoint = false,
@@ -79,6 +78,7 @@ const getEndpointFromArn = (options: ArnHostnameParams): BucketHostname => {
7978
const {
8079
pathStyleEndpoint,
8180
accelerateEndpoint = false,
81+
fipsEndpoint = false,
8282
tlsCompatible = true,
8383
bucketName,
8484
clientPartition = "aws",
@@ -106,6 +106,7 @@ const getEndpointFromArn = (options: ArnHostnameParams): BucketHostname => {
106106

107107
const getEndpointFromObjectLambdaArn = ({
108108
dualstackEndpoint = false,
109+
fipsEndpoint = false,
109110
tlsCompatible = true,
110111
useArnRegion,
111112
clientRegion,
@@ -120,7 +121,13 @@ const getEndpointFromObjectLambdaArn = ({
120121
}): BucketHostname => {
121122
const { accountId, region, service } = bucketName;
122123
validateRegionalClient(clientRegion);
123-
validateRegion(region, { useArnRegion, clientRegion, clientSigningRegion, allowFipsRegion: true });
124+
validateRegion(region, {
125+
useArnRegion,
126+
clientRegion,
127+
clientSigningRegion,
128+
allowFipsRegion: true,
129+
useFipsEndpoint: fipsEndpoint,
130+
});
124131
validateNoDualstack(dualstackEndpoint);
125132
const DNSHostLabel = `${accesspointName}-${accountId}`;
126133
validateDNSHostLabel(DNSHostLabel, { tlsCompatible });
@@ -130,9 +137,7 @@ const getEndpointFromObjectLambdaArn = ({
130137

131138
return {
132139
bucketEndpoint: true,
133-
hostname: `${DNSHostLabel}.${service}${isFipsRegion(clientRegion) ? "-fips" : ""}.${getPseudoRegion(
134-
endpointRegion
135-
)}.${hostnameSuffix}`,
140+
hostname: `${DNSHostLabel}.${service}${fipsEndpoint ? "-fips" : ""}.${endpointRegion}.${hostnameSuffix}`,
136141
signingRegion,
137142
signingService: service,
138143
};
@@ -165,22 +170,23 @@ const getEndpointFromOutpostArn = ({
165170
bucketName,
166171
outpostId,
167172
dualstackEndpoint = false,
173+
fipsEndpoint = false,
168174
tlsCompatible = true,
169175
accesspointName,
170176
isCustomEndpoint,
171177
hostnameSuffix,
172178
}: ArnHostnameParams & { outpostId: string; accesspointName: string; hostnameSuffix: string }): BucketHostname => {
173179
// if this is an Outpost ARN
174180
validateRegionalClient(clientRegion);
175-
validateRegion(bucketName.region, { useArnRegion, clientRegion, clientSigningRegion });
181+
validateRegion(bucketName.region, { useArnRegion, clientRegion, clientSigningRegion, useFipsEndpoint: fipsEndpoint });
176182
const DNSHostLabel = `${accesspointName}-${bucketName.accountId}`;
177183
validateDNSHostLabel(DNSHostLabel, { tlsCompatible });
178184
const endpointRegion = useArnRegion ? bucketName.region : clientRegion;
179185
const signingRegion = useArnRegion ? bucketName.region : clientSigningRegion;
180186
validateOutpostService(bucketName.service);
181187
validateDNSHostLabel(outpostId, { tlsCompatible });
182188
validateNoDualstack(dualstackEndpoint);
183-
validateNoFIPS(endpointRegion);
189+
validateNoFIPS(fipsEndpoint);
184190
const hostnamePrefix = `${DNSHostLabel}.${outpostId}`;
185191
return {
186192
bucketEndpoint: true,
@@ -196,14 +202,21 @@ const getEndpointFromAccessPointArn = ({
196202
clientSigningRegion = clientRegion,
197203
bucketName,
198204
dualstackEndpoint = false,
205+
fipsEndpoint = false,
199206
tlsCompatible = true,
200207
accesspointName,
201208
isCustomEndpoint,
202209
hostnameSuffix,
203210
}: ArnHostnameParams & { accesspointName: string; hostnameSuffix: string }): BucketHostname => {
204211
// construct endpoint from Accesspoint ARN
205212
validateRegionalClient(clientRegion);
206-
validateRegion(bucketName.region, { useArnRegion, clientRegion, clientSigningRegion, allowFipsRegion: true });
213+
validateRegion(bucketName.region, {
214+
useArnRegion,
215+
clientRegion,
216+
clientSigningRegion,
217+
allowFipsRegion: true,
218+
useFipsEndpoint: fipsEndpoint,
219+
});
207220
const hostnamePrefix = `${accesspointName}-${bucketName.accountId}`;
208221
validateDNSHostLabel(hostnamePrefix, { tlsCompatible });
209222
const endpointRegion = useArnRegion ? bucketName.region : clientRegion;
@@ -214,9 +227,7 @@ const getEndpointFromAccessPointArn = ({
214227
hostname: `${hostnamePrefix}${
215228
isCustomEndpoint
216229
? ""
217-
: `.s3-accesspoint${isFipsRegion(clientRegion) ? "-fips" : ""}${
218-
dualstackEndpoint ? ".dualstack" : ""
219-
}.${getPseudoRegion(endpointRegion)}`
230+
: `.s3-accesspoint${fipsEndpoint ? "-fips" : ""}${dualstackEndpoint ? ".dualstack" : ""}.${endpointRegion}`
220231
}.${hostnameSuffix}`,
221232
signingRegion,
222233
};

packages/middleware-bucket-endpoint/src/bucketHostnameUtils.ts

+8-18
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export interface BucketHostnameParams {
1919
clientRegion: string;
2020
accelerateEndpoint?: boolean;
2121
dualstackEndpoint?: boolean;
22+
fipsEndpoint?: boolean;
2223
pathStyleEndpoint?: boolean;
2324
tlsCompatible?: boolean;
2425
}
@@ -35,12 +36,6 @@ export const isBucketNameOptions = (
3536
options: BucketHostnameParams | ArnHostnameParams
3637
): options is BucketHostnameParams => typeof options.bucketName === "string";
3738

38-
/**
39-
* Get pseudo region from supplied region. For example, if supplied with `fips-us-west-2`, it returns `us-west-2`.
40-
* @internal
41-
*/
42-
export const getPseudoRegion = (region: string) => (isFipsRegion(region) ? region.replace(/fips-|-fips/, "") : region);
43-
4439
/**
4540
* Determines whether a given string is DNS compliant per the rules outlined by
4641
* S3. Length, capitaization, and leading dot restrictions are enforced by the
@@ -128,12 +123,13 @@ export const validateRegion = (
128123
allowFipsRegion?: boolean;
129124
clientRegion: string;
130125
clientSigningRegion: string;
126+
useFipsEndpoint: boolean;
131127
}
132128
) => {
133129
if (region === "") {
134130
throw new Error("ARN region is empty");
135131
}
136-
if (isFipsRegion(options.clientRegion)) {
132+
if (options.useFipsEndpoint) {
137133
if (!options.allowFipsRegion) {
138134
throw new Error("FIPS region is not supported");
139135
} else if (!isEqualRegions(region, options.clientRegion)) {
@@ -154,18 +150,12 @@ export const validateRegion = (
154150
* @param region
155151
*/
156152
export const validateRegionalClient = (region: string) => {
157-
if (["s3-external-1", "aws-global"].includes(getPseudoRegion(region))) {
153+
if (["s3-external-1", "aws-global"].includes(region)) {
158154
throw new Error(`Client region ${region} is not regional`);
159155
}
160156
};
161157

162-
/**
163-
* @internal
164-
*/
165-
export const isFipsRegion = (region: string) => region.startsWith("fips-") || region.endsWith("-fips");
166-
167-
const isEqualRegions = (regionA: string, regionB: string) =>
168-
regionA === regionB || getPseudoRegion(regionA) === regionB || regionA === getPseudoRegion(regionB);
158+
const isEqualRegions = (regionA: string, regionB: string) => regionA === regionB;
169159

170160
/**
171161
* Validate an account ID
@@ -250,11 +240,11 @@ export const validateNoDualstack = (dualstackEndpoint?: boolean) => {
250240
};
251241

252242
/**
253-
* Validate region is not appended or prepended with a `fips-`
243+
* Validate fips endpoint is not set up.
254244
* @internal
255245
*/
256-
export const validateNoFIPS = (region?: string) => {
257-
if (isFipsRegion(region ?? "")) throw new Error(`FIPS region is not supported with Outpost, got ${region}`);
246+
export const validateNoFIPS = (useFipsEndpoint?: boolean) => {
247+
if (useFipsEndpoint) throw new Error(`FIPS region is not supported with Outpost.`);
258248
};
259249

260250
/**

packages/middleware-bucket-endpoint/src/index.ts

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ export * from "./bucketHostname";
55
export * from "./configurations";
66
export {
77
getArnResources,
8-
getPseudoRegion,
98
getSuffixForArnEndpoint,
109
validateOutpostService,
1110
validatePartition,

0 commit comments

Comments
 (0)