Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
192 changes: 92 additions & 100 deletions lib/api/bucketPut.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,22 +45,19 @@
} else if (parsedHost && restEndpoints[parsedHost]) {
locationConstraintChecked = restEndpoints[parsedHost];
} else {
log.trace('no location constraint provided on bucket put;' +
'setting us-east-1');
log.trace('no location constraint provided on bucket put;' + 'setting us-east-1');
locationConstraintChecked = 'us-east-1';
}

if (!locationConstraints[locationConstraintChecked]) {
const errMsg = 'value of the location you are attempting to set - ' +
const errMsg =
'value of the location you are attempting to set - ' +
`${locationConstraintChecked} - is not listed in the ` +
'locationConstraint config';
log.trace(`locationConstraint is invalid - ${errMsg}`,
{ locationConstraint: locationConstraintChecked });
return { error: errorInstances.InvalidLocationConstraint.
customizeDescription(errMsg) };
log.trace(`locationConstraint is invalid - ${errMsg}`, { locationConstraint: locationConstraintChecked });
return { error: errorInstances.InvalidLocationConstraint.customizeDescription(errMsg) };
}
if (locationConstraints[locationConstraintChecked].isCold ||
locationConstraints[locationConstraintChecked].isCRR) {
if (locationConstraints[locationConstraintChecked].isCold || locationConstraints[locationConstraintChecked].isCRR) {
return { error: errors.InvalidLocationConstraint };
}
if (locationConstraintAddon) {
Expand All @@ -84,27 +81,26 @@
function _parseXML(request, log, cb) {
if (request.post) {
return parseString(request.post, (err, result) => {
if (err || !result.CreateBucketConfiguration
|| !result.CreateBucketConfiguration.LocationConstraint
|| !result.CreateBucketConfiguration.LocationConstraint[0]) {
if (
err ||
!result.CreateBucketConfiguration ||
!result.CreateBucketConfiguration.LocationConstraint ||
!result.CreateBucketConfiguration.LocationConstraint[0]
) {
log.debug('request xml is malformed');
return cb(errors.MalformedXML);
}
const locationConstraint = result.CreateBucketConfiguration
.LocationConstraint[0];
log.trace('location constraint',
{ locationConstraint });
const locationCheck = checkLocationConstraint(request,
locationConstraint, log);
const locationConstraint = result.CreateBucketConfiguration.LocationConstraint[0];
log.trace('location constraint', { locationConstraint });
const locationCheck = checkLocationConstraint(request, locationConstraint, log);
if (locationCheck.error) {
return cb(locationCheck.error);
}
return cb(null, locationCheck.locationConstraint);
});
}
return process.nextTick(() => {
const locationCheck = checkLocationConstraint(request,
undefined, log);
const locationCheck = checkLocationConstraint(request, undefined, log);
if (locationCheck.error) {
return cb(locationCheck.error);
}
Expand All @@ -113,7 +109,15 @@
}

function _buildConstantParams({
request, bucketName, authInfo, authParams, ip, isSecure, locationConstraint, apiMethod }) {
request,
bucketName,
authInfo,
authParams,
ip,
isSecure,
locationConstraint,
apiMethod,
}) {
return {
constantParams: {
headers: request.headers,
Expand All @@ -126,8 +130,8 @@
sslEnabled: isSecure,
awsService: 's3',
requesterInfo: authInfo,
signatureVersion: authParams.params.data.authType,
authType: authParams.params.data.signatureVersion,
signatureVersion: authParams.params.data.signatureVersion,
authType: authParams.params.data.authType,
signatureAge: authParams.params.data.signatureAge,
apiMethod,
locationConstraint,
Expand All @@ -140,16 +144,15 @@
if (err) {
return cb(err);
}
if (!authorizationResults.every(res => {
if (Array.isArray(res)) {
return res.every(subRes => subRes.isAllowed);
}
return res.isAllowed;
})) {
log.trace(
'authorization check failed for user',
{ locationConstraint },
);
if (
!authorizationResults.every(res => {
if (Array.isArray(res)) {
return res.every(subRes => subRes.isAllowed);
}
return res.isAllowed;
})
) {
log.trace('authorization check failed for user', { locationConstraint });
return cb(errors.AccessDenied);
}
return cb(null, locationConstraint);
Expand Down Expand Up @@ -177,30 +180,15 @@
authInfo,
locationConstraint,
};
const requestConstantParams = [Object.assign(
baseParams,
{ apiMethod: 'bucketPut' },
)];
const requestConstantParams = [Object.assign(baseParams, { apiMethod: 'bucketPut' })];

if (_isObjectLockEnabled(request.headers)) {
requestConstantParams.push(Object.assign(
{},
baseParams,
{ apiMethod: 'bucketPutObjectLock' },
));
requestConstantParams.push(Object.assign(
{},
baseParams,
{ apiMethod: 'bucketPutVersioning' },
));
requestConstantParams.push(Object.assign({}, baseParams, { apiMethod: 'bucketPutObjectLock' }));
requestConstantParams.push(Object.assign({}, baseParams, { apiMethod: 'bucketPutVersioning' }));
}

if (_isAclProvided(request.headers)) {
requestConstantParams.push(Object.assign(
{},
baseParams,
{ apiMethod: 'bucketPutACL' },
));
requestConstantParams.push(Object.assign({}, baseParams, { apiMethod: 'bucketPutACL' }));
}

return requestConstantParams;
Expand All @@ -219,66 +207,70 @@

if (authInfo.isRequesterPublicUser()) {
log.debug('operation not available for public user');
monitoring.promMetrics(
'PUT', request.bucketName, 403, 'createBucket');
monitoring.promMetrics('PUT', request.bucketName, 403, 'createBucket');
return callback(errors.AccessDenied);
}
if (!aclUtils.checkGrantHeaderValidity(request.headers)) {
log.trace('invalid acl header');
monitoring.promMetrics(
'PUT', request.bucketName, 400, 'createBucket');
monitoring.promMetrics('PUT', request.bucketName, 400, 'createBucket');
return callback(errors.InvalidArgument);
}
const { bucketName } = request;


if (request.bucketName === 'METADATA'
// Note: for this to work with Vault, would need way to set
// canonical ID to http://acs.zenko.io/accounts/service/clueso
&& !authInfo.isRequesterThisServiceAccount('clueso')) {
monitoring.promMetrics(
'PUT', bucketName, 403, 'createBucket');
return callback(errorInstances.AccessDenied
.customizeDescription('The bucket METADATA is used ' +
'for internal purposes'));
if (
request.bucketName === 'METADATA' &&
// Note: for this to work with Vault, would need way to set
// canonical ID to http://acs.zenko.io/accounts/service/clueso
!authInfo.isRequesterThisServiceAccount('clueso')
) {
monitoring.promMetrics('PUT', bucketName, 403, 'createBucket');
return callback(
errorInstances.AccessDenied.customizeDescription('The bucket METADATA is used ' + 'for internal purposes'),
);
}

return waterfall([
next => _parseXML(request, log, next),
(locationConstraint, next) => {
if (!isRequesterNonAccountUser(authInfo)) {
return next(null, locationConstraint);
}
return waterfall(
[
next => _parseXML(request, log, next),

Check notice

Code scanning / CodeQL

Callback-style function (async migration) Note

This function uses a callback parameter ('next'). Refactor to async/await.
(locationConstraint, next) => {
if (!isRequesterNonAccountUser(authInfo)) {
return next(null, locationConstraint);
}

const authParams = auth.server.extractParams(request, log, 's3', request.query);
const requestConstantParams = authBucketPut(
authParams, bucketName, locationConstraint, request, authInfo
);
const authParams = auth.server.extractParams(request, log, 's3', request.query);
const requestConstantParams = authBucketPut(
authParams,
bucketName,
locationConstraint,
request,
authInfo,
);

return vault.checkPolicies(
requestConstantParams.map(_buildConstantParams),
authInfo.getArn(),
log,
_handleAuthResults(locationConstraint, log, next),
);
},
(locationConstraint, next) => createBucket(authInfo, bucketName,
request.headers, locationConstraint, log, (err, previousBucket) => {
// if bucket already existed, gather any relevant cors
// headers
const corsHeaders = collectCorsHeaders(
request.headers.origin, request.method, previousBucket);
if (err) {
return next(err, corsHeaders);
}
pushMetric('createBucket', log, {
authInfo,
bucket: bucketName,
});
monitoring.promMetrics('PUT', bucketName, '200', 'createBucket');
return next(null, corsHeaders);
}),
], callback);
return vault.checkPolicies(
requestConstantParams.map(_buildConstantParams),
authInfo.getArn(),
log,
_handleAuthResults(locationConstraint, log, next),
);
},

Check notice

Code scanning / CodeQL

Callback-style function (async migration) Note

This function uses a callback parameter ('next'). Refactor to async/await.
Comment on lines +235 to +255
(locationConstraint, next) =>
createBucket(authInfo, bucketName, request.headers, locationConstraint, log, (err, previousBucket) => {
// if bucket already existed, gather any relevant cors
// headers
const corsHeaders = collectCorsHeaders(request.headers.origin, request.method, previousBucket);
if (err) {
return next(err, corsHeaders);
}
pushMetric('createBucket', log, {
authInfo,
bucket: bucketName,
});
monitoring.promMetrics('PUT', bucketName, '200', 'createBucket');
return next(null, corsHeaders);
}),

Check notice

Code scanning / CodeQL

Callback-style function (async migration) Note

This function uses a callback parameter ('next'). Refactor to async/await.
Comment on lines +256 to +270
],
callback,
);
}

module.exports = {
Expand Down
Loading
Loading