Skip to content

Commit

Permalink
Merge branch 'improvement/CLDSRV-408-Fix-metadata-getting-deleted-whe…
Browse files Browse the repository at this point in the history
…n-restoring' into tmp/octopus/w/8.8/improvement/CLDSRV-408-Fix-metadata-getting-deleted-when-restoring
  • Loading branch information
bert-e committed Jul 6, 2023
2 parents 0b58b3a + 4f4762f commit 13edfb6
Show file tree
Hide file tree
Showing 5 changed files with 437 additions and 11 deletions.
56 changes: 53 additions & 3 deletions lib/api/apiUtils/object/versioning.js
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,57 @@ function preprocessingVersioningDelete(bucketName, bucketMD, objectMD, reqVersio
return options;
}

/**
* Keep metadatas when the object is restored from cold storage
* but remove the specific ones we don't want to keep
* @param {object} objMD - obj metadata
* @param {object} metadataStoreParams - custom built object containing resource details.
* @return {undefined}
*/
function restoreMetadatas(objMD, metadataStoreParams) {
/* eslint-disable no-param-reassign */
const userMDToSkip = ['x-amz-meta-scal-s3-restore-attempt'];
// We need to keep user metadata and tags
Object.keys(objMD).forEach(key => {
if (key.startsWith('x-amz-meta-') && !userMDToSkip.includes(key)) {
metadataStoreParams.metaHeaders[key] = objMD[key];
} else if (key.startsWith('content-')) {
metadataStoreParams[key] = objMD[key];
}
});

if (objMD['x-amz-server-side-encryption']) {
metadataStoreParams.cipherBundle = {
algorithm: objMD['x-amz-server-side-encryption'],
masterKeyId: objMD['x-amz-server-side-encryption-aws-kms-key-id'] ||
objMD['x-amz-server-side-encryption-customer-algorithm'],
};
}

if (objMD['x-amz-website-redirect-location']) {
if (!metadataStoreParams.headers) {
metadataStoreParams.headers = {};
}
metadataStoreParams.headers['x-amz-website-redirect-location'] = objMD['x-amz-website-redirect-location'];
}

if (objMD.replicationInfo) {
metadataStoreParams.replicationInfo = objMD.replicationInfo;
}

if (objMD.legalHold) {
metadataStoreParams.legalHold = objMD.legalHold;
}

if (objMD.acl) {
metadataStoreParams.oldAcl = objMD.acl;
}

metadataStoreParams.creationTime = objMD['creation-time'];
metadataStoreParams.lastModifiedDate = objMD['last-modified'];
metadataStoreParams.taggingCopy = objMD.tags;
}

/** overwritingVersioning - return versioning information for S3 to handle
* storing version metadata with a specific version id.
* @param {object} objMD - obj metadata
Expand All @@ -445,9 +496,6 @@ function preprocessingVersioningDelete(bucketName, bucketMD, objectMD, reqVersio
* version id of the null version
*/
function overwritingVersioning(objMD, metadataStoreParams) {
/* eslint-disable no-param-reassign */
metadataStoreParams.creationTime = objMD['creation-time'];
metadataStoreParams.lastModifiedDate = objMD['last-modified'];
metadataStoreParams.updateMicroVersionId = true;

// set correct originOp
Expand Down Expand Up @@ -477,6 +525,8 @@ function overwritingVersioning(objMD, metadataStoreParams) {
};
}

restoreMetadatas(objMD, metadataStoreParams);

return options;
}

Expand Down
19 changes: 12 additions & 7 deletions lib/services.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ const services = {
tagging, taggingCopy, replicationInfo, defaultRetention,
dataStoreName, creationTime, retentionMode, retentionDate,
legalHold, originOp, updateMicroVersionId, archive, oldReplayId,
deleteNullKey } = params;
deleteNullKey, oldAcl } = params;
log.trace('storing object in metadata');
assert.strictEqual(typeof bucketName, 'string');
const md = new ObjectMD();
Expand Down Expand Up @@ -128,12 +128,11 @@ const services = {
if (lastModifiedDate) {
md.setLastModified(lastModifiedDate);
}
if (cipherBundle) {
md.setAmzServerSideEncryption(cipherBundle.algorithm);
// configuredMasterKeyId takes precedence
if (cipherBundle.configuredMasterKeyId || cipherBundle.masterKeyId) {
md.setAmzEncryptionKeyId(cipherBundle.configuredMasterKeyId || cipherBundle.masterKeyId);
}

if (cipherBundle || params.cipherBundle) {
const bundle = cipherBundle || params.cipherBundle;
md.setAmzServerSideEncryption(bundle.algorithm);
md.setAmzEncryptionKeyId(bundle.configuredMasterKeyId || bundle.masterKeyId);
}
if (headers && headers['x-amz-website-redirect-location']) {
md.setRedirectLocation(headers['x-amz-website-redirect-location']);
Expand Down Expand Up @@ -254,6 +253,12 @@ const services = {
if (multipart || md.getIsDeleteMarker()) {
return callback();
}
if (oldAcl) {
// In case of a restore we dont pass ACL in the headers
// but we take them from the old metadata
md.setAcl(oldAcl);
return callback();
}
const parseAclParams = {
headers,
resourceType: 'object',
Expand Down
1 change: 1 addition & 0 deletions tests/functional/aws-node-sdk/test/object/objectCopy.js
Original file line number Diff line number Diff line change
Expand Up @@ -1279,6 +1279,7 @@ describe('Object Copy', () => {
restoreCompletedAt: new Date(10),
restoreWillExpireAt: new Date(10 + (5 * 24 * 60 * 60 * 1000)),
};
originalMetadata['custom-user-md'] = 'custom-md';
fakeMetadataArchive(sourceBucketName, sourceObjName, undefined, archiveCompleted, err => {
assert.ifError(err);
s3.copyObject({
Expand Down
25 changes: 25 additions & 0 deletions tests/functional/aws-node-sdk/test/utils/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,31 @@ function fakeMetadataArchive(bucketName, objectName, versionId, archive, cb) {
/* eslint-disable no-param-reassign */
objMD.dataStoreName = 'location-dmf-v1';
objMD.archive = archive;
objMD['x-amz-meta-custom-user-md'] = 'custom-md';
objMD.tags = { tag1: 'value1', tag2: 'value2' };
objMD['x-amz-server-side-encryption'] = 'AES256';
objMD['x-amz-server-side-encryption-aws-kms-key-id'] = 'very-secret-key';
objMD['x-amz-website-redirect-location'] = 'https://scality.com/';
objMD.replicationInfo = {
'status': 'PENDING',
'backends': [
{
'site': 'azure-normal',
'status': 'PENDING',
'dataStoreVersionId': ''
}
],
'content': [
'DATA',
'METADATA'
],
'destination': 'arn:aws:s3:::versioned',
'storageClass': 'azure-normal',
'role': 'arn:aws:iam::root:role/s3-replication-role',
'storageType': 'azure',
'dataStoreVersionId': '',
'isNFS': null
};
/* eslint-enable no-param-reassign */
return metadata.putObjectMD(bucketName, objectName, objMD, { versionId: decodeVersionId(versionId) },
log, err => cb(err));
Expand Down
Loading

0 comments on commit 13edfb6

Please sign in to comment.