Compare commits
20 Commits
developmen
...
hotfix/7.9
Author | SHA1 | Date |
---|---|---|
Jonathan Gramain | 3b8ce9b034 | |
Jonathan Gramain | d68f21f270 | |
Jonathan Gramain | 9c951f0287 | |
Jonathan Gramain | 01ac1baed3 | |
Jonathan Gramain | 8bd3fb5ae9 | |
Jonathan Gramain | 5b13ef00c3 | |
Jonathan Gramain | 1b9e1b826a | |
Jonathan Gramain | 657f739a9c | |
Taylor McKinnon | 35eef6092b | |
Taylor McKinnon | 0397c655dd | |
Rached Ben Mustapha | 366ca2d4eb | |
Rached Ben Mustapha | a068ad7354 | |
Jonathan Gramain | c494cd05da | |
Jonathan Gramain | 7f188b97d4 | |
Jonathan Gramain | 43e8d4c315 | |
Jonathan Gramain | 627028a7f6 | |
Ronnie Smith | 9c57c4e630 | |
Taylor McKinnon | 40ff3d11df | |
Taylor McKinnon | 565f82169b | |
Taylor McKinnon | e0c2cf7045 |
|
@ -165,6 +165,14 @@ const constants = {
|
||||||
'location',
|
'location',
|
||||||
'versionId',
|
'versionId',
|
||||||
],
|
],
|
||||||
|
allowedUtapiEventFilterFields: [
|
||||||
|
'operationId',
|
||||||
|
'location',
|
||||||
|
'account',
|
||||||
|
'user',
|
||||||
|
'bucket',
|
||||||
|
],
|
||||||
|
allowedUtapiEventFilterStates: ['allow', 'deny'],
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = constants;
|
module.exports = constants;
|
||||||
|
|
|
@ -113,6 +113,10 @@ if [[ "$RECORDLOG_ENABLED" ]]; then
|
||||||
JQ_FILTERS_CONFIG="$JQ_FILTERS_CONFIG | .recordLog.enabled=true"
|
JQ_FILTERS_CONFIG="$JQ_FILTERS_CONFIG | .recordLog.enabled=true"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$BUCKET_DENY_FILTER" ]]; then
|
||||||
|
JQ_FILTERS_CONFIG="$JQ_FILTERS_CONFIG | .utapi.filter.deny.bucket=[\"$BUCKET_DENY_FILTER\"]"
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ $JQ_FILTERS_CONFIG != "." ]]; then
|
if [[ $JQ_FILTERS_CONFIG != "." ]]; then
|
||||||
jq "$JQ_FILTERS_CONFIG" config.json > config.json.tmp
|
jq "$JQ_FILTERS_CONFIG" config.json > config.json.tmp
|
||||||
mv config.json.tmp config.json
|
mv config.json.tmp config.json
|
||||||
|
|
|
@ -304,6 +304,7 @@ stages:
|
||||||
env:
|
env:
|
||||||
ENABLE_UTAPI_V2: t
|
ENABLE_UTAPI_V2: t
|
||||||
S3BACKEND: mem
|
S3BACKEND: mem
|
||||||
|
BUCKET_DENY_FILTER: utapi-event-filter-deny-bucket
|
||||||
steps:
|
steps:
|
||||||
- Git: *clone
|
- Git: *clone
|
||||||
- ShellCommand: *setup-github-ssh
|
- ShellCommand: *setup-github-ssh
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
FROM python:3-alpine
|
FROM python:3-alpine
|
||||||
|
|
||||||
|
|
||||||
RUN apk add --no-cache \
|
RUN apk add --no-cache \
|
||||||
libressl && \
|
libressl && \
|
||||||
apk add --no-cache --virtual .build-deps \
|
apk add --no-cache --virtual .build-deps \
|
||||||
|
@ -8,7 +7,9 @@ RUN apk add --no-cache \
|
||||||
libffi-dev \
|
libffi-dev \
|
||||||
libressl-dev \
|
libressl-dev \
|
||||||
sqlite-dev \
|
sqlite-dev \
|
||||||
build-base && \
|
build-base \
|
||||||
|
rust \
|
||||||
|
cargo && \
|
||||||
pip install pykmip requests && \
|
pip install pykmip requests && \
|
||||||
apk del .build-deps && \
|
apk del .build-deps && \
|
||||||
mkdir /pykmip
|
mkdir /pykmip
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
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
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
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
|
||||||
GDazMx7Yt7xHIjFmlw==
|
TFe5v6SCarqZ9kFvr6Yp
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
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
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
-----BEGIN PRIVATE KEY-----
|
-----BEGIN PRIVATE KEY-----
|
||||||
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDGTyLybxgTICpP
|
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC6neSYoBoWh/i2
|
||||||
xLUeHdXMou3wRB/piqeOC6cK5OLk+9h3km0qed4gG7n4mwhe3j9OVotSO1PxGJcu
|
mBpduJnTlXacpJ0iQqLezvcGy8qR0s/48mtfV2IRGTNVsq4LjLLRsPGt9KkJlUhH
|
||||||
1fEOCVzEpwRfUzzDBBHfl2PcnHfFBti/o+vUyqnr56Ai/HK4lhb2lzs3mB5AABNs
|
GWhG00cBGEsIiJiBUr+WrEsO04ME/Sk76kX8wk/t9Oljl7jtUDnQUwshj+hRFe0i
|
||||||
nqKq21j/7qXwpQoXxXbyShyBrGG9VSV/rZIpoVxq7UMIFC7xPAGyTskJD+RS3vlw
|
KAyE65JIutu5EiiNtOqMzbVgPNfNniAaGlrgwByJaS9arzsHPVju9yZBYzYhwAMy
|
||||||
ENXoQOmJKFntdgCj2HLd7K6Yy58o7m1MiXX9PYdhpVptvNhkFthbaSviy0EMuOWz
|
YFcXUGrgvHRCHKmxBi4QmV7DX4TeN4l9TrCyEmqDev4PRFipyR2Fh3WGSwWh45Hg
|
||||||
VbQlWa3hX2mf5OuvBF+FY8hejcqXFhFRuxbZnbbdAH6MKd0apx/t1lJqiLulVL60
|
MT+Jp6Uv6yI4wMXWJAcNkHdx1OhjBoUQrkavvdeVEnCwjQ+pSMLm0T4iNxedQWBt
|
||||||
rMifc/4dAgMBAAECggEABbdIOZasKfj2X0A7PDf97p0PoKpGBTRC6hw5312DkLgV
|
DM7ts4EjAgMBAAECggEANNXdUeUKXdSzcycPV/ea/c+0XFcy8e9B46lfQTpTqQOx
|
||||||
oDSvQtcqaOCDtr+5OQrM5lQmReOB4uQjj20JOq9YZi6uOJUsni5i2YACl9xGs34k
|
xD8GbWD1L/gdk6baJgT43+ukEWdSsJbmdtLXti29Ta8OF2VtIDhIbCVtvs3dq3zt
|
||||||
BzoRVRvWU/9kJT4DjIB+/vKS+WJAFPYrmSjlZWlXImFdlRccuFyvtgIe2jn+wzdB
|
vrvugsiVDr8nkP306qOrKrNIVIFE+igmEmSaXsu/h/33ladxeeV9/s2DC7NOOjWN
|
||||||
ErYirqHNnSJdiNBA58VmLR2ge3Ilo/S9YTgB/+aKtElhitGqSkVB8QKNWt2u5oFw
|
Mu4KYr5BBbu3qAavdzbrcz7Sch+GzsYqK/pBounCTQu3o9E4TSUcmcsasWmtHN3u
|
||||||
tJ0n1ikz1fiD16/kcpaOT9TWm1kkhIthSwZd65+HMSuxpO+KqmwgmXPXhDnTrlSd
|
e6G2UjObdzEW7J0wWvvtJ0wHQUVRueHfqwqKf0dymcZ3xOlx3ZPhKPz5n4F1UGUt
|
||||||
y5r//+ggAnDhuUmNmFwxHn8prThYGLKlLpUFtivJIQKBgQDqWMOf8Y4Im7nW7b+r
|
RQaNazqs5SzZpUgDuPw4k8h/aCHK21Yexw/l4+O9KQKBgQD1WZSRK54zFoExBQgt
|
||||||
r00gSu+XpvBBnC2Dpr0bw90OQYdLhDcdeqeJ2fFpQqXaevNhmqnAy6PFeqdoSscu
|
OZSBNZW3Ibti5lSiF0M0g+66yNZSWfPuABEH0tu5CXopdPDXo4kW8NLGEqQStWTX
|
||||||
gc1XkejZsPIQNSa7e0RC7kveVp3gkzcQ222vgJY7++R46/S3Du3oQ3FAlB7/0VOi
|
RGK0DE9buEL3eebOfjIdS2IZ3t3dX3lMypplVCj4HzAgITlweSH1LLTyAtaaOpwa
|
||||||
+9CBgdSI+d3u1rcXOW63uQRb1QKBgQDYofBl2a/SQmWcMFA20fN+z1ft4j3YXb1X
|
jksqfcn5Zw+XGkyc6GBBVaZetQKBgQDCt6Xf/g26+zjvHscjdzsfBhnYvTOrr6+F
|
||||||
KgluiJpBFGP1lWXEZ/+v7L2PI5fGAl1FJgjYYuzVH3T1f0kgZmuIUuZPMB7d8gLw
|
xqFFxOEOocGr+mL7UTAs+a9m/6lOWhlagk+m+TIZNL8o3IN7KFTYxPYPxTiewgVE
|
||||||
1qyfKH4MKTItwh38K28/dRckBlMj10Uc+aXMe1LTcl15jp6LLI4Mx09qy1QF/c/y
|
rIm3JBmPxRiPn01P3HrtjaqfzsXF30j3ele7ix5OxieZq4vsW7ZXP3GZE34a08Ov
|
||||||
76Cvkc2lKQKBgERpfVJn9grVSz9PULESD/XpamBfP6wnp7HTL0m3uAS9ZH3LLzvP
|
12sE1DlvdwKBgQDzpYQOLhyqazzcqzyVfMrnDYmiFVN7QXTmiudobWRUBUIhAcdl
|
||||||
3rEDitIrvrc1RW+s8vlxeXHhCJYNnnAZPJTf55YFbeUFXzVEGv1fC47wwk4ZK+4j
|
oJdJB7K/rJOuO704x+RJ7dnCbZyWH6EGzZifaGIemXuXO21jvpqR0NyZCGOXhUp2
|
||||||
4LVnWHRSaLRUTbBTD2jKp3kuxI3x0fS2hnwIJr+GEh/zVqfVAFlqDbexAoGABf1U
|
YfS1j8AntwEZxyS9du2sBjui4gKvomiHTquChOxgSmKHEcznPTTpbN8MyQKBgF5F
|
||||||
PDysk8+qJ4tebGWZqePptnYO57CPz50l7ZxxR2Nc8ClVSvzlIOQWyaJeS+c81PCc
|
LVCZniolkLXsL7tS8VOez4qoZ0i6wP7CYLf3joJX+/z4N023S9yqcaorItvlMRsp
|
||||||
Rf9WNP5NqYv/ZZnvVzGTlJTsBY7vbeFBnJTuB0AMVx+K3LIGvWZrYV+bZN5K1uZA
|
tciAIyoi6F2vDRTmPNXJ3dtav4PVKVnLMs1w89MwOCjoljSQ6Q7zpGTEZenbpWbz
|
||||||
I0s1mwsKcpXy5D4zHz9TfsxoYlIGMd1WQARz/yECgYB5JH9wFDKjMAhCGG9hxMSx
|
W2BYBS9cLjXu4MpoyInLFINo9YeleLs8TvrCiKAXAoGBANsduqLnlUW/f5zDb5Fe
|
||||||
drMeZ/Ypya/DTyN+1p3DnG+Tw0Mh6Hmpm04D6iDKrafLkmlD+ZduzhzfEqn0lDDg
|
SB51+KhBjsVIeYmU+8xtur9Z7IxZXK28wpoEsm7LmX7Va5dERjI+tItBiJ5+Unu1
|
||||||
uIFFvWO6BOo2KALtMpcuDGYFKjJJ0S47EiWhKHUn/OsnAzk2lKlEOcPfrc9lY5AM
|
Xs2ljDg35ARKHs0dWBJGpbnZg4dbT6xpIL4YMPXm1Zu++PgRpxPIMn646xqd8GlH
|
||||||
6P6Jg/Q21kr1j5gQedj7Cw==
|
bavm6Km/fXNG58xus+EeLpV5
|
||||||
-----END PRIVATE KEY-----
|
-----END PRIVATE KEY-----
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
-----BEGIN PRIVATE KEY-----
|
-----BEGIN PRIVATE KEY-----
|
||||||
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
|
||||||
M0iIzoBaJY36ZSK4LRgiHjM=
|
fv3OMNI8qpmQhEjpHHQS1g==
|
||||||
-----END PRIVATE KEY-----
|
-----END PRIVATE KEY-----
|
||||||
|
|
|
@ -12,7 +12,9 @@ const { isValidBucketName } = require('arsenal').s3routes.routesUtils;
|
||||||
const validateAuthConfig = require('arsenal').auth.inMemory.validateAuthConfig;
|
const validateAuthConfig = require('arsenal').auth.inMemory.validateAuthConfig;
|
||||||
const { buildAuthDataAccount } = require('./auth/in_memory/builder');
|
const { buildAuthDataAccount } = require('./auth/in_memory/builder');
|
||||||
const externalBackends = require('../constants').externalBackends;
|
const externalBackends = require('../constants').externalBackends;
|
||||||
const { azureAccountNameRegex, base64Regex } = require('../constants');
|
const { azureAccountNameRegex, base64Regex,
|
||||||
|
allowedUtapiEventFilterFields, allowedUtapiEventFilterStates,
|
||||||
|
} = require('../constants');
|
||||||
const { utapiVersion } = require('utapi');
|
const { utapiVersion } = require('utapi');
|
||||||
|
|
||||||
// whitelist IP, CIDR for health checks
|
// whitelist IP, CIDR for health checks
|
||||||
|
@ -805,6 +807,33 @@ class Config extends EventEmitter {
|
||||||
this.utapi.redis.sentinelPassword =
|
this.utapi.redis.sentinelPassword =
|
||||||
config.utapi.redis.sentinelPassword;
|
config.utapi.redis.sentinelPassword;
|
||||||
}
|
}
|
||||||
|
if (config.utapi.redis.retry !== undefined) {
|
||||||
|
if (config.utapi.redis.retry.connectBackoff !== undefined) {
|
||||||
|
const { min, max, jitter, factor, deadline } = config.utapi.redis.retry.connectBackoff;
|
||||||
|
assert.strictEqual(typeof min, 'number',
|
||||||
|
'utapi.redis.retry.connectBackoff: min must be a number');
|
||||||
|
assert.strictEqual(typeof max, 'number',
|
||||||
|
'utapi.redis.retry.connectBackoff: max must be a number');
|
||||||
|
assert.strictEqual(typeof jitter, 'number',
|
||||||
|
'utapi.redis.retry.connectBackoff: jitter must be a number');
|
||||||
|
assert.strictEqual(typeof factor, 'number',
|
||||||
|
'utapi.redis.retry.connectBackoff: factor must be a number');
|
||||||
|
assert.strictEqual(typeof deadline, 'number',
|
||||||
|
'utapi.redis.retry.connectBackoff: deadline must be a number');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.utapi.redis.retry = config.utapi.redis.retry;
|
||||||
|
} else {
|
||||||
|
this.utapi.redis.retry = {
|
||||||
|
connectBackoff: {
|
||||||
|
min: 10,
|
||||||
|
max: 1000,
|
||||||
|
jitter: 0.1,
|
||||||
|
factor: 1.5,
|
||||||
|
deadline: 10000,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
if (config.utapi.metrics) {
|
if (config.utapi.metrics) {
|
||||||
this.utapi.metrics = config.utapi.metrics;
|
this.utapi.metrics = config.utapi.metrics;
|
||||||
}
|
}
|
||||||
|
@ -877,6 +906,25 @@ class Config extends EventEmitter {
|
||||||
this.utapi.reindex = config.utapi.reindex;
|
this.utapi.reindex = config.utapi.reindex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (utapiVersion === 2 && config.utapi.filter) {
|
||||||
|
const { filter: filterConfig } = config.utapi;
|
||||||
|
const utapiResourceFilters = {};
|
||||||
|
allowedUtapiEventFilterFields.forEach(
|
||||||
|
field => allowedUtapiEventFilterStates.forEach(
|
||||||
|
state => {
|
||||||
|
const resources = (filterConfig[state] && filterConfig[state][field]) || null;
|
||||||
|
if (resources) {
|
||||||
|
assert.strictEqual(utapiResourceFilters[field], undefined,
|
||||||
|
`bad config: utapi.filter.${state}.${field} can't define an allow and a deny list`);
|
||||||
|
assert(resources.every(r => typeof r === 'string'),
|
||||||
|
`bad config: utapi.filter.${state}.${field} must be an array of strings`);
|
||||||
|
utapiResourceFilters[field] = { [state]: new Set(resources) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
|
this.utapi.filter = utapiResourceFilters;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.log = { logLevel: 'debug', dumpLevel: 'error' };
|
this.log = { logLevel: 'debug', dumpLevel: 'error' };
|
||||||
|
|
|
@ -253,6 +253,7 @@ function createAndStoreObject(bucketName, bucketMD, objectKey, objMD, authInfo,
|
||||||
metadataStoreParams.versioning = options.versioning;
|
metadataStoreParams.versioning = options.versioning;
|
||||||
metadataStoreParams.isNull = options.isNull;
|
metadataStoreParams.isNull = options.isNull;
|
||||||
metadataStoreParams.nullVersionId = options.nullVersionId;
|
metadataStoreParams.nullVersionId = options.nullVersionId;
|
||||||
|
metadataStoreParams.nullUploadId = options.nullUploadId;
|
||||||
return _storeInMDandDeleteData(bucketName, infoArr,
|
return _storeInMDandDeleteData(bucketName, infoArr,
|
||||||
cipherBundle, metadataStoreParams,
|
cipherBundle, metadataStoreParams,
|
||||||
options.dataToDelete, requestLogger, requestMethod, next);
|
options.dataToDelete, requestLogger, requestMethod, next);
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
* instability from the metadata layer. The check returns true if there was no
|
* instability from the metadata layer. The check returns true if there was no
|
||||||
* match and false if at least one key from the previous list exists in the
|
* match and false if at least one key from the previous list exists in the
|
||||||
* current list
|
* current list
|
||||||
* @param {array|string} prev - list of keys from the object being overwritten
|
* @param {array|string|null} prev - list of keys from the object being
|
||||||
|
* overwritten
|
||||||
* @param {array} curr - list of keys to be used in composing current object
|
* @param {array} curr - list of keys to be used in composing current object
|
||||||
* @returns {array} list of keys that can be deleted
|
* @returns {array} list of keys that can be deleted
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -144,10 +144,37 @@ function isObjectLocked(bucket, objectMD, headers) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function validateObjectLockUpdate(objectMD, retentionInfo, bypassGovernance) {
|
||||||
|
const { retentionMode: existingMode, retentionDate: existingDateISO } = objectMD;
|
||||||
|
if (!existingMode) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const existingDate = new Date(existingDateISO);
|
||||||
|
const isExpired = existingDate < Date.now();
|
||||||
|
|
||||||
|
if (existingMode === 'GOVERNANCE' && !isExpired && !bypassGovernance) {
|
||||||
|
return errors.AccessDenied;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (existingMode === 'COMPLIANCE') {
|
||||||
|
if (retentionInfo.mode === 'GOVERNANCE' && !isExpired) {
|
||||||
|
return errors.AccessDenied;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new Date(retentionInfo.date) < existingDate) {
|
||||||
|
return errors.AccessDenied;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
calculateRetainUntilDate,
|
calculateRetainUntilDate,
|
||||||
compareObjectLockInformation,
|
compareObjectLockInformation,
|
||||||
setObjectLockInformation,
|
setObjectLockInformation,
|
||||||
isObjectLocked,
|
isObjectLocked,
|
||||||
validateHeaders,
|
validateHeaders,
|
||||||
|
validateObjectLockUpdate,
|
||||||
};
|
};
|
||||||
|
|
|
@ -128,7 +128,23 @@ function _deleteNullVersionMD(bucketName, objKey, options, mst, log, cb) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function processVersioningState(mst, vstat, cb) {
|
/**
|
||||||
|
* Process state from the master version of an object and the bucket
|
||||||
|
* versioning configuration, return a set of options objects
|
||||||
|
*
|
||||||
|
* @param {object} mst - state of master version, as returned by
|
||||||
|
* getMasterState()
|
||||||
|
* @param {string} vstat - bucket versioning status: 'Enabled' or 'Suspended'
|
||||||
|
*
|
||||||
|
* @return {object} result object with the following attributes:
|
||||||
|
* - {object} options: versioning-related options to pass to the
|
||||||
|
services.metadataStoreObject() call
|
||||||
|
* - {object} [storeOptions]: options for metadata to create a new
|
||||||
|
null version key, if needed
|
||||||
|
* - {object} [delOptions]: options for metadata to delete the null
|
||||||
|
version key, if needed
|
||||||
|
*/
|
||||||
|
function processVersioningState(mst, vstat) {
|
||||||
const options = {};
|
const options = {};
|
||||||
const storeOptions = {};
|
const storeOptions = {};
|
||||||
const delOptions = {};
|
const delOptions = {};
|
||||||
|
@ -142,9 +158,12 @@ function processVersioningState(mst, vstat, cb) {
|
||||||
// if null version exists, clean it up prior to put
|
// if null version exists, clean it up prior to put
|
||||||
if (mst.isNull) {
|
if (mst.isNull) {
|
||||||
delOptions.versionId = mst.versionId;
|
delOptions.versionId = mst.versionId;
|
||||||
return cb(null, options, null, delOptions);
|
if (mst.uploadId) {
|
||||||
|
delOptions.replayId = mst.uploadId;
|
||||||
|
}
|
||||||
|
return { options, delOptions };
|
||||||
}
|
}
|
||||||
return cb(null, options);
|
return { options };
|
||||||
}
|
}
|
||||||
// versioning is enabled, create a new version
|
// versioning is enabled, create a new version
|
||||||
options.versioning = true;
|
options.versioning = true;
|
||||||
|
@ -154,9 +173,14 @@ function processVersioningState(mst, vstat, cb) {
|
||||||
storeOptions.versionId = versionId;
|
storeOptions.versionId = versionId;
|
||||||
storeOptions.isNull = true;
|
storeOptions.isNull = true;
|
||||||
options.nullVersionId = versionId;
|
options.nullVersionId = versionId;
|
||||||
return cb(null, options, storeOptions);
|
// non-versioned (non-null) MPU objects don't have a
|
||||||
|
// replay ID, so don't reference their uploadId
|
||||||
|
if (mst.isNull && mst.uploadId) {
|
||||||
|
options.nullUploadId = mst.uploadId;
|
||||||
|
}
|
||||||
|
return { options, storeOptions };
|
||||||
}
|
}
|
||||||
return cb(null, options);
|
return { options };
|
||||||
}
|
}
|
||||||
// master is versioned and is not a null version
|
// master is versioned and is not a null version
|
||||||
const nullVersionId = mst.nullVersionId;
|
const nullVersionId = mst.nullVersionId;
|
||||||
|
@ -165,17 +189,36 @@ function processVersioningState(mst, vstat, cb) {
|
||||||
options.versionId = '';
|
options.versionId = '';
|
||||||
options.isNull = true;
|
options.isNull = true;
|
||||||
if (nullVersionId === undefined) {
|
if (nullVersionId === undefined) {
|
||||||
return cb(null, options);
|
return { options };
|
||||||
}
|
}
|
||||||
delOptions.versionId = nullVersionId;
|
delOptions.versionId = nullVersionId;
|
||||||
return cb(null, options, null, delOptions);
|
if (mst.nullUploadId) {
|
||||||
|
delOptions.replayId = mst.nullUploadId;
|
||||||
|
}
|
||||||
|
return { options, delOptions };
|
||||||
}
|
}
|
||||||
// versioning is enabled, put the new version
|
// versioning is enabled, put the new version
|
||||||
options.versioning = true;
|
options.versioning = true;
|
||||||
options.nullVersionId = nullVersionId;
|
options.nullVersionId = nullVersionId;
|
||||||
return cb(null, options);
|
if (mst.nullUploadId) {
|
||||||
|
options.nullUploadId = mst.nullUploadId;
|
||||||
|
}
|
||||||
|
return { options };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the state of the master version from its object metadata
|
||||||
|
*
|
||||||
|
* @param {object} objMD - object metadata parsed from JSON
|
||||||
|
*
|
||||||
|
* @return {object} state of master version, with the following attributes:
|
||||||
|
* - {boolean} exists - true if the object exists (i.e. if `objMD` is truish)
|
||||||
|
* - {string} versionId - version ID of the master key
|
||||||
|
* - {boolean} isNull - whether the master version is a null version
|
||||||
|
* - {string} nullVersionId - if not a null version, reference to the
|
||||||
|
* null version ID
|
||||||
|
* - {array} objLocation - array of data locations
|
||||||
|
*/
|
||||||
function getMasterState(objMD) {
|
function getMasterState(objMD) {
|
||||||
if (!objMD) {
|
if (!objMD) {
|
||||||
return {};
|
return {};
|
||||||
|
@ -183,8 +226,10 @@ function getMasterState(objMD) {
|
||||||
const mst = {
|
const mst = {
|
||||||
exists: true,
|
exists: true,
|
||||||
versionId: objMD.versionId,
|
versionId: objMD.versionId,
|
||||||
|
uploadId: objMD.uploadId,
|
||||||
isNull: objMD.isNull,
|
isNull: objMD.isNull,
|
||||||
nullVersionId: objMD.nullVersionId,
|
nullVersionId: objMD.nullVersionId,
|
||||||
|
nullUploadId: objMD.nullUploadId,
|
||||||
};
|
};
|
||||||
if (objMD.location) {
|
if (objMD.location) {
|
||||||
mst.objLocation = Array.isArray(objMD.location) ?
|
mst.objLocation = Array.isArray(objMD.location) ?
|
||||||
|
@ -212,35 +257,29 @@ function getMasterState(objMD) {
|
||||||
*/
|
*/
|
||||||
function versioningPreprocessing(bucketName, bucketMD, objectKey, objMD,
|
function versioningPreprocessing(bucketName, bucketMD, objectKey, objMD,
|
||||||
log, callback) {
|
log, callback) {
|
||||||
const options = {};
|
|
||||||
const mst = getMasterState(objMD);
|
const mst = getMasterState(objMD);
|
||||||
const vCfg = bucketMD.getVersioningConfiguration();
|
const vCfg = bucketMD.getVersioningConfiguration();
|
||||||
// bucket is not versioning configured
|
// bucket is not versioning configured
|
||||||
if (!vCfg) {
|
if (!vCfg) {
|
||||||
options.dataToDelete = mst.objLocation;
|
const options = { dataToDelete: mst.objLocation };
|
||||||
return process.nextTick(callback, null, options);
|
return process.nextTick(callback, null, options);
|
||||||
}
|
}
|
||||||
// bucket is versioning configured
|
// bucket is versioning configured
|
||||||
return async.waterfall([
|
const { options, storeOptions, delOptions } =
|
||||||
function processState(next) {
|
processVersioningState(mst, vCfg.Status);
|
||||||
processVersioningState(mst, vCfg.Status,
|
return async.series([
|
||||||
(err, options, storeOptions, delOptions) => {
|
function storeVersion(next) {
|
||||||
process.nextTick(next, err, options, storeOptions,
|
|
||||||
delOptions);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
function storeVersion(options, storeOptions, delOptions, next) {
|
|
||||||
if (!storeOptions) {
|
if (!storeOptions) {
|
||||||
return process.nextTick(next, null, options, delOptions);
|
return process.nextTick(next);
|
||||||
}
|
}
|
||||||
const versionMD = Object.assign({}, objMD, storeOptions);
|
const versionMD = Object.assign({}, objMD, storeOptions);
|
||||||
const params = { versionId: storeOptions.versionId };
|
const params = { versionId: storeOptions.versionId };
|
||||||
return _storeNullVersionMD(bucketName, objectKey, versionMD,
|
return _storeNullVersionMD(bucketName, objectKey, versionMD,
|
||||||
params, log, err => next(err, options, delOptions));
|
params, log, next);
|
||||||
},
|
},
|
||||||
function deleteNullVersion(options, delOptions, next) {
|
function deleteNullVersion(next) {
|
||||||
if (!delOptions) {
|
if (!delOptions) {
|
||||||
return process.nextTick(next, null, options);
|
return process.nextTick(next);
|
||||||
}
|
}
|
||||||
return _deleteNullVersionMD(bucketName, objectKey, delOptions, mst,
|
return _deleteNullVersionMD(bucketName, objectKey, delOptions, mst,
|
||||||
log, (err, nullDataToDelete) => {
|
log, (err, nullDataToDelete) => {
|
||||||
|
@ -258,10 +297,10 @@ function versioningPreprocessing(bucketName, bucketMD, objectKey, objMD,
|
||||||
return next(errors.InternalError);
|
return next(errors.InternalError);
|
||||||
}
|
}
|
||||||
Object.assign(options, { dataToDelete: nullDataToDelete });
|
Object.assign(options, { dataToDelete: nullDataToDelete });
|
||||||
return next(null, options);
|
return next();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
], (err, options) => callback(err, options));
|
], err => callback(err, options));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** preprocessingVersioningDelete - return versioning information for S3 to
|
/** preprocessingVersioningDelete - return versioning information for S3 to
|
||||||
|
@ -290,6 +329,9 @@ function preprocessingVersioningDelete(bucketName, bucketMD, objectMD,
|
||||||
// deleting a specific version
|
// deleting a specific version
|
||||||
options.deleteData = true;
|
options.deleteData = true;
|
||||||
options.versionId = reqVersionId;
|
options.versionId = reqVersionId;
|
||||||
|
if (objectMD.uploadId) {
|
||||||
|
options.replayId = objectMD.uploadId;
|
||||||
|
}
|
||||||
return callback(null, options);
|
return callback(null, options);
|
||||||
}
|
}
|
||||||
if (reqVersionId) {
|
if (reqVersionId) {
|
||||||
|
@ -297,18 +339,26 @@ function preprocessingVersioningDelete(bucketName, bucketMD, objectMD,
|
||||||
if (objectMD.versionId === undefined) {
|
if (objectMD.versionId === undefined) {
|
||||||
// object is not versioned, deleting it
|
// object is not versioned, deleting it
|
||||||
options.deleteData = true;
|
options.deleteData = true;
|
||||||
|
// non-versioned (non-null) MPU objects don't have a
|
||||||
|
// replay ID, so don't reference their uploadId
|
||||||
return callback(null, options);
|
return callback(null, options);
|
||||||
}
|
}
|
||||||
if (objectMD.isNull) {
|
if (objectMD.isNull) {
|
||||||
// master is the null version
|
// master is the null version
|
||||||
options.deleteData = true;
|
options.deleteData = true;
|
||||||
options.versionId = objectMD.versionId;
|
options.versionId = objectMD.versionId;
|
||||||
|
if (objectMD.uploadId) {
|
||||||
|
options.replayId = objectMD.uploadId;
|
||||||
|
}
|
||||||
return callback(null, options);
|
return callback(null, options);
|
||||||
}
|
}
|
||||||
if (objectMD.nullVersionId) {
|
if (objectMD.nullVersionId) {
|
||||||
// null version exists, deleting it
|
// null version exists, deleting it
|
||||||
options.deleteData = true;
|
options.deleteData = true;
|
||||||
options.versionId = objectMD.nullVersionId;
|
options.versionId = objectMD.nullVersionId;
|
||||||
|
if (objectMD.nullUploadId) {
|
||||||
|
options.replayId = objectMD.nullUploadId;
|
||||||
|
}
|
||||||
return callback(null, options);
|
return callback(null, options);
|
||||||
}
|
}
|
||||||
// null version does not exist, no deletion
|
// null version does not exist, no deletion
|
||||||
|
@ -323,6 +373,8 @@ module.exports = {
|
||||||
decodeVersionId,
|
decodeVersionId,
|
||||||
getVersionIdResHeader,
|
getVersionIdResHeader,
|
||||||
checkQueryVersionId,
|
checkQueryVersionId,
|
||||||
|
processVersioningState,
|
||||||
|
getMasterState,
|
||||||
versioningPreprocessing,
|
versioningPreprocessing,
|
||||||
preprocessingVersioningDelete,
|
preprocessingVersioningDelete,
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,7 +15,6 @@ const collectCorsHeaders = require('../utilities/collectCorsHeaders');
|
||||||
const constants = require('../../constants');
|
const constants = require('../../constants');
|
||||||
const { versioningPreprocessing, checkQueryVersionId }
|
const { versioningPreprocessing, checkQueryVersionId }
|
||||||
= require('./apiUtils/object/versioning');
|
= require('./apiUtils/object/versioning');
|
||||||
const metadata = require('../metadata/wrapper');
|
|
||||||
const services = require('../services');
|
const services = require('../services');
|
||||||
const { metadataValidateBucketAndObj } = require('../metadata/metadataUtils');
|
const { metadataValidateBucketAndObj } = require('../metadata/metadataUtils');
|
||||||
const { skipMpuPartProcessing } = require('../data/external/utils');
|
const { skipMpuPartProcessing } = require('../data/external/utils');
|
||||||
|
@ -126,44 +125,36 @@ function completeMultipartUpload(authInfo, request, log, callback) {
|
||||||
oldByteLength = objMD['content-length'];
|
oldByteLength = objMD['content-length'];
|
||||||
}
|
}
|
||||||
services.metadataValidateMultipart(metadataValParams,
|
services.metadataValidateMultipart(metadataValParams,
|
||||||
(err, mpuBucket) => {
|
(err, mpuBucket, mpuOverview, storedMetadata) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return next(err, destBucket);
|
return next(err, destBucket);
|
||||||
}
|
}
|
||||||
return next(null, destBucket, objMD, mpuBucket);
|
return next(null, destBucket, objMD, mpuBucket,
|
||||||
|
storedMetadata);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
function parsePartsList(destBucket, objMD, mpuBucket, next) {
|
function parsePartsList(destBucket, objMD, mpuBucket,
|
||||||
|
storedMetadata, next) {
|
||||||
|
const location = storedMetadata.controllingLocationConstraint;
|
||||||
|
// BACKWARD: Remove to remove the old splitter
|
||||||
|
if (mpuBucket.getMdBucketModelVersion() < 2) {
|
||||||
|
splitter = constants.oldSplitter;
|
||||||
|
}
|
||||||
|
// Reconstruct mpuOverviewKey to point to metadata
|
||||||
|
// originally stored when mpu initiated
|
||||||
|
const mpuOverviewKey =
|
||||||
|
`overview${splitter}${objectKey}${splitter}${uploadId}`;
|
||||||
if (request.post) {
|
if (request.post) {
|
||||||
return parseXml(request.post, (err, jsonList) => {
|
return parseXml(request.post, (err, jsonList) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return next(err, destBucket);
|
return next(err, destBucket);
|
||||||
}
|
}
|
||||||
return next(err, destBucket, objMD, mpuBucket, jsonList);
|
return next(null, destBucket, objMD, mpuBucket,
|
||||||
|
jsonList, storedMetadata, location, mpuOverviewKey);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return next(errors.MalformedXML, destBucket);
|
return next(errors.MalformedXML, destBucket);
|
||||||
},
|
},
|
||||||
function getMPUMetadata(destBucket, objMD, mpuBucket, jsonList, next) {
|
|
||||||
// BACKWARD: Remove to remove the old splitter
|
|
||||||
if (mpuBucket.getMdBucketModelVersion() < 2) {
|
|
||||||
splitter = constants.oldSplitter;
|
|
||||||
}
|
|
||||||
// Reconstruct mpuOverviewKey to serve
|
|
||||||
// as key to pull metadata originally stored when mpu initiated
|
|
||||||
const mpuOverviewKey =
|
|
||||||
`overview${splitter}${objectKey}${splitter}${uploadId}`;
|
|
||||||
|
|
||||||
return metadata.getObjectMD(mpuBucket.getName(), mpuOverviewKey,
|
|
||||||
{}, log, (err, storedMetadata) => {
|
|
||||||
if (err) {
|
|
||||||
return next(err, destBucket);
|
|
||||||
}
|
|
||||||
const location = storedMetadata.controllingLocationConstraint;
|
|
||||||
return next(null, destBucket, objMD, mpuBucket, jsonList,
|
|
||||||
storedMetadata, location, mpuOverviewKey);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
function retrieveParts(destBucket, objMD, mpuBucket, jsonList,
|
function retrieveParts(destBucket, objMD, mpuBucket, jsonList,
|
||||||
storedMetadata, location, mpuOverviewKey, next) {
|
storedMetadata, location, mpuOverviewKey, next) {
|
||||||
return services.getMPUparts(mpuBucket.getName(), uploadId, log,
|
return services.getMPUparts(mpuBucket.getName(), uploadId, log,
|
||||||
|
@ -344,6 +335,7 @@ function completeMultipartUpload(authInfo, request, log, callback) {
|
||||||
metaStoreParams.versioning = options.versioning;
|
metaStoreParams.versioning = options.versioning;
|
||||||
metaStoreParams.isNull = options.isNull;
|
metaStoreParams.isNull = options.isNull;
|
||||||
metaStoreParams.nullVersionId = options.nullVersionId;
|
metaStoreParams.nullVersionId = options.nullVersionId;
|
||||||
|
metaStoreParams.nullUploadId = options.nullUploadId;
|
||||||
return next(null, destBucket, dataLocations,
|
return next(null, destBucket, dataLocations,
|
||||||
metaStoreParams, mpuBucket, keysToDelete, aggregateETag,
|
metaStoreParams, mpuBucket, keysToDelete, aggregateETag,
|
||||||
objMD, extraPartLocations, pseudoCipherBundle,
|
objMD, extraPartLocations, pseudoCipherBundle,
|
||||||
|
@ -354,6 +346,46 @@ function completeMultipartUpload(authInfo, request, log, callback) {
|
||||||
metaStoreParams, mpuBucket, keysToDelete, aggregateETag, objMD,
|
metaStoreParams, mpuBucket, keysToDelete, aggregateETag, objMD,
|
||||||
extraPartLocations, pseudoCipherBundle, dataToDelete,
|
extraPartLocations, pseudoCipherBundle, dataToDelete,
|
||||||
completeObjData, next) {
|
completeObjData, next) {
|
||||||
|
if (objMD) {
|
||||||
|
// An object with the same key already exists, check
|
||||||
|
// if it has been created by the same MPU upload by
|
||||||
|
// checking if any of its internal location keys match
|
||||||
|
// the new keys. In such case, it must be a duplicate
|
||||||
|
// from a retry of a previous failed completion
|
||||||
|
// attempt, hence do the following:
|
||||||
|
//
|
||||||
|
// - skip writing the new metadata key to avoid
|
||||||
|
// creating a new version pointing to the same data
|
||||||
|
// keys
|
||||||
|
//
|
||||||
|
// - skip old data locations deletion since the old
|
||||||
|
// data location keys overlap the new ones (in
|
||||||
|
// principle they should be fully identical as there
|
||||||
|
// is no reuse of previous versions' data keys in
|
||||||
|
// the normal process) - note that the previous
|
||||||
|
// failed completion attempt may have left orphan
|
||||||
|
// data keys but we lost track of them so we cannot
|
||||||
|
// delete them now
|
||||||
|
//
|
||||||
|
// - proceed to the deletion of overview and part
|
||||||
|
// metadata keys, which are likely to have failed in
|
||||||
|
// the previous MPU completion attempt
|
||||||
|
//
|
||||||
|
const onlyDifferentLocationKeys = locationKeysSanityCheck(
|
||||||
|
objMD.location, dataLocations);
|
||||||
|
if (!onlyDifferentLocationKeys) {
|
||||||
|
log.info('MPU complete request replay detected', {
|
||||||
|
method: 'completeMultipartUpload.storeAsNewObj',
|
||||||
|
bucketName: destinationBucket.getName(),
|
||||||
|
objectKey: metaStoreParams.objectKey,
|
||||||
|
uploadId: metaStoreParams.uploadId,
|
||||||
|
});
|
||||||
|
return next(null, mpuBucket, keysToDelete, aggregateETag,
|
||||||
|
extraPartLocations, destinationBucket,
|
||||||
|
// pass the original version ID as generatedVersionId
|
||||||
|
objMD.versionId);
|
||||||
|
}
|
||||||
|
}
|
||||||
return services.metadataStoreObject(destinationBucket.getName(),
|
return services.metadataStoreObject(destinationBucket.getName(),
|
||||||
dataLocations, pseudoCipherBundle, metaStoreParams,
|
dataLocations, pseudoCipherBundle, metaStoreParams,
|
||||||
(err, res) => {
|
(err, res) => {
|
||||||
|
@ -367,31 +399,22 @@ function completeMultipartUpload(authInfo, request, log, callback) {
|
||||||
// unless the preexisting object and the completed mpu
|
// unless the preexisting object and the completed mpu
|
||||||
// are on external backends
|
// are on external backends
|
||||||
if (dataToDelete) {
|
if (dataToDelete) {
|
||||||
// check keys against accidental deletion, if any
|
|
||||||
// existing key is found in the current object,
|
|
||||||
// deletion is skipped
|
|
||||||
const sanityCheckPassed =
|
|
||||||
locationKeysSanityCheck(dataToDelete,
|
|
||||||
dataLocations);
|
|
||||||
|
|
||||||
const newDataStoreName =
|
const newDataStoreName =
|
||||||
Array.isArray(dataLocations) && dataLocations[0] ?
|
Array.isArray(dataLocations) && dataLocations[0] ?
|
||||||
dataLocations[0].dataStoreName : null;
|
dataLocations[0].dataStoreName : null;
|
||||||
if (sanityCheckPassed) {
|
const delLog =
|
||||||
const delLog =
|
logger.newRequestLoggerFromSerializedUids(log
|
||||||
logger.newRequestLoggerFromSerializedUids(log
|
.getSerializedUids());
|
||||||
.getSerializedUids());
|
return data.batchDelete(dataToDelete,
|
||||||
return data.batchDelete(dataToDelete,
|
request.method,
|
||||||
request.method,
|
newDataStoreName, delLog, err => {
|
||||||
newDataStoreName, delLog, err => {
|
if (err) {
|
||||||
if (err) {
|
return next(err);
|
||||||
return next(err);
|
}
|
||||||
}
|
return next(null, mpuBucket, keysToDelete,
|
||||||
return next(null, mpuBucket, keysToDelete,
|
aggregateETag, extraPartLocations,
|
||||||
aggregateETag, extraPartLocations,
|
destinationBucket, generatedVersionId);
|
||||||
destinationBucket, generatedVersionId);
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return next(null, mpuBucket, keysToDelete, aggregateETag,
|
return next(null, mpuBucket, keysToDelete, aggregateETag,
|
||||||
extraPartLocations, destinationBucket,
|
extraPartLocations, destinationBucket,
|
||||||
|
|
|
@ -429,6 +429,8 @@ function objectCopy(authInfo, request, sourceBucket,
|
||||||
storeMetadataParams.isNull = options.isNull;
|
storeMetadataParams.isNull = options.isNull;
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
storeMetadataParams.nullVersionId = options.nullVersionId;
|
storeMetadataParams.nullVersionId = options.nullVersionId;
|
||||||
|
// eslint-disable-next-line
|
||||||
|
storeMetadataParams.nullUploadId = options.nullUploadId;
|
||||||
const dataToDelete = options.dataToDelete;
|
const dataToDelete = options.dataToDelete;
|
||||||
return next(null, storeMetadataParams, destDataGetInfoArr,
|
return next(null, storeMetadataParams, destDataGetInfoArr,
|
||||||
destObjMD, serverSideEncryption, destBucketMD,
|
destObjMD, serverSideEncryption, destBucketMD,
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
const async = require('async');
|
const async = require('async');
|
||||||
const { errors, s3middleware } = require('arsenal');
|
const { errors, s3middleware, auth, policies } = require('arsenal');
|
||||||
|
|
||||||
|
const vault = require('../auth/vault');
|
||||||
const { decodeVersionId, getVersionIdResHeader } =
|
const { decodeVersionId, getVersionIdResHeader } =
|
||||||
require('./apiUtils/object/versioning');
|
require('./apiUtils/object/versioning');
|
||||||
|
const { validateObjectLockUpdate } =
|
||||||
|
require('./apiUtils/object/objectLockHelpers');
|
||||||
const { metadataValidateBucketAndObj } = require('../metadata/metadataUtils');
|
const { metadataValidateBucketAndObj } = require('../metadata/metadataUtils');
|
||||||
const { pushMetric } = require('../utapi/utilities');
|
const { pushMetric } = require('../utapi/utilities');
|
||||||
const getReplicationInfo = require('./apiUtils/object/getReplicationInfo');
|
const getReplicationInfo = require('./apiUtils/object/getReplicationInfo');
|
||||||
const collectCorsHeaders = require('../utilities/collectCorsHeaders');
|
const collectCorsHeaders = require('../utilities/collectCorsHeaders');
|
||||||
const metadata = require('../metadata/wrapper');
|
const metadata = require('../metadata/wrapper');
|
||||||
|
const { config } = require('../Config');
|
||||||
|
|
||||||
const { parseRetentionXml } = s3middleware.retention;
|
const { parseRetentionXml } = s3middleware.retention;
|
||||||
const REPLICATION_ACTION = 'PUT_RETENTION';
|
const REPLICATION_ACTION = 'PUT_RETENTION';
|
||||||
|
@ -78,6 +81,57 @@ function objectPutRetention(authInfo, request, log, callback) {
|
||||||
parseRetentionXml(request.post, log,
|
parseRetentionXml(request.post, log,
|
||||||
(err, retentionInfo) => next(err, bucket, retentionInfo, objectMD));
|
(err, retentionInfo) => next(err, bucket, retentionInfo, objectMD));
|
||||||
},
|
},
|
||||||
|
(bucket, retentionInfo, objectMD, next) => {
|
||||||
|
if (objectMD.retentionMode === 'GOVERNANCE' && authInfo.isRequesterAnIAMUser()) {
|
||||||
|
log.trace('object in GOVERNANCE mode and is user, checking for attached policies',
|
||||||
|
{ method: 'objectPutRetention' });
|
||||||
|
const authParams = auth.server.extractParams(request, log, 's3',
|
||||||
|
request.query);
|
||||||
|
const ip = policies.requestUtils.getClientIp(request, config);
|
||||||
|
const requestContextParams = {
|
||||||
|
constantParams: {
|
||||||
|
headers: request.headers,
|
||||||
|
query: request.query,
|
||||||
|
generalResource: bucketName,
|
||||||
|
specificResource: { key: objectKey },
|
||||||
|
requesterIp: ip,
|
||||||
|
sslEnabled: request.connection.encrypted,
|
||||||
|
apiMethod: 'bypassGovernanceRetention',
|
||||||
|
awsService: 's3',
|
||||||
|
locationConstraint: bucket.getLocationConstraint(),
|
||||||
|
requesterInfo: authInfo,
|
||||||
|
signatureVersion: authParams.params.data.signatureVersion,
|
||||||
|
authType: authParams.params.data.authType,
|
||||||
|
signatureAge: authParams.params.data.signatureAge,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return vault.checkPolicies(requestContextParams,
|
||||||
|
authInfo.getArn(), log, (err, authorizationResults) => {
|
||||||
|
if (err) {
|
||||||
|
return next(err);
|
||||||
|
}
|
||||||
|
if (authorizationResults[0].isAllowed !== true) {
|
||||||
|
log.trace('authorization check failed for user',
|
||||||
|
{
|
||||||
|
'method': 'objectPutRetention',
|
||||||
|
's3:BypassGovernanceRetention': false,
|
||||||
|
});
|
||||||
|
return next(errors.AccessDenied);
|
||||||
|
}
|
||||||
|
return next(null, bucket, retentionInfo, objectMD);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return next(null, bucket, retentionInfo, objectMD);
|
||||||
|
},
|
||||||
|
(bucket, retentionInfo, objectMD, next) => {
|
||||||
|
const bypassHeader = request.headers['x-amz-bypass-governance-retention'] || '';
|
||||||
|
const bypassGovernance = bypassHeader.toLowerCase() === 'true';
|
||||||
|
const validationError = validateObjectLockUpdate(objectMD, retentionInfo, bypassGovernance);
|
||||||
|
if (validationError) {
|
||||||
|
return next(validationError, bucket, objectMD);
|
||||||
|
}
|
||||||
|
return next(null, bucket, retentionInfo, objectMD);
|
||||||
|
},
|
||||||
(bucket, retentionInfo, objectMD, next) => {
|
(bucket, retentionInfo, objectMD, next) => {
|
||||||
/* eslint-disable no-param-reassign */
|
/* eslint-disable no-param-reassign */
|
||||||
objectMD.retentionMode = retentionInfo.mode;
|
objectMD.retentionMode = retentionInfo.mode;
|
||||||
|
|
|
@ -96,7 +96,8 @@ const services = {
|
||||||
const { objectKey, authInfo, size, contentMD5, metaHeaders,
|
const { objectKey, authInfo, size, contentMD5, metaHeaders,
|
||||||
contentType, cacheControl, contentDisposition, contentEncoding,
|
contentType, cacheControl, contentDisposition, contentEncoding,
|
||||||
expires, multipart, headers, overrideMetadata, log,
|
expires, multipart, headers, overrideMetadata, log,
|
||||||
lastModifiedDate, versioning, versionId, tagging, taggingCopy,
|
lastModifiedDate, versioning, versionId, uploadId,
|
||||||
|
tagging, taggingCopy,
|
||||||
replicationInfo, defaultRetention, dataStoreName,
|
replicationInfo, defaultRetention, dataStoreName,
|
||||||
retentionMode, retentionDate, legalHold, originOp } = params;
|
retentionMode, retentionDate, legalHold, originOp } = params;
|
||||||
log.trace('storing object in metadata');
|
log.trace('storing object in metadata');
|
||||||
|
@ -156,11 +157,16 @@ const services = {
|
||||||
if (versionId || versionId === '') {
|
if (versionId || versionId === '') {
|
||||||
options.versionId = versionId;
|
options.versionId = versionId;
|
||||||
}
|
}
|
||||||
|
if (uploadId) {
|
||||||
|
md.setUploadId(uploadId);
|
||||||
|
options.replayId = uploadId;
|
||||||
|
}
|
||||||
// information to store about the version and the null version id
|
// information to store about the version and the null version id
|
||||||
// in the object metadata
|
// in the object metadata
|
||||||
const { isNull, nullVersionId, isDeleteMarker } = params;
|
const { isNull, nullVersionId, nullUploadId, isDeleteMarker } = params;
|
||||||
md.setIsNull(isNull)
|
md.setIsNull(isNull)
|
||||||
.setNullVersionId(nullVersionId)
|
.setNullVersionId(nullVersionId)
|
||||||
|
.setNullUploadId(nullUploadId)
|
||||||
.setIsDeleteMarker(isDeleteMarker);
|
.setIsDeleteMarker(isDeleteMarker);
|
||||||
if (versionId && versionId !== 'null') {
|
if (versionId && versionId !== 'null') {
|
||||||
md.setVersionId(versionId);
|
md.setVersionId(versionId);
|
||||||
|
@ -449,13 +455,16 @@ const services = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether bucket exists, multipart upload
|
* Checks whether bucket exists, multipart upload
|
||||||
* has been initatied and the user is authorized
|
* has been initiated and the user is authorized
|
||||||
* @param {object} params - custom built object containing
|
* @param {object} params - custom built object containing
|
||||||
* bucket name, uploadId, authInfo etc.
|
* bucket name, uploadId, authInfo etc.
|
||||||
* @param {function} cb - callback containing error and
|
* @param {function} cb - callback containing error and
|
||||||
* bucket reference for the next task
|
* bucket reference for the next task
|
||||||
* @return {function} calls callback with arguments:
|
* @return {undefined} calls callback with arguments:
|
||||||
* error, bucket and the multipart upload metadata
|
* - error
|
||||||
|
* - bucket
|
||||||
|
* - the multipart upload metadata
|
||||||
|
* - the overview key stored metadata
|
||||||
*/
|
*/
|
||||||
metadataValidateMultipart(params, cb) {
|
metadataValidateMultipart(params, cb) {
|
||||||
const { bucketName, uploadId, authInfo,
|
const { bucketName, uploadId, authInfo,
|
||||||
|
@ -522,7 +531,7 @@ const services = {
|
||||||
// If access was provided by the destination bucket's
|
// If access was provided by the destination bucket's
|
||||||
// bucket policies, go ahead.
|
// bucket policies, go ahead.
|
||||||
if (requestType === 'bucketPolicyGoAhead') {
|
if (requestType === 'bucketPolicyGoAhead') {
|
||||||
return cb(null, mpuBucket, mpuOverview);
|
return cb(null, mpuBucket, mpuOverview, storedMetadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
const requesterID = authInfo.isRequesterAnIAMUser() ?
|
const requesterID = authInfo.isRequesterAnIAMUser() ?
|
||||||
|
@ -558,7 +567,7 @@ const services = {
|
||||||
return cb(errors.AccessDenied);
|
return cb(errors.AccessDenied);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cb(null, mpuBucket, mpuOverview);
|
return cb(null, mpuBucket, mpuOverview, storedMetadata);
|
||||||
});
|
});
|
||||||
return undefined;
|
return undefined;
|
||||||
});
|
});
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
"homepage": "https://github.com/scality/S3#readme",
|
"homepage": "https://github.com/scality/S3#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hapi/joi": "^17.1.0",
|
"@hapi/joi": "^17.1.0",
|
||||||
"arsenal": "github:scality/Arsenal#65966f5",
|
"arsenal": "github:scality/Arsenal#9491909",
|
||||||
"async": "~2.5.0",
|
"async": "~2.5.0",
|
||||||
"aws-sdk": "2.831.0",
|
"aws-sdk": "2.831.0",
|
||||||
"azure-storage": "^2.1.0",
|
"azure-storage": "^2.1.0",
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
"npm-run-all": "~4.1.5",
|
"npm-run-all": "~4.1.5",
|
||||||
"sinon": "^9.0.2",
|
"sinon": "^9.0.2",
|
||||||
"sproxydclient": "scality/sproxydclient#44f025b",
|
"sproxydclient": "scality/sproxydclient#44f025b",
|
||||||
"utapi": "scality/utapi#1af6532",
|
"utapi": "scality/utapi#8829793",
|
||||||
"utf8": "~2.1.1",
|
"utf8": "~2.1.1",
|
||||||
"uuid": "^3.0.1",
|
"uuid": "^3.0.1",
|
||||||
"vaultclient": "scality/vaultclient#21d03b1",
|
"vaultclient": "scality/vaultclient#21d03b1",
|
||||||
|
@ -96,4 +96,4 @@
|
||||||
"unit_coverage": "CI=true mkdir -p coverage/unit/ && S3BACKEND=mem istanbul cover --dir coverage/unit _mocha -- --reporter mocha-multi-reporters --reporter-options configFile=$INIT_CWD/tests/reporter-config.json --recursive tests/unit",
|
"unit_coverage": "CI=true mkdir -p coverage/unit/ && S3BACKEND=mem istanbul cover --dir coverage/unit _mocha -- --reporter mocha-multi-reporters --reporter-options configFile=$INIT_CWD/tests/reporter-config.json --recursive tests/unit",
|
||||||
"unit_coverage_legacy_location": "CI=true mkdir -p coverage/unitlegacylocation/ && S3_LOCATION_FILE=tests/locationConfig/locationConfigLegacy.json S3BACKEND=mem istanbul cover --dir coverage/unitlegacylocation _mocha -- --reporter mocha-multi-reporters --reporter-options configFile=$INIT_CWD/tests/reporter-config.json --reporter mocha-junit-reporter --recursive tests/unit"
|
"unit_coverage_legacy_location": "CI=true mkdir -p coverage/unitlegacylocation/ && S3_LOCATION_FILE=tests/locationConfig/locationConfigLegacy.json S3BACKEND=mem istanbul cover --dir coverage/unitlegacylocation _mocha -- --reporter mocha-multi-reporters --reporter-options configFile=$INIT_CWD/tests/reporter-config.json --reporter mocha-junit-reporter --recursive tests/unit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -662,13 +662,19 @@ describe('GET object', () => {
|
||||||
it('If-None-Match & If-Modified-Since: returns NotModified when ' +
|
it('If-None-Match & If-Modified-Since: returns NotModified when ' +
|
||||||
'Etag does not match and lastModified is greater',
|
'Etag does not match and lastModified is greater',
|
||||||
done => {
|
done => {
|
||||||
requestGet({
|
const req = s3.getObject({
|
||||||
|
Bucket: bucketName,
|
||||||
|
Key: objectName,
|
||||||
IfNoneMatch: etagTrim,
|
IfNoneMatch: etagTrim,
|
||||||
IfModifiedSince: dateFromNow(-1),
|
IfModifiedSince: dateFromNow(1),
|
||||||
}, err => {
|
}, err => {
|
||||||
checkError(err, 'NotModified');
|
checkError(err, 'NotModified');
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
req.on('httpHeaders', (code, headers) => {
|
||||||
|
assert(!headers['content-type']);
|
||||||
|
assert(!headers['content-length']);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('If-None-Match not match & If-Modified-Since not match',
|
it('If-None-Match not match & If-Modified-Since not match',
|
||||||
|
|
|
@ -32,4 +32,10 @@ describe('Sanity check for location keys', () => {
|
||||||
const curr = [{ key: 'ddd' }, { key: 'eee' }, { key: 'fff' }];
|
const curr = [{ key: 'ddd' }, { key: 'eee' }, { key: 'fff' }];
|
||||||
assert.strictEqual(locationKeysSanityCheck(prev, curr), true);
|
assert.strictEqual(locationKeysSanityCheck(prev, curr), true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should return true if prev location is null', () => {
|
||||||
|
const prev = null;
|
||||||
|
const curr = [{ key: 'ddd' }, { key: 'eee' }, { key: 'fff' }];
|
||||||
|
assert.strictEqual(locationKeysSanityCheck(prev, curr), true);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,6 +6,7 @@ const { DummyRequestLogger } = require('../../helpers');
|
||||||
const {
|
const {
|
||||||
calculateRetainUntilDate,
|
calculateRetainUntilDate,
|
||||||
validateHeaders,
|
validateHeaders,
|
||||||
|
validateObjectLockUpdate,
|
||||||
} = require('../../../../lib/api/apiUtils/object/objectLockHelpers');
|
} = require('../../../../lib/api/apiUtils/object/objectLockHelpers');
|
||||||
|
|
||||||
const mockName = 'testbucket';
|
const mockName = 'testbucket';
|
||||||
|
@ -176,3 +177,110 @@ describe('objectLockHelpers: calculateRetainUntilDate', () => {
|
||||||
expectedRetainUntilDate.toISOString().slice(0, 16));
|
expectedRetainUntilDate.toISOString().slice(0, 16));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('objectLockHelpers: validateObjectLockUpdate', () => {
|
||||||
|
it('should allow GOVERNANCE => COMPLIANCE if bypassGovernanceRetention is true', () => {
|
||||||
|
const objMD = {
|
||||||
|
retentionMode: 'GOVERNANCE',
|
||||||
|
retentionDate: moment().add(1, 'days').toISOString(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const retentionInfo = {
|
||||||
|
mode: 'COMPLIANCE',
|
||||||
|
date: moment().add(1, 'days').toISOString(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const error = validateObjectLockUpdate(objMD, retentionInfo, true);
|
||||||
|
assert.strictEqual(error, null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should disallow GOVERNANCE => COMPLIANCE if bypassGovernanceRetention is false', () => {
|
||||||
|
const objMD = {
|
||||||
|
retentionMode: 'GOVERNANCE',
|
||||||
|
retentionDate: moment().add(1, 'days').toISOString(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const retentionInfo = {
|
||||||
|
mode: 'COMPLIANCE',
|
||||||
|
date: moment().add(1, 'days').toISOString(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const error = validateObjectLockUpdate(objMD, retentionInfo, false);
|
||||||
|
assert.deepStrictEqual(error, errors.AccessDenied);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should disallow COMPLIANCE => GOVERNANCE if retention is not expired', () => {
|
||||||
|
const objMD = {
|
||||||
|
retentionMode: 'COMPLIANCE',
|
||||||
|
retentionDate: moment().add(1, 'days').toISOString(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const retentionInfo = {
|
||||||
|
mode: 'GOVERNANCE',
|
||||||
|
date: moment().add(1, 'days').toISOString(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const error = validateObjectLockUpdate(objMD, retentionInfo);
|
||||||
|
assert.deepStrictEqual(error, errors.AccessDenied);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow COMPLIANCE => GOVERNANCE if retention is expired', () => {
|
||||||
|
const objMD = {
|
||||||
|
retentionMode: 'COMPLIANCE',
|
||||||
|
retentionDate: moment().subtract(1, 'days').toISOString(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const retentionInfo = {
|
||||||
|
mode: 'GOVERNANCE',
|
||||||
|
date: moment().add(1, 'days').toISOString(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const error = validateObjectLockUpdate(objMD, retentionInfo);
|
||||||
|
assert.strictEqual(error, null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow extending retention period if in COMPLIANCE', () => {
|
||||||
|
const objMD = {
|
||||||
|
retentionMode: 'COMPLIANCE',
|
||||||
|
retentionDate: moment().add(1, 'days').toISOString(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const retentionInfo = {
|
||||||
|
mode: 'COMPLIANCE',
|
||||||
|
date: moment().add(2, 'days').toISOString(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const error = validateObjectLockUpdate(objMD, retentionInfo);
|
||||||
|
assert.strictEqual(error, null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should disallow shortening retention period if in COMPLIANCE', () => {
|
||||||
|
const objMD = {
|
||||||
|
retentionMode: 'COMPLIANCE',
|
||||||
|
retentionDate: moment().add(2, 'days').toISOString(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const retentionInfo = {
|
||||||
|
mode: 'COMPLIANCE',
|
||||||
|
date: moment().add(1, 'days').toISOString(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const error = validateObjectLockUpdate(objMD, retentionInfo);
|
||||||
|
assert.deepStrictEqual(error, errors.AccessDenied);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow shortening retention period if in GOVERNANCE', () => {
|
||||||
|
const objMD = {
|
||||||
|
retentionMode: 'GOVERNANCE',
|
||||||
|
retentionDate: moment().add(2, 'days').toISOString(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const retentionInfo = {
|
||||||
|
mode: 'GOVERNANCE',
|
||||||
|
date: moment().add(1, 'days').toISOString(),
|
||||||
|
};
|
||||||
|
|
||||||
|
const error = validateObjectLockUpdate(objMD, retentionInfo, true);
|
||||||
|
assert.strictEqual(error, null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -0,0 +1,437 @@
|
||||||
|
const assert = require('assert');
|
||||||
|
|
||||||
|
const { errors, versioning } = require('arsenal');
|
||||||
|
const { config } = require('../../../../lib/Config');
|
||||||
|
const INF_VID = versioning.VersionID.getInfVid(config.replicationGroupId);
|
||||||
|
|
||||||
|
const { processVersioningState, getMasterState,
|
||||||
|
preprocessingVersioningDelete } =
|
||||||
|
require('../../../../lib/api/apiUtils/object/versioning');
|
||||||
|
|
||||||
|
describe('versioning helpers', () => {
|
||||||
|
describe('getMasterState+processVersioningState', () => {
|
||||||
|
[
|
||||||
|
{
|
||||||
|
description: 'no prior version exists',
|
||||||
|
objMD: null,
|
||||||
|
versioningEnabledExpectedRes: {
|
||||||
|
options: {
|
||||||
|
versioning: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
versioningSuspendedExpectedRes: {
|
||||||
|
options: {
|
||||||
|
isNull: true,
|
||||||
|
versionId: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'prior non-null object version exists',
|
||||||
|
objMD: {
|
||||||
|
versionId: 'v1',
|
||||||
|
},
|
||||||
|
versioningEnabledExpectedRes: {
|
||||||
|
options: {
|
||||||
|
versioning: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
versioningSuspendedExpectedRes: {
|
||||||
|
options: {
|
||||||
|
isNull: true,
|
||||||
|
versionId: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'prior MPU object non-null version exists',
|
||||||
|
objMD: {
|
||||||
|
versionId: 'v1',
|
||||||
|
uploadId: 'fooUploadId',
|
||||||
|
},
|
||||||
|
versioningEnabledExpectedRes: {
|
||||||
|
options: {
|
||||||
|
versioning: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
versioningSuspendedExpectedRes: {
|
||||||
|
options: {
|
||||||
|
isNull: true,
|
||||||
|
versionId: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'prior null object version exists',
|
||||||
|
objMD: {
|
||||||
|
versionId: 'vnull',
|
||||||
|
isNull: true,
|
||||||
|
},
|
||||||
|
versioningEnabledExpectedRes: {
|
||||||
|
options: {
|
||||||
|
versioning: true,
|
||||||
|
nullVersionId: 'vnull',
|
||||||
|
},
|
||||||
|
// instruct to first copy the null version onto a
|
||||||
|
// newly created version key preserving the version ID
|
||||||
|
storeOptions: {
|
||||||
|
isNull: true,
|
||||||
|
versionId: 'vnull',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
versioningSuspendedExpectedRes: {
|
||||||
|
options: {
|
||||||
|
isNull: true,
|
||||||
|
versionId: '',
|
||||||
|
},
|
||||||
|
delOptions: {
|
||||||
|
versionId: 'vnull',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'prior MPU object null version exists',
|
||||||
|
objMD: {
|
||||||
|
versionId: 'vnull',
|
||||||
|
isNull: true,
|
||||||
|
uploadId: 'fooUploadId',
|
||||||
|
},
|
||||||
|
versioningEnabledExpectedRes: {
|
||||||
|
options: {
|
||||||
|
versioning: true,
|
||||||
|
nullVersionId: 'vnull',
|
||||||
|
nullUploadId: 'fooUploadId',
|
||||||
|
},
|
||||||
|
// instruct to first copy the null version onto a
|
||||||
|
// newly created version key preserving the version ID
|
||||||
|
storeOptions: {
|
||||||
|
isNull: true,
|
||||||
|
versionId: 'vnull',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
versioningSuspendedExpectedRes: {
|
||||||
|
options: {
|
||||||
|
isNull: true,
|
||||||
|
versionId: '',
|
||||||
|
},
|
||||||
|
delOptions: {
|
||||||
|
versionId: 'vnull',
|
||||||
|
replayId: 'fooUploadId',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description:
|
||||||
|
'prior object exists, put before versioning was first enabled',
|
||||||
|
objMD: {},
|
||||||
|
versioningEnabledExpectedRes: {
|
||||||
|
options: {
|
||||||
|
versioning: true,
|
||||||
|
nullVersionId: INF_VID,
|
||||||
|
},
|
||||||
|
// instruct to first copy the null version onto a
|
||||||
|
// newly created version key as the oldest version
|
||||||
|
storeOptions: {
|
||||||
|
isNull: true,
|
||||||
|
versionId: INF_VID,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
versioningSuspendedExpectedRes: {
|
||||||
|
options: {
|
||||||
|
isNull: true,
|
||||||
|
versionId: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'prior MPU object exists, put before versioning ' +
|
||||||
|
'was first enabled',
|
||||||
|
objMD: {
|
||||||
|
uploadId: 'fooUploadId',
|
||||||
|
},
|
||||||
|
versioningEnabledExpectedRes: {
|
||||||
|
options: {
|
||||||
|
versioning: true,
|
||||||
|
nullVersionId: INF_VID,
|
||||||
|
},
|
||||||
|
// instruct to first copy the null version onto a
|
||||||
|
// newly created version key as the oldest version
|
||||||
|
storeOptions: {
|
||||||
|
isNull: true,
|
||||||
|
versionId: INF_VID,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
versioningSuspendedExpectedRes: {
|
||||||
|
options: {
|
||||||
|
isNull: true,
|
||||||
|
versionId: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description:
|
||||||
|
'prior non-null object version exists with ref to null version',
|
||||||
|
objMD: {
|
||||||
|
versionId: 'v1',
|
||||||
|
nullVersionId: 'vnull',
|
||||||
|
},
|
||||||
|
versioningEnabledExpectedRes: {
|
||||||
|
options: {
|
||||||
|
versioning: true,
|
||||||
|
nullVersionId: 'vnull',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
versioningSuspendedExpectedRes: {
|
||||||
|
options: {
|
||||||
|
isNull: true,
|
||||||
|
versionId: '',
|
||||||
|
},
|
||||||
|
delOptions: {
|
||||||
|
versionId: 'vnull',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'prior MPU object non-null version exists with ' +
|
||||||
|
'ref to null version',
|
||||||
|
objMD: {
|
||||||
|
versionId: 'v1',
|
||||||
|
uploadId: 'fooUploadId',
|
||||||
|
nullVersionId: 'vnull',
|
||||||
|
},
|
||||||
|
versioningEnabledExpectedRes: {
|
||||||
|
options: {
|
||||||
|
versioning: true,
|
||||||
|
nullVersionId: 'vnull',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
versioningSuspendedExpectedRes: {
|
||||||
|
options: {
|
||||||
|
isNull: true,
|
||||||
|
versionId: '',
|
||||||
|
},
|
||||||
|
delOptions: {
|
||||||
|
versionId: 'vnull',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'prior object non-null version exists with ' +
|
||||||
|
'ref to MPU null version',
|
||||||
|
objMD: {
|
||||||
|
versionId: 'v1',
|
||||||
|
nullVersionId: 'vnull',
|
||||||
|
nullUploadId: 'nullFooUploadId',
|
||||||
|
},
|
||||||
|
versioningEnabledExpectedRes: {
|
||||||
|
options: {
|
||||||
|
versioning: true,
|
||||||
|
nullVersionId: 'vnull',
|
||||||
|
nullUploadId: 'nullFooUploadId',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
versioningSuspendedExpectedRes: {
|
||||||
|
options: {
|
||||||
|
isNull: true,
|
||||||
|
versionId: '',
|
||||||
|
},
|
||||||
|
delOptions: {
|
||||||
|
versionId: 'vnull',
|
||||||
|
replayId: 'nullFooUploadId',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
].forEach(testCase =>
|
||||||
|
['Enabled', 'Suspended'].forEach(versioningStatus => it(
|
||||||
|
`${testCase.description}, versioning Status=${versioningStatus}`,
|
||||||
|
() => {
|
||||||
|
const mst = getMasterState(testCase.objMD);
|
||||||
|
// stringify and parse to get rid of the "undefined"
|
||||||
|
// properties, artifacts of how the function builds the
|
||||||
|
// result
|
||||||
|
const res = JSON.parse(
|
||||||
|
JSON.stringify(
|
||||||
|
processVersioningState(mst, versioningStatus)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const expectedRes =
|
||||||
|
testCase[`versioning${versioningStatus}ExpectedRes`];
|
||||||
|
assert.deepStrictEqual(res, expectedRes);
|
||||||
|
})));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('preprocessingVersioningDelete', () => {
|
||||||
|
[
|
||||||
|
{
|
||||||
|
description: 'no reqVersionId: no delete action',
|
||||||
|
objMD: {
|
||||||
|
versionId: 'v1',
|
||||||
|
},
|
||||||
|
expectedRes: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'delete non-null object version',
|
||||||
|
objMD: {
|
||||||
|
versionId: 'v1',
|
||||||
|
},
|
||||||
|
reqVersionId: 'v1',
|
||||||
|
expectedRes: {
|
||||||
|
deleteData: true,
|
||||||
|
versionId: 'v1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'delete MPU object non-null version',
|
||||||
|
objMD: {
|
||||||
|
versionId: 'v1',
|
||||||
|
uploadId: 'fooUploadId',
|
||||||
|
},
|
||||||
|
reqVersionId: 'v1',
|
||||||
|
expectedRes: {
|
||||||
|
deleteData: true,
|
||||||
|
versionId: 'v1',
|
||||||
|
replayId: 'fooUploadId',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'delete null object version',
|
||||||
|
objMD: {
|
||||||
|
versionId: 'vnull',
|
||||||
|
isNull: true,
|
||||||
|
},
|
||||||
|
reqVersionId: 'null',
|
||||||
|
expectedRes: {
|
||||||
|
deleteData: true,
|
||||||
|
versionId: 'vnull',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'delete MPU object null version',
|
||||||
|
objMD: {
|
||||||
|
versionId: 'vnull',
|
||||||
|
isNull: true,
|
||||||
|
uploadId: 'fooUploadId',
|
||||||
|
},
|
||||||
|
reqVersionId: 'null',
|
||||||
|
expectedRes: {
|
||||||
|
deleteData: true,
|
||||||
|
versionId: 'vnull',
|
||||||
|
replayId: 'fooUploadId',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description:
|
||||||
|
'delete object put before versioning was first enabled',
|
||||||
|
objMD: {},
|
||||||
|
reqVersionId: 'null',
|
||||||
|
expectedRes: {
|
||||||
|
deleteData: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description:
|
||||||
|
'delete MPU object put before versioning was first enabled',
|
||||||
|
objMD: {
|
||||||
|
uploadId: 'fooUploadId',
|
||||||
|
},
|
||||||
|
reqVersionId: 'null',
|
||||||
|
expectedRes: {
|
||||||
|
deleteData: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description:
|
||||||
|
'delete non-null object version with ref to null version',
|
||||||
|
objMD: {
|
||||||
|
versionId: 'v1',
|
||||||
|
nullVersionId: 'vnull',
|
||||||
|
},
|
||||||
|
reqVersionId: 'v1',
|
||||||
|
expectedRes: {
|
||||||
|
deleteData: true,
|
||||||
|
versionId: 'v1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description:
|
||||||
|
'delete MPU object non-null version with ref to null version',
|
||||||
|
objMD: {
|
||||||
|
versionId: 'v1',
|
||||||
|
uploadId: 'fooUploadId',
|
||||||
|
nullVersionId: 'vnull',
|
||||||
|
},
|
||||||
|
reqVersionId: 'v1',
|
||||||
|
expectedRes: {
|
||||||
|
deleteData: true,
|
||||||
|
versionId: 'v1',
|
||||||
|
replayId: 'fooUploadId',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description:
|
||||||
|
'delete non-null object version with ref to MPU null version',
|
||||||
|
objMD: {
|
||||||
|
versionId: 'v1',
|
||||||
|
nullVersionId: 'vnull',
|
||||||
|
nullUploadId: 'nullFooUploadId',
|
||||||
|
},
|
||||||
|
reqVersionId: 'v1',
|
||||||
|
expectedRes: {
|
||||||
|
deleteData: true,
|
||||||
|
versionId: 'v1',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description:
|
||||||
|
'delete null object version from ref to null version',
|
||||||
|
objMD: {
|
||||||
|
versionId: 'v1',
|
||||||
|
nullVersionId: 'vnull',
|
||||||
|
},
|
||||||
|
reqVersionId: 'null',
|
||||||
|
expectedRes: {
|
||||||
|
deleteData: true,
|
||||||
|
versionId: 'vnull',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description:
|
||||||
|
'delete MPU object null version from ref to null version',
|
||||||
|
objMD: {
|
||||||
|
versionId: 'v1',
|
||||||
|
nullVersionId: 'vnull',
|
||||||
|
nullUploadId: 'nullFooUploadId',
|
||||||
|
},
|
||||||
|
reqVersionId: 'null',
|
||||||
|
expectedRes: {
|
||||||
|
deleteData: true,
|
||||||
|
versionId: 'vnull',
|
||||||
|
replayId: 'nullFooUploadId',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: 'delete null version that does not exist',
|
||||||
|
objMD: {
|
||||||
|
versionId: 'v1',
|
||||||
|
},
|
||||||
|
reqVersionId: 'null',
|
||||||
|
expectedError: errors.NoSuchKey,
|
||||||
|
},
|
||||||
|
].forEach(testCase => it(testCase.description, done => {
|
||||||
|
const mockBucketMD = {
|
||||||
|
getVersioningConfiguration: () => ({ Status: 'Enabled' }),
|
||||||
|
};
|
||||||
|
preprocessingVersioningDelete(
|
||||||
|
'foobucket', mockBucketMD, testCase.objMD,
|
||||||
|
testCase.reqVersionId, null, (err, options) => {
|
||||||
|
if (testCase.expectedError) {
|
||||||
|
assert.strictEqual(err, testCase.expectedError);
|
||||||
|
} else {
|
||||||
|
assert.ifError(err);
|
||||||
|
assert.deepStrictEqual(options, testCase.expectedRes);
|
||||||
|
}
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
});
|
|
@ -20,6 +20,7 @@ const getObjectRetention = require('../../../lib/api/objectGetRetention');
|
||||||
const initiateMultipartUpload
|
const initiateMultipartUpload
|
||||||
= require('../../../lib/api/initiateMultipartUpload');
|
= require('../../../lib/api/initiateMultipartUpload');
|
||||||
const { metadata } = require('../../../lib/metadata/in_memory/metadata');
|
const { metadata } = require('../../../lib/metadata/in_memory/metadata');
|
||||||
|
const metadataBackend = require('../../../lib/metadata/in_memory/backend');
|
||||||
const multipartDelete = require('../../../lib/api/multipartDelete');
|
const multipartDelete = require('../../../lib/api/multipartDelete');
|
||||||
const objectPutPart = require('../../../lib/api/objectPutPart');
|
const objectPutPart = require('../../../lib/api/objectPutPart');
|
||||||
const DummyRequest = require('../DummyRequest');
|
const DummyRequest = require('../DummyRequest');
|
||||||
|
@ -556,6 +557,7 @@ describe('Multipart Upload API', () => {
|
||||||
assert(MD);
|
assert(MD);
|
||||||
assert.strictEqual(MD['x-amz-meta-stuff'],
|
assert.strictEqual(MD['x-amz-meta-stuff'],
|
||||||
'I am some user metadata');
|
'I am some user metadata');
|
||||||
|
assert.strictEqual(MD.uploadId, testUploadId);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1374,7 +1376,7 @@ describe('Multipart Upload API', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return no error if attempt to abort/delete ' +
|
it('should return no error if attempt to abort/delete ' +
|
||||||
'a multipart upload that does not exist and not using' +
|
'a multipart upload that does not exist and not using ' +
|
||||||
'legacyAWSBehavior', done => {
|
'legacyAWSBehavior', done => {
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
next => bucketPut(authInfo, bucketPutRequest, log, next),
|
next => bucketPut(authInfo, bucketPutRequest, log, next),
|
||||||
|
@ -1628,7 +1630,7 @@ describe('Multipart Upload API', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error on put of an object part with an invalid' +
|
it('should throw an error on put of an object part with an invalid ' +
|
||||||
'uploadId', done => {
|
'uploadId', done => {
|
||||||
const testUploadId = 'invalidUploadID';
|
const testUploadId = 'invalidUploadID';
|
||||||
const partRequest = new DummyRequest({
|
const partRequest = new DummyRequest({
|
||||||
|
@ -1720,6 +1722,68 @@ describe('Multipart Upload API', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not delete data locations on completeMultipartUpload retry',
|
||||||
|
done => {
|
||||||
|
const partBody = Buffer.from('foo', 'utf8');
|
||||||
|
let origDeleteObject;
|
||||||
|
async.waterfall([
|
||||||
|
next =>
|
||||||
|
bucketPut(authInfo, bucketPutRequest, log, err => next(err)),
|
||||||
|
next =>
|
||||||
|
initiateMultipartUpload(authInfo, initiateRequest, log, next),
|
||||||
|
(result, corsHeaders, next) => parseString(result, next),
|
||||||
|
(json, next) => {
|
||||||
|
const testUploadId =
|
||||||
|
json.InitiateMultipartUploadResult.UploadId[0];
|
||||||
|
const partRequest = _createPutPartRequest(testUploadId, 1,
|
||||||
|
partBody);
|
||||||
|
objectPutPart(authInfo, partRequest, undefined, log,
|
||||||
|
(err, eTag) => next(err, eTag, testUploadId));
|
||||||
|
},
|
||||||
|
(eTag, testUploadId, next) => {
|
||||||
|
origDeleteObject = metadataBackend.deleteObject;
|
||||||
|
metadataBackend.deleteObject = (
|
||||||
|
bucketName, objName, params, log, cb) => {
|
||||||
|
// prevent deletions from MPU bucket only
|
||||||
|
if (bucketName === mpuBucket) {
|
||||||
|
return process.nextTick(
|
||||||
|
() => cb(errors.InternalError));
|
||||||
|
}
|
||||||
|
return origDeleteObject(
|
||||||
|
bucketName, objName, params, log, cb);
|
||||||
|
};
|
||||||
|
const parts = [{ partNumber: 1, eTag }];
|
||||||
|
const completeRequest = _createCompleteMpuRequest(
|
||||||
|
testUploadId, parts);
|
||||||
|
completeMultipartUpload(authInfo, completeRequest, log, err => {
|
||||||
|
// expect a failure here because we could not
|
||||||
|
// remove the overview key
|
||||||
|
assert.strictEqual(err, errors.InternalError);
|
||||||
|
next(null, eTag, testUploadId);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
(eTag, testUploadId, next) => {
|
||||||
|
// allow MPU bucket metadata deletions to happen again
|
||||||
|
metadataBackend.deleteObject = origDeleteObject;
|
||||||
|
// retry the completeMultipartUpload with the same
|
||||||
|
// metadata, as an application would normally do after
|
||||||
|
// a failure
|
||||||
|
const parts = [{ partNumber: 1, eTag }];
|
||||||
|
const completeRequest = _createCompleteMpuRequest(
|
||||||
|
testUploadId, parts);
|
||||||
|
completeMultipartUpload(authInfo, completeRequest, log, next);
|
||||||
|
},
|
||||||
|
], err => {
|
||||||
|
assert.ifError(err);
|
||||||
|
// check that the original data has not been deleted
|
||||||
|
// during the replay
|
||||||
|
assert.strictEqual(ds[0], undefined);
|
||||||
|
assert.notStrictEqual(ds[1], undefined);
|
||||||
|
assert.deepStrictEqual(ds[1].value, partBody);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('complete mpu with versioning', () => {
|
describe('complete mpu with versioning', () => {
|
||||||
|
@ -1729,33 +1793,16 @@ describe('complete mpu with versioning', () => {
|
||||||
const enableVersioningRequest =
|
const enableVersioningRequest =
|
||||||
versioningTestUtils.createBucketPutVersioningReq(bucketName, 'Enabled');
|
versioningTestUtils.createBucketPutVersioningReq(bucketName, 'Enabled');
|
||||||
const suspendVersioningRequest = versioningTestUtils
|
const suspendVersioningRequest = versioningTestUtils
|
||||||
.createBucketPutVersioningReq(bucketName, 'Suspended');
|
.createBucketPutVersioningReq(bucketName, 'Suspended');
|
||||||
const testPutObjectRequests = objData.slice(0, 2).map(data =>
|
let testPutObjectRequests;
|
||||||
versioningTestUtils.createPutObjectRequest(bucketName, objectKey,
|
|
||||||
data));
|
|
||||||
|
|
||||||
before(done => {
|
beforeEach(done => {
|
||||||
cleanup();
|
cleanup();
|
||||||
async.series([
|
testPutObjectRequests = objData
|
||||||
callback => bucketPut(authInfo, bucketPutRequest, log,
|
.slice(0, 2)
|
||||||
callback),
|
.map(data => versioningTestUtils.createPutObjectRequest(
|
||||||
// putting null version: put obj before versioning configured
|
bucketName, objectKey, data));
|
||||||
callback => objectPut(authInfo, testPutObjectRequests[0],
|
bucketPut(authInfo, bucketPutRequest, log, done);
|
||||||
undefined, log, callback),
|
|
||||||
callback => bucketPutVersioning(authInfo,
|
|
||||||
enableVersioningRequest, log, callback),
|
|
||||||
// put another version:
|
|
||||||
callback => objectPut(authInfo, testPutObjectRequests[1],
|
|
||||||
undefined, log, callback),
|
|
||||||
callback => bucketPutVersioning(authInfo,
|
|
||||||
suspendVersioningRequest, log, callback),
|
|
||||||
], err => {
|
|
||||||
if (err) {
|
|
||||||
return done(err);
|
|
||||||
}
|
|
||||||
versioningTestUtils.assertDataStoreValues(ds, objData.slice(0, 2));
|
|
||||||
return done();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
after(done => {
|
after(done => {
|
||||||
|
@ -1764,8 +1811,127 @@ describe('complete mpu with versioning', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should delete null version when creating new null version, ' +
|
it('should delete null version when creating new null version, ' +
|
||||||
'even when null version is not the latest version', done => {
|
'when null version is the latest version', done => {
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
|
next => bucketPutVersioning(authInfo,
|
||||||
|
suspendVersioningRequest, log, err => next(err)),
|
||||||
|
next => initiateMultipartUpload(
|
||||||
|
authInfo, initiateRequest, log, next),
|
||||||
|
(result, corsHeaders, next) => parseString(result, next),
|
||||||
|
(json, next) => {
|
||||||
|
const partBody = objData[2];
|
||||||
|
const testUploadId =
|
||||||
|
json.InitiateMultipartUploadResult.UploadId[0];
|
||||||
|
const partRequest = _createPutPartRequest(testUploadId, 1,
|
||||||
|
partBody);
|
||||||
|
objectPutPart(authInfo, partRequest, undefined, log,
|
||||||
|
(err, eTag) => next(err, eTag, testUploadId));
|
||||||
|
},
|
||||||
|
(eTag, testUploadId, next) => {
|
||||||
|
const origPutObject = metadataBackend.putObject;
|
||||||
|
metadataBackend.putObject =
|
||||||
|
(bucketName, objName, objVal, params, log, cb) => {
|
||||||
|
assert.strictEqual(params.replayId, testUploadId);
|
||||||
|
metadataBackend.putObject = origPutObject;
|
||||||
|
metadataBackend.putObject(
|
||||||
|
bucketName, objName, objVal, params, log, cb);
|
||||||
|
};
|
||||||
|
const parts = [{ partNumber: 1, eTag }];
|
||||||
|
const completeRequest = _createCompleteMpuRequest(testUploadId,
|
||||||
|
parts);
|
||||||
|
completeMultipartUpload(authInfo, completeRequest, log,
|
||||||
|
err => next(err, testUploadId));
|
||||||
|
},
|
||||||
|
(testUploadId, next) => {
|
||||||
|
const origDeleteObject = metadataBackend.deleteObject;
|
||||||
|
metadataBackend.deleteObject =
|
||||||
|
(bucketName, objName, params, log, cb) => {
|
||||||
|
assert.strictEqual(params.replayId, testUploadId);
|
||||||
|
metadataBackend.deleteObject = origDeleteObject;
|
||||||
|
metadataBackend.deleteObject(
|
||||||
|
bucketName, objName, params, log, cb);
|
||||||
|
};
|
||||||
|
// overwrite null version with a non-MPU object
|
||||||
|
objectPut(authInfo, testPutObjectRequests[1],
|
||||||
|
undefined, log, err => next(err));
|
||||||
|
},
|
||||||
|
], err => {
|
||||||
|
assert.ifError(err, `Unexpected err: ${err}`);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should delete null version when creating new null version, ' +
|
||||||
|
'when null version is not the latest version', done => {
|
||||||
|
async.waterfall([
|
||||||
|
// putting null version: put obj before versioning configured
|
||||||
|
next => objectPut(authInfo, testPutObjectRequests[0],
|
||||||
|
undefined, log, err => next(err)),
|
||||||
|
next => bucketPutVersioning(authInfo,
|
||||||
|
enableVersioningRequest, log, err => next(err)),
|
||||||
|
// put another version:
|
||||||
|
next => objectPut(authInfo, testPutObjectRequests[1],
|
||||||
|
undefined, log, err => next(err)),
|
||||||
|
next => bucketPutVersioning(authInfo,
|
||||||
|
suspendVersioningRequest, log, err => next(err)),
|
||||||
|
next => {
|
||||||
|
versioningTestUtils.assertDataStoreValues(
|
||||||
|
ds, objData.slice(0, 2));
|
||||||
|
initiateMultipartUpload(authInfo, initiateRequest, log, next);
|
||||||
|
},
|
||||||
|
(result, corsHeaders, next) => parseString(result, next),
|
||||||
|
(json, next) => {
|
||||||
|
const partBody = objData[2];
|
||||||
|
const testUploadId =
|
||||||
|
json.InitiateMultipartUploadResult.UploadId[0];
|
||||||
|
const partRequest = _createPutPartRequest(testUploadId, 1,
|
||||||
|
partBody);
|
||||||
|
objectPutPart(authInfo, partRequest, undefined, log,
|
||||||
|
(err, eTag) => next(err, eTag, testUploadId));
|
||||||
|
},
|
||||||
|
(eTag, testUploadId, next) => {
|
||||||
|
const origPutObject = metadataBackend.putObject;
|
||||||
|
metadataBackend.putObject =
|
||||||
|
(bucketName, objName, objVal, params, log, cb) => {
|
||||||
|
assert.strictEqual(params.replayId, testUploadId);
|
||||||
|
metadataBackend.putObject = origPutObject;
|
||||||
|
metadataBackend.putObject(
|
||||||
|
bucketName, objName, objVal, params, log, cb);
|
||||||
|
};
|
||||||
|
const parts = [{ partNumber: 1, eTag }];
|
||||||
|
const completeRequest = _createCompleteMpuRequest(testUploadId,
|
||||||
|
parts);
|
||||||
|
completeMultipartUpload(authInfo, completeRequest, log,
|
||||||
|
err => next(err, testUploadId));
|
||||||
|
},
|
||||||
|
(testUploadId, next) => {
|
||||||
|
versioningTestUtils.assertDataStoreValues(
|
||||||
|
ds, [undefined, objData[1], objData[2]]);
|
||||||
|
|
||||||
|
const origDeleteObject = metadataBackend.deleteObject;
|
||||||
|
metadataBackend.deleteObject =
|
||||||
|
(bucketName, objName, params, log, cb) => {
|
||||||
|
assert.strictEqual(params.replayId, testUploadId);
|
||||||
|
metadataBackend.deleteObject = origDeleteObject;
|
||||||
|
metadataBackend.deleteObject(
|
||||||
|
bucketName, objName, params, log, cb);
|
||||||
|
};
|
||||||
|
// overwrite null version with a non-MPU object
|
||||||
|
objectPut(authInfo, testPutObjectRequests[1],
|
||||||
|
undefined, log, err => next(err));
|
||||||
|
},
|
||||||
|
], err => {
|
||||||
|
assert.ifError(err, `Unexpected err: ${err}`);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should finish deleting metadata on completeMultipartUpload retry',
|
||||||
|
done => {
|
||||||
|
let origDeleteObject;
|
||||||
|
async.waterfall([
|
||||||
|
next => bucketPutVersioning(authInfo,
|
||||||
|
enableVersioningRequest, log, err => next(err)),
|
||||||
next =>
|
next =>
|
||||||
initiateMultipartUpload(authInfo, initiateRequest, log, next),
|
initiateMultipartUpload(authInfo, initiateRequest, log, next),
|
||||||
(result, corsHeaders, next) => parseString(result, next),
|
(result, corsHeaders, next) => parseString(result, next),
|
||||||
|
@ -1779,18 +1945,54 @@ describe('complete mpu with versioning', () => {
|
||||||
(err, eTag) => next(err, eTag, testUploadId));
|
(err, eTag) => next(err, eTag, testUploadId));
|
||||||
},
|
},
|
||||||
(eTag, testUploadId, next) => {
|
(eTag, testUploadId, next) => {
|
||||||
|
origDeleteObject = metadataBackend.deleteObject;
|
||||||
|
metadataBackend.deleteObject = (
|
||||||
|
bucketName, objName, params, log, cb) => {
|
||||||
|
// prevent deletions from MPU bucket only
|
||||||
|
if (bucketName === mpuBucket) {
|
||||||
|
return process.nextTick(
|
||||||
|
() => cb(errors.InternalError));
|
||||||
|
}
|
||||||
|
return origDeleteObject(
|
||||||
|
bucketName, objName, params, log, cb);
|
||||||
|
};
|
||||||
const parts = [{ partNumber: 1, eTag }];
|
const parts = [{ partNumber: 1, eTag }];
|
||||||
const completeRequest = _createCompleteMpuRequest(testUploadId,
|
const completeRequest = _createCompleteMpuRequest(
|
||||||
parts);
|
testUploadId, parts);
|
||||||
|
completeMultipartUpload(authInfo, completeRequest, log, err => {
|
||||||
|
// expect a failure here because we could not
|
||||||
|
// remove the overview key
|
||||||
|
assert.strictEqual(err, errors.InternalError);
|
||||||
|
next(null, eTag, testUploadId);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
(eTag, testUploadId, next) => {
|
||||||
|
// allow MPU bucket metadata deletions to happen again
|
||||||
|
metadataBackend.deleteObject = origDeleteObject;
|
||||||
|
// retry the completeMultipartUpload with the same
|
||||||
|
// metadata, as an application would normally do after
|
||||||
|
// a failure
|
||||||
|
const parts = [{ partNumber: 1, eTag }];
|
||||||
|
const completeRequest = _createCompleteMpuRequest(
|
||||||
|
testUploadId, parts);
|
||||||
completeMultipartUpload(authInfo, completeRequest, log, next);
|
completeMultipartUpload(authInfo, completeRequest, log, next);
|
||||||
},
|
},
|
||||||
], err => {
|
], err => {
|
||||||
assert.ifError(err, `Unexpected err: ${err}`);
|
assert.ifError(err);
|
||||||
process.nextTick(() => {
|
let nbVersions = 0;
|
||||||
versioningTestUtils.assertDataStoreValues(ds, [undefined,
|
for (const key of metadata.keyMaps.get(bucketName).keys()) {
|
||||||
objData[1], objData[2]]);
|
if (key !== objectKey && key.startsWith(objectKey)) {
|
||||||
done(err);
|
nbVersions += 1;
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
// There should be only one version of the object, since
|
||||||
|
// the second call should not have created a new version
|
||||||
|
assert.strictEqual(nbVersions, 1);
|
||||||
|
for (const key of metadata.keyMaps.get(mpuBucket).keys()) {
|
||||||
|
assert.fail('There should be no more keys in MPU bucket, ' +
|
||||||
|
`found "${key}"`);
|
||||||
|
}
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
|
const async = require('async');
|
||||||
|
const crypto = require('crypto');
|
||||||
const { errors } = require('arsenal');
|
const { errors } = require('arsenal');
|
||||||
|
const xml2js = require('xml2js');
|
||||||
|
|
||||||
const { bucketPut } = require('../../../lib/api/bucketPut');
|
const { bucketPut } = require('../../../lib/api/bucketPut');
|
||||||
const bucketPutACL = require('../../../lib/api/bucketPutACL');
|
const bucketPutACL = require('../../../lib/api/bucketPutACL');
|
||||||
|
@ -8,6 +11,11 @@ const { cleanup, DummyRequestLogger, makeAuthInfo } = require('../helpers');
|
||||||
const objectPut = require('../../../lib/api/objectPut');
|
const objectPut = require('../../../lib/api/objectPut');
|
||||||
const objectDelete = require('../../../lib/api/objectDelete');
|
const objectDelete = require('../../../lib/api/objectDelete');
|
||||||
const objectGet = require('../../../lib/api/objectGet');
|
const objectGet = require('../../../lib/api/objectGet');
|
||||||
|
const initiateMultipartUpload
|
||||||
|
= require('../../../lib/api/initiateMultipartUpload');
|
||||||
|
const objectPutPart = require('../../../lib/api/objectPutPart');
|
||||||
|
const completeMultipartUpload
|
||||||
|
= require('../../../lib/api/completeMultipartUpload');
|
||||||
const DummyRequest = require('../DummyRequest');
|
const DummyRequest = require('../DummyRequest');
|
||||||
|
|
||||||
const log = new DummyRequestLogger();
|
const log = new DummyRequestLogger();
|
||||||
|
@ -69,6 +77,14 @@ describe('objectDelete API', () => {
|
||||||
url: `/${bucketName}/${objectKey}`,
|
url: `/${bucketName}/${objectKey}`,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const initiateMPURequest = {
|
||||||
|
bucketName,
|
||||||
|
namespace,
|
||||||
|
objectKey,
|
||||||
|
headers: { host: `${bucketName}.s3.amazonaws.com` },
|
||||||
|
url: `/${objectKey}?uploads`,
|
||||||
|
};
|
||||||
|
|
||||||
it('should delete an object', done => {
|
it('should delete an object', done => {
|
||||||
bucketPut(authInfo, testBucketPutRequest, log, () => {
|
bucketPut(authInfo, testBucketPutRequest, log, () => {
|
||||||
objectPut(authInfo, testPutObjectRequest,
|
objectPut(authInfo, testPutObjectRequest,
|
||||||
|
@ -112,6 +128,57 @@ describe('objectDelete API', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should delete a multipart upload', done => {
|
||||||
|
const partBody = Buffer.from('I am a part\n', 'utf8');
|
||||||
|
let testUploadId;
|
||||||
|
let calculatedHash;
|
||||||
|
async.waterfall([
|
||||||
|
next => bucketPut(authInfo, testBucketPutRequest, log, next),
|
||||||
|
(corsHeaders, next) => initiateMultipartUpload(authInfo,
|
||||||
|
initiateMPURequest, log, next),
|
||||||
|
(result, corsHeaders, next) => xml2js.parseString(result, next),
|
||||||
|
(json, next) => {
|
||||||
|
testUploadId = json.InitiateMultipartUploadResult.UploadId[0];
|
||||||
|
const md5Hash = crypto.createHash('md5').update(partBody);
|
||||||
|
calculatedHash = md5Hash.digest('hex');
|
||||||
|
const partRequest = new DummyRequest({
|
||||||
|
bucketName,
|
||||||
|
namespace,
|
||||||
|
objectKey,
|
||||||
|
headers: { host: `${bucketName}.s3.amazonaws.com` },
|
||||||
|
url: `/${objectKey}?partNumber=1&uploadId=${testUploadId}`,
|
||||||
|
query: {
|
||||||
|
partNumber: '1',
|
||||||
|
uploadId: testUploadId,
|
||||||
|
},
|
||||||
|
calculatedHash,
|
||||||
|
}, partBody);
|
||||||
|
objectPutPart(authInfo, partRequest, undefined, log, next);
|
||||||
|
},
|
||||||
|
(hexDigest, corsHeaders, next) => {
|
||||||
|
const completeBody = '<CompleteMultipartUpload>' +
|
||||||
|
'<Part>' +
|
||||||
|
'<PartNumber>1</PartNumber>' +
|
||||||
|
`<ETag>"${calculatedHash}"</ETag>` +
|
||||||
|
'</Part>' +
|
||||||
|
'</CompleteMultipartUpload>';
|
||||||
|
const completeRequest = {
|
||||||
|
bucketName,
|
||||||
|
namespace,
|
||||||
|
objectKey,
|
||||||
|
parsedHost: 's3.amazonaws.com',
|
||||||
|
url: `/${objectKey}?uploadId=${testUploadId}`,
|
||||||
|
headers: { host: `${bucketName}.s3.amazonaws.com` },
|
||||||
|
query: { uploadId: testUploadId },
|
||||||
|
post: completeBody,
|
||||||
|
};
|
||||||
|
completeMultipartUpload(authInfo, completeRequest, log, next);
|
||||||
|
},
|
||||||
|
(result, resHeaders, next) =>
|
||||||
|
objectDelete(authInfo, testDeleteRequest, log, next),
|
||||||
|
], done);
|
||||||
|
});
|
||||||
|
|
||||||
it('should prevent anonymous user deleteObject API access', done => {
|
it('should prevent anonymous user deleteObject API access', done => {
|
||||||
const publicAuthInfo = makeAuthInfo(constants.publicId);
|
const publicAuthInfo = makeAuthInfo(constants.publicId);
|
||||||
objectDelete(publicAuthInfo, testDeleteRequest, log, err => {
|
objectDelete(publicAuthInfo, testDeleteRequest, log, err => {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
|
const moment = require('moment');
|
||||||
|
|
||||||
|
const { errors } = require('arsenal');
|
||||||
const { bucketPut } = require('../../../lib/api/bucketPut');
|
const { bucketPut } = require('../../../lib/api/bucketPut');
|
||||||
const objectPut = require('../../../lib/api/objectPut');
|
const objectPut = require('../../../lib/api/objectPut');
|
||||||
const objectPutRetention = require('../../../lib/api/objectPutRetention');
|
const objectPutRetention = require('../../../lib/api/objectPutRetention');
|
||||||
|
@ -31,17 +33,53 @@ const putObjectRequest = new DummyRequest({
|
||||||
url: `/${bucketName}/${objectName}`,
|
url: `/${bucketName}/${objectName}`,
|
||||||
}, postBody);
|
}, postBody);
|
||||||
|
|
||||||
const objectRetentionXml = '<Retention ' +
|
const objectRetentionXmlGovernance = '<Retention ' +
|
||||||
'xmlns="http://s3.amazonaws.com/doc/2006-03-01/">' +
|
'xmlns="http://s3.amazonaws.com/doc/2006-03-01/">' +
|
||||||
'<Mode>GOVERNANCE</Mode>' +
|
'<Mode>GOVERNANCE</Mode>' +
|
||||||
`<RetainUntilDate>${date.toISOString()}</RetainUntilDate>` +
|
`<RetainUntilDate>${date.toISOString()}</RetainUntilDate>` +
|
||||||
'</Retention>';
|
'</Retention>';
|
||||||
|
|
||||||
const putObjRetRequest = {
|
const objectRetentionXmlCompliance = '<Retention ' +
|
||||||
|
'xmlns="http://s3.amazonaws.com/doc/2006-03-01/">' +
|
||||||
|
'<Mode>COMPLIANCE</Mode>' +
|
||||||
|
`<RetainUntilDate>${moment().add(2, 'days').toISOString()}</RetainUntilDate>` +
|
||||||
|
'</Retention>';
|
||||||
|
|
||||||
|
const objectRetentionXmlComplianceShorter = '<Retention ' +
|
||||||
|
'xmlns="http://s3.amazonaws.com/doc/2006-03-01/">' +
|
||||||
|
'<Mode>COMPLIANCE</Mode>' +
|
||||||
|
`<RetainUntilDate>${moment().add(1, 'days').toISOString()}</RetainUntilDate>` +
|
||||||
|
'</Retention>';
|
||||||
|
|
||||||
|
const putObjRetRequestGovernance = {
|
||||||
bucketName,
|
bucketName,
|
||||||
objectKey: objectName,
|
objectKey: objectName,
|
||||||
headers: { host: `${bucketName}.s3.amazonaws.com` },
|
headers: { host: `${bucketName}.s3.amazonaws.com` },
|
||||||
post: objectRetentionXml,
|
post: objectRetentionXmlGovernance,
|
||||||
|
};
|
||||||
|
|
||||||
|
const putObjRetRequestGovernanceWithHeader = {
|
||||||
|
bucketName,
|
||||||
|
objectKey: objectName,
|
||||||
|
headers: {
|
||||||
|
'host': `${bucketName}.s3.amazonaws.com`,
|
||||||
|
'x-amz-bypass-governance-retention': 'true',
|
||||||
|
},
|
||||||
|
post: objectRetentionXmlGovernance,
|
||||||
|
};
|
||||||
|
|
||||||
|
const putObjRetRequestCompliance = {
|
||||||
|
bucketName,
|
||||||
|
objectKey: objectName,
|
||||||
|
headers: { host: `${bucketName}.s3.amazonaws.com` },
|
||||||
|
post: objectRetentionXmlCompliance,
|
||||||
|
};
|
||||||
|
|
||||||
|
const putObjRetRequestComplianceShorter = {
|
||||||
|
bucketName,
|
||||||
|
objectKey: objectName,
|
||||||
|
headers: { host: `${bucketName}.s3.amazonaws.com` },
|
||||||
|
post: objectRetentionXmlComplianceShorter,
|
||||||
};
|
};
|
||||||
|
|
||||||
const expectedMode = 'GOVERNANCE';
|
const expectedMode = 'GOVERNANCE';
|
||||||
|
@ -60,7 +98,7 @@ describe('putObjectRetention API', () => {
|
||||||
afterEach(() => cleanup());
|
afterEach(() => cleanup());
|
||||||
|
|
||||||
it('should return InvalidRequest error', done => {
|
it('should return InvalidRequest error', done => {
|
||||||
objectPutRetention(authInfo, putObjRetRequest, log, err => {
|
objectPutRetention(authInfo, putObjRetRequestGovernance, log, err => {
|
||||||
assert.strictEqual(err.InvalidRequest, true);
|
assert.strictEqual(err.InvalidRequest, true);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -80,7 +118,7 @@ describe('putObjectRetention API', () => {
|
||||||
afterEach(() => cleanup());
|
afterEach(() => cleanup());
|
||||||
|
|
||||||
it('should update an object\'s metadata with retention info', done => {
|
it('should update an object\'s metadata with retention info', done => {
|
||||||
objectPutRetention(authInfo, putObjRetRequest, log, err => {
|
objectPutRetention(authInfo, putObjRetRequestGovernance, log, err => {
|
||||||
assert.ifError(err);
|
assert.ifError(err);
|
||||||
return metadata.getObjectMD(bucketName, objectName, {}, log,
|
return metadata.getObjectMD(bucketName, objectName, {}, log,
|
||||||
(err, objMD) => {
|
(err, objMD) => {
|
||||||
|
@ -91,5 +129,48 @@ describe('putObjectRetention API', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should disallow COMPLIANCE => GOVERNANCE', done => {
|
||||||
|
objectPutRetention(authInfo, putObjRetRequestCompliance, log, err => {
|
||||||
|
assert.ifError(err);
|
||||||
|
return objectPutRetention(authInfo, putObjRetRequestGovernance, log, err => {
|
||||||
|
assert.deepStrictEqual(err, errors.AccessDenied);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should disallow shortening of COMPLIANCE retention', done => {
|
||||||
|
objectPutRetention(authInfo, putObjRetRequestCompliance, log, err => {
|
||||||
|
assert.ifError(err);
|
||||||
|
return objectPutRetention(authInfo, putObjRetRequestComplianceShorter, log, err => {
|
||||||
|
assert.deepStrictEqual(err, errors.AccessDenied);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should disallow update if the x-amz-bypass-governance-retention header is missing and'
|
||||||
|
+ 'GOVERNANCE mode is enabled', done => {
|
||||||
|
objectPutRetention(authInfo, putObjRetRequestGovernance, log, err => {
|
||||||
|
assert.ifError(err);
|
||||||
|
return objectPutRetention(authInfo, putObjRetRequestGovernance, log, err => {
|
||||||
|
assert.deepStrictEqual(err, errors.AccessDenied);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should allow update if the x-amz-bypass-governance-retention header is present and'
|
||||||
|
+ 'GOVERNANCE mode is enabled', done => {
|
||||||
|
objectPutRetention(authInfo, putObjRetRequestGovernance, log, err => {
|
||||||
|
assert.ifError(err);
|
||||||
|
return objectPutRetention(authInfo, putObjRetRequestGovernanceWithHeader, log, err => {
|
||||||
|
assert.ifError(err);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -471,4 +471,24 @@ describe('utapi v2 metrics incoming and outgoing bytes', function t() {
|
||||||
next => deleteBucket(bucket, next),
|
next => deleteBucket(bucket, next),
|
||||||
], done);
|
], done);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not push a metric for a filtered bucket', done => {
|
||||||
|
const bucket = 'utapi-event-filter-deny-bucket';
|
||||||
|
const objSize = 2 * 1024 * 1024;
|
||||||
|
const key = '1.txt';
|
||||||
|
async.series([
|
||||||
|
next => createBucket(bucket, next),
|
||||||
|
next => putObject(bucket, key, objSize, next),
|
||||||
|
next => wait(WAIT_MS, () => {
|
||||||
|
checkMetrics(0, 0, 0);
|
||||||
|
next();
|
||||||
|
}),
|
||||||
|
next => deleteObject(bucket, key, next),
|
||||||
|
next => wait(WAIT_MS, () => {
|
||||||
|
checkMetrics(0, 0, 0);
|
||||||
|
next();
|
||||||
|
}),
|
||||||
|
next => deleteBucket(bucket, next),
|
||||||
|
], done);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
268
yarn.lock
268
yarn.lock
|
@ -656,9 +656,9 @@ arraybuffer.slice@~0.0.7:
|
||||||
resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675"
|
resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675"
|
||||||
integrity sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==
|
integrity sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==
|
||||||
|
|
||||||
"arsenal@github:scality/Arsenal#65966f5", arsenal@scality/Arsenal#65966f5:
|
"arsenal@github:scality/Arsenal#9491909":
|
||||||
version "7.7.0"
|
version "7.7.1"
|
||||||
resolved "https://codeload.github.com/scality/Arsenal/tar.gz/65966f5ddf93b048906d14a8c26056abfd4c22ba"
|
resolved "https://codeload.github.com/scality/Arsenal/tar.gz/9491909355d35a36c86cafcc6d51789ca0223334"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@hapi/joi" "^15.1.0"
|
"@hapi/joi" "^15.1.0"
|
||||||
JSONStream "^1.0.0"
|
JSONStream "^1.0.0"
|
||||||
|
@ -707,6 +707,67 @@ arsenal@scality/Arsenal#580e25a:
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
ioctl "2.0.0"
|
ioctl "2.0.0"
|
||||||
|
|
||||||
|
arsenal@scality/Arsenal#65966f5:
|
||||||
|
version "7.7.0"
|
||||||
|
resolved "https://codeload.github.com/scality/Arsenal/tar.gz/65966f5ddf93b048906d14a8c26056abfd4c22ba"
|
||||||
|
dependencies:
|
||||||
|
"@hapi/joi" "^15.1.0"
|
||||||
|
JSONStream "^1.0.0"
|
||||||
|
agentkeepalive "^4.1.3"
|
||||||
|
ajv "6.12.2"
|
||||||
|
async "~2.1.5"
|
||||||
|
debug "~2.6.9"
|
||||||
|
diskusage "^1.1.1"
|
||||||
|
ioredis "4.9.5"
|
||||||
|
ipaddr.js "1.9.1"
|
||||||
|
level "~5.0.1"
|
||||||
|
level-sublevel "~6.6.5"
|
||||||
|
node-forge "^0.7.1"
|
||||||
|
simple-glob "^0.2"
|
||||||
|
socket.io "~2.3.0"
|
||||||
|
socket.io-client "~2.3.0"
|
||||||
|
utf8 "2.1.2"
|
||||||
|
uuid "^3.0.1"
|
||||||
|
werelogs scality/werelogs#0ff7ec82
|
||||||
|
xml2js "~0.4.23"
|
||||||
|
optionalDependencies:
|
||||||
|
ioctl "2.0.0"
|
||||||
|
|
||||||
|
arsenal@scality/Arsenal#8ed8478:
|
||||||
|
version "8.2.1"
|
||||||
|
resolved "https://codeload.github.com/scality/Arsenal/tar.gz/8ed84786fce31f603b1e8cd641b3b44b8f715b0b"
|
||||||
|
dependencies:
|
||||||
|
"@hapi/joi" "^15.1.0"
|
||||||
|
JSONStream "^1.0.0"
|
||||||
|
ajv "6.12.2"
|
||||||
|
async "~2.6.1"
|
||||||
|
aws-sdk "2.80.0"
|
||||||
|
azure-storage "^2.1.0"
|
||||||
|
backo "^1.1.0"
|
||||||
|
bson "4.0.0"
|
||||||
|
debug "~4.1.0"
|
||||||
|
diskusage "^1.1.1"
|
||||||
|
fcntl "github:scality/node-fcntl"
|
||||||
|
hdclient scality/hdclient#5145e04e5ed33e85106765b1caa90cd245ef482b
|
||||||
|
https-proxy-agent "^2.2.0"
|
||||||
|
ioredis "4.9.5"
|
||||||
|
ipaddr.js "1.9.1"
|
||||||
|
level "~5.0.1"
|
||||||
|
level-sublevel "~6.6.5"
|
||||||
|
mongodb "^3.0.1"
|
||||||
|
node-forge "^0.7.1"
|
||||||
|
prom-client "10.2.3"
|
||||||
|
simple-glob "^0.2.0"
|
||||||
|
socket.io "~2.3.0"
|
||||||
|
socket.io-client "~2.3.0"
|
||||||
|
sproxydclient "github:scality/sproxydclient#30e7115"
|
||||||
|
utf8 "3.0.0"
|
||||||
|
uuid "^3.0.1"
|
||||||
|
werelogs scality/werelogs#0ff7ec82
|
||||||
|
xml2js "~0.4.23"
|
||||||
|
optionalDependencies:
|
||||||
|
ioctl "2.0.1"
|
||||||
|
|
||||||
arsenal@scality/Arsenal#9f2e74e:
|
arsenal@scality/Arsenal#9f2e74e:
|
||||||
version "7.4.3"
|
version "7.4.3"
|
||||||
resolved "https://codeload.github.com/scality/Arsenal/tar.gz/9f2e74ec6972527c2a9ca6ecb4155618f123fc19"
|
resolved "https://codeload.github.com/scality/Arsenal/tar.gz/9f2e74ec6972527c2a9ca6ecb4155618f123fc19"
|
||||||
|
@ -757,41 +818,6 @@ arsenal@scality/Arsenal#b03f5b8:
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
ioctl "2.0.0"
|
ioctl "2.0.0"
|
||||||
|
|
||||||
arsenal@scality/Arsenal#c57cde8:
|
|
||||||
version "8.1.4"
|
|
||||||
resolved "https://codeload.github.com/scality/Arsenal/tar.gz/c57cde88bb04fe9803ec08c3a883f6eb986e4149"
|
|
||||||
dependencies:
|
|
||||||
JSONStream "^1.0.0"
|
|
||||||
ajv "4.10.0"
|
|
||||||
async "~2.6.1"
|
|
||||||
aws-sdk "2.80.0"
|
|
||||||
azure-storage "^2.1.0"
|
|
||||||
backo "^1.1.0"
|
|
||||||
bson "4.0.0"
|
|
||||||
debug "~4.1.0"
|
|
||||||
diskusage "^1.1.1"
|
|
||||||
fcntl "github:scality/node-fcntl"
|
|
||||||
hdclient scality/hdclient#5145e04e5ed33e85106765b1caa90cd245ef482b
|
|
||||||
https-proxy-agent "^2.2.0"
|
|
||||||
ioredis "4.9.5"
|
|
||||||
ipaddr.js "1.8.1"
|
|
||||||
joi "^14.3.0"
|
|
||||||
level "~5.0.1"
|
|
||||||
level-sublevel "~6.6.5"
|
|
||||||
mongodb "^3.0.1"
|
|
||||||
node-forge "^0.7.1"
|
|
||||||
prom-client "10.2.3"
|
|
||||||
simple-glob "^0.2.0"
|
|
||||||
socket.io "~2.2.0"
|
|
||||||
socket.io-client "~2.2.0"
|
|
||||||
sproxydclient "github:scality/sproxydclient#a6ec980"
|
|
||||||
utf8 "3.0.0"
|
|
||||||
uuid "^3.0.1"
|
|
||||||
werelogs scality/werelogs#0ff7ec82
|
|
||||||
xml2js "~0.4.16"
|
|
||||||
optionalDependencies:
|
|
||||||
ioctl "2.0.1"
|
|
||||||
|
|
||||||
asap@~2.0.3:
|
asap@~2.0.3:
|
||||||
version "2.0.6"
|
version "2.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
|
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
|
||||||
|
@ -1206,7 +1232,7 @@ bucketclient@scality/bucketclient:
|
||||||
resolved "https://codeload.github.com/scality/bucketclient/tar.gz/07d5a3813878b2746ed00e41c177bc2a0460e243"
|
resolved "https://codeload.github.com/scality/bucketclient/tar.gz/07d5a3813878b2746ed00e41c177bc2a0460e243"
|
||||||
dependencies:
|
dependencies:
|
||||||
agentkeepalive "^4.1.3"
|
agentkeepalive "^4.1.3"
|
||||||
arsenal scality/Arsenal#c57cde8
|
arsenal scality/Arsenal#8ed8478
|
||||||
werelogs scality/werelogs#351a2a3
|
werelogs scality/werelogs#351a2a3
|
||||||
|
|
||||||
bucketclient@scality/bucketclient#6d2d5a4:
|
bucketclient@scality/bucketclient#6d2d5a4:
|
||||||
|
@ -1215,7 +1241,6 @@ bucketclient@scality/bucketclient#6d2d5a4:
|
||||||
dependencies:
|
dependencies:
|
||||||
arsenal scality/Arsenal#9f2e74e
|
arsenal scality/Arsenal#9f2e74e
|
||||||
werelogs scality/werelogs#4e0d97c
|
werelogs scality/werelogs#4e0d97c
|
||||||
yarn "^1.17.3"
|
|
||||||
|
|
||||||
buffer-equal-constant-time@1.0.1:
|
buffer-equal-constant-time@1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
|
@ -1761,6 +1786,13 @@ debug@^3.1.0, debug@^3.2.5, debug@^3.2.6:
|
||||||
dependencies:
|
dependencies:
|
||||||
ms "^2.1.1"
|
ms "^2.1.1"
|
||||||
|
|
||||||
|
debug@^4.3.1:
|
||||||
|
version "4.3.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
|
||||||
|
integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==
|
||||||
|
dependencies:
|
||||||
|
ms "2.1.2"
|
||||||
|
|
||||||
debug@~4.1.0:
|
debug@~4.1.0:
|
||||||
version "4.1.1"
|
version "4.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
|
resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
|
||||||
|
@ -2049,23 +2081,6 @@ engine.io-client@~1.8.4:
|
||||||
xmlhttprequest-ssl "1.5.3"
|
xmlhttprequest-ssl "1.5.3"
|
||||||
yeast "0.1.2"
|
yeast "0.1.2"
|
||||||
|
|
||||||
engine.io-client@~3.3.1:
|
|
||||||
version "3.3.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.3.2.tgz#04e068798d75beda14375a264bb3d742d7bc33aa"
|
|
||||||
integrity sha512-y0CPINnhMvPuwtqXfsGuWE8BB66+B6wTtCofQDRecMQPYX3MYUZXFNKDhdrSe3EVjgOu4V3rxdeqN/Tr91IgbQ==
|
|
||||||
dependencies:
|
|
||||||
component-emitter "1.2.1"
|
|
||||||
component-inherit "0.0.3"
|
|
||||||
debug "~3.1.0"
|
|
||||||
engine.io-parser "~2.1.1"
|
|
||||||
has-cors "1.1.0"
|
|
||||||
indexof "0.0.1"
|
|
||||||
parseqs "0.0.5"
|
|
||||||
parseuri "0.0.5"
|
|
||||||
ws "~6.1.0"
|
|
||||||
xmlhttprequest-ssl "~1.5.4"
|
|
||||||
yeast "0.1.2"
|
|
||||||
|
|
||||||
engine.io-client@~3.4.0:
|
engine.io-client@~3.4.0:
|
||||||
version "3.4.4"
|
version "3.4.4"
|
||||||
resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.4.4.tgz#77d8003f502b0782dd792b073a4d2cf7ca5ab967"
|
resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.4.4.tgz#77d8003f502b0782dd792b073a4d2cf7ca5ab967"
|
||||||
|
@ -2095,17 +2110,6 @@ engine.io-parser@1.3.2:
|
||||||
has-binary "0.1.7"
|
has-binary "0.1.7"
|
||||||
wtf-8 "1.0.0"
|
wtf-8 "1.0.0"
|
||||||
|
|
||||||
engine.io-parser@~2.1.0, engine.io-parser@~2.1.1:
|
|
||||||
version "2.1.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.1.3.tgz#757ab970fbf2dfb32c7b74b033216d5739ef79a6"
|
|
||||||
integrity sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==
|
|
||||||
dependencies:
|
|
||||||
after "0.8.2"
|
|
||||||
arraybuffer.slice "~0.0.7"
|
|
||||||
base64-arraybuffer "0.1.5"
|
|
||||||
blob "0.0.5"
|
|
||||||
has-binary2 "~1.0.2"
|
|
||||||
|
|
||||||
engine.io-parser@~2.2.0:
|
engine.io-parser@~2.2.0:
|
||||||
version "2.2.1"
|
version "2.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.2.1.tgz#57ce5611d9370ee94f99641b589f94c97e4f5da7"
|
resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.2.1.tgz#57ce5611d9370ee94f99641b589f94c97e4f5da7"
|
||||||
|
@ -2129,18 +2133,6 @@ engine.io@~1.8.4:
|
||||||
engine.io-parser "1.3.2"
|
engine.io-parser "1.3.2"
|
||||||
ws "~1.1.5"
|
ws "~1.1.5"
|
||||||
|
|
||||||
engine.io@~3.3.1:
|
|
||||||
version "3.3.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.3.2.tgz#18cbc8b6f36e9461c5c0f81df2b830de16058a59"
|
|
||||||
integrity sha512-AsaA9KG7cWPXWHp5FvHdDWY3AMWeZ8x+2pUVLcn71qE5AtAzgGbxuclOytygskw8XGmiQafTmnI9Bix3uihu2w==
|
|
||||||
dependencies:
|
|
||||||
accepts "~1.3.4"
|
|
||||||
base64id "1.0.0"
|
|
||||||
cookie "0.3.1"
|
|
||||||
debug "~3.1.0"
|
|
||||||
engine.io-parser "~2.1.0"
|
|
||||||
ws "~6.1.0"
|
|
||||||
|
|
||||||
engine.io@~3.4.0:
|
engine.io@~3.4.0:
|
||||||
version "3.4.2"
|
version "3.4.2"
|
||||||
resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.4.2.tgz#8fc84ee00388e3e228645e0a7d3dfaeed5bd122c"
|
resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.4.2.tgz#8fc84ee00388e3e228645e0a7d3dfaeed5bd122c"
|
||||||
|
@ -3072,11 +3064,6 @@ hoek@4.x.x:
|
||||||
resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb"
|
resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb"
|
||||||
integrity sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==
|
integrity sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==
|
||||||
|
|
||||||
hoek@6.x.x:
|
|
||||||
version "6.1.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/hoek/-/hoek-6.1.3.tgz#73b7d33952e01fe27a38b0457294b79dd8da242c"
|
|
||||||
integrity sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==
|
|
||||||
|
|
||||||
hosted-git-info@^2.1.4, hosted-git-info@^2.7.1:
|
hosted-git-info@^2.1.4, hosted-git-info@^2.7.1:
|
||||||
version "2.8.8"
|
version "2.8.8"
|
||||||
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
|
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
|
||||||
|
@ -3329,21 +3316,22 @@ ioredis@4.9.5:
|
||||||
redis-parser "^3.0.0"
|
redis-parser "^3.0.0"
|
||||||
standard-as-callback "^2.0.1"
|
standard-as-callback "^2.0.1"
|
||||||
|
|
||||||
ioredis@^4.9.5:
|
ioredis@^4.28.0:
|
||||||
version "4.19.4"
|
version "4.28.0"
|
||||||
resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-4.19.4.tgz#11112005f87ad3acac247ada3b22eb31b947f7c7"
|
resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-4.28.0.tgz#5a2be3f37ff2075e2332f280eaeb02ab4d9ff0d3"
|
||||||
integrity sha512-3haQWw9dpEjcfVcRktXlayVNrrqvvc2io7Q/uiV2UsYw8/HC2YwwJr78Wql7zu5bzwci0x9bZYA69U7KkevAvw==
|
integrity sha512-I+zkeeWp3XFgPT2CtJKxvaF5FjGBGt4yGYljRjQecdQKteThuAsKqffeF1lgHVlYnuNeozRbPOCDNZ7tDWPeig==
|
||||||
dependencies:
|
dependencies:
|
||||||
cluster-key-slot "^1.1.0"
|
cluster-key-slot "^1.1.0"
|
||||||
debug "^4.1.1"
|
debug "^4.3.1"
|
||||||
denque "^1.1.0"
|
denque "^1.1.0"
|
||||||
lodash.defaults "^4.2.0"
|
lodash.defaults "^4.2.0"
|
||||||
lodash.flatten "^4.4.0"
|
lodash.flatten "^4.4.0"
|
||||||
|
lodash.isarguments "^3.1.0"
|
||||||
p-map "^2.1.0"
|
p-map "^2.1.0"
|
||||||
redis-commands "1.6.0"
|
redis-commands "1.7.0"
|
||||||
redis-errors "^1.2.0"
|
redis-errors "^1.2.0"
|
||||||
redis-parser "^3.0.0"
|
redis-parser "^3.0.0"
|
||||||
standard-as-callback "^2.0.1"
|
standard-as-callback "^2.1.0"
|
||||||
|
|
||||||
ip@1.1.5, ip@^1.1.5:
|
ip@1.1.5, ip@^1.1.5:
|
||||||
version "1.1.5"
|
version "1.1.5"
|
||||||
|
@ -3355,11 +3343,6 @@ ipaddr.js@1.2.0:
|
||||||
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.2.0.tgz#8aba49c9192799585bdd643e0ccb50e8ae777ba4"
|
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.2.0.tgz#8aba49c9192799585bdd643e0ccb50e8ae777ba4"
|
||||||
integrity sha1-irpJyRknmVhb3WQ+DMtQ6K53e6Q=
|
integrity sha1-irpJyRknmVhb3WQ+DMtQ6K53e6Q=
|
||||||
|
|
||||||
ipaddr.js@1.8.1:
|
|
||||||
version "1.8.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.1.tgz#fa4b79fa47fd3def5e3b159825161c0a519c9427"
|
|
||||||
integrity sha1-+kt5+kf9Pe9eOxWYJRYcClGclCc=
|
|
||||||
|
|
||||||
ipaddr.js@1.9.1:
|
ipaddr.js@1.9.1:
|
||||||
version "1.9.1"
|
version "1.9.1"
|
||||||
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
|
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
|
||||||
|
@ -3604,13 +3587,6 @@ isemail@2.x.x:
|
||||||
resolved "https://registry.yarnpkg.com/isemail/-/isemail-2.2.1.tgz#0353d3d9a62951080c262c2aa0a42b8ea8e9e2a6"
|
resolved "https://registry.yarnpkg.com/isemail/-/isemail-2.2.1.tgz#0353d3d9a62951080c262c2aa0a42b8ea8e9e2a6"
|
||||||
integrity sha1-A1PT2aYpUQgMJiwqoKQrjqjp4qY=
|
integrity sha1-A1PT2aYpUQgMJiwqoKQrjqjp4qY=
|
||||||
|
|
||||||
isemail@3.x.x:
|
|
||||||
version "3.2.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/isemail/-/isemail-3.2.0.tgz#59310a021931a9fb06bbb51e155ce0b3f236832c"
|
|
||||||
integrity sha512-zKqkK+O+dGqevc93KNsbZ/TqTUFd46MwWjYOoMrjIMZ51eU7DtQG3Wmd9SQQT7i7RVnuTPEiYEWHU3MSbxC1Tg==
|
|
||||||
dependencies:
|
|
||||||
punycode "2.x.x"
|
|
||||||
|
|
||||||
isexe@^2.0.0:
|
isexe@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
||||||
|
@ -3750,15 +3726,6 @@ joi@^10.6:
|
||||||
items "2.x.x"
|
items "2.x.x"
|
||||||
topo "2.x.x"
|
topo "2.x.x"
|
||||||
|
|
||||||
joi@^14.3.0:
|
|
||||||
version "14.3.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/joi/-/joi-14.3.1.tgz#164a262ec0b855466e0c35eea2a885ae8b6c703c"
|
|
||||||
integrity sha512-LQDdM+pkOrpAn4Lp+neNIFV3axv1Vna3j38bisbQhETPMANYRbFJFUyOZcOClYvM/hppMhGWuKSFEK9vjrB+bQ==
|
|
||||||
dependencies:
|
|
||||||
hoek "6.x.x"
|
|
||||||
isemail "3.x.x"
|
|
||||||
topo "3.x.x"
|
|
||||||
|
|
||||||
"js-tokens@^3.0.0 || ^4.0.0":
|
"js-tokens@^3.0.0 || ^4.0.0":
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||||
|
@ -4210,6 +4177,11 @@ lodash.invert@^4.3.0:
|
||||||
resolved "https://registry.yarnpkg.com/lodash.invert/-/lodash.invert-4.3.0.tgz#8ffe20d4b616f56bea8f1aa0c6ebd80dcf742aee"
|
resolved "https://registry.yarnpkg.com/lodash.invert/-/lodash.invert-4.3.0.tgz#8ffe20d4b616f56bea8f1aa0c6ebd80dcf742aee"
|
||||||
integrity sha1-j/4g1LYW9WvqjxqgxuvYDc90Ku4=
|
integrity sha1-j/4g1LYW9WvqjxqgxuvYDc90Ku4=
|
||||||
|
|
||||||
|
lodash.isarguments@^3.1.0:
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a"
|
||||||
|
integrity sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=
|
||||||
|
|
||||||
lodash.isboolean@^3.0.3:
|
lodash.isboolean@^3.0.3:
|
||||||
version "3.0.3"
|
version "3.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
|
resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
|
||||||
|
@ -5404,7 +5376,7 @@ punycode@1.3.2:
|
||||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
|
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
|
||||||
integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=
|
integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=
|
||||||
|
|
||||||
punycode@2.x.x, punycode@^2.1.0, punycode@^2.1.1:
|
punycode@^2.1.0, punycode@^2.1.1:
|
||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
||||||
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
|
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
|
||||||
|
@ -5553,10 +5525,10 @@ redis-commands@1.4.0:
|
||||||
resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.4.0.tgz#52f9cf99153efcce56a8f86af986bd04e988602f"
|
resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.4.0.tgz#52f9cf99153efcce56a8f86af986bd04e988602f"
|
||||||
integrity sha512-cu8EF+MtkwI4DLIT0x9P8qNTLFhQD4jLfxLR0cCNkeGzs87FN6879JOJwNQR/1zD7aSYNbU0hgsV9zGY71Itvw==
|
integrity sha512-cu8EF+MtkwI4DLIT0x9P8qNTLFhQD4jLfxLR0cCNkeGzs87FN6879JOJwNQR/1zD7aSYNbU0hgsV9zGY71Itvw==
|
||||||
|
|
||||||
redis-commands@1.6.0:
|
redis-commands@1.7.0:
|
||||||
version "1.6.0"
|
version "1.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.6.0.tgz#36d4ca42ae9ed29815cdb30ad9f97982eba1ce23"
|
resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.7.0.tgz#15a6fea2d58281e27b1cd1acfb4b293e278c3a89"
|
||||||
integrity sha512-2jnZ0IkjZxvguITjFTrGiLyzQZcTvaw8DAaCXxZq/dsHXz7KfMQ3OUJy7Tz9vnRtZRVz6VRCPDvruvU8Ts44wQ==
|
integrity sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==
|
||||||
|
|
||||||
redis-errors@^1.0.0, redis-errors@^1.2.0:
|
redis-errors@^1.0.0, redis-errors@^1.2.0:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
|
@ -6306,26 +6278,6 @@ socket.io-client@1.7.4, socket.io-client@~1.7.3:
|
||||||
socket.io-parser "2.3.1"
|
socket.io-parser "2.3.1"
|
||||||
to-array "0.1.4"
|
to-array "0.1.4"
|
||||||
|
|
||||||
socket.io-client@2.2.0, socket.io-client@~2.2.0:
|
|
||||||
version "2.2.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.2.0.tgz#84e73ee3c43d5020ccc1a258faeeb9aec2723af7"
|
|
||||||
integrity sha512-56ZrkTDbdTLmBIyfFYesgOxsjcLnwAKoN4CiPyTVkMQj3zTUh0QAx3GbvIvLpFEOvQWu92yyWICxB0u7wkVbYA==
|
|
||||||
dependencies:
|
|
||||||
backo2 "1.0.2"
|
|
||||||
base64-arraybuffer "0.1.5"
|
|
||||||
component-bind "1.0.0"
|
|
||||||
component-emitter "1.2.1"
|
|
||||||
debug "~3.1.0"
|
|
||||||
engine.io-client "~3.3.1"
|
|
||||||
has-binary2 "~1.0.2"
|
|
||||||
has-cors "1.1.0"
|
|
||||||
indexof "0.0.1"
|
|
||||||
object-component "0.0.3"
|
|
||||||
parseqs "0.0.5"
|
|
||||||
parseuri "0.0.5"
|
|
||||||
socket.io-parser "~3.3.0"
|
|
||||||
to-array "0.1.4"
|
|
||||||
|
|
||||||
socket.io-client@2.3.0:
|
socket.io-client@2.3.0:
|
||||||
version "2.3.0"
|
version "2.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.3.0.tgz#14d5ba2e00b9bcd145ae443ab96b3f86cbcc1bb4"
|
resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.3.0.tgz#14d5ba2e00b9bcd145ae443ab96b3f86cbcc1bb4"
|
||||||
|
@ -6404,18 +6356,6 @@ socket.io@~1.7.3:
|
||||||
socket.io-client "1.7.4"
|
socket.io-client "1.7.4"
|
||||||
socket.io-parser "2.3.1"
|
socket.io-parser "2.3.1"
|
||||||
|
|
||||||
socket.io@~2.2.0:
|
|
||||||
version "2.2.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-2.2.0.tgz#f0f633161ef6712c972b307598ecd08c9b1b4d5b"
|
|
||||||
integrity sha512-wxXrIuZ8AILcn+f1B4ez4hJTPG24iNgxBBDaJfT6MsyOhVYiTXWexGoPkd87ktJG8kQEcL/NBvRi64+9k4Kc0w==
|
|
||||||
dependencies:
|
|
||||||
debug "~4.1.0"
|
|
||||||
engine.io "~3.3.1"
|
|
||||||
has-binary2 "~1.0.2"
|
|
||||||
socket.io-adapter "~1.1.0"
|
|
||||||
socket.io-client "2.2.0"
|
|
||||||
socket.io-parser "~3.3.0"
|
|
||||||
|
|
||||||
socket.io@~2.3.0:
|
socket.io@~2.3.0:
|
||||||
version "2.3.0"
|
version "2.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-2.3.0.tgz#cd762ed6a4faeca59bc1f3e243c0969311eb73fb"
|
resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-2.3.0.tgz#cd762ed6a4faeca59bc1f3e243c0969311eb73fb"
|
||||||
|
@ -6510,11 +6450,12 @@ sprintf-js@~1.0.2:
|
||||||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
||||||
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
|
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
|
||||||
|
|
||||||
"sproxydclient@github:scality/sproxydclient#a6ec980":
|
"sproxydclient@github:scality/sproxydclient#30e7115":
|
||||||
version "7.4.0"
|
version "8.0.2"
|
||||||
resolved "https://codeload.github.com/scality/sproxydclient/tar.gz/a6ec98079fcbfde113de3f3afdcb57835d2ac55f"
|
resolved "https://codeload.github.com/scality/sproxydclient/tar.gz/30e7115668bc7e10b4ec3cfdbaa7a124cdc21cc5"
|
||||||
dependencies:
|
dependencies:
|
||||||
werelogs scality/werelogs#0ff7ec82
|
async "^3.1.0"
|
||||||
|
werelogs scality/werelogs#351a2a3
|
||||||
|
|
||||||
sproxydclient@scality/sproxydclient#44f025b:
|
sproxydclient@scality/sproxydclient#44f025b:
|
||||||
version "7.4.7"
|
version "7.4.7"
|
||||||
|
@ -6580,6 +6521,11 @@ standard-as-callback@^2.0.1:
|
||||||
resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.0.1.tgz#ed8bb25648e15831759b6023bdb87e6b60b38126"
|
resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.0.1.tgz#ed8bb25648e15831759b6023bdb87e6b60b38126"
|
||||||
integrity sha512-NQOxSeB8gOI5WjSaxjBgog2QFw55FV8TkS6Y07BiB3VJ8xNTvUYm0wl0s8ObgQ5NhdpnNfigMIKjgPESzgr4tg==
|
integrity sha512-NQOxSeB8gOI5WjSaxjBgog2QFw55FV8TkS6Y07BiB3VJ8xNTvUYm0wl0s8ObgQ5NhdpnNfigMIKjgPESzgr4tg==
|
||||||
|
|
||||||
|
standard-as-callback@^2.1.0:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz#8953fc05359868a77b5b9739a665c5977bb7df45"
|
||||||
|
integrity sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==
|
||||||
|
|
||||||
"statuses@>= 1.5.0 < 2", statuses@~1.5.0:
|
"statuses@>= 1.5.0 < 2", statuses@~1.5.0:
|
||||||
version "1.5.0"
|
version "1.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
|
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
|
||||||
|
@ -6926,13 +6872,6 @@ topo@2.x.x:
|
||||||
dependencies:
|
dependencies:
|
||||||
hoek "4.x.x"
|
hoek "4.x.x"
|
||||||
|
|
||||||
topo@3.x.x:
|
|
||||||
version "3.0.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/topo/-/topo-3.0.3.tgz#d5a67fb2e69307ebeeb08402ec2a2a6f5f7ad95c"
|
|
||||||
integrity sha512-IgpPtvD4kjrJ7CRA3ov2FhWQADwv+Tdqbsf1ZnPUSAtCJ9e1Z44MmoSGDXGk4IppoZA7jd/QRkNddlLJWlUZsQ==
|
|
||||||
dependencies:
|
|
||||||
hoek "6.x.x"
|
|
||||||
|
|
||||||
tough-cookie@~2.5.0:
|
tough-cookie@~2.5.0:
|
||||||
version "2.5.0"
|
version "2.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
|
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
|
||||||
|
@ -7154,15 +7093,16 @@ user-home@^2.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
os-homedir "^1.0.0"
|
os-homedir "^1.0.0"
|
||||||
|
|
||||||
utapi@scality/utapi#1af6532:
|
utapi@scality/utapi#8829793:
|
||||||
version "7.8.0"
|
version "7.8.0"
|
||||||
resolved "https://codeload.github.com/scality/utapi/tar.gz/1af6532d83b7e323a62d9048cd6478cab12dfa71"
|
resolved "https://codeload.github.com/scality/utapi/tar.gz/8829793597295ef382e592a1a84bcc770699ace3"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@hapi/joi" "^17.1.1"
|
"@hapi/joi" "^17.1.1"
|
||||||
"@senx/warp10" "^1.0.14"
|
"@senx/warp10" "^1.0.14"
|
||||||
arsenal scality/Arsenal#65966f5
|
arsenal scality/Arsenal#65966f5
|
||||||
async "^3.2.0"
|
async "^3.2.0"
|
||||||
aws4 "^1.8.0"
|
aws4 "^1.8.0"
|
||||||
|
backo "^1.1.0"
|
||||||
body-parser "^1.19.0"
|
body-parser "^1.19.0"
|
||||||
bucketclient scality/bucketclient
|
bucketclient scality/bucketclient
|
||||||
byte-size "^7.0.0"
|
byte-size "^7.0.0"
|
||||||
|
@ -7171,7 +7111,7 @@ utapi@scality/utapi#1af6532:
|
||||||
diskusage "^1.1.3"
|
diskusage "^1.1.3"
|
||||||
express "^4.17.1"
|
express "^4.17.1"
|
||||||
get-folder-size "^2.0.1"
|
get-folder-size "^2.0.1"
|
||||||
ioredis "^4.9.5"
|
ioredis "^4.28.0"
|
||||||
js-yaml "^3.14.0"
|
js-yaml "^3.14.0"
|
||||||
level-mem "^5.0.1"
|
level-mem "^5.0.1"
|
||||||
needle "^2.5.0"
|
needle "^2.5.0"
|
||||||
|
|
Loading…
Reference in New Issue