Compare commits
5 Commits
developmen
...
task/S3C-7
Author | SHA1 | Date |
---|---|---|
williamlardier | 70e9228c4f | |
williamlardier | cf230e7c07 | |
williamlardier | 7ccf386da5 | |
williamlardier | d596264f01 | |
williamlardier | 9a29d19a5a |
|
@ -139,9 +139,10 @@ const api = {
|
|||
|
||||
function checkAuthResults(authResults) {
|
||||
let returnTagCount = true;
|
||||
let isImplicitDeny = true;
|
||||
if (apiMethod === 'objectGet') {
|
||||
// first item checks s3:GetObject(Version) action
|
||||
if (!authResults[0].isAllowed) {
|
||||
if (!authResults[0].isAllowed && !authResults[0].isImplicit) {
|
||||
log.trace('get object authorization denial from Vault');
|
||||
return errors.AccessDenied;
|
||||
}
|
||||
|
@ -153,13 +154,22 @@ const api = {
|
|||
}
|
||||
} else {
|
||||
for (let i = 0; i < authResults.length; i++) {
|
||||
if (!authResults[i].isAllowed) {
|
||||
if (!authResults[i].isAllowed && !authResults[i].isImplicit) {
|
||||
// Any explicit deny rejects the current APÏ call
|
||||
log.trace('authorization denial from Vault');
|
||||
return errors.AccessDenied;
|
||||
} else if (authResults[i].isAllowed) {
|
||||
// If the action is allowed, the result is not implicit
|
||||
// Deny.
|
||||
isImplicitDeny = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnTagCount;
|
||||
// Specific APIs are not checking any ACLs or Bucket Policies.
|
||||
if (apiMethod === 'bucketPut' || apiMethod === 'serviceGet' && isImplicitDeny) {
|
||||
return errors.AccessDenied;
|
||||
}
|
||||
return { returnTagCount, isImplicitDeny };
|
||||
}
|
||||
|
||||
return async.waterfall([
|
||||
|
@ -237,7 +247,8 @@ const api = {
|
|||
if (checkedResults instanceof Error) {
|
||||
return callback(checkedResults);
|
||||
}
|
||||
returnTagCount = checkedResults;
|
||||
returnTagCount = checkedResults.returnTagCount;
|
||||
request.isImplicitIdentityDeny = checkedResults.isImplicitDeny;
|
||||
}
|
||||
if (apiMethod === 'objectPut' || apiMethod === 'objectPutPart') {
|
||||
request._response = response;
|
||||
|
|
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -268,7 +284,18 @@ function checkBucketPolicy(policy, requestType, canonicalID, arn, bucketOwner, l
|
|||
return permission;
|
||||
}
|
||||
|
||||
function isBucketAuthorized(bucket, requestType, canonicalID, authInfo, log, request) {
|
||||
function isIdentityAndResourceAuthorized(isImplicitIdentityDeny, resourceAuthzResult) {
|
||||
// If resourceAuthzResult is true, the the IAM result is either Allow or
|
||||
// implicit Deny (nothing applicable): in this case, we allow the request.
|
||||
if (resourceAuthzResult === true) {
|
||||
return true;
|
||||
}
|
||||
// If resourceAuthzResult is false, we only return true if IAM result is
|
||||
// Allow. Otherwise we default to an implicit Deny.
|
||||
return isImplicitIdentityDeny === false;
|
||||
}
|
||||
|
||||
function isBucketAuthorized(bucket, requestType, canonicalID, authInfo, isImplicitIdentityDeny, log, request) {
|
||||
// Check to see if user is authorized to perform a
|
||||
// particular action on bucket based on ACLs.
|
||||
// TODO: Add IAM checks
|
||||
|
@ -280,32 +307,34 @@ function isBucketAuthorized(bucket, requestType, canonicalID, authInfo, log, req
|
|||
}
|
||||
// if the bucket owner is an account, users should not have default access
|
||||
if ((bucket.getOwner() === canonicalID) && requesterIsNotUser) {
|
||||
return true;
|
||||
return isIdentityAndResourceAuthorized(isImplicitIdentityDeny, true);
|
||||
}
|
||||
const aclPermission = checkBucketAcls(bucket, requestType, canonicalID);
|
||||
const aclPermission = checkBucketAcls(bucket, requestType, canonicalID, requesterIsNotUser);
|
||||
const bucketPolicy = bucket.getBucketPolicy();
|
||||
if (!bucketPolicy) {
|
||||
return aclPermission;
|
||||
return isIdentityAndResourceAuthorized(isImplicitIdentityDeny, aclPermission);
|
||||
}
|
||||
const bucketPolicyPermission = checkBucketPolicy(bucketPolicy, requestType,
|
||||
canonicalID, arn, bucket.getOwner(), log, request);
|
||||
if (bucketPolicyPermission === 'explicitDeny') {
|
||||
return false;
|
||||
}
|
||||
return (aclPermission || (bucketPolicyPermission === 'allow'));
|
||||
return isIdentityAndResourceAuthorized(isImplicitIdentityDeny,
|
||||
(aclPermission || (bucketPolicyPermission === 'allow')));
|
||||
}
|
||||
|
||||
function isObjAuthorized(bucket, objectMD, requestType, canonicalID, authInfo, log, request) {
|
||||
function isObjAuthorized(bucket, objectMD, requestType, canonicalID, authInfo, isImplicitIdentityDeny, log, request) {
|
||||
const bucketOwner = bucket.getOwner();
|
||||
if (!objectMD) {
|
||||
// User is already authorized on the bucket for FULL_CONTROL or WRITE or
|
||||
// bucket has canned ACL public-read-write
|
||||
if (requestType === 'objectPut' || requestType === 'objectDelete') {
|
||||
return true;
|
||||
return isIdentityAndResourceAuthorized(isImplicitIdentityDeny, true);
|
||||
}
|
||||
// check bucket has read access
|
||||
// 'bucketGet' covers listObjects and listMultipartUploads, bucket read actions
|
||||
return isBucketAuthorized(bucket, 'bucketGet', canonicalID, authInfo, log, request);
|
||||
return isIdentityAndResourceAuthorized(isImplicitIdentityDeny,
|
||||
isBucketAuthorized(bucket, 'bucketGet', canonicalID, authInfo, isImplicitIdentityDeny, log, request));
|
||||
}
|
||||
let requesterIsNotUser = true;
|
||||
let arn = null;
|
||||
|
@ -314,7 +343,7 @@ function isObjAuthorized(bucket, objectMD, requestType, canonicalID, authInfo, l
|
|||
arn = authInfo.getArn();
|
||||
}
|
||||
if (objectMD['owner-id'] === canonicalID && requesterIsNotUser) {
|
||||
return true;
|
||||
return isIdentityAndResourceAuthorized(isImplicitIdentityDeny, true);
|
||||
}
|
||||
// account is authorized if:
|
||||
// - requesttype is included in bucketOwnerActions and
|
||||
|
@ -323,20 +352,21 @@ function isObjAuthorized(bucket, objectMD, requestType, canonicalID, authInfo, l
|
|||
if (bucketOwnerActions.includes(requestType)
|
||||
&& (bucketOwner === canonicalID)
|
||||
&& requesterIsNotUser) {
|
||||
return true;
|
||||
return isIdentityAndResourceAuthorized(isImplicitIdentityDeny, true);
|
||||
}
|
||||
const aclPermission = checkObjectAcls(bucket, objectMD, requestType,
|
||||
canonicalID);
|
||||
const bucketPolicy = bucket.getBucketPolicy();
|
||||
if (!bucketPolicy) {
|
||||
return aclPermission;
|
||||
return isIdentityAndResourceAuthorized(isImplicitIdentityDeny, aclPermission);
|
||||
}
|
||||
const bucketPolicyPermission = checkBucketPolicy(bucketPolicy, requestType,
|
||||
canonicalID, arn, bucket.getOwner(), log, request);
|
||||
if (bucketPolicyPermission === 'explicitDeny') {
|
||||
return false;
|
||||
}
|
||||
return (aclPermission || (bucketPolicyPermission === 'allow'));
|
||||
return isIdentityAndResourceAuthorized(isImplicitIdentityDeny,
|
||||
(aclPermission || (bucketPolicyPermission === 'allow')));
|
||||
}
|
||||
|
||||
function _checkResource(resource, bucketArn) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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', {
|
||||
|
|
|
@ -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', {
|
||||
|
|
|
@ -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', {
|
||||
|
|
|
@ -30,7 +30,7 @@ async function bucketDeleteTagging(authInfo, request, log, callback) {
|
|||
};
|
||||
|
||||
try {
|
||||
bucket = await metadataValidateBucketPromise(metadataValParams, log);
|
||||
bucket = await metadataValidateBucketPromise(metadataValParams, request.isImplicitIdentityDeny, log);
|
||||
bucket.setTags([]);
|
||||
// eslint-disable-next-line no-unused-expressions
|
||||
await updateBucketPromise(bucket.getName(), bucket, log);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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', {
|
||||
|
|
|
@ -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', {
|
||||
|
|
|
@ -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', {
|
||||
|
|
|
@ -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', {
|
||||
|
|
|
@ -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', {
|
||||
|
|
|
@ -78,7 +78,7 @@ async function bucketGetTagging(authInfo, request, log, callback) {
|
|||
let xml = null;
|
||||
|
||||
try {
|
||||
bucket = await metadataValidateBucketPromise(metadataValParams, log);
|
||||
bucket = await metadataValidateBucketPromise(metadataValParams, request.isImplicitIdentityDeny, log);
|
||||
// eslint-disable-next-line no-unused-expressions
|
||||
await checkExpectedBucketOwnerPromise(headers, bucket, log);
|
||||
const tags = bucket.getTags();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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', {
|
||||
|
|
|
@ -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' });
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -94,6 +94,7 @@ function metadataGetObject(bucketName, objectKey, versionId, log, cb) {
|
|||
* @param {string} params.requestType - type of request
|
||||
* @param {string} [params.preciseRequestType] - precise type of request
|
||||
* @param {object} params.request - http request object
|
||||
* @param {object} isImplicitIdentityDeny - identity authorization results
|
||||
* @param {RequestLogger} log - request logger
|
||||
* @return {ArsenalError|null} returns a validation error, or null if validation OK
|
||||
* The following errors may be returned:
|
||||
|
@ -102,7 +103,7 @@ function metadataGetObject(bucketName, objectKey, versionId, log, cb) {
|
|||
* bucket policy operation
|
||||
* - AccessDenied: bucket is not authorized
|
||||
*/
|
||||
function validateBucket(bucket, params, log) {
|
||||
function validateBucket(bucket, params, isImplicitIdentityDeny, log) {
|
||||
const { authInfo, requestType, preciseRequestType, request } = params;
|
||||
if (bucketShield(bucket, requestType)) {
|
||||
log.debug('bucket is shielded from request', {
|
||||
|
@ -119,7 +120,7 @@ function validateBucket(bucket, params, log) {
|
|||
return errors.MethodNotAllowed;
|
||||
}
|
||||
if (!isBucketAuthorized(bucket, (preciseRequestType || requestType), canonicalID,
|
||||
authInfo, log, request)) {
|
||||
authInfo, isImplicitIdentityDeny, log, request)) {
|
||||
log.debug('access denied for user on bucket', { requestType });
|
||||
return errors.AccessDenied;
|
||||
}
|
||||
|
@ -135,11 +136,12 @@ function validateBucket(bucket, params, log) {
|
|||
* @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 {boolean} isImplicitIdentityDeny - identity authorization results
|
||||
* @param {RequestLogger} log - request logger
|
||||
* @param {function} callback - callback
|
||||
* @return {undefined} - and call callback with params err, bucket md
|
||||
*/
|
||||
function metadataValidateBucketAndObj(params, log, callback) {
|
||||
function metadataValidateBucketAndObj(params, isImplicitIdentityDeny, log, callback) {
|
||||
const { authInfo, bucketName, objectKey, versionId, getDeleteMarker,
|
||||
requestType, request } = params;
|
||||
async.waterfall([
|
||||
|
@ -161,7 +163,7 @@ function metadataValidateBucketAndObj(params, log, callback) {
|
|||
});
|
||||
return next(errors.NoSuchBucket);
|
||||
}
|
||||
const validationError = validateBucket(bucket, params, log);
|
||||
const validationError = validateBucket(bucket, params, isImplicitIdentityDeny, log);
|
||||
if (validationError) {
|
||||
return next(validationError, bucket);
|
||||
}
|
||||
|
@ -174,7 +176,8 @@ function metadataValidateBucketAndObj(params, log, callback) {
|
|||
},
|
||||
(bucket, objMD, next) => {
|
||||
const canonicalID = authInfo.getCanonicalID();
|
||||
if (!isObjAuthorized(bucket, objMD, requestType, canonicalID, authInfo, log, request)) {
|
||||
if (!isObjAuthorized(bucket, objMD, requestType, canonicalID, authInfo, isImplicitIdentityDeny,
|
||||
log, request)) {
|
||||
log.debug('access denied for user on object', { requestType });
|
||||
return next(errors.AccessDenied, bucket);
|
||||
}
|
||||
|
@ -196,18 +199,19 @@ function metadataValidateBucketAndObj(params, log, callback) {
|
|||
* @param {string} params.bucketName - name of bucket
|
||||
* @param {string} params.requestType - type of request
|
||||
* @param {string} params.request - http request object
|
||||
* @param {boolean} isImplicitIdentityDeny - identity authorization results
|
||||
* @param {RequestLogger} log - request logger
|
||||
* @param {function} callback - callback
|
||||
* @return {undefined} - and call callback with params err, bucket md
|
||||
*/
|
||||
function metadataValidateBucket(params, log, callback) {
|
||||
function metadataValidateBucket(params, isImplicitIdentityDeny, log, callback) {
|
||||
const { bucketName } = params;
|
||||
return metadata.getBucket(bucketName, log, (err, bucket) => {
|
||||
if (err) {
|
||||
log.debug('metadata getbucket failed', { error: err });
|
||||
return callback(err);
|
||||
}
|
||||
const validationError = validateBucket(bucket, params, log);
|
||||
const validationError = validateBucket(bucket, params, isImplicitIdentityDeny, log);
|
||||
return callback(validationError, bucket);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1271,7 +1271,7 @@ function routeBackbeat(clientIP, request, response, log) {
|
|||
requestType: 'ReplicateObject',
|
||||
request,
|
||||
};
|
||||
return metadataValidateBucketAndObj(mdValParams, log, next);
|
||||
return metadataValidateBucketAndObj(mdValParams, request.isImplicitIdentityDeny, log, next);
|
||||
},
|
||||
(bucketInfo, objMd, next) => {
|
||||
if (useMultipleBackend) {
|
||||
|
|
|
@ -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#f4894a6d6ebb36ba1a559de4811180cb942d55a7",
|
||||
"async": "~2.5.0",
|
||||
"aws-sdk": "2.905.0",
|
||||
"azure-storage": "^2.1.0",
|
||||
|
|
|
@ -68,6 +68,7 @@ describe('GET object retention', () => {
|
|||
|
||||
afterEach(() => {
|
||||
process.stdout.write('Removing object lock\n');
|
||||
console.log(changeLockPromise, bucketName, objectName, versionId, changeObjectLock)
|
||||
return changeLockPromise([{ bucket: bucketName, key: objectName, versionId }], '')
|
||||
.then(() => {
|
||||
process.stdout.write('Emptying and deleting buckets\n');
|
||||
|
@ -81,7 +82,7 @@ describe('GET object retention', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('should return AccessDenied putting retention with another account',
|
||||
it.only('should return AccessDenied putting retention with another account',
|
||||
done => {
|
||||
otherAccountS3.getObjectRetention({
|
||||
Bucket: bucketName,
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
|
|
|
@ -48,7 +48,7 @@ describe('validateBucket', () => {
|
|||
authInfo: otherAuthInfo,
|
||||
requestType: 'bucketGet',
|
||||
request: null,
|
||||
}, log);
|
||||
}, true, log);
|
||||
assert(validationResult);
|
||||
assert(validationResult.is.AccessDenied);
|
||||
});
|
||||
|
|
|
@ -10,6 +10,7 @@ const versionIdUtils = versioning.VersionID;
|
|||
const log = new DummyRequestLogger();
|
||||
|
||||
function changeObjectLock(objects, newConfig, cb) {
|
||||
console.log('>W>>>', metadata, objects, newConfig, metadata.setup, metadata.client)
|
||||
async.each(objects, (object, next) => {
|
||||
const { bucket, key, versionId } = object;
|
||||
metadataGetObject(bucket, key, versionIdUtils.decode(versionId), log, (err, objMD) => {
|
||||
|
|
132
yarn.lock
132
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#f4894a6d6ebb36ba1a559de4811180cb942d55a7":
|
||||
version "7.70.6"
|
||||
resolved "git+https://github.com/scality/arsenal#f4894a6d6ebb36ba1a559de4811180cb942d55a7"
|
||||
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"
|
||||
|
|
Loading…
Reference in New Issue