Skip to content

Commit

Permalink
fix: support FIPS in endpoint heuristics (#3923)
Browse files Browse the repository at this point in the history
  • Loading branch information
trivikr authored Oct 21, 2021
1 parent 48e996b commit 5f06f52
Show file tree
Hide file tree
Showing 11 changed files with 4,450 additions and 12 deletions.
5 changes: 5 additions & 0 deletions .changes/next-release/bugfix-endpoint-20c8cdb9.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"type": "bugfix",
"category": "endpoint",
"description": "Support FIPS in endpoint heuristics"
}
35 changes: 34 additions & 1 deletion lib/region_config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ var regionConfig = require('./region_config_data.json');

function generateRegionPrefix(region) {
if (!region) return null;
if (isFipsRegion(region)) {
if (isFipsCnRegion(region)) return 'fips-cn-*';
return 'fips-*';
}

var parts = region.split('-');
if (parts.length < 3) return null;
Expand Down Expand Up @@ -56,6 +60,12 @@ function configureEndpoint(service) {
);
}

// set FIPS signingRegion and endpoint.
if (isFipsRegion(service.config.region)) {
config = util.copy(config);
service.signingRegion = getRealRegion(service.config.region);
}

// set global endpoint
service.isGlobalEndpoint = !!config.globalEndpoint;
if (config.signingRegion) {
Expand Down Expand Up @@ -90,10 +100,33 @@ function getEndpointSuffix(region) {
return defaultSuffix;
}

function isFipsRegion(region) {
return region && (region.startsWith('fips-') || region.endsWith('-fips'));
}

function isFipsCnRegion(region) {
return (
region &&
region.startsWith('fips-cn-') ||
(region.startsWith('cn-') && region.endsWith('-fips'))
);
}

function getRealRegion(region) {
return isFipsRegion(region)
? ['fips-aws-global', 'aws-fips'].includes(region)
? 'us-east-1'
: region === 'fips-aws-us-gov-global'
? 'us-gov-west-1'
: region.replace(/fips-(dkr-|prod-)?|-fips/, '')
: region;
}

/**
* @api private
*/
module.exports = {
configureEndpoint: configureEndpoint,
getEndpointSuffix: getEndpointSuffix
getEndpointSuffix: getEndpointSuffix,
getRealRegion: getRealRegion,
};
91 changes: 91 additions & 0 deletions lib/region_config_data.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
"*/*": {
"endpoint": "{service}.{region}.amazonaws.com"
},
"fips-*/*": {
"endpoint": "{service}-fips.{region}.amazonaws.com"
},
"fips-cn-*/*": {
"endpoint": "{service}-fips.{region}.amazonaws.com.cn"
},
"cn-*/*": {
"endpoint": "{service}.{region}.amazonaws.com.cn"
},
Expand Down Expand Up @@ -61,6 +67,91 @@
"*/sdb": {
"endpoint": "{service}.{region}.amazonaws.com",
"signatureVersion": "v2"
},

"fips-*/api.ecr": {
"endpoint": "ecr-fips.{region}.amazonaws.com"
},
"fips-*/api.sagemaker": {
"endpoint": "api-fips.sagemaker.{region}.amazonaws.com"
},
"fips-*/batch": {
"endpoint": "fips.batch.{region}.amazonaws.com"
},
"fips-*/streams.dynamodb": {
"endpoint": "dynamodb-fips.{region}.amazonaws.com"
},
"fips-*/route53": {
"endpoint": "route53-fips.amazonaws.com"
},
"fips-*/transcribe": {
"endpoint": "fips.transcribe.{region}.amazonaws.com"
},
"fips-*/waf": {
"endpoint": "waf-fips.amazonaws.com"
},
"fips-us-gov-east-1/acm-pca": {
"endpoint": "acm-pca.{region}.amazonaws.com"
},
"fips-us-gov-west-1/acm-pca": {
"endpoint": "acm-pca.{region}.amazonaws.com"
},
"fips-us-gov-east-1/batch": {
"endpoint": "batch.{region}.amazonaws.com"
},
"fips-us-gov-west-1/batch": {
"endpoint": "batch.{region}.amazonaws.com"
},
"us-gov-east-1-fips/dynamodb": {
"endpoint": "dynamodb.{region}.amazonaws.com"
},
"us-gov-west-1-fips/dynamodb": {
"endpoint": "dynamodb.{region}.amazonaws.com"
},
"fips-us-gov-east-1/elasticloadbalancing": {
"endpoint": "elasticloadbalancing.{region}.amazonaws.com"
},
"fips-us-gov-west-1/elasticloadbalancing": {
"endpoint": "elasticloadbalancing.{region}.amazonaws.com"
},
"us-gov-east-1-fips/guardduty": {
"endpoint": "guardduty.{region}.amazonaws.com"
},
"us-gov-west-1-fips/guardduty": {
"endpoint": "guardduty.{region}.amazonaws.com"
},
"fips-us-gov-east-1/monitoring": {
"endpoint": "monitoring.{region}.amazonaws.com"
},
"fips-us-gov-west-1/monitoring": {
"endpoint": "monitoring.{region}.amazonaws.com"
},
"fips-aws-us-gov-global/organizations": {
"endpoint": "organizations.{region}.amazonaws.com"
},
"fips-us-gov-east-1/resource-groups": {
"endpoint": "resource-groups.{region}.amazonaws.com"
},
"fips-us-gov-west-1/resource-groups": {
"endpoint": "resource-groups.{region}.amazonaws.com"
},
"fips-aws-us-gov-global/route53": {
"endpoint": "route53.us-gov.amazonaws.com"
},
"fips-us-gov-east-1/servicecatalog-appregistry": {
"endpoint": "servicecatalog-appregistry.{region}.amazonaws.com"
},
"fips-us-gov-west-1/servicecatalog-appregistry": {
"endpoint": "servicecatalog-appregistry.{region}.amazonaws.com"
},
"fips-us-gov-west-1/states": {
"endpoint": "states.{region}.amazonaws.com"
},
"us-gov-east-1-fips/streams.dynamodb": {
"endpoint": "dynamodb.{region}.amazonaws.com"
},
"us-gov-west-1-fips/streams.dynamodb": {
"endpoint": "dynamodb.{region}.amazonaws.com"
}
},

Expand Down
10 changes: 4 additions & 6 deletions lib/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -313,12 +313,10 @@ AWS.Request = inherit({
var region = service.config.region;
var customUserAgent = service.config.customUserAgent;

if (service.isGlobalEndpoint) {
if (service.signingRegion) {
region = service.signingRegion;
} else {
region = 'us-east-1';
}
if (service.signingRegion) {
region = service.signingRegion;
} else if (service.isGlobalEndpoint) {
region = 'us-east-1';
}

this.domain = domain && domain.active;
Expand Down
2 changes: 1 addition & 1 deletion lib/service.js
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,7 @@ AWS.Service = inherit({

var e = endpoint;
e = e.replace(/\{service\}/g, this.api.endpointPrefix);
e = e.replace(/\{region\}/g, this.config.region);
e = e.replace(/\{region\}/g, regionConfig.getRealRegion(this.config.region));
e = e.replace(/\{scheme\}/g, this.config.sslEnabled ? 'https' : 'http');
return e;
},
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"url": "https://aws.amazon.com/"
},
"config": {
"test_args": "test test/json test/model test/protocol test/query test/services test/signers test/xml test/s3 test/cloudfront test/dynamodb test/polly test/rds test/publisher test/event-stream"
"test_args": "test test/json test/model test/protocol test/query test/services test/signers test/xml test/s3 test/cloudfront test/dynamodb test/polly test/rds test/publisher test/event-stream test/endpoint"
},
"homepage": "https://github.com/aws/aws-sdk-js",
"contributors": [
Expand Down
4 changes: 4 additions & 0 deletions scripts/region-checker/allowlist.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ var allowlist = {
110,
112
],
'/region_config.js': [
117
],
'/request.js': [
318,
319
],
'/services/s3.js': [
Expand Down
42 changes: 42 additions & 0 deletions test/endpoint/fips/fips.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const test_cases = require('./test_cases.json');
const helpers = require('../../helpers');
const AWS = helpers.AWS;

async function testApiCall(input) {
const { clientName, region, signingRegion, hostname } = input;

if (!AWS[clientName]) {
throw new Error(`${clientName} does not exist`);
}

const client =
clientName === 'IotData'
? // requires an explicit `endpoint' configuration option.
new AWS.IotData({ region, endpoint: 'endpoint' })
: new AWS[clientName]({ region });

const req = client[Object.keys(client.api.operations)[0]]();
req.on('complete', () => {
expect(region).to.equal(client.config.region);
expect(signingRegion).to.equal(req.httpRequest.region);
expect(hostname).to.equal(req.httpRequest.endpoint.host);
});

try {
await req.promise();
} catch (error) {}
};

describe('endpoints.fips', function() {
beforeEach(function () {
helpers.mockResponse({
data: {}
});
});

for (const test_case of test_cases) {
it(`testing ${test_case.clientName} with region: ${test_case.region}`, async function() {
await testApiCall(test_case);
});
}
});
Loading

0 comments on commit 5f06f52

Please sign in to comment.