Skip to content

Commit 9ab1750

Browse files
committed
Merge remote-tracking branch 'origin/development/9.1' into HEAD
2 parents 4f9b629 + ae9f7cd commit 9ab1750

24 files changed

+1984
-105
lines changed

constants.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,6 @@ const constants = {
117117
'accelerate',
118118
'analytics',
119119
'inventory',
120-
'logging',
121120
'metrics',
122121
'policyStatus',
123122
'publicAccessBlock',
@@ -191,6 +190,8 @@ const constants = {
191190
'bucketPutReplication',
192191
'bucketPutVersioning',
193192
'bucketPutWebsite',
193+
'bucketPutLogging',
194+
'bucketGetLogging',
194195
'objectDeleteTagging',
195196
'objectGetTagging',
196197
'objectPutTagging',
@@ -267,7 +268,13 @@ const constants = {
267268
],
268269
// if requester is not bucket owner, bucket policy actions should be denied with
269270
// MethodNotAllowed error
270-
onlyOwnerAllowed: ['bucketDeletePolicy', 'bucketGetPolicy', 'bucketPutPolicy'],
271+
onlyOwnerAllowed: [
272+
'bucketDeletePolicy',
273+
'bucketGetPolicy',
274+
'bucketPutPolicy',
275+
'bucketPutLogging',
276+
'bucketGetLogging',
277+
],
271278
};
272279

273280
module.exports = constants;

lib/api/api.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ const bucketPutObjectLock = require('./bucketPutObjectLock');
3838
const bucketUpdateQuota = require('./bucketUpdateQuota');
3939
const bucketGetReplication = require('./bucketGetReplication');
4040
const bucketDeleteReplication = require('./bucketDeleteReplication');
41+
const bucketGetLogging = require('./bucketGetLogging');
42+
const bucketPutLogging = require('./bucketPutLogging');
4143
const corsPreflight = require('./corsPreflight');
4244
const completeMultipartUpload = require('./completeMultipartUpload');
4345
const initiateMultipartUpload = require('./initiateMultipartUpload');
@@ -368,6 +370,8 @@ const api = {
368370
bucketPutNotification,
369371
bucketGetNotification,
370372
bucketPutEncryption,
373+
bucketGetLogging,
374+
bucketPutLogging,
371375
corsPreflight,
372376
completeMultipartUpload,
373377
initiateMultipartUpload,

lib/api/apiUtils/object/createAndStoreObject.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ function createAndStoreObject(bucketName, bucketMD, objectKey, objMD, authInfo,
218218
metadataStoreParams.contentMD5 = constants.emptyFileMd5;
219219
return next(null, null, null);
220220
}
221+
221222
// Handle mdOnlyHeader as a metadata only operation. If
222223
// the object in question is actually 0 byte or has a body size
223224
// then handle normally.
@@ -244,6 +245,7 @@ function createAndStoreObject(bucketName, bucketMD, objectKey, objMD, authInfo,
244245
return next(null, dataGetInfo, _md5);
245246
}
246247
}
248+
247249
return dataStore(objectKeyContext, cipherBundle, request, size,
248250
streamingV4Params, backendInfo, log, next);
249251
},
@@ -280,10 +282,12 @@ function createAndStoreObject(bucketName, bucketMD, objectKey, objMD, authInfo,
280282
const options = overwritingVersioning(objMD, metadataStoreParams);
281283
return process.nextTick(() => next(null, options, infoArr));
282284
}
285+
283286
if (!bucketMD.isVersioningEnabled() && objMD?.archive?.archiveInfo) {
284287
// Ensure we trigger a "delete" event in the oplog for the previously archived object
285288
metadataStoreParams.needOplogUpdate = 's3:ReplaceArchivedObject';
286289
}
290+
287291
return versioningPreprocessing(bucketName, bucketMD,
288292
metadataStoreParams.objectKey, objMD, log, (err, options) => {
289293
if (err) {
@@ -316,9 +320,11 @@ function createAndStoreObject(bucketName, bucketMD, objectKey, objMD, authInfo,
316320
metadataStoreParams.versioning = options.versioning;
317321
metadataStoreParams.isNull = options.isNull;
318322
metadataStoreParams.deleteNullKey = options.deleteNullKey;
323+
319324
if (options.extraMD) {
320325
Object.assign(metadataStoreParams, options.extraMD);
321326
}
327+
322328
return _storeInMDandDeleteData(bucketName, infoArr,
323329
cipherBundle, metadataStoreParams,
324330
options.dataToDelete, log, requestMethod, next);

lib/api/apiUtils/object/versioning.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ function _storeNullVersionMD(bucketName, objKey, nullVersionId, objMD, log, cb)
103103
log.debug('error from metadata storing null version as new version',
104104
{ error: err });
105105
}
106+
106107
cb(err);
107108
});
108109
}
@@ -252,6 +253,7 @@ function processVersioningState(mst, vstat, nullVersionCompatMode) {
252253
}
253254
return { options, nullVersionId };
254255
}
256+
255257
if (mst.isNull && !mst.isNull2) {
256258
// if master null version was put with an older
257259
// Cloudserver (or in compat mode), there is a
@@ -265,6 +267,7 @@ function processVersioningState(mst, vstat, nullVersionCompatMode) {
265267
}
266268
return { options, nullVersionId };
267269
}
270+
268271
// backward-compat: keep a reference to the existing null
269272
// versioned key
270273
if (mst.nullVersionId) {
@@ -295,6 +298,7 @@ function getMasterState(objMD) {
295298
if (!objMD) {
296299
return {};
297300
}
301+
298302
const mst = {
299303
exists: true,
300304
versionId: objMD.versionId,
@@ -304,10 +308,12 @@ function getMasterState(objMD) {
304308
nullVersionId: objMD.nullVersionId,
305309
nullUploadId: objMD.nullUploadId,
306310
};
311+
307312
if (objMD.location) {
308313
mst.objLocation = Array.isArray(objMD.location) ?
309314
objMD.location : [objMD.location];
310315
}
316+
311317
return mst;
312318
}
313319
/** versioningPreprocessing - return versioning information for S3 to handle
@@ -329,19 +335,22 @@ function versioningPreprocessing(bucketName, bucketMD, objectKey, objMD,
329335
log, callback) {
330336
const mst = getMasterState(objMD);
331337
const vCfg = bucketMD.getVersioningConfiguration();
332-
// bucket is not versioning configured
338+
333339
if (!vCfg) {
334340
const options = { dataToDelete: mst.objLocation };
335341
return process.nextTick(callback, null, options);
336342
}
337-
// bucket is versioning configured
343+
338344
const { options, nullVersionId, delOptions } =
339345
processVersioningState(mst, vCfg.Status, config.nullVersionCompatMode);
346+
340347
return async.series([
341348
function storeNullVersionMD(next) {
342349
if (!nullVersionId) {
343350
return process.nextTick(next);
344351
}
352+
353+
options.nullVersionId = nullVersionId;
345354
return _storeNullVersionMD(bucketName, objectKey, nullVersionId, objMD, log, next);
346355
},
347356
function prepareNullVersionDeletion(next) {

lib/api/bucketGetLogging.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
const { standardMetadataValidateBucket } = require('../metadata/metadataUtils');
2+
const { checkExpectedBucketOwner } = require('./apiUtils/authorization/bucketOwner');
3+
const monitoring = require('../utilities/monitoringHandler');
4+
const { waterfall } = require('async');
5+
6+
const BucketLoggingStatusNotFoundBody = '<?xml version="1.0" encoding="UTF-8"?>\n' +
7+
'<BucketLoggingStatus xmlns="http://doc.s3.amazonaws.com/2006-03-01" />';
8+
9+
function bucketGetLogging(authInfo, request, log, callback) {
10+
log.debug('processing request', { method: 'bucketGetLogging' });
11+
12+
const bucketName = request.bucketName;
13+
const metadataValParams = {
14+
authInfo,
15+
bucketName,
16+
requestType: request.apiMethods || 'bucketGetLogging',
17+
request,
18+
};
19+
20+
return waterfall([
21+
next => standardMetadataValidateBucket(metadataValParams, request.actionImplicitDenies, log, (err, bucket) => {
22+
if (err) {
23+
return next(err);
24+
}
25+
26+
return next(null, bucket);
27+
}),
28+
(bucket, next) => checkExpectedBucketOwner(request.headers, bucket, log, err => {
29+
if (err) {
30+
return next(err);
31+
}
32+
33+
return next(null, bucket);
34+
}),
35+
(bucket, next) => {
36+
const bucketLoggingStatus = bucket.getBucketLoggingStatus();
37+
if (!bucketLoggingStatus) {
38+
return next(null, BucketLoggingStatusNotFoundBody);
39+
}
40+
41+
return next(null, bucketLoggingStatus.toXML());
42+
}
43+
], (err, body) => {
44+
if (err) {
45+
log.trace('error processing request', { error: err, method: 'bucketGetLogging' });
46+
monitoring.promMetrics('GET', bucketName, err.code, 'bucketGetLogging');
47+
return callback(err);
48+
}
49+
50+
monitoring.promMetrics('GET', bucketName, '200', 'bucketGetLogging');
51+
return callback(null, body);
52+
});
53+
}
54+
55+
module.exports = bucketGetLogging;

lib/api/bucketPutLogging.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
const { waterfall } = require('async');
2+
const { standardMetadataValidateBucket } = require('../metadata/metadataUtils');
3+
const { checkExpectedBucketOwner } = require('./apiUtils/authorization/bucketOwner');
4+
const BucketLoggingStatus = require('arsenal').models.BucketLoggingStatus;
5+
const metadata = require('../metadata/wrapper');
6+
const monitoring = require('../utilities/monitoringHandler');
7+
const { errorInstances } = require('arsenal');
8+
9+
function bucketPutLogging(authInfo, request, log, callback) {
10+
log.debug('processing request', { method: 'bucketPutLogging' });
11+
12+
const bucketName = request.bucketName;
13+
const parsed = BucketLoggingStatus.fromXML(request.post);
14+
if (parsed.error) {
15+
log.trace('error processing request', { error: parsed.error, method: 'bucketPutLogging' });
16+
monitoring.promMetrics('PUT', bucketName, parsed.error.arsenalError, 'bucketPutLogging');
17+
return callback(parsed.error.arsenalError);
18+
}
19+
20+
const metadataValParams = {
21+
authInfo,
22+
bucketName,
23+
requestType: request.apiMethods || 'bucketPutLogging',
24+
request,
25+
};
26+
27+
return waterfall([
28+
next => standardMetadataValidateBucket(metadataValParams, request.actionImplicitDenies, log, (err, bucket) => {
29+
if (err) {
30+
return next(err);
31+
}
32+
33+
return next(null, bucket);
34+
}),
35+
(bucket, next) => {
36+
const loggingEnabled = parsed.res.getLoggingEnabled();
37+
if (!loggingEnabled) {
38+
return next(null, bucket);
39+
}
40+
41+
return metadata.getBucket(loggingEnabled.TargetBucket, log, err => {
42+
if (err) {
43+
return next(errorInstances.InvalidTargetBucketForLogging.customizeDescription(err.description));
44+
}
45+
46+
return next(null, bucket);
47+
});
48+
},
49+
(bucket, next) => checkExpectedBucketOwner(request.headers, bucket, log, err => {
50+
if (err) {
51+
return next(err);
52+
}
53+
54+
return next(null, bucket);
55+
}),
56+
(bucket, next) => {
57+
bucket.setBucketLoggingStatus(parsed.res);
58+
return metadata.updateBucket(bucket.getName(), bucket, log, err => {
59+
if (err) {
60+
return next(err);
61+
}
62+
63+
return next();
64+
});
65+
},
66+
], err => {
67+
if (err) {
68+
log.trace('error processing request', { error: err, method: 'bucketPutLogging' });
69+
monitoring.promMetrics('PUT', bucketName, err.code, 'bucketPutLogging');
70+
return callback(err);
71+
}
72+
73+
monitoring.promMetrics('PUT', bucketName, '200', 'bucketPutLogging');
74+
return callback();
75+
});
76+
}
77+
78+
module.exports = bucketPutLogging;

0 commit comments

Comments
 (0)