prowler-sdk-poc
Version:
203 lines (182 loc) • 6.56 kB
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', s3util.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;
endpoint.hostname = [
's3-outposts',
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;
endpoint.hostname = [
's3-outposts',
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
*/
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);
}
},
});