211 lines
6.7 KiB
JavaScript
211 lines
6.7 KiB
JavaScript
var AWS = require('../core');
|
|
var s3util = require('./s3util');
|
|
var regionUtil = require('../region_config');
|
|
|
|
AWS.util.update(AWS.S3Control.prototype, {
|
|
/**
|
|
* @api private
|
|
*/
|
|
setupRequestListeners: function setupRequestListeners(request) {
|
|
request.addListener('extractError', this.extractHostId);
|
|
request.addListener('extractData', this.extractHostId);
|
|
request.addListener('validate', this.validateAccountId);
|
|
|
|
var isArnInBucket = s3util.isArnInParam(request, 'Bucket');
|
|
var isArnInName = s3util.isArnInParam(request, 'Name');
|
|
|
|
if (isArnInBucket) {
|
|
request._parsedArn = AWS.util.ARN.parse(request.params['Bucket']);
|
|
request.addListener('validate', this.validateOutpostsBucketArn);
|
|
request.addListener('validate', s3util.validateOutpostsArn);
|
|
request.addListener('afterBuild', this.addOutpostIdHeader);
|
|
} else if (isArnInName) {
|
|
request._parsedArn = AWS.util.ARN.parse(request.params['Name']);
|
|
request.addListener('validate', s3util.validateOutpostsAccessPointArn);
|
|
request.addListener('validate', s3util.validateOutpostsArn);
|
|
request.addListener('afterBuild', this.addOutpostIdHeader);
|
|
}
|
|
|
|
if (isArnInBucket || isArnInName) {
|
|
request.addListener('validate', this.validateArnRegion);
|
|
request.addListener('validate', this.validateArnAccountWithParams, true);
|
|
request.addListener('validate', s3util.validateArnAccount);
|
|
request.addListener('validate', s3util.validateArnService);
|
|
request.addListener('build', this.populateParamFromArn, true);
|
|
request.addListener('build', this.populateUriFromArn);
|
|
request.addListener('build', s3util.validatePopulateUriFromArn);
|
|
}
|
|
|
|
if (request.params.OutpostId &&
|
|
(request.operation === 'createBucket' ||
|
|
request.operation === 'listRegionalBuckets')) {
|
|
request.addListener('build', this.populateEndpointForOutpostId);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Adds outpostId header
|
|
*/
|
|
addOutpostIdHeader: function addOutpostIdHeader(req) {
|
|
req.httpRequest.headers['x-amz-outpost-id'] = req._parsedArn.outpostId;
|
|
},
|
|
|
|
/**
|
|
* Validate Outposts ARN supplied in Bucket parameter is a valid bucket name
|
|
*/
|
|
validateOutpostsBucketArn: function validateOutpostsBucketArn(req) {
|
|
var parsedArn = req._parsedArn;
|
|
|
|
//can be ':' or '/'
|
|
var delimiter = parsedArn.resource['outpost'.length];
|
|
|
|
if (parsedArn.resource.split(delimiter).length !== 4) {
|
|
throw AWS.util.error(new Error(), {
|
|
code: 'InvalidARN',
|
|
message: 'Bucket ARN should have two resources outpost/{outpostId}/bucket/{accesspointName}'
|
|
});
|
|
}
|
|
|
|
var bucket = parsedArn.resource.split(delimiter)[3];
|
|
if (!s3util.dnsCompatibleBucketName(bucket) || bucket.match(/\./)) {
|
|
throw AWS.util.error(new Error(), {
|
|
code: 'InvalidARN',
|
|
message: 'Bucket ARN is not DNS compatible. Got ' + bucket
|
|
});
|
|
}
|
|
|
|
//set parsed valid bucket
|
|
req._parsedArn.bucket = bucket;
|
|
},
|
|
|
|
/**
|
|
* @api private
|
|
*/
|
|
populateParamFromArn: function populateParamFromArn(req) {
|
|
var parsedArn = req._parsedArn;
|
|
if (s3util.isArnInParam(req, 'Bucket')) {
|
|
req.params.Bucket = parsedArn.bucket;
|
|
} else if (s3util.isArnInParam(req, 'Name')) {
|
|
req.params.Name = parsedArn.accessPoint;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Populate URI according to the ARN
|
|
*/
|
|
populateUriFromArn: function populateUriFromArn(req) {
|
|
var parsedArn = req._parsedArn;
|
|
|
|
var endpoint = req.httpRequest.endpoint;
|
|
var useArnRegion = req.service.config.s3UseArnRegion;
|
|
var useFipsEndpoint = req.service.config.useFipsEndpoint;
|
|
|
|
endpoint.hostname = [
|
|
's3-outposts' + (useFipsEndpoint ? '-fips': ''),
|
|
useArnRegion ? parsedArn.region : req.service.config.region,
|
|
'amazonaws.com'
|
|
].join('.');
|
|
endpoint.host = endpoint.hostname;
|
|
},
|
|
|
|
/**
|
|
* @api private
|
|
*/
|
|
populateEndpointForOutpostId: function populateEndpointForOutpostId(req) {
|
|
var endpoint = req.httpRequest.endpoint;
|
|
var useFipsEndpoint = req.service.config.useFipsEndpoint;
|
|
endpoint.hostname = [
|
|
's3-outposts' + (useFipsEndpoint ? '-fips': ''),
|
|
req.service.config.region,
|
|
'amazonaws.com'
|
|
].join('.');
|
|
endpoint.host = endpoint.hostname;
|
|
},
|
|
|
|
/**
|
|
* @api private
|
|
*/
|
|
extractHostId: function(response) {
|
|
var hostId = response.httpResponse.headers ? response.httpResponse.headers['x-amz-id-2'] : null;
|
|
response.extendedRequestId = hostId;
|
|
if (response.error) {
|
|
response.error.extendedRequestId = hostId;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* @api private
|
|
*/
|
|
validateArnRegion: function validateArnRegion(req) {
|
|
s3util.validateArnRegion(req, { allowFipsEndpoint: true });
|
|
},
|
|
|
|
/**
|
|
* @api private
|
|
*/
|
|
validateArnAccountWithParams: function validateArnAccountWithParams(req) {
|
|
var params = req.params;
|
|
var inputModel = req.service.api.operations[req.operation].input;
|
|
if (inputModel.members.AccountId) {
|
|
var parsedArn = req._parsedArn;
|
|
if (parsedArn.accountId) {
|
|
if (params.AccountId) {
|
|
if (params.AccountId !== parsedArn.accountId) {
|
|
throw AWS.util.error(
|
|
new Error(),
|
|
{code: 'ValidationError', message: 'AccountId in ARN and request params should be same.'}
|
|
);
|
|
}
|
|
} else {
|
|
// Store accountId from ARN in params
|
|
params.AccountId = parsedArn.accountId;
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* @api private
|
|
*/
|
|
validateAccountId: function(request) {
|
|
var params = request.params;
|
|
if (!Object.prototype.hasOwnProperty.call(params, 'AccountId')) return;
|
|
var accountId = params.AccountId;
|
|
//validate type
|
|
if (typeof accountId !== 'string') {
|
|
throw AWS.util.error(
|
|
new Error(),
|
|
{code: 'ValidationError', message: 'AccountId must be a string.'}
|
|
);
|
|
}
|
|
//validate length
|
|
if (accountId.length < 1 || accountId.length > 63) {
|
|
throw AWS.util.error(
|
|
new Error(),
|
|
{code: 'ValidationError', message: 'AccountId length should be between 1 to 63 characters, inclusive.'}
|
|
);
|
|
}
|
|
//validate pattern
|
|
var hostPattern = /^[a-zA-Z0-9]{1}$|^[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9]$/;
|
|
if (!hostPattern.test(accountId)) {
|
|
throw AWS.util.error(new Error(),
|
|
{code: 'ValidationError', message: 'AccountId should be hostname compatible. AccountId: ' + accountId});
|
|
}
|
|
},
|
|
|
|
/**
|
|
* @api private
|
|
*/
|
|
getSigningName: function getSigningName(req) {
|
|
var _super = AWS.Service.prototype.getSigningName;
|
|
if (req && req._parsedArn && req._parsedArn.service) {
|
|
return req._parsedArn.service;
|
|
} else if (req.params.OutpostId &&
|
|
(req.operation === 'createBucket' ||
|
|
req.operation === 'listRegionalBuckets')) {
|
|
return 's3-outposts';
|
|
} else {
|
|
return _super.call(this, req);
|
|
}
|
|
},
|
|
});
|