Compare commits

...

1 Commits

Author SHA1 Message Date
naren-scality 034436f13d bf: CLDSRV-12 bucket policy resource security fix
Adds resource check for bucket policies. S3 actions are modified to pass
request object for resource validation.
2021-08-13 03:05:15 -07:00
58 changed files with 94 additions and 44 deletions

View File

@ -1,4 +1,4 @@
const { evaluators, actionMaps } = require('arsenal').policies;
const { evaluators, actionMaps, RequestContext } = require('arsenal').policies;
const constants = require('../../../../constants');
const { allAuthedUsersId, bucketOwnerActions, logId, publicId } = constants;
@ -182,6 +182,17 @@ function _checkBucketPolicyActions(requestType, actions, log) {
return evaluators.isActionApplicable(mappedAction, actions, log);
}
function _checkBucketPolicyResources(request, resource, log) {
if (!request || (Array.isArray(resource) && resource.length === 0)) {
return true;
}
// build request context from the request!
const requestContext = new RequestContext(request.headers, request.query,
request.bucketName, request.objectKey, null,
request.connection.encrypted, request.resourceType, 's3');
return evaluators.isResourceApplicable(requestContext, resource, log);
}
function _getAccountId(arn) {
// account or user arn is of format 'arn:aws:iam::<12-digit-acct-id>:etc...
return arn.substr(13, 12);
@ -226,7 +237,7 @@ function _checkPrincipals(canonicalID, arn, principal) {
return false;
}
function checkBucketPolicy(policy, requestType, canonicalID, arn, bucketOwner, log) {
function checkBucketPolicy(policy, requestType, canonicalID, arn, bucketOwner, log, request) {
let permission = 'defaultDeny';
// if requester is user within bucket owner account, actions should be
// allowed unless explicitly denied (assumes allowed by IAM policy)
@ -238,12 +249,13 @@ function checkBucketPolicy(policy, requestType, canonicalID, arn, bucketOwner, l
const s = copiedStatement[0];
const principalMatch = _checkPrincipals(canonicalID, arn, s.Principal);
const actionMatch = _checkBucketPolicyActions(requestType, s.Action, log);
const resourceMatch = _checkBucketPolicyResources(request, s.Resource, log);
if (principalMatch && actionMatch && s.Effect === 'Deny') {
if (principalMatch && actionMatch && resourceMatch && s.Effect === 'Deny') {
// explicit deny trumps any allows, so return immediately
return 'explicitDeny';
}
if (principalMatch && actionMatch && s.Effect === 'Allow') {
if (principalMatch && actionMatch && resourceMatch && s.Effect === 'Allow') {
permission = 'allow';
}
copiedStatement = copiedStatement.splice(1);
@ -251,7 +263,7 @@ function checkBucketPolicy(policy, requestType, canonicalID, arn, bucketOwner, l
return permission;
}
function isBucketAuthorized(bucket, requestType, canonicalID, authInfo, log) {
function isBucketAuthorized(bucket, requestType, canonicalID, authInfo, log, request) {
// Check to see if user is authorized to perform a
// particular action on bucket based on ACLs.
// TODO: Add IAM checks
@ -271,14 +283,14 @@ function isBucketAuthorized(bucket, requestType, canonicalID, authInfo, log) {
return aclPermission;
}
const bucketPolicyPermission = checkBucketPolicy(bucketPolicy, requestType,
canonicalID, arn, bucket.getOwner(), log);
canonicalID, arn, bucket.getOwner(), log, request);
if (bucketPolicyPermission === 'explicitDeny') {
return false;
}
return (aclPermission || (bucketPolicyPermission === 'allow'));
}
function isObjAuthorized(bucket, objectMD, requestType, canonicalID, authInfo, log) {
function isObjAuthorized(bucket, objectMD, requestType, canonicalID, authInfo, log, request) {
const bucketOwner = bucket.getOwner();
if (!objectMD) {
// User is already authorized on the bucket for FULL_CONTROL or WRITE or
@ -288,7 +300,7 @@ function isObjAuthorized(bucket, objectMD, requestType, canonicalID, authInfo, l
}
// check bucket has read access
// 'bucketGet' covers listObjects and listMultipartUploads, bucket read actions
return isBucketAuthorized(bucket, 'bucketGet', canonicalID, authInfo, log);
return isBucketAuthorized(bucket, 'bucketGet', canonicalID, authInfo, log, request);
}
let requesterIsNotUser = true;
let arn = null;
@ -315,7 +327,7 @@ function isObjAuthorized(bucket, objectMD, requestType, canonicalID, authInfo, l
return aclPermission;
}
const bucketPolicyPermission = checkBucketPolicy(bucketPolicy, requestType,
canonicalID, arn, bucket.getOwner(), log);
canonicalID, arn, bucket.getOwner(), log, request);
if (bucketPolicyPermission === 'explicitDeny') {
return false;
}

View File

@ -17,6 +17,7 @@ function abortMultipartUpload(authInfo, bucketName, objectKey, uploadId, log,
objectKey,
uploadId,
preciseRequestType: 'multipartDelete',
request,
};
// For validating the request at the destinationBucket level
// params are the same as validating at the MPU level

View File

@ -28,6 +28,7 @@ function bucketDelete(authInfo, request, log, cb) {
authInfo,
bucketName,
requestType: 'bucketDelete',
request,
};
return metadataValidateBucket(metadataValParams, log,

View File

@ -33,8 +33,7 @@ function bucketDeleteCors(authInfo, request, log, callback) {
}
log.trace('found bucket in metadata');
if (!isBucketAuthorized(bucket, requestType, canonicalID, authInfo,
log)) {
if (!isBucketAuthorized(bucket, requestType, canonicalID, authInfo, log, request)) {
log.debug('access denied for user on bucket', {
requestType,
method: 'bucketDeleteCors',

View File

@ -22,6 +22,7 @@ function bucketDeleteEncryption(authInfo, request, log, callback) {
authInfo,
bucketName,
requestType: 'bucketDeleteEncryption',
request,
};
return async.waterfall([

View File

@ -18,6 +18,7 @@ function bucketDeleteLifecycle(authInfo, request, log, callback) {
authInfo,
bucketName,
requestType: 'bucketDeleteLifecycle',
request,
};
return metadataValidateBucket(metadataValParams, log, (err, bucket) => {
const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);

View File

@ -17,6 +17,7 @@ function bucketDeletePolicy(authInfo, request, log, callback) {
authInfo,
bucketName,
requestType: 'bucketDeletePolicy',
request,
};
return metadataValidateBucket(metadataValParams, log, (err, bucket) => {
const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);

View File

@ -18,6 +18,7 @@ function bucketDeleteReplication(authInfo, request, log, callback) {
authInfo,
bucketName,
requestType: 'bucketDeleteReplication',
request,
};
return metadataValidateBucket(metadataValParams, log, (err, bucket) => {
const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);

View File

@ -25,8 +25,7 @@ function bucketDeleteWebsite(authInfo, request, log, callback) {
}
log.trace('found bucket in metadata');
if (!isBucketAuthorized(bucket, requestType, canonicalID, authInfo,
log)) {
if (!isBucketAuthorized(bucket, requestType, canonicalID, authInfo, log, request)) {
log.debug('access denied for user on bucket', {
requestType,
method: 'bucketDeleteWebsite',

View File

@ -315,6 +315,7 @@ function bucketGet(authInfo, request, log, callback) {
authInfo,
bucketName,
requestType: 'bucketGet',
request,
};
const listParams = {
listingType: 'DelimiterMaster',

View File

@ -45,6 +45,7 @@ function bucketGetACL(authInfo, request, log, callback) {
authInfo,
bucketName,
requestType: 'bucketGetACL',
request,
};
const grantInfo = {
grants: [],

View File

@ -34,8 +34,7 @@ function bucketGetCors(authInfo, request, log, callback) {
const corsHeaders = collectCorsHeaders(request.headers.origin,
request.method, bucket);
if (!isBucketAuthorized(bucket, requestType, canonicalID, authInfo,
log)) {
if (!isBucketAuthorized(bucket, requestType, canonicalID, authInfo, log, request)) {
log.debug('access denied for user on bucket', {
requestType,
method: 'bucketGetCors',

View File

@ -23,6 +23,7 @@ function bucketGetEncryption(authInfo, request, log, callback) {
authInfo,
bucketName,
requestType: 'bucketGetEncryption',
request,
};
return async.waterfall([

View File

@ -21,6 +21,7 @@ function bucketGetLifecycle(authInfo, request, log, callback) {
authInfo,
bucketName,
requestType: 'bucketGetLifecycle',
request,
};
return metadataValidateBucket(metadataValParams, log, (err, bucket) => {
const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);

View File

@ -36,8 +36,7 @@ function bucketGetLocation(authInfo, request, log, callback) {
const corsHeaders = collectCorsHeaders(request.headers.origin,
request.method, bucket);
if (!isBucketAuthorized(bucket, requestType, canonicalID, authInfo,
log)) {
if (!isBucketAuthorized(bucket, requestType, canonicalID, authInfo, log, request)) {
log.debug('access denied for account on bucket', {
requestType,
method: 'bucketGetLocation',

View File

@ -38,6 +38,7 @@ function bucketGetNotification(authInfo, request, log, callback) {
authInfo,
bucketName,
requestType: 'bucketGetNotification',
request,
};
return metadataValidateBucket(metadataValParams, log, (err, bucket) => {

View File

@ -34,6 +34,7 @@ function bucketGetObjectLock(authInfo, request, log, callback) {
authInfo,
bucketName,
requestType: 'bucketGetObjectLock',
request,
};
return metadataValidateBucket(metadataValParams, log, (err, bucket) => {
const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);

View File

@ -18,6 +18,7 @@ function bucketGetPolicy(authInfo, request, log, callback) {
authInfo,
bucketName,
requestType: 'bucketGetPolicy',
request,
};
return metadataValidateBucket(metadataValParams, log, (err, bucket) => {

View File

@ -21,6 +21,7 @@ function bucketGetReplication(authInfo, request, log, callback) {
authInfo,
bucketName,
requestType: 'bucketGetReplication',
request,
};
return metadataValidateBucket(metadataValParams, log, (err, bucket) => {
const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);

View File

@ -54,6 +54,7 @@ function bucketGetVersioning(authInfo, request, log, callback) {
authInfo,
bucketName,
requestType: 'bucketGetVersioning',
request,
};
metadataValidateBucket(metadataValParams, log, (err, bucket) => {

View File

@ -34,8 +34,7 @@ function bucketGetWebsite(authInfo, request, log, callback) {
const corsHeaders = collectCorsHeaders(request.headers.origin,
request.method, bucket);
if (!isBucketAuthorized(bucket, requestType, canonicalID, authInfo,
log)) {
if (!isBucketAuthorized(bucket, requestType, canonicalID, authInfo, log, request)) {
log.debug('access denied for user on bucket', {
requestType,
method: 'bucketGetWebsite',

View File

@ -19,6 +19,7 @@ function bucketHead(authInfo, request, log, callback) {
authInfo,
bucketName,
requestType: 'bucketHead',
request,
};
metadataValidateBucket(metadataValParams, log, (err, bucket) => {
const corsHeaders = collectCorsHeaders(request.headers.origin,

View File

@ -72,6 +72,7 @@ function bucketPutACL(authInfo, request, log, callback) {
authInfo,
bucketName,
requestType: 'bucketPutACL',
request,
};
const possibleGrants = ['FULL_CONTROL', 'WRITE',
'WRITE_ACP', 'READ', 'READ_ACP'];

View File

@ -66,8 +66,7 @@ function bucketPutCors(authInfo, request, log, callback) {
});
},
function validateBucketAuthorization(bucket, rules, corsHeaders, next) {
if (!isBucketAuthorized(bucket, requestType, canonicalID,
authInfo, log)) {
if (!isBucketAuthorized(bucket, requestType, canonicalID, authInfo, log, request)) {
log.debug('access denied for account on bucket', {
requestType,
});

View File

@ -24,6 +24,7 @@ function bucketPutEncryption(authInfo, request, log, callback) {
authInfo,
bucketName,
requestType: 'bucketPutEncryption',
request,
};
return async.waterfall([

View File

@ -26,6 +26,7 @@ function bucketPutLifecycle(authInfo, request, log, callback) {
authInfo,
bucketName,
requestType: 'bucketPutLifecycle',
request,
};
return waterfall([
next => parseXML(request.post, log, next),

View File

@ -24,6 +24,7 @@ function bucketPutNotification(authInfo, request, log, callback) {
authInfo,
bucketName,
requestType: 'bucketPutNotification',
request,
};
return async.waterfall([

View File

@ -27,6 +27,7 @@ function bucketPutObjectLock(authInfo, request, log, callback) {
authInfo,
bucketName,
requestType: 'bucketPutObjectLock',
request,
};
return waterfall([
next => parseXML(request.post, log, next),

View File

@ -38,6 +38,7 @@ function bucketPutPolicy(authInfo, request, log, callback) {
authInfo,
bucketName,
requestType: 'bucketPutPolicy',
request,
};
return async.waterfall([

View File

@ -28,6 +28,7 @@ function bucketPutReplication(authInfo, request, log, callback) {
authInfo,
bucketName,
requestType: 'bucketPutReplication',
request,
};
return waterfall([
// Validate the request XML and return the replication configuration.

View File

@ -88,6 +88,7 @@ function bucketPutVersioning(authInfo, request, log, callback) {
authInfo,
bucketName,
requestType: 'bucketPutVersioning',
request,
};
return waterfall([

View File

@ -46,8 +46,7 @@ function bucketPutWebsite(authInfo, request, log, callback) {
});
},
function validateBucketAuthorization(bucket, config, next) {
if (!isBucketAuthorized(bucket, requestType, canonicalID,
authInfo, log)) {
if (!isBucketAuthorized(bucket, requestType, canonicalID, authInfo, log, request)) {
log.debug('access denied for user on bucket', {
requestType,
method: 'bucketPutWebsite',

View File

@ -84,6 +84,7 @@ function completeMultipartUpload(authInfo, request, log, callback) {
// same as putting a part.
requestType: 'putPart or complete',
log,
request,
};
const xmlParams = {
bucketName,

View File

@ -88,6 +88,7 @@ function initiateMultipartUpload(authInfo, request, log, callback) {
bucketName,
// Required permissions for this action are same as objectPut
requestType: 'objectPut',
request,
};
const accountCanonicalID = authInfo.getCanonicalID();
let initiatorID = accountCanonicalID;

View File

@ -97,6 +97,7 @@ function listMultipartUploads(authInfo, request, log, callback) {
// as listing objects in a bucket.
requestType: 'bucketGet',
preciseRequestType: 'listMultipartUploads',
request,
};
async.waterfall([

View File

@ -96,6 +96,7 @@ function listParts(authInfo, request, log, callback) {
objectKey,
uploadId,
preciseRequestType: 'listParts',
request,
};
// For validating the request at the destinationBucket level
// params are the same as validating at the MPU level

View File

@ -460,8 +460,7 @@ function multiObjectDelete(authInfo, request, log, callback) {
return next(null, quietSetting, errorResults, inPlay,
bucketMD);
}
if (!isBucketAuthorized(bucketMD, 'objectDelete',
canonicalID, authInfo, log)) {
if (!isBucketAuthorized(bucketMD, 'objectDelete', canonicalID, authInfo, log, request)) {
log.trace("access denied due to bucket acl's");
// if access denied at the bucket level, no access for
// any of the objects so all results will be error results

View File

@ -213,12 +213,14 @@ function objectCopy(authInfo, request, sourceBucket,
objectKey: sourceObject,
versionId: sourceVersionId,
requestType: 'objectGet',
request,
};
const valPutParams = {
authInfo,
bucketName: destBucketName,
objectKey: destObjectKey,
requestType: 'objectPut',
request,
};
const dataStoreContext = {
bucketName: destBucketName,

View File

@ -48,6 +48,7 @@ function objectDelete(authInfo, request, log, cb) {
objectKey,
versionId: reqVersionId,
requestType: 'objectDelete',
request,
};
const canonicalID = authInfo.getCanonicalID();

View File

@ -43,6 +43,7 @@ function objectDeleteTagging(authInfo, request, log, callback) {
objectKey,
requestType: 'objectDeleteTagging',
versionId: reqVersionId,
request,
};
return async.waterfall([

View File

@ -44,6 +44,7 @@ function objectGet(authInfo, request, returnTagCount, log, callback) {
objectKey,
versionId,
requestType: 'objectGet',
request,
};
return metadataValidateBucketAndObj(mdValParams, log,

View File

@ -60,6 +60,7 @@ function objectGetACL(authInfo, request, log, callback) {
objectKey,
versionId,
requestType: 'objectGetACL',
request,
};
const grantInfo = {
grants: [],

View File

@ -39,6 +39,7 @@ function objectGetLegalHold(authInfo, request, log, callback) {
objectKey,
requestType: 'objectGetLegalHold',
versionId,
request,
};
return async.waterfall([

View File

@ -39,6 +39,7 @@ function objectGetRetention(authInfo, request, log, callback) {
objectKey,
requestType: 'objectGetRetention',
versionId: reqVersionId,
request,
};
return async.waterfall([

View File

@ -39,6 +39,7 @@ function objectGetTagging(authInfo, request, log, callback) {
objectKey,
requestType: 'objectGetTagging',
versionId: reqVersionId,
request,
};
return async.waterfall([

View File

@ -44,6 +44,7 @@ function objectHead(authInfo, request, log, callback) {
objectKey,
versionId,
requestType: 'objectHead',
request,
};
return metadataValidateBucketAndObj(mdValParams, log,

View File

@ -56,7 +56,7 @@ function objectPut(authInfo, request, streamingV4Params, log, callback) {
const invalidSSEError = errors.InvalidArgument.customizeDescription(
'The encryption method specified is not supported');
const requestType = 'objectPut';
const valParams = { authInfo, bucketName, objectKey, requestType };
const valParams = { authInfo, bucketName, objectKey, requestType, request };
const canonicalID = authInfo.getCanonicalID();
log.trace('owner canonicalID to send to data', { canonicalID });

View File

@ -42,6 +42,7 @@ function objectPutCopyPart(authInfo, request, sourceBucket,
objectKey: sourceObject,
versionId: reqVersionId,
requestType: 'objectGet',
request,
};
const partNumber = Number.parseInt(request.query.partNumber, 10);
@ -62,6 +63,7 @@ function objectPutCopyPart(authInfo, request, sourceBucket,
bucketName: destBucketName,
objectKey: destObjectKey,
requestType: 'objectPut',
request,
};
// For validating the request at the MPU, the params are the same

View File

@ -42,6 +42,7 @@ function objectPutLegalHold(authInfo, request, log, callback) {
objectKey,
requestType: 'objectPutLegalHold',
versionId,
request,
};
return async.waterfall([

View File

@ -110,8 +110,7 @@ function objectPutPart(authInfo, request, streamingV4Params, log,
// For validating the request at the destinationBucket level the
// `requestType` is the general 'objectPut'.
const requestType = 'objectPut';
if (!isBucketAuthorized(destinationBucket, requestType,
canonicalID, authInfo, log)) {
if (!isBucketAuthorized(destinationBucket, requestType, canonicalID, authInfo, log, request)) {
log.debug('access denied for user on bucket', { requestType });
return next(errors.AccessDenied, destinationBucket);
}

View File

@ -45,6 +45,7 @@ function objectPutRetention(authInfo, request, log, callback) {
objectKey,
requestType: 'objectPutRetention',
versionId: reqVersionId,
request,
};
return async.waterfall([

View File

@ -44,6 +44,7 @@ function objectPutTagging(authInfo, request, log, callback) {
objectKey,
requestType: 'objectPutTagging',
versionId: reqVersionId,
request,
};
return async.waterfall([

View File

@ -144,7 +144,7 @@ function websiteGet(request, log, callback) {
{ error: err });
let returnErr = err;
const bucketAuthorized = isBucketAuthorized(bucket,
'bucketGet', constants.publicId, null, log);
'bucketGet', constants.publicId, null, log, request);
// if index object does not exist and bucket is private AWS
// returns 403 - AccessDenied error.
if (err === errors.NoSuchKey && !bucketAuthorized) {
@ -156,7 +156,7 @@ function websiteGet(request, log, callback) {
callback);
}
if (!isObjAuthorized(bucket, objMD, 'objectGet',
constants.publicId, null, log)) {
constants.publicId, null, log, request)) {
const err = errors.AccessDenied;
log.trace('request not authorized', { error: err });
return _errorActions(err, websiteConfig.getErrorDocument(),

View File

@ -104,7 +104,7 @@ function websiteHead(request, log, callback) {
{ error: err });
let returnErr = err;
const bucketAuthorized = isBucketAuthorized(bucket,
'bucketGet', constants.publicId, null, log);
'bucketGet', constants.publicId, null, log, request);
// if index object does not exist and bucket is private AWS
// returns 403 - AccessDenied error.
if (err === errors.NoSuchKey && !bucketAuthorized) {
@ -114,7 +114,7 @@ function websiteHead(request, log, callback) {
reqObjectKey, corsHeaders, log, callback);
}
if (!isObjAuthorized(bucket, objMD, 'objectGet',
constants.publicId, null, log)) {
constants.publicId, null, log, request)) {
const err = errors.AccessDenied;
log.trace('request not authorized', { error: err });
return _errorActions(err, routingRules, reqObjectKey,

View File

@ -169,12 +169,13 @@ function metadataGetObject(bucketName, objectKey, versionId, log, cb) {
* @param {string} params.objectKey - name of object
* @param {string} [params.versionId] - version id if getting specific version
* @param {string} params.requestType - type of request
* @param {object} params.request - http request object
* @param {RequestLogger} log - request logger
* @param {function} callback - callback
* @return {undefined} - and call callback with params err, bucket md
*/
function metadataValidateBucketAndObj(params, log, callback) {
const { authInfo, bucketName, objectKey, versionId, requestType, preciseRequestType } = params;
const { authInfo, bucketName, objectKey, versionId, requestType, preciseRequestType, request } = params;
const canonicalID = authInfo.getCanonicalID();
async.waterfall([
function getBucketAndObjectMD(next) {
@ -189,7 +190,7 @@ function metadataValidateBucketAndObj(params, log, callback) {
return next(errors.MethodNotAllowed, bucket);
}
if (!isBucketAuthorized(bucket, (preciseRequestType || requestType), canonicalID,
authInfo, log)) {
authInfo, log, request)) {
log.debug('access denied for user on bucket', { requestType });
return next(errors.AccessDenied, bucket);
}
@ -203,8 +204,7 @@ function metadataValidateBucketAndObj(params, log, callback) {
return next(null, bucket, objMD);
},
function checkObjectAuth(bucket, objMD, next) {
if (!isObjAuthorized(bucket, objMD, requestType, canonicalID,
authInfo, log)) {
if (!isObjAuthorized(bucket, objMD, requestType, canonicalID, authInfo, log, request)) {
log.debug('access denied for user on object', { requestType });
return next(errors.AccessDenied, bucket);
}
@ -251,12 +251,13 @@ function metadataGetBucket(requestType, bucketName, log, cb) {
* @param {AuthInfo} params.authInfo - AuthInfo class instance, requester's info
* @param {string} params.bucketName - name of bucket
* @param {string} params.requestType - type of request
* @param {string} params.request - http request object
* @param {RequestLogger} log - request logger
* @param {function} callback - callback
* @return {undefined} - and call callback with params err, bucket md
*/
function metadataValidateBucket(params, log, callback) {
const { authInfo, bucketName, requestType, preciseRequestType } = params;
const { authInfo, bucketName, requestType, preciseRequestType, request } = params;
const canonicalID = authInfo.getCanonicalID();
return metadataGetBucket(requestType, bucketName, log, (err, bucket) => {
if (err) {
@ -269,7 +270,7 @@ function metadataValidateBucket(params, log, callback) {
return callback(errors.MethodNotAllowed, bucket);
}
// still return bucket for cors headers
if (!isBucketAuthorized(bucket, (preciseRequestType || requestType), canonicalID, authInfo, log)) {
if (!isBucketAuthorized(bucket, (preciseRequestType || requestType), canonicalID, authInfo, log, request)) {
log.debug('access denied for user on bucket', { requestType });
return callback(errors.AccessDenied, bucket);
}

View File

@ -808,11 +808,14 @@ function routeBackbeat(clientIP, request, response, log) {
// Bucket and object do not exist in metadata.
return next(null, null, null);
}
const mdValParams = { bucketName: request.bucketName,
const mdValParams = {
bucketName: request.bucketName,
objectKey: request.objectKey,
authInfo: userInfo,
versionId,
requestType: 'ReplicateObject' };
requestType: 'ReplicateObject',
request,
};
return metadataValidateBucketAndObj(mdValParams, log, next);
},
(bucketInfo, objMd, next) => {

View File

@ -20,7 +20,7 @@
"homepage": "https://github.com/scality/S3#readme",
"dependencies": {
"@hapi/joi": "^17.1.0",
"arsenal": "github:scality/Arsenal#9aa8710",
"arsenal": "github:scality/Arsenal#db7d8b0",
"async": "~2.5.0",
"aws-sdk": "2.905.0",
"azure-storage": "^2.1.0",
@ -77,7 +77,7 @@
"install_ft_deps": "yarn install aws-sdk@2.28.0 bluebird@3.3.1 mocha@2.3.4 mocha-junit-reporter@1.23.1 tv4@1.2.7",
"lint": "eslint $(git ls-files '*.js')",
"lint_md": "mdlint $(git ls-files '*.md')",
"mem_backend": "S3BACKEND=mem node index.js",
"mem_backend": "S3BACKEND=mem node --inspect index.js",
"start": "npm-run-all --parallel start_dmd start_s3server",
"start_mdserver": "node mdserver.js",
"start_dataserver": "node dataserver.js",

View File

@ -650,9 +650,9 @@ arraybuffer.slice@~0.0.7:
resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675"
integrity sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==
"arsenal@github:scality/Arsenal#9aa8710":
"arsenal@github:scality/Arsenal#db7d8b0":
version "7.7.2"
resolved "https://codeload.github.com/scality/Arsenal/tar.gz/9aa8710a57b037685ad2851543808df3a41476b2"
resolved "https://codeload.github.com/scality/Arsenal/tar.gz/db7d8b0b4536653361d8e22092c09b87563d6901"
dependencies:
"@hapi/joi" "^15.1.0"
JSONStream "^1.0.0"