diff --git a/constants.js b/constants.js index 3d83d33f22..8fbdacef95 100644 --- a/constants.js +++ b/constants.js @@ -89,6 +89,20 @@ const constants = { // Maximum HTTP headers size allowed maxHttpHeadersSize: 14122, + // AWS sets the maximum number of objects deleted to 1000 for multiDeleteObjects + // https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteObjects.html + maxMultiObjectDeleteLen: 1000, + + oneMegaBytes: 1024 * 1024, + halfMegaBytes: 512 * 1024, + + // Some apis may need a custom body length limit : + apisLengthLimits: { + // Multi Objects Delete request can be large : up to 1000 keys of 1024 bytes is + // already 1mb, with the other fields it could reach 2mb + 'multiObjectDelete': 2 * 1024 * 1024, + }, + // hex digest of sha256 hash of empty string: emptyStringHash: crypto.createHash('sha256') .update('', 'binary').digest('hex'), @@ -252,4 +266,5 @@ const constants = { onlyOwnerAllowed: ['bucketDeletePolicy', 'bucketGetPolicy', 'bucketPutPolicy'], }; + module.exports = constants; diff --git a/lib/api/api.js b/lib/api/api.js index 3d36e3fe6b..fae4b8d1b1 100644 --- a/lib/api/api.js +++ b/lib/api/api.js @@ -74,6 +74,7 @@ const parseCopySource = require('./apiUtils/object/parseCopySource'); const { tagConditionKeyAuth } = require('./apiUtils/authorization/tagConditionKeys'); const { isRequesterASessionUser } = require('./apiUtils/authorization/permissionChecks'); const checkHttpHeadersSize = require('./apiUtils/object/checkHttpHeadersSize'); +const constants = require('../../constants'); const monitoringMap = policies.actionMaps.actionMonitoringMapS3; @@ -219,8 +220,10 @@ const api = { } // issue 100 Continue to the client writeContinue(request, response); - const MAX_POST_LENGTH = request.method === 'POST' ? - 1024 * 1024 : 1024 * 1024 / 2; // 1 MB or 512 KB + + const defaultMaxPostLength = request.method === 'POST' ? + constants.oneMegaBytes : constants.halfMegaBytes; + const MAX_POST_LENGTH = constants.apisLengthLimits[apiMethod] || defaultMaxPostLength; const post = []; let postLength = 0; request.on('data', chunk => { diff --git a/lib/api/multiObjectDelete.js b/lib/api/multiObjectDelete.js index 27d8dec3ff..1ae0d974c3 100644 --- a/lib/api/multiObjectDelete.js +++ b/lib/api/multiObjectDelete.js @@ -19,6 +19,7 @@ const createAndStoreObject = require('./apiUtils/object/createAndStoreObject'); const monitoring = require('../utilities/monitoringHandler'); const metadataUtils = require('../metadata/metadataUtils'); const { config } = require('../Config'); +const constants = require('../../constants'); const { isRequesterNonAccountUser } = require('./apiUtils/authorization/permissionChecks'); const { hasGovernanceBypassHeader, checkUserGovernanceBypass, ObjectLockInfo } = require('./apiUtils/object/objectLockHelpers'); @@ -492,7 +493,7 @@ function multiObjectDelete(authInfo, request, log, callback) { function parseXML(next) { return _parseXml(request.post, (err, quietSetting, objects) => { - if (err || objects.length < 1 || objects.length > 1000) { + if (err || objects.length < 1 || objects.length > constants.maxMultiObjectDeleteLen) { return next(errors.MalformedXML); } return next(null, quietSetting, objects);