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;
_action?: string;
_needQuota: boolean;
_postXml?: string;
_requestObjTags: string | null;
_existingObjTag: string | null;
_needTagEval: boolean;
@ -190,7 +189,9 @@ export default class RequestContext {
securityToken: string,
policyArn: string,
action?: string,
postXml?: string,
requestObjTags?: string | null,
existingObjTag?: string | null,
needTagEval?: boolean,
) {
this._headers = headers;
this._query = query;
@ -220,10 +221,9 @@ export default class RequestContext {
this._policyArn = policyArn;
this._action = action;
this._needQuota = _actionNeedQuotaCheck[apiMethod] === true;
this._postXml = postXml;
this._requestObjTags = null;
this._existingObjTag = null;
this._needTagEval = false;
this._requestObjTags = requestObjTags || null;
this._existingObjTag = existingObjTag || null;
this._needTagEval = needTagEval || false;
return this;
}
@ -252,7 +252,6 @@ export default class RequestContext {
securityToken: this._securityToken,
policyArn: this._policyArn,
action: this._action,
postXml: this._postXml,
requestObjTags: this._requestObjTags,
existingObjTag: this._existingObjTag,
needTagEval: this._needTagEval,
@ -281,7 +280,7 @@ export default class RequestContext {
obj.apiMethod, obj.awsService, obj.locationConstraint,
obj.requesterInfo, obj.signatureVersion,
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;
}
/**
* 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
*

View File

@ -13,7 +13,12 @@ const operatorsWithVariables = ['StringEquals', 'StringNotEquals',
const operatorsWithNegation = ['StringNotEquals',
'StringNotEqualsIgnoreCase', 'StringNotLike', 'ArnNotEquals',
'ArnNotLike', 'NumericNotEquals'];
const tagConditions = new Set(['s3:ExistingObjectTag', 's3:RequestObjectTagKey', 's3:RequestObjectTagKeys']);
const tagConditions = new Set([
's3:ExistingObjectTag',
's3:RequestObjectTagKey',
's3:RequestObjectTagKeys',
]);
/**
@ -128,17 +133,13 @@ export const meetConditions = (
[prefix, bareOperator] = bareOperator.split(':');
}
const operatorCanHaveVariables =
operatorsWithVariables.indexOf(bareOperator) > -1;
operatorsWithVariables.indexOf(bareOperator) > -1;
const isNegationOperator =
operatorsWithNegation.indexOf(bareOperator) > -1;
// Loop through conditions with the same operator
// Note: this should be the actual operator name, not the bareOperator
const conditionsWithSameOperator = statementCondition[operator];
const conditionKeys = Object.keys(conditionsWithSameOperator);
if (conditionKeys.some(key => tagConditions.has(key)) && !requestContext.getNeedTagEval()) {
// @ts-expect-error
conditionEval.tagConditions = true;
}
const conditionKeysLength = conditionKeys.length;
for (let j = 0; j < conditionKeysLength; j++) {
const key = conditionKeys[j];
@ -155,6 +156,12 @@ export const meetConditions = (
// tag key is included in condition key and needs to be
// moved to value for evaluation, otherwise key/value are unchanged
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
// TODO: If applicable to S3, handle policy set operations
// where a keyBasedOnRequestContext returns multiple values and
@ -171,6 +178,7 @@ export const meetConditions = (
'negation operator', { method: 'evaluators.evaluatePolicy' });
continue;
}
log.info('evaluator', { keyBasedOnRequestContext, transformedKey, bareOperator, transformedValue });
// If no IfExists qualifier, the key does not exist and the
// condition operator is not Null, the
// condition is not met so return false.
@ -311,7 +319,10 @@ export const evaluateAllPolicies = (
if (singlePolicyVerdict === '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;
};

View File

@ -6,13 +6,14 @@
*/
export function transformTagKeyValue(key: string, value: string): [string, string | string[]] {
const patternKeys = ['s3:ExistingObjectTag/', 's3:RequestObjectTagKey/'];
if (!patternKeys.some(k => key.includes(k))) {
if (!patternKeys.some(k => key.startsWith(k))) {
return [key, value];
}
// if key is RequestObjectTag or ExistingObjectTag,
// remove tag key from condition key and add to value
// 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('=');
return [conditionKey, [transformedValue]];
}