-
Notifications
You must be signed in to change notification settings - Fork 255
Build multi-destination replicationInfo per backend #6172
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: development/9.4
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -31,29 +31,46 @@ const acl = { | |||||||
| * contain the same number of elements, and all elements from one | ||||||||
| * grant are incuded in the other grant | ||||||||
| */ | ||||||||
| return oldAcl[grant].length === newAcl[grant].length | ||||||||
| && oldAcl[grant].every(value => newAcl[grant].includes(value)); | ||||||||
| return ( | ||||||||
| oldAcl[grant].length === newAcl[grant].length && oldAcl[grant].every(value => newAcl[grant].includes(value)) | ||||||||
| ); | ||||||||
| }, | ||||||||
|
|
||||||||
| addObjectACL(bucket, objectKey, objectMD, addACLParams, params, log, cb) { | ||||||||
| log.trace('updating object acl in metadata'); | ||||||||
| const isAclUnchanged = Object.keys(objectMD.acl).length === Object.keys(addACLParams).length | ||||||||
| && Object.keys(objectMD.acl).every(grant => this._aclGrantDidNotChange(grant, objectMD.acl, addACLParams)); | ||||||||
| const isAclUnchanged = | ||||||||
| Object.keys(objectMD.acl).length === Object.keys(addACLParams).length && | ||||||||
| Object.keys(objectMD.acl).every(grant => this._aclGrantDidNotChange(grant, objectMD.acl, addACLParams)); | ||||||||
| if (!isAclUnchanged) { | ||||||||
| /* eslint-disable no-param-reassign */ | ||||||||
| objectMD.acl = addACLParams; | ||||||||
| objectMD.originOp = 's3:ObjectAcl:Put'; | ||||||||
|
|
||||||||
| // Use storageType to determine if replication update is needed, as it is set only for | ||||||||
| // "cloud" locations. This ensures that we reset replication when CRR is used, but not | ||||||||
| // when multi-backend replication (i.e. Zenko) is used. | ||||||||
| // TODO: this should be refactored to properly update the replication info, accounting | ||||||||
| // for multiple rules and resetting the status only if needed CLDSRV-646 | ||||||||
| // Rebuild replication info from the current bucket config to | ||||||||
| // pick up any new destinations. A "role" on the entry means | ||||||||
| // backbeat uses IAM role-based auth on the destination | ||||||||
| // (CRR). No role means credentials live in the location | ||||||||
| // configuration (cloud, including scality-to-scality via | ||||||||
| // stored S3 creds), and ACL replication is not supported — | ||||||||
| // preserve the existing status instead of resetting to | ||||||||
| // PENDING. | ||||||||
| const hasDestRole = b => !!b.role; | ||||||||
|
|
||||||||
| const replicationInfo = getReplicationInfo(config, objectKey, bucket, true); | ||||||||
| if (replicationInfo && !replicationInfo.storageType) { | ||||||||
| if (replicationInfo && replicationInfo.backends.some(hasDestRole)) { | ||||||||
| const backends = replicationInfo.backends.map(b => { | ||||||||
| if (hasDestRole(b)) { | ||||||||
| return b; | ||||||||
| } | ||||||||
|
|
||||||||
| const existing = objectMD.replicationInfo.backends.find(e => e.site === b.site); | ||||||||
| return existing || b; | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this still adds a newly configured cloud backend on an ACL-only update if there is also a CRR backend.
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch, switched to dropping newly configured cloud backends instead of adding them as PENDING, and matching existing entries by site + destination + role rather than site alone. |
||||||||
| }); | ||||||||
|
|
||||||||
| objectMD.replicationInfo = { | ||||||||
| ...objectMD.replicationInfo, | ||||||||
| ...replicationInfo, | ||||||||
| backends, | ||||||||
| }; | ||||||||
| } | ||||||||
|
|
||||||||
|
|
@@ -77,14 +94,22 @@ const acl = { | |||||||
| }; | ||||||||
| let validCannedACL = []; | ||||||||
| if (resourceType === 'bucket') { | ||||||||
| validCannedACL = | ||||||||
| ['private', 'public-read', 'public-read-write', | ||||||||
| 'authenticated-read', 'log-delivery-write']; | ||||||||
| validCannedACL = [ | ||||||||
| 'private', | ||||||||
| 'public-read', | ||||||||
| 'public-read-write', | ||||||||
| 'authenticated-read', | ||||||||
| 'log-delivery-write', | ||||||||
| ]; | ||||||||
| } else if (resourceType === 'object') { | ||||||||
| validCannedACL = | ||||||||
| ['private', 'public-read', 'public-read-write', | ||||||||
| 'authenticated-read', 'bucket-owner-read', | ||||||||
| 'bucket-owner-full-control']; | ||||||||
| validCannedACL = [ | ||||||||
| 'private', | ||||||||
| 'public-read', | ||||||||
| 'public-read-write', | ||||||||
| 'authenticated-read', | ||||||||
| 'bucket-owner-read', | ||||||||
| 'bucket-owner-full-control', | ||||||||
| ]; | ||||||||
| } | ||||||||
|
|
||||||||
| // parse canned acl | ||||||||
|
|
@@ -98,45 +123,34 @@ const acl = { | |||||||
| } | ||||||||
|
|
||||||||
| // parse grant headers | ||||||||
| const grantReadHeader = | ||||||||
| aclUtils.parseGrant(headers['x-amz-grant-read'], 'READ'); | ||||||||
| const grantReadHeader = aclUtils.parseGrant(headers['x-amz-grant-read'], 'READ'); | ||||||||
| let grantWriteHeader = []; | ||||||||
| if (resourceType === 'bucket') { | ||||||||
| grantWriteHeader = aclUtils | ||||||||
| .parseGrant(headers['x-amz-grant-write'], 'WRITE'); | ||||||||
| grantWriteHeader = aclUtils.parseGrant(headers['x-amz-grant-write'], 'WRITE'); | ||||||||
| } | ||||||||
| const grantReadACPHeader = aclUtils | ||||||||
| .parseGrant(headers['x-amz-grant-read-acp'], 'READ_ACP'); | ||||||||
| const grantWriteACPHeader = aclUtils | ||||||||
| .parseGrant(headers['x-amz-grant-write-acp'], 'WRITE_ACP'); | ||||||||
| const grantFullControlHeader = aclUtils | ||||||||
| .parseGrant(headers['x-amz-grant-full-control'], 'FULL_CONTROL'); | ||||||||
| const allGrantHeaders = | ||||||||
| [].concat(grantReadHeader, grantWriteHeader, | ||||||||
| grantReadACPHeader, grantWriteACPHeader, | ||||||||
| grantFullControlHeader).filter(item => item !== undefined); | ||||||||
| const grantReadACPHeader = aclUtils.parseGrant(headers['x-amz-grant-read-acp'], 'READ_ACP'); | ||||||||
| const grantWriteACPHeader = aclUtils.parseGrant(headers['x-amz-grant-write-acp'], 'WRITE_ACP'); | ||||||||
| const grantFullControlHeader = aclUtils.parseGrant(headers['x-amz-grant-full-control'], 'FULL_CONTROL'); | ||||||||
| const allGrantHeaders = [] | ||||||||
| .concat(grantReadHeader, grantWriteHeader, grantReadACPHeader, grantWriteACPHeader, grantFullControlHeader) | ||||||||
| .filter(item => item !== undefined); | ||||||||
| if (allGrantHeaders.length === 0) { | ||||||||
| return cb(null, currentResourceACL); | ||||||||
| } | ||||||||
|
|
||||||||
| const usersIdentifiedByEmail = allGrantHeaders | ||||||||
| .filter(it => it && it.userIDType.toLowerCase() === 'emailaddress'); | ||||||||
| const usersIdentifiedByGroup = allGrantHeaders | ||||||||
| .filter(item => item && item.userIDType.toLowerCase() === 'uri'); | ||||||||
| const usersIdentifiedByEmail = allGrantHeaders.filter( | ||||||||
| it => it && it.userIDType.toLowerCase() === 'emailaddress', | ||||||||
| ); | ||||||||
| const usersIdentifiedByGroup = allGrantHeaders.filter(item => item && item.userIDType.toLowerCase() === 'uri'); | ||||||||
| const justEmails = usersIdentifiedByEmail.map(item => item.identifier); | ||||||||
| const validGroups = [ | ||||||||
| constants.allAuthedUsersId, | ||||||||
| constants.publicId, | ||||||||
| constants.logId, | ||||||||
| ]; | ||||||||
| const validGroups = [constants.allAuthedUsersId, constants.publicId, constants.logId]; | ||||||||
|
|
||||||||
| for (let i = 0; i < usersIdentifiedByGroup.length; i++) { | ||||||||
| if (validGroups.indexOf(usersIdentifiedByGroup[i].identifier) < 0) { | ||||||||
| return cb(errors.InvalidArgument); | ||||||||
| } | ||||||||
| } | ||||||||
| const usersIdentifiedByID = allGrantHeaders | ||||||||
| .filter(item => item && item.userIDType.toLowerCase() === 'id'); | ||||||||
| const usersIdentifiedByID = allGrantHeaders.filter(item => item && item.userIDType.toLowerCase() === 'id'); | ||||||||
| // TODO: Consider whether want to verify with Vault | ||||||||
| // whether canonicalID is associated with existing | ||||||||
| // account before adding to ACL | ||||||||
|
|
@@ -148,27 +162,26 @@ const acl = { | |||||||
| if (err) { | ||||||||
| return cb(err); | ||||||||
| } | ||||||||
| const reconstructedUsersIdentifiedByEmail = aclUtils. | ||||||||
| reconstructUsersIdentifiedByEmail(results, | ||||||||
| usersIdentifiedByEmail); | ||||||||
| const reconstructedUsersIdentifiedByEmail = aclUtils.reconstructUsersIdentifiedByEmail( | ||||||||
| results, | ||||||||
| usersIdentifiedByEmail, | ||||||||
| ); | ||||||||
| const allUsers = [].concat( | ||||||||
| reconstructedUsersIdentifiedByEmail, | ||||||||
| usersIdentifiedByGroup, | ||||||||
| usersIdentifiedByID); | ||||||||
| const revisedACL = | ||||||||
| aclUtils.sortHeaderGrants(allUsers, resourceACL); | ||||||||
| usersIdentifiedByID, | ||||||||
| ); | ||||||||
| const revisedACL = aclUtils.sortHeaderGrants(allUsers, resourceACL); | ||||||||
| return cb(null, revisedACL); | ||||||||
| }); | ||||||||
| } else { | ||||||||
| // If don't have to look up canonicalID's just sort grants | ||||||||
| // and add to bucket | ||||||||
| const revisedACL = aclUtils | ||||||||
| .sortHeaderGrants(allGrantHeaders, resourceACL); | ||||||||
| const revisedACL = aclUtils.sortHeaderGrants(allGrantHeaders, resourceACL); | ||||||||
| return cb(null, revisedACL); | ||||||||
| } | ||||||||
| return undefined; | ||||||||
| }, | ||||||||
| }; | ||||||||
|
|
||||||||
| module.exports = acl; | ||||||||
|
|
||||||||
Uh oh!
There was an error while loading. Please reload this page.