diff --git a/lib/api/api.js b/lib/api/api.js index 6d8384de02..4e563b7371 100644 --- a/lib/api/api.js +++ b/lib/api/api.js @@ -165,6 +165,10 @@ const api = { } } } + // Specific APIs are not checking any ACLs or Bucket Policies. + if (apiMethod === 'bucketPut' || apiMethod === 'serviceGet' && isImplicitDeny) { + return errors.AccessDenied; + } return { returnTagCount, isImplicitDeny }; } diff --git a/lib/api/apiUtils/authorization/permissionChecks.js b/lib/api/apiUtils/authorization/permissionChecks.js index 64e924d1b8..edeb9d285b 100644 --- a/lib/api/apiUtils/authorization/permissionChecks.js +++ b/lib/api/apiUtils/authorization/permissionChecks.js @@ -1,5 +1,6 @@ -const { evaluators, actionMaps, RequestContext } = require('arsenal').policies; +const { evaluators, actionMaps, RequestContext, requestUtils } = require('arsenal').policies; const constants = require('../../../../constants'); +const { config } = require('../../../Config'); const { allAuthedUsersId, bucketOwnerActions, logId, publicId, assumedRoleArnResourceType, backbeatLifecycleSessionName } = constants; @@ -8,8 +9,8 @@ const { allAuthedUsersId, bucketOwnerActions, logId, publicId, const publicReadBuckets = process.env.ALLOW_PUBLIC_READ_BUCKETS ? process.env.ALLOW_PUBLIC_READ_BUCKETS.split(',') : []; -function checkBucketAcls(bucket, requestType, canonicalID, requesterIsNotUser) { - if (bucket.getOwner() === canonicalID && requesterIsNotUser) { +function checkBucketAcls(bucket, requestType, canonicalID) { + if (bucket.getOwner() === canonicalID) { return true; } @@ -198,6 +199,20 @@ function _checkBucketPolicyResources(request, resource, log) { return evaluators.isResourceApplicable(requestContext, resource, log); } +function _checkBucketPolicyConditions(request, conditions, log) { + const ip = request ? requestUtils.getClientIp(request, config) : undefined; + if (!conditions) { + return true; + } + // build request context from the request! + const requestContext = new RequestContext(request.headers, request.query, + request.bucketName, request.objectKey, ip, + request.connection.encrypted, request.resourceType, 's3', null, null, + null, null, null, null, null, null, null, null, null, + request.objectLockRetentionDays); + return evaluators.meetConditions(requestContext, conditions, log); +} + function _getAccountId(arn) { // account or user arn is of format 'arn:aws:iam::<12-digit-acct-id>:etc... return arn.substr(13, 12); @@ -255,12 +270,13 @@ function checkBucketPolicy(policy, requestType, canonicalID, arn, bucketOwner, l const principalMatch = _checkPrincipals(canonicalID, arn, s.Principal); const actionMatch = _checkBucketPolicyActions(requestType, s.Action, log); const resourceMatch = _checkBucketPolicyResources(request, s.Resource, log); + const conditionsMatch = _checkBucketPolicyConditions(request, s.Condition, log); - if (principalMatch && actionMatch && resourceMatch && s.Effect === 'Deny') { + if (principalMatch && actionMatch && resourceMatch && conditionsMatch && s.Effect === 'Deny') { // explicit deny trumps any allows, so return immediately return 'explicitDeny'; } - if (principalMatch && actionMatch && resourceMatch && s.Effect === 'Allow') { + if (principalMatch && actionMatch && resourceMatch && conditionsMatch && s.Effect === 'Allow') { permission = 'allow'; } copiedStatement = copiedStatement.splice(1); @@ -318,7 +334,7 @@ function isObjAuthorized(bucket, objectMD, requestType, canonicalID, authInfo, i // check bucket has read access // 'bucketGet' covers listObjects and listMultipartUploads, bucket read actions return isIdentityAndResourceAuthorized(isImplicitIdentityDeny, - isBucketAuthorized(bucket, 'bucketGet', canonicalID, authInfo, log, request)); + isBucketAuthorized(bucket, 'bucketGet', canonicalID, authInfo, isImplicitIdentityDeny, log, request)); } let requesterIsNotUser = true; let arn = null; diff --git a/lib/api/apiUtils/object/abortMultipartUpload.js b/lib/api/apiUtils/object/abortMultipartUpload.js index 8112c7e47d..cf4545913b 100644 --- a/lib/api/apiUtils/object/abortMultipartUpload.js +++ b/lib/api/apiUtils/object/abortMultipartUpload.js @@ -22,10 +22,11 @@ function abortMultipartUpload(authInfo, bucketName, objectKey, uploadId, log, // but the requestType is the more general 'objectDelete' const metadataValParams = Object.assign({}, metadataValMPUparams); metadataValParams.requestType = 'objectPut'; + const authzIdentityResult = request ? request.isImplicitIdentityDeny : true; async.waterfall([ function checkDestBucketVal(next) { - metadataValidateBucketAndObj(metadataValParams, log, + metadataValidateBucketAndObj(metadataValParams, authzIdentityResult, log, (err, destinationBucket) => { if (err) { return next(err, destinationBucket); diff --git a/lib/api/bucketDelete.js b/lib/api/bucketDelete.js index a64a162c04..f508fb464c 100644 --- a/lib/api/bucketDelete.js +++ b/lib/api/bucketDelete.js @@ -34,7 +34,7 @@ function bucketDelete(authInfo, request, log, cb) { request, }; - return metadataValidateBucket(metadataValParams, log, + return metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucketMD) => { const corsHeaders = collectCorsHeaders(request.headers.origin, request.method, bucketMD); diff --git a/lib/api/bucketDeleteEncryption.js b/lib/api/bucketDeleteEncryption.js index 793516fc53..c506f530a9 100644 --- a/lib/api/bucketDeleteEncryption.js +++ b/lib/api/bucketDeleteEncryption.js @@ -26,7 +26,7 @@ function bucketDeleteEncryption(authInfo, request, log, callback) { }; return async.waterfall([ - next => metadataValidateBucket(metadataValParams, log, next), + next => metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, next), (bucket, next) => checkExpectedBucketOwner(request.headers, bucket, log, err => next(err, bucket)), (bucket, next) => { const sseConfig = bucket.getServerSideEncryption(); diff --git a/lib/api/bucketDeleteLifecycle.js b/lib/api/bucketDeleteLifecycle.js index a8850e034a..0f779fb5b7 100644 --- a/lib/api/bucketDeleteLifecycle.js +++ b/lib/api/bucketDeleteLifecycle.js @@ -21,7 +21,7 @@ function bucketDeleteLifecycle(authInfo, request, log, callback) { requestType: 'bucketDeleteLifecycle', request, }; - return metadataValidateBucket(metadataValParams, log, (err, bucket) => { + return metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => { const corsHeaders = collectCorsHeaders(headers.origin, method, bucket); if (err) { log.debug('error processing request', { diff --git a/lib/api/bucketDeletePolicy.js b/lib/api/bucketDeletePolicy.js index d5a85d0bbd..fda4842d1b 100644 --- a/lib/api/bucketDeletePolicy.js +++ b/lib/api/bucketDeletePolicy.js @@ -19,7 +19,7 @@ function bucketDeletePolicy(authInfo, request, log, callback) { requestType: 'bucketDeletePolicy', request, }; - return metadataValidateBucket(metadataValParams, log, (err, bucket) => { + return metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => { const corsHeaders = collectCorsHeaders(headers.origin, method, bucket); if (err) { log.debug('error processing request', { diff --git a/lib/api/bucketDeleteReplication.js b/lib/api/bucketDeleteReplication.js index c40100dd58..3b22f61f1c 100644 --- a/lib/api/bucketDeleteReplication.js +++ b/lib/api/bucketDeleteReplication.js @@ -21,7 +21,7 @@ function bucketDeleteReplication(authInfo, request, log, callback) { requestType: 'bucketDeleteReplication', request, }; - return metadataValidateBucket(metadataValParams, log, (err, bucket) => { + return metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => { const corsHeaders = collectCorsHeaders(headers.origin, method, bucket); if (err) { log.debug('error processing request', { diff --git a/lib/api/bucketGet.js b/lib/api/bucketGet.js index 4237534ebf..a029419563 100644 --- a/lib/api/bucketGet.js +++ b/lib/api/bucketGet.js @@ -351,7 +351,7 @@ function bucketGet(authInfo, request, log, callback) { listParams.marker = params.marker; } - metadataValidateBucket(metadataValParams, log, (err, bucket) => { + metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => { const corsHeaders = collectCorsHeaders(request.headers.origin, request.method, bucket); if (err) { diff --git a/lib/api/bucketGetACL.js b/lib/api/bucketGetACL.js index 37cb76113f..6c967403f7 100644 --- a/lib/api/bucketGetACL.js +++ b/lib/api/bucketGetACL.js @@ -55,7 +55,7 @@ function bucketGetACL(authInfo, request, log, callback) { }, }; - metadataValidateBucket(metadataValParams, log, (err, bucket) => { + metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => { const corsHeaders = collectCorsHeaders(request.headers.origin, request.method, bucket); if (err) { diff --git a/lib/api/bucketGetEncryption.js b/lib/api/bucketGetEncryption.js index 8720b69b4d..a0d530f61e 100644 --- a/lib/api/bucketGetEncryption.js +++ b/lib/api/bucketGetEncryption.js @@ -27,7 +27,7 @@ function bucketGetEncryption(authInfo, request, log, callback) { }; return async.waterfall([ - next => metadataValidateBucket(metadataValParams, log, next), + next => metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, next), (bucket, next) => checkExpectedBucketOwner(request.headers, bucket, log, err => next(err, bucket)), (bucket, next) => { // If sseInfo is present but the `mandatory` flag is not set diff --git a/lib/api/bucketGetLifecycle.js b/lib/api/bucketGetLifecycle.js index f0ec10fa53..1701f9fb70 100644 --- a/lib/api/bucketGetLifecycle.js +++ b/lib/api/bucketGetLifecycle.js @@ -24,7 +24,7 @@ function bucketGetLifecycle(authInfo, request, log, callback) { requestType: 'bucketGetLifecycle', request, }; - return metadataValidateBucket(metadataValParams, log, (err, bucket) => { + return metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => { const corsHeaders = collectCorsHeaders(headers.origin, method, bucket); if (err) { log.debug('error processing request', { diff --git a/lib/api/bucketGetNotification.js b/lib/api/bucketGetNotification.js index a3e41c03ae..a6baaed72b 100644 --- a/lib/api/bucketGetNotification.js +++ b/lib/api/bucketGetNotification.js @@ -41,7 +41,7 @@ function bucketGetNotification(authInfo, request, log, callback) { request, }; - return metadataValidateBucket(metadataValParams, log, (err, bucket) => { + return metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => { const corsHeaders = collectCorsHeaders(headers.origin, method, bucket); if (err) { log.debug('error processing request', { diff --git a/lib/api/bucketGetObjectLock.js b/lib/api/bucketGetObjectLock.js index cbb92d34b2..15c36f9bd2 100644 --- a/lib/api/bucketGetObjectLock.js +++ b/lib/api/bucketGetObjectLock.js @@ -36,7 +36,7 @@ function bucketGetObjectLock(authInfo, request, log, callback) { requestType: 'bucketGetObjectLock', request, }; - return metadataValidateBucket(metadataValParams, log, (err, bucket) => { + return metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => { const corsHeaders = collectCorsHeaders(headers.origin, method, bucket); if (err) { log.debug('error processing request', { diff --git a/lib/api/bucketGetPolicy.js b/lib/api/bucketGetPolicy.js index c87bb12cce..7409de1158 100644 --- a/lib/api/bucketGetPolicy.js +++ b/lib/api/bucketGetPolicy.js @@ -21,7 +21,7 @@ function bucketGetPolicy(authInfo, request, log, callback) { request, }; - return metadataValidateBucket(metadataValParams, log, (err, bucket) => { + return metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => { const corsHeaders = collectCorsHeaders(headers.origin, method, bucket); if (err) { log.debug('error processing request', { diff --git a/lib/api/bucketGetReplication.js b/lib/api/bucketGetReplication.js index 4bd825b376..8937a6f901 100644 --- a/lib/api/bucketGetReplication.js +++ b/lib/api/bucketGetReplication.js @@ -24,7 +24,7 @@ function bucketGetReplication(authInfo, request, log, callback) { requestType: 'bucketGetReplication', request, }; - return metadataValidateBucket(metadataValParams, log, (err, bucket) => { + return metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => { const corsHeaders = collectCorsHeaders(headers.origin, method, bucket); if (err) { log.debug('error processing request', { diff --git a/lib/api/bucketGetVersioning.js b/lib/api/bucketGetVersioning.js index 2f0fc07603..85b0430f28 100644 --- a/lib/api/bucketGetVersioning.js +++ b/lib/api/bucketGetVersioning.js @@ -58,7 +58,7 @@ function bucketGetVersioning(authInfo, request, log, callback) { request, }; - metadataValidateBucket(metadataValParams, log, (err, bucket) => { + metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => { const corsHeaders = collectCorsHeaders(request.headers.origin, request.method, bucket); if (err) { diff --git a/lib/api/bucketHead.js b/lib/api/bucketHead.js index 232dadea74..911a27e683 100644 --- a/lib/api/bucketHead.js +++ b/lib/api/bucketHead.js @@ -22,7 +22,7 @@ function bucketHead(authInfo, request, log, callback) { requestType: 'bucketHead', request, }; - metadataValidateBucket(metadataValParams, log, (err, bucket) => { + metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => { const corsHeaders = collectCorsHeaders(request.headers.origin, request.method, bucket); if (err) { diff --git a/lib/api/bucketPutACL.js b/lib/api/bucketPutACL.js index f5c0bf92a3..f74a81a6b4 100644 --- a/lib/api/bucketPutACL.js +++ b/lib/api/bucketPutACL.js @@ -105,7 +105,7 @@ function bucketPutACL(authInfo, request, log, callback) { return async.waterfall([ function waterfall1(next) { - metadataValidateBucket(metadataValParams, log, + metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => { if (err) { log.trace('request authorization failed', { diff --git a/lib/api/bucketPutEncryption.js b/lib/api/bucketPutEncryption.js index 148c1ec3a3..40c78a2952 100644 --- a/lib/api/bucketPutEncryption.js +++ b/lib/api/bucketPutEncryption.js @@ -28,7 +28,7 @@ function bucketPutEncryption(authInfo, request, log, callback) { }; return async.waterfall([ - next => metadataValidateBucket(metadataValParams, log, next), + next => metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, next), (bucket, next) => checkExpectedBucketOwner(request.headers, bucket, log, err => next(err, bucket)), (bucket, next) => { log.trace('parsing encryption config', { method: 'bucketPutEncryption' }); diff --git a/lib/api/bucketPutLifecycle.js b/lib/api/bucketPutLifecycle.js index 5292218095..911c1cce62 100644 --- a/lib/api/bucketPutLifecycle.js +++ b/lib/api/bucketPutLifecycle.js @@ -43,7 +43,7 @@ function bucketPutLifecycle(authInfo, request, log, callback) { return next(null, configObj); }); }, - (lcConfig, next) => metadataValidateBucket(metadataValParams, log, + (lcConfig, next) => metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => { if (err) { return next(err, bucket); diff --git a/lib/api/bucketPutNotification.js b/lib/api/bucketPutNotification.js index 3418ca5e2b..06732ad5b9 100644 --- a/lib/api/bucketPutNotification.js +++ b/lib/api/bucketPutNotification.js @@ -34,7 +34,7 @@ function bucketPutNotification(authInfo, request, log, callback) { const notifConfig = notificationConfig.error ? undefined : notificationConfig; process.nextTick(() => next(notificationConfig.error, notifConfig)); }, - (notifConfig, next) => metadataValidateBucket(metadataValParams, log, + (notifConfig, next) => metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => next(err, bucket, notifConfig)), (bucket, notifConfig, next) => { bucket.setNotificationConfiguration(notifConfig); diff --git a/lib/api/bucketPutObjectLock.js b/lib/api/bucketPutObjectLock.js index ba240516f1..833a242aab 100644 --- a/lib/api/bucketPutObjectLock.js +++ b/lib/api/bucketPutObjectLock.js @@ -41,7 +41,7 @@ function bucketPutObjectLock(authInfo, request, log, callback) { return next(configObj.error || null, configObj); }); }, - (objectLockConfig, next) => metadataValidateBucket(metadataValParams, + (objectLockConfig, next) => metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => { if (err) { return next(err, bucket); diff --git a/lib/api/bucketPutPolicy.js b/lib/api/bucketPutPolicy.js index 328c98a306..91e919ee06 100644 --- a/lib/api/bucketPutPolicy.js +++ b/lib/api/bucketPutPolicy.js @@ -17,8 +17,7 @@ const { BucketPolicy } = models; function _checkNotImplementedPolicy(policyString) { // bucket names and key names cannot include "", so including those // isolates not implemented keys - return policyString.includes('"Condition"') - || policyString.includes('"Service"') + return policyString.includes('"Service"') || policyString.includes('"Federated"'); } @@ -70,7 +69,7 @@ function bucketPutPolicy(authInfo, request, log, callback) { return next(null, bucketPolicy); }); }, - (bucketPolicy, next) => metadataValidateBucket(metadataValParams, log, + (bucketPolicy, next) => metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => { if (err) { return next(err, bucket); diff --git a/lib/api/bucketPutReplication.js b/lib/api/bucketPutReplication.js index b25dfbb264..3a47faef56 100644 --- a/lib/api/bucketPutReplication.js +++ b/lib/api/bucketPutReplication.js @@ -37,7 +37,7 @@ function bucketPutReplication(authInfo, request, log, callback) { // Check bucket user privileges and ensure versioning is 'Enabled'. (config, next) => // TODO: Validate that destination bucket exists and has versioning. - metadataValidateBucket(metadataValParams, log, (err, bucket) => { + metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => { if (err) { return next(err); } diff --git a/lib/api/bucketPutTagging.js b/lib/api/bucketPutTagging.js index eb8147c180..27cb62e1e6 100644 --- a/lib/api/bucketPutTagging.js +++ b/lib/api/bucketPutTagging.js @@ -42,7 +42,7 @@ function bucketPutTagging(authInfo, request, log, callback) { }; let bucket = null; return waterfall([ - next => metadataValidateBucket(metadataValParams, log, + next => metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, b) => { bucket = b; return next(err); diff --git a/lib/api/bucketPutVersioning.js b/lib/api/bucketPutVersioning.js index 98ab960ba4..dbc5c0a8c7 100644 --- a/lib/api/bucketPutVersioning.js +++ b/lib/api/bucketPutVersioning.js @@ -94,7 +94,7 @@ function bucketPutVersioning(authInfo, request, log, callback) { return waterfall([ next => _parseXML(request, log, next), - next => metadataValidateBucket(metadataValParams, log, + next => metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => next(err, bucket)), // ignore extra null object, (bucket, next) => parseString(request.post, (err, result) => { // just for linting; there should not be any parsing error here diff --git a/lib/api/completeMultipartUpload.js b/lib/api/completeMultipartUpload.js index e728b2d269..781f449611 100644 --- a/lib/api/completeMultipartUpload.js +++ b/lib/api/completeMultipartUpload.js @@ -120,7 +120,7 @@ function completeMultipartUpload(authInfo, request, log, callback) { // at the destinationBucket level are same as objectPut requestType: 'objectPut', }; - metadataValidateBucketAndObj(metadataValParams, log, next); + metadataValidateBucketAndObj(metadataValParams, request.isImplicitIdentityDeny, log, next); }, function validateMultipart(destBucket, objMD, next) { if (objMD) { diff --git a/lib/api/initiateMultipartUpload.js b/lib/api/initiateMultipartUpload.js index 2973c790f4..6e98f9d436 100644 --- a/lib/api/initiateMultipartUpload.js +++ b/lib/api/initiateMultipartUpload.js @@ -262,7 +262,7 @@ function initiateMultipartUpload(authInfo, request, log, callback) { } async.waterfall([ - next => metadataValidateBucketAndObj(metadataValParams, log, + next => metadataValidateBucketAndObj(metadataValParams, request.isImplicitIdentityDeny, log, (error, destinationBucket) => { const corsHeaders = collectCorsHeaders(request.headers.origin, request.method, destinationBucket); diff --git a/lib/api/listMultipartUploads.js b/lib/api/listMultipartUploads.js index 343772f668..272f6301ff 100644 --- a/lib/api/listMultipartUploads.js +++ b/lib/api/listMultipartUploads.js @@ -105,7 +105,7 @@ function listMultipartUploads(authInfo, request, log, callback) { function waterfall1(next) { // Check final destination bucket for authorization rather // than multipart upload bucket - metadataValidateBucket(metadataValParams, log, + metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => next(err, bucket)); }, function getMPUBucket(bucket, next) { diff --git a/lib/api/listParts.js b/lib/api/listParts.js index 166e8a1154..cc4160b31a 100644 --- a/lib/api/listParts.js +++ b/lib/api/listParts.js @@ -115,7 +115,7 @@ function listParts(authInfo, request, log, callback) { async.waterfall([ function checkDestBucketVal(next) { - metadataValidateBucketAndObj(metadataValParams, log, + metadataValidateBucketAndObj(metadataValParams, request.isImplicitIdentityDeny, log, (err, destinationBucket) => { if (err) { return next(err, destinationBucket, null); diff --git a/lib/api/objectCopy.js b/lib/api/objectCopy.js index 3171114064..74e8014003 100644 --- a/lib/api/objectCopy.js +++ b/lib/api/objectCopy.js @@ -249,7 +249,7 @@ function objectCopy(authInfo, request, sourceBucket, } return async.waterfall([ function checkDestAuth(next) { - return metadataValidateBucketAndObj(valPutParams, log, + return metadataValidateBucketAndObj(valPutParams, request.isImplicitIdentityDeny, log, (err, destBucketMD, destObjMD) => { if (err) { log.debug('error validating put part of request', @@ -267,7 +267,7 @@ function objectCopy(authInfo, request, sourceBucket, }); }, function checkSourceAuthorization(destBucketMD, destObjMD, next) { - return metadataValidateBucketAndObj(valGetParams, log, + return metadataValidateBucketAndObj(valGetParams, request.isImplicitIdentityDeny, log, (err, sourceBucketMD, sourceObjMD) => { if (err) { log.debug('error validating get part of request', diff --git a/lib/api/objectDelete.js b/lib/api/objectDelete.js index beee7c64e0..5b7dbc6a73 100644 --- a/lib/api/objectDelete.js +++ b/lib/api/objectDelete.js @@ -59,7 +59,7 @@ function objectDelete(authInfo, request, log, cb) { const canonicalID = authInfo.getCanonicalID(); return async.waterfall([ function validateBucketAndObj(next) { - return metadataValidateBucketAndObj(valParams, log, + return metadataValidateBucketAndObj(valParams, request.isImplicitIdentityDeny, log, (err, bucketMD, objMD) => { if (err) { return next(err, bucketMD); diff --git a/lib/api/objectDeleteTagging.js b/lib/api/objectDeleteTagging.js index e16fd37df1..167cb0e967 100644 --- a/lib/api/objectDeleteTagging.js +++ b/lib/api/objectDeleteTagging.js @@ -49,7 +49,7 @@ function objectDeleteTagging(authInfo, request, log, callback) { }; return async.waterfall([ - next => metadataValidateBucketAndObj(metadataValParams, log, + next => metadataValidateBucketAndObj(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket, objectMD) => { if (err) { log.trace('request authorization failed', diff --git a/lib/api/objectGet.js b/lib/api/objectGet.js index f36a177051..ce1bc42132 100644 --- a/lib/api/objectGet.js +++ b/lib/api/objectGet.js @@ -50,7 +50,7 @@ function objectGet(authInfo, request, returnTagCount, log, callback) { request, }; - return metadataValidateBucketAndObj(mdValParams, log, + return metadataValidateBucketAndObj(mdValParams, request.isImplicitIdentityDeny, log, (err, bucket, objMD) => { const corsHeaders = collectCorsHeaders(request.headers.origin, request.method, bucket); diff --git a/lib/api/objectGetACL.js b/lib/api/objectGetACL.js index 3f39c12c65..c39aa5a7d3 100644 --- a/lib/api/objectGetACL.js +++ b/lib/api/objectGetACL.js @@ -74,7 +74,7 @@ function objectGetACL(authInfo, request, log, callback) { return async.waterfall([ function validateBucketAndObj(next) { - return metadataValidateBucketAndObj(metadataValParams, log, + return metadataValidateBucketAndObj(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket, objectMD) => { if (err) { log.trace('request authorization failed', diff --git a/lib/api/objectGetLegalHold.js b/lib/api/objectGetLegalHold.js index 64321cbd62..17e2cb10c0 100644 --- a/lib/api/objectGetLegalHold.js +++ b/lib/api/objectGetLegalHold.js @@ -45,7 +45,7 @@ function objectGetLegalHold(authInfo, request, log, callback) { }; return async.waterfall([ - next => metadataValidateBucketAndObj(metadataValParams, log, + next => metadataValidateBucketAndObj(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket, objectMD) => { if (err) { log.trace('request authorization failed', diff --git a/lib/api/objectGetRetention.js b/lib/api/objectGetRetention.js index 114130043f..aef9445169 100644 --- a/lib/api/objectGetRetention.js +++ b/lib/api/objectGetRetention.js @@ -45,7 +45,7 @@ function objectGetRetention(authInfo, request, log, callback) { }; return async.waterfall([ - next => metadataValidateBucketAndObj(metadataValParams, log, + next => metadataValidateBucketAndObj(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket, objectMD) => { if (err) { log.trace('request authorization failed', diff --git a/lib/api/objectGetTagging.js b/lib/api/objectGetTagging.js index eb437a4c11..c5bb7bb25b 100644 --- a/lib/api/objectGetTagging.js +++ b/lib/api/objectGetTagging.js @@ -46,7 +46,7 @@ function objectGetTagging(authInfo, request, log, callback) { }; return async.waterfall([ - next => metadataValidateBucketAndObj(metadataValParams, log, + next => metadataValidateBucketAndObj(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket, objectMD) => { if (err) { log.trace('request authorization failed', diff --git a/lib/api/objectHead.js b/lib/api/objectHead.js index 01420d8443..d7d7477bda 100644 --- a/lib/api/objectHead.js +++ b/lib/api/objectHead.js @@ -50,7 +50,7 @@ function objectHead(authInfo, request, log, callback) { request, }; - return metadataValidateBucketAndObj(mdValParams, log, + return metadataValidateBucketAndObj(mdValParams, request.isImplicitIdentityDeny, log, (err, bucket, objMD) => { const corsHeaders = collectCorsHeaders(request.headers.origin, request.method, bucket); diff --git a/lib/api/objectPut.js b/lib/api/objectPut.js index 77b518ee96..56381a18c1 100644 --- a/lib/api/objectPut.js +++ b/lib/api/objectPut.js @@ -71,7 +71,7 @@ function objectPut(authInfo, request, streamingV4Params, log, callback) { log.trace('owner canonicalID to send to data', { canonicalID }); - return metadataValidateBucketAndObj(valParams, log, + return metadataValidateBucketAndObj(valParams, request.isImplicitIdentityDeny, log, (err, bucket, objMD) => { const responseHeaders = collectCorsHeaders(headers.origin, method, bucket); diff --git a/lib/api/objectPutACL.js b/lib/api/objectPutACL.js index ec040cb322..a0098c057e 100644 --- a/lib/api/objectPutACL.js +++ b/lib/api/objectPutACL.js @@ -112,7 +112,7 @@ function objectPutACL(authInfo, request, log, cb) { return async.waterfall([ function validateBucketAndObj(next) { - return metadataValidateBucketAndObj(metadataValParams, log, + return metadataValidateBucketAndObj(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket, objectMD) => { if (err) { return next(err); diff --git a/lib/api/objectPutCopyPart.js b/lib/api/objectPutCopyPart.js index c423cc556b..cfcbc57b8a 100644 --- a/lib/api/objectPutCopyPart.js +++ b/lib/api/objectPutCopyPart.js @@ -93,7 +93,7 @@ function objectPutCopyPart(authInfo, request, sourceBucket, return async.waterfall([ function checkDestAuth(next) { - return metadataValidateBucketAndObj(valPutParams, log, + return metadataValidateBucketAndObj(valPutParams, request.isImplicitIdentityDeny, log, (err, destBucketMD) => { if (err) { log.debug('error validating authorization for ' + @@ -112,7 +112,7 @@ function objectPutCopyPart(authInfo, request, sourceBucket, }); }, function checkSourceAuthorization(destBucketMD, next) { - return metadataValidateBucketAndObj(valGetParams, log, + return metadataValidateBucketAndObj(valGetParams, request.isImplicitIdentityDeny, log, (err, sourceBucketMD, sourceObjMD) => { if (err) { log.debug('error validating get part of request', diff --git a/lib/api/objectPutLegalHold.js b/lib/api/objectPutLegalHold.js index 5d4a62708e..aa48333532 100644 --- a/lib/api/objectPutLegalHold.js +++ b/lib/api/objectPutLegalHold.js @@ -48,7 +48,7 @@ function objectPutLegalHold(authInfo, request, log, callback) { }; return async.waterfall([ - next => metadataValidateBucketAndObj(metadataValParams, log, + next => metadataValidateBucketAndObj(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket, objectMD) => { if (err) { log.trace('request authorization failed', diff --git a/lib/api/objectPutRetention.js b/lib/api/objectPutRetention.js index da8eb79b23..57e84c1173 100644 --- a/lib/api/objectPutRetention.js +++ b/lib/api/objectPutRetention.js @@ -49,7 +49,22 @@ function objectPutRetention(authInfo, request, log, callback) { }; return async.waterfall([ - next => metadataValidateBucketAndObj(metadataValParams, log, + next => { + log.trace('parsing retention information'); + parseRetentionXml(request.post, log, + (err, retentionInfo) => { + if (err) { + log.trace('error parsing retention information', + { error: err }); + return next(err); + } + const remainingDays = Math.ceil( + (new Date(retentionInfo.date) - Date.now()) / (1000 * 3600 * 24)); + metadataValParams.request.objectLockRetentionDays = remainingDays; + return next(null, retentionInfo); + }); + }, + (retentionInfo, next) => metadataValidateBucketAndObj(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket, objectMD) => { if (err) { log.trace('request authorization failed', @@ -77,13 +92,8 @@ function objectPutRetention(authInfo, request, log, callback) { 'Bucket is missing Object Lock Configuration' ), bucket); } - return next(null, bucket, objectMD); + return next(null, bucket, retentionInfo, objectMD); }), - (bucket, objectMD, next) => { - log.trace('parsing retention information'); - parseRetentionXml(request.post, log, - (err, retentionInfo) => next(err, bucket, retentionInfo, objectMD)); - }, (bucket, retentionInfo, objectMD, next) => { const hasGovernanceBypass = hasGovernanceBypassHeader(request.headers); if (hasGovernanceBypass && authInfo.isRequesterAnIAMUser()) { diff --git a/lib/api/objectPutTagging.js b/lib/api/objectPutTagging.js index c37b11c569..9708e6b0f7 100644 --- a/lib/api/objectPutTagging.js +++ b/lib/api/objectPutTagging.js @@ -50,7 +50,7 @@ function objectPutTagging(authInfo, request, log, callback) { }; return async.waterfall([ - next => metadataValidateBucketAndObj(metadataValParams, log, + next => metadataValidateBucketAndObj(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket, objectMD) => { if (err) { log.trace('request authorization failed', diff --git a/lib/routes/routeBackbeat.js b/lib/routes/routeBackbeat.js index d017007720..266a2278f8 100644 --- a/lib/routes/routeBackbeat.js +++ b/lib/routes/routeBackbeat.js @@ -1271,7 +1271,7 @@ function routeBackbeat(clientIP, request, response, log) { requestType: 'ReplicateObject', request, }; - return metadataValidateBucketAndObj(mdValParams, log, next); + return metadataValidateBucketAndObj(mdValParams, false, log, next); }, (bucketInfo, objMd, next) => { if (useMultipleBackend) { diff --git a/package.json b/package.json index 56f011c840..813179b80f 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "homepage": "https://github.com/scality/S3#readme", "dependencies": { "@hapi/joi": "^17.1.0", - "arsenal": "git+https://github.com/scality/arsenal#7.70.4", + "arsenal": "git+https://github.com/scality/arsenal#2aad26b33c529d724cbdfafc473b93d2600463a2", "async": "~2.5.0", "aws-sdk": "2.905.0", "azure-storage": "^2.1.0", diff --git a/tests/unit/api/bucketPolicyAuth.js b/tests/unit/api/bucketPolicyAuth.js index fc0e42d56d..7c1a255e87 100644 --- a/tests/unit/api/bucketPolicyAuth.js +++ b/tests/unit/api/bucketPolicyAuth.js @@ -244,7 +244,7 @@ describe('bucket policy authorization', () => { describe('isBucketAuthorized with no policy set', () => { it('should allow access to bucket owner', done => { const allowed = isBucketAuthorized(bucket, 'bucketPut', - bucketOwnerCanonicalId, null, log); + bucketOwnerCanonicalId, null, true, log); assert.equal(allowed, true); done(); }); @@ -252,7 +252,7 @@ describe('bucket policy authorization', () => { it('should deny access to non-bucket owner', done => { const allowed = isBucketAuthorized(bucket, 'bucketPut', - altAcctCanonicalId, null, log); + altAcctCanonicalId, null, true, log); assert.equal(allowed, false); done(); }); @@ -268,7 +268,7 @@ describe('bucket policy authorization', () => { it('should allow access to non-bucket owner if principal is set to "*"', done => { const allowed = isBucketAuthorized(bucket, bucAction, - altAcctCanonicalId, null, log); + altAcctCanonicalId, null, true, log); assert.equal(allowed, true); done(); }); @@ -276,7 +276,7 @@ describe('bucket policy authorization', () => { it('should allow access to public user if principal is set to "*"', done => { const allowed = isBucketAuthorized(bucket, bucAction, - constants.publicId, null, log); + constants.publicId, null, true, log); assert.equal(allowed, true); done(); }); @@ -287,7 +287,7 @@ describe('bucket policy authorization', () => { newPolicy.Statement[0][t.keyToChange] = t.bucketValue; bucket.setBucketPolicy(newPolicy); const allowed = isBucketAuthorized(bucket, bucAction, - t.bucketId, t.bucketAuthInfo, log); + t.bucketId, t.bucketAuthInfo, true, log); assert.equal(allowed, t.expected); done(); }); @@ -304,7 +304,7 @@ describe('bucket policy authorization', () => { }; bucket.setBucketPolicy(newPolicy); const allowed = isBucketAuthorized(bucket, bucAction, - altAcctCanonicalId, null, log); + altAcctCanonicalId, null, true, log); assert.equal(allowed, false); done(); }); @@ -312,7 +312,7 @@ describe('bucket policy authorization', () => { it('should deny access to non-bucket owner with an unsupported action type', done => { const allowed = isBucketAuthorized(bucket, 'unsupportedAction', - altAcctCanonicalId, null, log); + altAcctCanonicalId, null, true, log); assert.equal(allowed, false); done(); }); @@ -325,7 +325,7 @@ describe('bucket policy authorization', () => { it('should allow access to object owner', done => { const allowed = isObjAuthorized(bucket, object, objAction, - objectOwnerCanonicalId, null, log); + objectOwnerCanonicalId, null, true, log); assert.equal(allowed, true); done(); }); @@ -333,7 +333,7 @@ describe('bucket policy authorization', () => { it('should deny access to non-object owner', done => { const allowed = isObjAuthorized(bucket, object, objAction, - altAcctCanonicalId, null, log); + altAcctCanonicalId, null, true, log); assert.equal(allowed, false); done(); }); @@ -352,7 +352,7 @@ describe('bucket policy authorization', () => { it('should allow access to non-object owner if principal is set to "*"', done => { const allowed = isObjAuthorized(bucket, object, objAction, - altAcctCanonicalId, null, log); + altAcctCanonicalId, null, true, log); assert.equal(allowed, true); done(); }); @@ -360,7 +360,7 @@ describe('bucket policy authorization', () => { it('should allow access to public user if principal is set to "*"', done => { const allowed = isObjAuthorized(bucket, object, objAction, - constants.publicId, null, log); + constants.publicId, null, true, log); assert.equal(allowed, true); done(); }); @@ -371,7 +371,7 @@ describe('bucket policy authorization', () => { newPolicy.Statement[0][t.keyToChange] = t.objectValue; bucket.setBucketPolicy(newPolicy); const allowed = isObjAuthorized(bucket, object, objAction, - t.objectId, t.objectAuthInfo, log); + t.objectId, t.objectAuthInfo, true, log); assert.equal(allowed, t.expected); done(); }); @@ -383,7 +383,7 @@ describe('bucket policy authorization', () => { newPolicy.Statement[0].Action = ['s3:GetObject']; bucket.setBucketPolicy(newPolicy); const allowed = isObjAuthorized(bucket, object, 'objectHead', - altAcctCanonicalId, altAcctAuthInfo, log); + altAcctCanonicalId, altAcctAuthInfo, true, log); assert.equal(allowed, true); done(); }); @@ -393,7 +393,7 @@ describe('bucket policy authorization', () => { newPolicy.Statement[0].Action = ['s3:PutObject']; bucket.setBucketPolicy(newPolicy); const allowed = isObjAuthorized(bucket, object, 'objectHead', - altAcctCanonicalId, altAcctAuthInfo, log); + altAcctCanonicalId, altAcctAuthInfo, true, log); assert.equal(allowed, false); done(); }); @@ -408,7 +408,7 @@ describe('bucket policy authorization', () => { }; bucket.setBucketPolicy(newPolicy); const allowed = isObjAuthorized(bucket, object, objAction, - altAcctCanonicalId, null, log); + altAcctCanonicalId, null, true, log); assert.equal(allowed, false); done(); }); @@ -416,7 +416,7 @@ describe('bucket policy authorization', () => { it('should deny access to non-object owner with an unsupported action type', done => { const allowed = isObjAuthorized(bucket, object, 'unsupportedAction', - altAcctCanonicalId, null, log); + altAcctCanonicalId, null, true, log); assert.equal(allowed, false); done(); }); diff --git a/tests/unit/api/bucketPutPolicy.js b/tests/unit/api/bucketPutPolicy.js index 33cce4a1bc..c3c3774285 100644 --- a/tests/unit/api/bucketPutPolicy.js +++ b/tests/unit/api/bucketPutPolicy.js @@ -76,7 +76,7 @@ describe('putBucketPolicy API', () => { }); }); - it('should return error if policy contains conditions', done => { + it.skip('should return error if policy contains conditions', done => { expectedBucketPolicy.Statement[0].Condition = { StringEquals: { 's3:x-amz-acl': ['public-read'] } }; bucketPutPolicy(authInfo, getPolicyRequest(expectedBucketPolicy), log, diff --git a/tests/unit/api/objectACLauth.js b/tests/unit/api/objectACLauth.js index 87f1b70f2a..c5b5c52fad 100644 --- a/tests/unit/api/objectACLauth.js +++ b/tests/unit/api/objectACLauth.js @@ -456,7 +456,7 @@ describe('without object metadata', () => { bucket.setCannedAcl(value.canned); const results = requestTypes.map(type => - isObjAuthorized(bucket, null, type, value.id, authInfoUser, log)); + isObjAuthorized(bucket, null, type, value.id, authInfoUser, true, log)); assert.deepStrictEqual(results, value.response); done(); }); diff --git a/tests/unit/metadata/metadataUtils.spec.js b/tests/unit/metadata/metadataUtils.spec.js index 574c90e41e..7e2ab7f9be 100644 --- a/tests/unit/metadata/metadataUtils.spec.js +++ b/tests/unit/metadata/metadataUtils.spec.js @@ -48,7 +48,7 @@ describe('validateBucket', () => { authInfo: otherAuthInfo, requestType: 'bucketGet', request: null, - }, log); + }, true, log); assert(validationResult); assert(validationResult.is.AccessDenied); }); diff --git a/yarn.lock b/yarn.lock index 3d1f57eb0e..9ec7ee7dcc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -129,6 +129,11 @@ resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz#5981a8db18b56ba38ef0efb7d995b12aa7b51918" integrity sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ== +"@socket.io/component-emitter@~3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553" + integrity sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg== + "@tootallnate/once@1": version "1.1.2" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" @@ -139,6 +144,23 @@ resolved "https://registry.yarnpkg.com/@types/async/-/async-3.2.15.tgz#26d4768fdda0e466f18d6c9918ca28cc89a4e1fe" integrity sha512-PAmPfzvFA31mRoqZyTVsgJMsvbynR429UTTxhmfsUCrWGh3/fxOrzqBtaTPJsn4UtzTv4Vb0+/O7CARWb69N4g== +"@types/cookie@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d" + integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q== + +"@types/cors@^2.8.12": + version "2.8.13" + resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.13.tgz#b8ade22ba455a1b8cb3b5d3f35910fd204f84f94" + integrity sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA== + dependencies: + "@types/node" "*" + +"@types/node@*", "@types/node@>=10.0.0": + version "20.4.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.4.1.tgz#a6033a8718653c50ac4962977e14d0f984d9527d" + integrity sha512-JIzsAvJeA/5iY6Y/OxZbv1lUcc8dNSE77lb2gnBH+/PJ3lFR1Ccvgwl5JWnHAkNHcRsT0TbpVOsiMKZ1F/yyJg== + "@types/utf8@^3.0.1": version "3.0.1" resolved "https://registry.yarnpkg.com/@types/utf8/-/utf8-3.0.1.tgz#bf081663d4fff05ee63b41f377a35f8b189f7e5b" @@ -426,9 +448,9 @@ arraybuffer.slice@~0.0.7: optionalDependencies: ioctl "^2.0.2" -"arsenal@git+https://github.com/scality/arsenal#7.70.4": - version "7.70.4" - resolved "git+https://github.com/scality/arsenal#c4cc5a2c3dfa4a8d6d565c4029ec05cbb0bf1a3e" +"arsenal@git+https://github.com/scality/arsenal#2aad26b33c529d724cbdfafc473b93d2600463a2": + version "7.10.47" + resolved "git+https://github.com/scality/arsenal#2aad26b33c529d724cbdfafc473b93d2600463a2" dependencies: "@types/async" "^3.2.12" "@types/utf8" "^3.0.1" @@ -456,8 +478,8 @@ arraybuffer.slice@~0.0.7: node-forge "^0.7.1" prom-client "14.2.0" simple-glob "^0.2" - socket.io "~2.3.0" - socket.io-client "~2.3.0" + socket.io "~4.6.1" + socket.io-client "~4.6.1" sproxydclient "github:scality/sproxydclient#8.0.4" utf8 "2.1.2" uuid "^3.0.1" @@ -712,7 +734,7 @@ base64-js@^1.0.2, base64-js@^1.3.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== -base64id@2.0.0: +base64id@2.0.0, base64id@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6" integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== @@ -1150,6 +1172,11 @@ cookie@0.5.0: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== +cookie@~0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== + core-js@^2.4.0: version "2.6.12" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" @@ -1165,6 +1192,14 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== +cors@~2.8.5: + version "2.8.5" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== + dependencies: + object-assign "^4" + vary "^1" + cron-parser@^2.11.0, cron-parser@^2.15.0, cron-parser@^2.18.0: version "2.18.0" resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-2.18.0.tgz#de1bb0ad528c815548371993f81a54e5a089edcf" @@ -1228,7 +1263,7 @@ debug@2.6.9, debug@^2.1.1, debug@^2.2.0, debug@^2.6.8, debug@~2.6.9: dependencies: ms "2.0.0" -debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.3: +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.3, debug@~4.3.1, debug@~4.3.2: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -1423,6 +1458,17 @@ engine.io-client@~3.4.0: xmlhttprequest-ssl "~1.5.4" yeast "0.1.2" +engine.io-client@~6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-6.4.0.tgz#88cd3082609ca86d7d3c12f0e746d12db4f47c91" + integrity sha512-GyKPDyoEha+XZ7iEqam49vz6auPnNJ9ZBfy89f+rMMas8AuiMWOZ9PVzu8xb9ZC6rafUqiGHSCfu22ih66E+1g== + dependencies: + "@socket.io/component-emitter" "~3.1.0" + debug "~4.3.1" + engine.io-parser "~5.0.3" + ws "~8.11.0" + xmlhttprequest-ssl "~2.0.0" + engine.io-parser@~2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.2.1.tgz#57ce5611d9370ee94f99641b589f94c97e4f5da7" @@ -1434,6 +1480,11 @@ engine.io-parser@~2.2.0: blob "0.0.5" has-binary2 "~1.0.2" +engine.io-parser@~5.0.3: + version "5.0.7" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.0.7.tgz#ed5eae76c71f398284c578ab6deafd3ba7e4e4f6" + integrity sha512-P+jDFbvK6lE3n1OL+q9KuzdOFWkkZ/cMV9gol/SbVfpyqfvrfrFTOFJ6fQm2VC3PZHlU3QPhVwmbsCnauHF2MQ== + engine.io@~3.4.0: version "3.4.2" resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.4.2.tgz#8fc84ee00388e3e228645e0a7d3dfaeed5bd122c" @@ -1446,6 +1497,22 @@ engine.io@~3.4.0: engine.io-parser "~2.2.0" ws "^7.1.2" +engine.io@~6.4.2: + version "6.4.2" + resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.4.2.tgz#ffeaf68f69b1364b0286badddf15ff633476473f" + integrity sha512-FKn/3oMiJjrOEOeUub2WCox6JhxBXq/Zn3fZOMCBxKnNYtsdKjxhl7yR3fZhM9PV+rdE75SU5SYMc+2PGzo+Tg== + dependencies: + "@types/cookie" "^0.4.1" + "@types/cors" "^2.8.12" + "@types/node" ">=10.0.0" + accepts "~1.3.4" + base64id "2.0.0" + cookie "~0.4.1" + cors "~2.8.5" + debug "~4.3.1" + engine.io-parser "~5.0.3" + ws "~8.11.0" + entities@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" @@ -3839,7 +3906,7 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4.0.1, object-assign@^4.1.0: +object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== @@ -4585,6 +4652,13 @@ socket.io-adapter@~1.1.0: resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz#ab3f0d6f66b8fc7fca3959ab5991f82221789be9" integrity sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g== +socket.io-adapter@~2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz#5de9477c9182fdc171cd8c8364b9a8894ec75d12" + integrity sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA== + dependencies: + ws "~8.11.0" + socket.io-client@2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.3.0.tgz#14d5ba2e00b9bcd145ae443ab96b3f86cbcc1bb4" @@ -4622,6 +4696,16 @@ socket.io-client@~2.3.0: socket.io-parser "~3.3.0" to-array "0.1.4" +socket.io-client@~4.6.1: + version "4.6.2" + resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-4.6.2.tgz#2bfde952e74625d54e622718a7cb1d591ee62fd6" + integrity sha512-OwWrMbbA8wSqhBAR0yoPK6EdQLERQAYjXb3A0zLpgxfM1ZGLKoxHx8gVmCHA6pcclRX5oA/zvQf7bghAS11jRA== + dependencies: + "@socket.io/component-emitter" "~3.1.0" + debug "~4.3.2" + engine.io-client "~6.4.0" + socket.io-parser "~4.2.4" + socket.io-parser@~3.3.0: version "3.3.2" resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.3.2.tgz#ef872009d0adcf704f2fbe830191a14752ad50b6" @@ -4640,6 +4724,14 @@ socket.io-parser@~3.4.0: debug "~4.1.0" isarray "2.0.1" +socket.io-parser@~4.2.4: + version "4.2.4" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.4.tgz#c806966cf7270601e47469ddeec30fbdfda44c83" + integrity sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew== + dependencies: + "@socket.io/component-emitter" "~3.1.0" + debug "~4.3.1" + socket.io@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-2.3.0.tgz#cd762ed6a4faeca59bc1f3e243c0969311eb73fb" @@ -4652,6 +4744,18 @@ socket.io@~2.3.0: socket.io-client "2.3.0" socket.io-parser "~3.4.0" +socket.io@~4.6.1: + version "4.6.2" + resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.6.2.tgz#d597db077d4df9cbbdfaa7a9ed8ccc3d49439786" + integrity sha512-Vp+lSks5k0dewYTfwgPT9UeGGd+ht7sCpB7p0e83VgO4X/AHYWhXITMrNk/pg8syY2bpx23ptClCQuHhqi2BgQ== + dependencies: + accepts "~1.3.4" + base64id "~2.0.0" + debug "~4.3.2" + engine.io "~6.4.2" + socket.io-adapter "~2.5.2" + socket.io-parser "~4.2.4" + socks-proxy-agent@^6.0.0: version "6.2.1" resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz#2687a31f9d7185e38d530bef1944fe1f1496d6ce" @@ -5251,7 +5355,7 @@ validator@^13.0.0, validator@^13.6.0, validator@^13.7.0: resolved "https://registry.yarnpkg.com/validator/-/validator-13.7.0.tgz#4f9658ba13ba8f3d82ee881d3516489ea85c0857" integrity sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw== -vary@~1.1.2: +vary@^1, vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== @@ -5414,6 +5518,11 @@ ws@~6.1.0: dependencies: async-limiter "~1.0.0" +ws@~8.11.0: + version "8.11.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143" + integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg== + xml2js@0.4.19: version "0.4.19" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" @@ -5457,6 +5566,11 @@ xmlhttprequest-ssl@~1.5.4: resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz#c2876b06168aadc40e57d97e81191ac8f4398b3e" integrity sha512-/bFPLUgJrfGUL10AIv4Y7/CUt6so9CLtB/oFxQSHseSDNNCdC6vwwKEqwLN6wNPBg9YWXAiMu8jkf6RPRS/75Q== +xmlhttprequest-ssl@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz#91360c86b914e67f44dce769180027c0da618c67" + integrity sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A== + xtend@^4.0.0, xtend@^4.0.2, xtend@~4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"