Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add useFipsEndpoint configuration #3951

Merged
merged 24 commits into from Nov 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
1ed9fe2
chore: npm run add-change
trivikr Nov 10, 2021
d206f62
chore: update release message
trivikr Nov 10, 2021
cace36c
chore(config): add useFipsEndpoint
trivikr Nov 10, 2021
44144ba
test(endpoint): add test cases for useFipsEndpoint
trivikr Nov 10, 2021
dcaffb9
test(endpoint): remove test cases for useFipsEndpoint
trivikr Nov 10, 2021
c9507b6
chore: switch to useFipsRegion instead of isFipsRegion
trivikr Nov 11, 2021
e8fc0a2
feat: store real region in region_config
trivikr Nov 11, 2021
42c08b9
test(endpoint): remove checks for signingRegion
trivikr Nov 11, 2021
492a4bf
test(endpoint): add test cases for useFipsEndpoint
trivikr Nov 11, 2021
5b12c22
chore: set real region for global regions
trivikr Nov 11, 2021
6c267fd
chore(region_config): add support for us-iso-* and us-isob-*
trivikr Nov 11, 2021
c919355
chore(region_config): add support for iam under fips
trivikr Nov 11, 2021
407d2fe
chore: npm run add-change
trivikr Nov 11, 2021
0fe42a8
fix(service): check for config before checking for region
trivikr Nov 11, 2021
e8cd520
chore: update region-checker allowlist
trivikr Nov 11, 2021
7d2be4b
test(region_config): remove fips signingRegion tests
trivikr Nov 11, 2021
c665393
chore(s3): check useFipsEndpoint for fips compatibility
trivikr Nov 11, 2021
f25bcd2
test(s3): add all combinations of fips testing
trivikr Nov 11, 2021
87b8a25
test(service): set original signingName and endpointPrefix after testing
trivikr Nov 11, 2021
62b8bc2
test(region_utils): add tests for region utils
trivikr Nov 11, 2021
7373695
test(service): useFipsEndpoint for fips region and global region
trivikr Nov 11, 2021
259e486
chore(node_loader): set real region and useFipsEndpoint
trivikr Nov 11, 2021
0715654
test(service): delete AWS.config.s3 before exiting test
trivikr Nov 11, 2021
20e5a6e
chore(node_loader): read useFipsEndpoint from env/shared ini
trivikr Nov 11, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changes/next-release/feature-endpoint-e156c0ec.json
@@ -0,0 +1,5 @@
{
"type": "feature",
"category": "endpoint",
"description": "Add useFipsEndpoint configuration"
}
4 changes: 4 additions & 0 deletions lib/config-base.d.ts
Expand Up @@ -267,4 +267,8 @@ export abstract class ConfigurationOptions {
* regional endpoints.
*/
stsRegionalEndpoints?: "legacy"|"regional";
/**
* Enables FIPS compatible endpoints.
*/
useFipsEndpoint?: boolean;
}
10 changes: 8 additions & 2 deletions lib/config.js
Expand Up @@ -185,7 +185,10 @@ var PromisesDependency;
* @!attribute stsRegionalEndpoints
* @return ['legacy'|'regional'] whether to send sts request to global endpoints or
* regional endpoints.
* Defaults to 'legacy'
* Defaults to 'legacy'.
*
* @!attribute useFipsEndpoint
* @return [Boolean] Enables FIPS compatible endpoints. Defaults to `false`.
*/
AWS.Config = AWS.util.inherit({
/**
Expand Down Expand Up @@ -340,6 +343,8 @@ AWS.Config = AWS.util.inherit({
* @option options stsRegionalEndpoints ['legacy'|'regional'] whether to send sts request
* to global endpoints or regional endpoints.
* Defaults to 'legacy'.
* @option options useFipsEndpoint [Boolean] Enables FIPS compatible endpoints.
* Defaults to `false`.
*/
constructor: function Config(options) {
if (options === undefined) options = {};
Expand Down Expand Up @@ -563,7 +568,8 @@ AWS.Config = AWS.util.inherit({
endpointDiscoveryEnabled: undefined,
endpointCacheSize: 1000,
hostPrefixEnabled: true,
stsRegionalEndpoints: 'legacy'
stsRegionalEndpoints: 'legacy',
useFipsEndpoint: false
},

/**
Expand Down
71 changes: 50 additions & 21 deletions lib/node_loader.js
@@ -1,5 +1,9 @@
var util = require('./util');

var region_utils = require('./region/utils');
var isFipsRegion = region_utils.isFipsRegion;
var getRealRegion = region_utils.getRealRegion;

util.isBrowser = function() { return false; };
util.isNode = function() { return true; };

Expand Down Expand Up @@ -96,6 +100,44 @@ AWS.CredentialProviderChain.defaultProviders = [
function () { return new AWS.EC2MetadataCredentials(); }
];

var getRegion = function() {
var env = process.env;
var region = env.AWS_REGION || env.AMAZON_REGION;
if (env[AWS.util.configOptInEnv]) {
var toCheck = [
{filename: env[AWS.util.sharedCredentialsFileEnv]},
{isConfig: true, filename: env[AWS.util.sharedConfigFileEnv]}
];
var iniLoader = AWS.util.iniLoader;
while (!region && toCheck.length) {
var configFile = {};
var fileInfo = toCheck.shift();
try {
configFile = iniLoader.loadFrom(fileInfo);
} catch (err) {
if (fileInfo.isConfig) throw err;
}
var profile = configFile[env.AWS_PROFILE || AWS.util.defaultProfile];
region = profile && profile.region;
}
}
return region;
};

var getBooleanValue = function(value) {
return value === 'true' ? true: value === 'false' ? false: undefined;
};

var USE_FIPS_ENDPOINT_CONFIG_OPTIONS = {
environmentVariableSelector: function(env) {
return getBooleanValue(env['AWS_USE_FIPS_ENDPOINT']);
},
configFileSelector: function(profile) {
return getBooleanValue(profile['use_fips_endpoint']);
},
default: false,
};

// Update configuration keys
AWS.util.update(AWS.Config.prototype.keys, {
credentials: function () {
Expand All @@ -116,27 +158,14 @@ AWS.util.update(AWS.Config.prototype.keys, {
return process.env.AWSJS_DEBUG ? console : null;
},
region: function() {
var env = process.env;
var region = env.AWS_REGION || env.AMAZON_REGION;
if (env[AWS.util.configOptInEnv]) {
var toCheck = [
{filename: env[AWS.util.sharedCredentialsFileEnv]},
{isConfig: true, filename: env[AWS.util.sharedConfigFileEnv]}
];
var iniLoader = AWS.util.iniLoader;
while (!region && toCheck.length) {
var configFile = {};
var fileInfo = toCheck.shift();
try {
configFile = iniLoader.loadFrom(fileInfo);
} catch (err) {
if (fileInfo.isConfig) throw err;
}
var profile = configFile[env.AWS_PROFILE || AWS.util.defaultProfile];
region = profile && profile.region;
}
}
return region;
var region = getRegion();
return region ? getRealRegion(region): undefined;
},
useFipsEndpoint: function() {
var region = getRegion();
return isFipsRegion(region)
? true
: util.loadConfig(USE_FIPS_ENDPOINT_CONFIG_OPTIONS);
}
});

Expand Down
21 changes: 21 additions & 0 deletions lib/region/utils.js
@@ -0,0 +1,21 @@
function isFipsRegion(region) {
return typeof region === 'string' && (region.startsWith('fips-') || region.endsWith('-fips'));
}

function isGlobalRegion(region) {
return typeof region === 'string' && ['aws-global', 'aws-us-gov-global'].includes(region);
}

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

module.exports = {
isFipsRegion: isFipsRegion,
isGlobalRegion: isGlobalRegion,
getRealRegion: getRealRegion
};
29 changes: 2 additions & 27 deletions lib/region_config.js
Expand Up @@ -3,10 +3,6 @@ var regionConfig = require('./region_config_data.json');

function generateRegionPrefix(region) {
if (!region) return null;
if (isFipsRegion(region)) {
region = getRealRegion(region);
}

var parts = region.split('-');
if (parts.length < 3) return null;
return parts.slice(0, parts.length - 2).join('-') + '-*';
Expand Down Expand Up @@ -40,12 +36,12 @@ function applyConfig(service, config) {

function configureEndpoint(service) {
var keys = derivedKeys(service);
var region = service.config.region;
var useFipsEndpoint = service.config.useFipsEndpoint;
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
if (!key) continue;

var rules = isFipsRegion(region) ? regionConfig.fipsRules : regionConfig.rules;
var rules = useFipsEndpoint ? regionConfig.fipsRules : regionConfig.rules;
if (Object.prototype.hasOwnProperty.call(rules, key)) {
var config = rules[key];
if (typeof config === 'string') {
Expand All @@ -61,12 +57,6 @@ 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 @@ -101,25 +91,10 @@ function getEndpointSuffix(region) {
return defaultSuffix;
}

function isFipsRegion(region) {
return region && (region.startsWith('fips-') || 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,
getRealRegion: getRealRegion,
};
31 changes: 21 additions & 10 deletions lib/region_config_data.json
Expand Up @@ -6,12 +6,8 @@
"cn-*/*": {
"endpoint": "{service}.{region}.amazonaws.com.cn"
},
"us-iso-*/*": {
"endpoint": "{service}.{region}.c2s.ic.gov"
},
"us-isob-*/*": {
"endpoint": "{service}.{region}.sc2s.sgov.gov"
},
"us-iso-*/*": "usIso",
"us-isob-*/*": "usIsob",
"*/budgets": "globalSSL",
"*/cloudfront": "globalSSL",
"*/sts": "globalSSL",
Expand Down Expand Up @@ -67,6 +63,14 @@
"fipsRules": {
"*/*": "fipsStandard",
"us-gov-*/*": "fipsStandard",
"us-iso-*/*": {
"endpoint": "{service}-fips.{region}.c2s.ic.gov"
},
"us-iso-*/dms": "usIso",
"us-isob-*/*": {
"endpoint": "{service}-fips.{region}.sc2s.sgov.gov"
},
"us-isob-*/dms": "usIsob",
"cn-*/*": {
"endpoint": "{service}-fips.{region}.amazonaws.com.cn"
},
Expand All @@ -79,6 +83,7 @@
"*/runtime.sagemaker": {
"endpoint": "runtime-fips.sagemaker.{region}.amazonaws.com"
},
"*/iam": "fipsWithoutRegion",
"*/route53": "fipsWithoutRegion",
"*/transcribe": "fipsDotPrefix",
"*/waf": "fipsWithoutRegion",
Expand All @@ -105,12 +110,12 @@
"us-gov-*/ssm": "fipsWithServiceOnly",
"us-gov-*/sts": "fipsWithServiceOnly",
"us-gov-*/support": "fipsWithServiceOnly",
"fips-us-gov-west-1/states": "fipsWithServiceOnly",
"fips-us-iso-east-1/elasticfilesystem": {
"us-gov-west-1/states": "fipsWithServiceOnly",
"us-iso-east-1/elasticfilesystem": {
"endpoint": "elasticfilesystem-fips.{region}.c2s.ic.gov"
},
"fips-aws-us-gov-global/organizations": "fipsWithServiceOnly",
"fips-aws-us-gov-global/route53": {
"us-gov-west-1/organizations": "fipsWithServiceOnly",
"us-gov-west-1/route53": {
"endpoint": "route53.us-gov.amazonaws.com"
}
},
Expand All @@ -130,6 +135,12 @@
"endpoint": "{service}.{region}.amazonaws.com",
"signatureVersion": "s3"
},
"usIso": {
"endpoint": "{service}.{region}.c2s.ic.gov"
},
"usIsob": {
"endpoint": "{service}.{region}.sc2s.sgov.gov"
},
"fipsStandard": {
"endpoint": "{service}-fips.{region}.amazonaws.com"
},
Expand Down
15 changes: 14 additions & 1 deletion lib/service.js
Expand Up @@ -4,6 +4,7 @@ var regionConfig = require('./region_config');

var inherit = AWS.util.inherit;
var clientCount = 0;
var region_utils = require('./region/utils');

/**
* The service class representing an AWS service.
Expand All @@ -25,6 +26,18 @@ AWS.Service = inherit({
throw AWS.util.error(new Error(),
'Service must be constructed with `new\' operator');
}

if (config && config.region) {
var region = config.region;
if (region_utils.isFipsRegion(region)) {
config.region = region_utils.getRealRegion(region);
config.useFipsEndpoint = true;
}
if (region_utils.isGlobalRegion(region)) {
config.region = region_utils.getRealRegion(region);
}
}

var ServiceClass = this.loadServiceClass(config || {});
if (ServiceClass) {
var originalConfig = AWS.util.copy(config);
Expand Down Expand Up @@ -636,7 +649,7 @@ AWS.Service = inherit({

var e = endpoint;
e = e.replace(/\{service\}/g, this.api.endpointPrefix);
e = e.replace(/\{region\}/g, regionConfig.getRealRegion(this.config.region));
e = e.replace(/\{region\}/g, this.config.region);
e = e.replace(/\{scheme\}/g, this.config.sslEnabled ? 'https' : 'http');
return e;
},
Expand Down
3 changes: 2 additions & 1 deletion lib/services/s3util.js
Expand Up @@ -136,6 +136,7 @@ var s3util = {
var useArnRegion = s3util.loadUseArnRegionConfig(req);
var regionFromArn = req._parsedArn.region;
var clientRegion = req.service.config.region;
var useFipsEndpoint = req.service.config.useFipsEndpoint;

if (!regionFromArn) {
throw AWS.util.error(new Error(), {
Expand All @@ -145,7 +146,7 @@ var s3util = {
}

if (
clientRegion.indexOf('fips') >= 0 ||
useFipsEndpoint ||
regionFromArn.indexOf('fips') >= 0
) {
throw AWS.util.error(new Error(), {
Expand Down
10 changes: 5 additions & 5 deletions scripts/region-checker/allowlist.js
Expand Up @@ -4,9 +4,9 @@ var allowlist = {
25,
85,
86,
201,
255,
256
204,
258,
259
],
'/credentials/cognito_identity_credentials.js': [
78,
Expand All @@ -27,8 +27,8 @@ var allowlist = {
110,
112
],
'/region_config.js': [
110
'/region/utils.js': [
10
],
'/request.js': [
318,
Expand Down
4 changes: 1 addition & 3 deletions test/endpoint/fips/fips.spec.js
Expand Up @@ -3,7 +3,7 @@ const helpers = require('../../helpers');
const AWS = helpers.AWS;

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

if (!AWS[clientName]) {
throw new Error(`${clientName} does not exist`);
Expand All @@ -13,8 +13,6 @@ function testApiCall(input, done) {

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