Compare commits

...

4 Commits

Author SHA1 Message Date
Dora Korpar 0e595bc89f [quash] rework tagconditions func 2020-09-17 12:50:37 -07:00
Dora Korpar 0f382bf391 [squash] add all components 2020-09-17 01:36:56 -07:00
Dora Korpar d2c3202cbf ft: S3C-3177 policy tag condition keys 2020-09-16 02:42:04 -07:00
Dora Korpar bb85f98d90 ft: S3C-3177 tag iam policy condition keys 2020-09-04 12:24:04 -07:00
3 changed files with 125 additions and 18 deletions

View File

@ -60,6 +60,7 @@ const websiteHead = require('./websiteHead');
const writeContinue = require('../utilities/writeContinue'); const writeContinue = require('../utilities/writeContinue');
const validateQueryAndHeaders = require('../utilities/validateQueryAndHeaders'); const validateQueryAndHeaders = require('../utilities/validateQueryAndHeaders');
const parseCopySource = require('./apiUtils/object/parseCopySource'); const parseCopySource = require('./apiUtils/object/parseCopySource');
const tagConditionKeyAuth = require('./apiUtils/authorization/tagConditionKeys');
auth.setHandler(vault); auth.setHandler(vault);
@ -100,34 +101,35 @@ const api = {
log.trace('authentication error', { error: err }); log.trace('authentication error', { error: err });
return callback(err); return callback(err);
} }
if (authorizationResults) { function ifAuthResults(authResults) {
if (apiMethod === 'objectGet') { if (apiMethod === 'objectGet') {
// first item checks s3:GetObject(Version) action // first item checks s3:GetObject(Version) action
if (!authorizationResults[0].isAllowed) { if (!authResults[0].isAllowed) {
log.trace('get object authorization denial from Vault'); log.trace('get object authorization denial from Vault');
return callback(errors.AccessDenied); return callback(errors.AccessDenied);
} }
// second item checks s3:GetObject(Version)Tagging action // second item checks s3:GetObject(Version)Tagging action
if (!authorizationResults[1].isAllowed) { if (!authResults[1].isAllowed) {
log.trace('get tagging authorization denial ' + log.trace('get tagging authorization denial ' +
'from Vault'); 'from Vault');
returnTagCount = false; returnTagCount = false;
} }
} else { } else {
for (let i = 0; i < authorizationResults.length; i++) { for (let i = 0; i < authResults.length; i++) {
if (!authorizationResults[i].isAllowed) { if (!authResults[i].isAllowed) {
log.trace('authorization denial from Vault'); log.trace('authorization denial from Vault');
return callback(errors.AccessDenied); return callback(errors.AccessDenied);
} }
} }
} }
} }
if (authorizationResults) {
console.log(`\n\n!!!!!!!!!!auth results`);
ifAuthResults(authorizationResults);
}
// issue 100 Continue to the client // issue 100 Continue to the client
writeContinue(request, response); writeContinue(request, response);
if (apiMethod === 'objectPut' || apiMethod === 'objectPutPart') {
return this[apiMethod](userInfo, request, streamingV4Params,
log, callback);
}
const MAX_POST_LENGTH = request.method.toUpperCase() === 'POST' ? const MAX_POST_LENGTH = request.method.toUpperCase() === 'POST' ?
1024 * 1024 : 1024 * 1024 / 2; // 1 MB or 512 KB 1024 * 1024 : 1024 * 1024 / 2; // 1 MB or 512 KB
const post = []; const post = [];
@ -157,6 +159,21 @@ const api = {
// Convert array of post buffers into one string // Convert array of post buffers into one string
request.post = Buffer.concat(post, postLength).toString(); request.post = Buffer.concat(post, postLength).toString();
console.log(`\n\n--------auth results?????????? ${authorizationResults}`);
// IAM policy -Tag condition keys require information from CloudServer for evaluation
return tagConditionKeyAuth(authorizationResults, request, requestContexts, log,
(err, tagAuthResults) => {
if (err) {
log.trace('tag authentication error', { error: err });
return callback(err);
}
if (tagAuthResults) {
ifAuthResults(tagAuthResults);
}
if (apiMethod === 'objectPut' || apiMethod === 'objectPutPart') {
return this[apiMethod](userInfo, request, streamingV4Params,
log, callback);
}
if (apiMethod === 'objectCopy' || if (apiMethod === 'objectCopy' ||
apiMethod === 'objectPutCopyPart') { apiMethod === 'objectPutCopyPart') {
return this[apiMethod](userInfo, request, sourceBucket, return this[apiMethod](userInfo, request, sourceBucket,
@ -166,8 +183,11 @@ const api = {
return this[apiMethod](userInfo, request, return this[apiMethod](userInfo, request,
returnTagCount, log, callback); returnTagCount, log, callback);
} }
const util = require('util');
console.log(`\n\n------- request post in api method call:::::: ${util.inspect(request.post, false, null)}`);
return this[apiMethod](userInfo, request, log, callback); return this[apiMethod](userInfo, request, log, callback);
}); });
});
return undefined; return undefined;
}, 's3', requestContexts); }, 's3', requestContexts);
}, },

View File

@ -0,0 +1,83 @@
const async = require('async');
const { auth, s3middleware } = require('arsenal');
const metadata = require('../../../metadata/wrapper');
const { decodeVersionId } = require('../object/versioning');
const { parseTagXml } = s3middleware.tagging;
function makeTagQuery(tags) {
const tagsArray = Object.keys(tags);
tagsArray.map(t => `${t}=${tags[t]}`);
return tagsArray.join(',');
}
function updateRequestContexts(request, requestContexts, log, cb) {
requestContexts.forEach(rc => {
rc.setNeedTagEval(true);
async.series([
next => {
if (request.post) {
parseTagXml(request.post, log, (err, tags) => {
if (err) {
log.trace('error parsing request tags');
return next(err);
}
rc.setRequestObjTags(makeTagQuery(tags));
return next();
});
}
process.nextTick(() => next());
},
next => {
const objectKey = request.objectKey;
const bucketName = request.bucketName;
const decodedVidResult = decodeVersionId(request.query);
if (decodedVidResult instanceof Error) {
log.trace('invalid versionId query', {
versionId: request.query.versionId,
error: decodedVidResult,
});
return process.nextTick(() => next(decodedVidResult));
}
const reqVersionId = decodedVidResult;
return metadata.getObjectMD(bucketName, objectKey, { versionId: reqVersionId }, log,
(err, objMD) => {
if (err) {
log.trace('error getting request object tags');
return next(err);
}
const existingTags = objMD['x-amz-tagging'];
rc.setExistingObjTags(makeTagQuery(existingTags));
return next();
});
},
], err => {
if (err) {
log.trace('error processing tag condition key evaluation');
return cb(err);
}
return cb(null, requestContexts);
});
});
}
function tagConditionKeyAuth(authorizationResults, request, requestContexts, log, cb) {
if (!authorizationResults) {
return cb();
}
if (!authorizationResults.some(authRes => authRes.checkTagConditions)) {
return cb();
}
return updateRequestContexts(request, requestContexts, log, (err, updatedContexts) => {
if (err) {
return cb(err);
}
return auth.server.doAuth(request, log,
(err, userInfo, tagAuthResults) => cb(err, tagAuthResults), 's3', updatedContexts);
});
}
module.exports = tagConditionKeyAuth;

View File

@ -46,6 +46,8 @@ function objectPutTagging(authInfo, request, log, callback) {
versionId: reqVersionId, versionId: reqVersionId,
}; };
const util = require('util');
console.log(`\n\n------- REQUEST POST IN PUT OBJ TAGGING::::::::; ${util.inspect(request.post, false, null)}`);
return async.waterfall([ return async.waterfall([
next => metadataValidateBucketAndObj(metadataValParams, log, next => metadataValidateBucketAndObj(metadataValParams, log,
(err, bucket, objectMD) => { (err, bucket, objectMD) => {
@ -75,6 +77,8 @@ function objectPutTagging(authInfo, request, log, callback) {
}, },
(bucket, tags, objectMD, next) => { (bucket, tags, objectMD, next) => {
// eslint-disable-next-line no-param-reassign // eslint-disable-next-line no-param-reassign
const util = require('util');
console.log(`\n\n----------PARSED TAG XML::::: ${util.inspect(tags, false, null)}\n\n`);
objectMD.tags = tags; objectMD.tags = tags;
const params = objectMD.versionId ? { versionId: const params = objectMD.versionId ? { versionId:
objectMD.versionId } : {}; objectMD.versionId } : {};