Compare commits

...

1 Commits

Author SHA1 Message Date
Jonathan Gramain 4ef5cf3cf8 S3C-5884 wip 2022-08-01 16:06:42 -07:00
3 changed files with 28 additions and 37 deletions

View File

@ -166,7 +166,6 @@ export default class RequestContext {
_policyArn: string; _policyArn: string;
_action?: string; _action?: string;
_needQuota: boolean; _needQuota: boolean;
_postXml?: string;
_requestObjTags: string | null; _requestObjTags: string | null;
_existingObjTag: string | null; _existingObjTag: string | null;
_needTagEval: boolean; _needTagEval: boolean;
@ -190,7 +189,9 @@ export default class RequestContext {
securityToken: string, securityToken: string,
policyArn: string, policyArn: string,
action?: string, action?: string,
postXml?: string, requestObjTags?: string | null,
existingObjTag?: string | null,
needTagEval?: boolean,
) { ) {
this._headers = headers; this._headers = headers;
this._query = query; this._query = query;
@ -220,10 +221,9 @@ export default class RequestContext {
this._policyArn = policyArn; this._policyArn = policyArn;
this._action = action; this._action = action;
this._needQuota = _actionNeedQuotaCheck[apiMethod] === true; this._needQuota = _actionNeedQuotaCheck[apiMethod] === true;
this._postXml = postXml; this._requestObjTags = requestObjTags || null;
this._requestObjTags = null; this._existingObjTag = existingObjTag || null;
this._existingObjTag = null; this._needTagEval = needTagEval || false;
this._needTagEval = false;
return this; return this;
} }
@ -252,7 +252,6 @@ export default class RequestContext {
securityToken: this._securityToken, securityToken: this._securityToken,
policyArn: this._policyArn, policyArn: this._policyArn,
action: this._action, action: this._action,
postXml: this._postXml,
requestObjTags: this._requestObjTags, requestObjTags: this._requestObjTags,
existingObjTag: this._existingObjTag, existingObjTag: this._existingObjTag,
needTagEval: this._needTagEval, needTagEval: this._needTagEval,
@ -281,7 +280,7 @@ export default class RequestContext {
obj.apiMethod, obj.awsService, obj.locationConstraint, obj.apiMethod, obj.awsService, obj.locationConstraint,
obj.requesterInfo, obj.signatureVersion, obj.requesterInfo, obj.signatureVersion,
obj.authType, obj.signatureAge, obj.securityToken, obj.policyArn, obj.authType, obj.signatureAge, obj.securityToken, obj.policyArn,
obj.action, obj.postXml); obj.action, obj.requestObjTags, obj.existingObjTag, obj.needTagEval);
} }
/** /**
@ -625,26 +624,6 @@ export default class RequestContext {
return this._needQuota; return this._needQuota;
} }
/**
* Set request post
*
* @param postXml - request post
* @return itself
*/
setPostXml(postXml: string) {
this._postXml = postXml;
return this;
}
/**
* Get request post
*
* @return request post
*/
getPostXml() {
return this._postXml;
}
/** /**
* Set request object tags * Set request object tags
* *

View File

@ -13,7 +13,12 @@ const operatorsWithVariables = ['StringEquals', 'StringNotEquals',
const operatorsWithNegation = ['StringNotEquals', const operatorsWithNegation = ['StringNotEquals',
'StringNotEqualsIgnoreCase', 'StringNotLike', 'ArnNotEquals', 'StringNotEqualsIgnoreCase', 'StringNotLike', 'ArnNotEquals',
'ArnNotLike', 'NumericNotEquals']; 'ArnNotLike', 'NumericNotEquals'];
const tagConditions = new Set(['s3:ExistingObjectTag', 's3:RequestObjectTagKey', 's3:RequestObjectTagKeys']);
const tagConditions = new Set([
's3:ExistingObjectTag',
's3:RequestObjectTagKey',
's3:RequestObjectTagKeys',
]);
/** /**
@ -135,10 +140,6 @@ export const meetConditions = (
// Note: this should be the actual operator name, not the bareOperator // Note: this should be the actual operator name, not the bareOperator
const conditionsWithSameOperator = statementCondition[operator]; const conditionsWithSameOperator = statementCondition[operator];
const conditionKeys = Object.keys(conditionsWithSameOperator); const conditionKeys = Object.keys(conditionsWithSameOperator);
if (conditionKeys.some(key => tagConditions.has(key)) && !requestContext.getNeedTagEval()) {
// @ts-expect-error
conditionEval.tagConditions = true;
}
const conditionKeysLength = conditionKeys.length; const conditionKeysLength = conditionKeys.length;
for (let j = 0; j < conditionKeysLength; j++) { for (let j = 0; j < conditionKeysLength; j++) {
const key = conditionKeys[j]; const key = conditionKeys[j];
@ -155,6 +156,12 @@ export const meetConditions = (
// tag key is included in condition key and needs to be // tag key is included in condition key and needs to be
// moved to value for evaluation, otherwise key/value are unchanged // moved to value for evaluation, otherwise key/value are unchanged
const [transformedKey, transformedValue] = transformTagKeyValue(key, value); const [transformedKey, transformedValue] = transformTagKeyValue(key, value);
if (tagConditions.has(transformedKey) && !requestContext.getNeedTagEval()) {
log.info('tagConditions true', { requestContext, operator, transformedKey });
// @ts-expect-error
conditionEval.tagConditions = true;
continue;
}
// Pull key using requestContext // Pull key using requestContext
// TODO: If applicable to S3, handle policy set operations // TODO: If applicable to S3, handle policy set operations
// where a keyBasedOnRequestContext returns multiple values and // where a keyBasedOnRequestContext returns multiple values and
@ -171,6 +178,7 @@ export const meetConditions = (
'negation operator', { method: 'evaluators.evaluatePolicy' }); 'negation operator', { method: 'evaluators.evaluatePolicy' });
continue; continue;
} }
log.info('evaluator', { keyBasedOnRequestContext, transformedKey, bareOperator, transformedValue });
// If no IfExists qualifier, the key does not exist and the // If no IfExists qualifier, the key does not exist and the
// condition operator is not Null, the // condition operator is not Null, the
// condition is not met so return false. // condition is not met so return false.
@ -311,7 +319,10 @@ export const evaluateAllPolicies = (
if (singlePolicyVerdict === 'Allow') { if (singlePolicyVerdict === 'Allow') {
verdict = 'Allow'; verdict = 'Allow';
} }
if (verdict === 'Deny' && singlePolicyVerdict === 'NeedTagConditionEval') {
verdict = 'NeedTagConditionEval';
} }
log.trace('result of evaluating all pollicies', { verdict }); }
log.trace('result of evaluating all policies', { verdict });
return verdict; return verdict;
}; };

View File

@ -6,13 +6,14 @@
*/ */
export function transformTagKeyValue(key: string, value: string): [string, string | string[]] { export function transformTagKeyValue(key: string, value: string): [string, string | string[]] {
const patternKeys = ['s3:ExistingObjectTag/', 's3:RequestObjectTagKey/']; const patternKeys = ['s3:ExistingObjectTag/', 's3:RequestObjectTagKey/'];
if (!patternKeys.some(k => key.includes(k))) { if (!patternKeys.some(k => key.startsWith(k))) {
return [key, value]; return [key, value];
} }
// if key is RequestObjectTag or ExistingObjectTag, // if key is RequestObjectTag or ExistingObjectTag,
// remove tag key from condition key and add to value // remove tag key from condition key and add to value
// and transform value into query string // and transform value into query string
const [conditionKey, tagKey] = key.split('/'); const slashIndex = key.indexOf('/');
const [conditionKey, tagKey] = [key.slice(0, slashIndex), key.slice(slashIndex + 1)];
const transformedValue = [tagKey, value].join('='); const transformedValue = [tagKey, value].join('=');
return [conditionKey, [transformedValue]]; return [conditionKey, [transformedValue]];
} }