Compare commits

...

4 Commits

Author SHA1 Message Date
williamlardier f4894a6d6e
fix test 2023-07-11 10:09:16 +02:00
williamlardier 40a5498374
S3C-7845: support object retention days condition 2023-07-11 10:09:16 +02:00
williamlardier 3e68510093
update tests 2023-07-11 10:09:16 +02:00
williamlardier 068b8dabf1
return if implicit deny when evaluating policies 2023-07-11 10:09:12 +02:00
6 changed files with 122 additions and 24 deletions

View File

@ -36,6 +36,7 @@ export type ParsedRetention =
export default class ObjectLockConfiguration {
_parsedXml: any;
_config: Config;
_days: number | null;
/**
* Create an Object Lock Configuration instance
@ -45,6 +46,7 @@ export default class ObjectLockConfiguration {
constructor(xml: any) {
this._parsedXml = xml;
this._config = {};
this._days = null;
}
/**
@ -183,6 +185,8 @@ export default class ObjectLockConfiguration {
this._config.rule = {};
this._config.rule.mode = validMode.mode;
this._config.rule[validTime.timeType!] = validTime.timeValue;
// Store the number of days
this._days = validTime.timeType === 'years' ? 365 * validTime.timeValue : validTime.timeValue;
}
return validConfig;
}

View File

@ -171,6 +171,7 @@ export default class RequestContext {
_needTagEval: boolean;
_foundAction?: string;
_foundResource?: string;
_objectLockRetentionDays?: number | null;
constructor(
headers: { [key: string]: string | string[] },
@ -192,6 +193,7 @@ export default class RequestContext {
requestObjTags?: string,
existingObjTag?: string,
needTagEval?: false,
objectLockRetentionDays?: number,
) {
this._headers = headers;
this._query = query;
@ -224,6 +226,7 @@ export default class RequestContext {
this._requestObjTags = requestObjTags || null;
this._existingObjTag = existingObjTag || null;
this._needTagEval = needTagEval || false;
this._objectLockRetentionDays = objectLockRetentionDays || null;
return this;
}
@ -255,6 +258,7 @@ export default class RequestContext {
requestObjTags: this._requestObjTags,
existingObjTag: this._existingObjTag,
needTagEval: this._needTagEval,
objectLockRetentionDays: this._objectLockRetentionDays,
};
return JSON.stringify(requestInfo);
}
@ -295,6 +299,7 @@ export default class RequestContext {
obj.requestObjTags,
obj.existingObjTag,
obj.needTagEval,
obj.objectLockRetentionDays,
);
}
@ -698,4 +703,24 @@ export default class RequestContext {
getNeedTagEval() {
return this._needTagEval;
}
/**
* Get object lock retention days
*
* @returns objectLockRetentionDays - object lock retention days
*/
getObjectLockRetentionDays() {
return this._objectLockRetentionDays;
}
/**
* Set object lock retention days
*
* @param objectLockRetentionDays - object lock retention days
* @returns itself
*/
setObjectLockRetentionDays(objectLockRetentionDays: number) {
this._objectLockRetentionDays = objectLockRetentionDays;
return this;
}
}

View File

@ -324,7 +324,10 @@ export function evaluateAllPolicies(
requestContext: RequestContext,
allPolicies: any[],
log: Logger,
): string {
): {
verdict: string;
isImplicit: boolean;
} {
log.trace('evaluating all policies');
let allow = false;
let allowWithTagCondition = false;
@ -333,7 +336,10 @@ export function evaluateAllPolicies(
const singlePolicyVerdict = evaluatePolicy(requestContext, allPolicies[i], log);
// If there is any Deny, just return Deny
if (singlePolicyVerdict === 'Deny') {
return 'Deny';
return {
verdict: 'Deny',
isImplicit: false,
};
}
if (singlePolicyVerdict === 'Allow') {
allow = true;
@ -344,6 +350,7 @@ export function evaluateAllPolicies(
} // else 'Neutral'
}
let verdict;
let isImplicit = false;
if (allow) {
if (denyWithTagCondition) {
verdict = 'NeedTagConditionEval';
@ -355,8 +362,9 @@ export function evaluateAllPolicies(
verdict = 'NeedTagConditionEval';
} else {
verdict = 'Deny';
isImplicit = true;
}
}
log.trace('result of evaluating all policies', { verdict });
return verdict;
log.trace('result of evaluating all policies', { verdict, isImplicit });
return { verdict, isImplicit };
}

View File

@ -166,6 +166,9 @@ export function findConditionKey(
return requestContext.getNeedTagEval() && requestContext.getRequestObjTags()
? getTagKeys(requestContext.getRequestObjTags()!)
: undefined;
// The maximum retention period is 100 years.
case 's3:object-lock-remaining-retention-days':
return requestContext.getObjectLockRetentionDays() || undefined;
default:
return undefined;
}

View File

@ -1425,7 +1425,10 @@ describe('policyEvaluator', () => {
const result = evaluateAllPolicies(requestContext,
[samples['arn:aws:iam::aws:policy/AmazonS3FullAccess'],
samples['Deny Bucket Policy']], log);
assert.strictEqual(result, 'Deny');
assert.deepStrictEqual(result, {
verdict: 'Deny',
isImplicit: false,
});
});
it('should deny access if request action is not in any policy', () => {
@ -1436,7 +1439,10 @@ describe('policyEvaluator', () => {
const result = evaluateAllPolicies(requestContext,
[samples['Multi-Statement Policy'],
samples['Variable Bucket Policy']], log);
assert.strictEqual(result, 'Deny');
assert.deepStrictEqual(result, {
verdict: 'Deny',
isImplicit: true,
});
});
it('should deny access if request resource is not in any policy', () => {
@ -1448,7 +1454,10 @@ describe('policyEvaluator', () => {
samples['Multi-Statement Policy'],
samples['Variable Bucket Policy'],
], log);
assert.strictEqual(result, 'Deny');
assert.deepStrictEqual(result, {
verdict: 'Deny',
isImplicit: true,
});
});
const TestMatrixPolicies = {
@ -1507,67 +1516,115 @@ describe('policyEvaluator', () => {
const TestMatrix = [
{
policiesToEvaluate: [],
expectedPolicyEvaluation: 'Deny',
expectedPolicyEvaluation: {
verdict: 'Deny',
isImplicit: true,
},
},
{
policiesToEvaluate: ['Allow'],
expectedPolicyEvaluation: 'Allow',
expectedPolicyEvaluation: {
verdict: 'Allow',
isImplicit: false,
},
},
{
policiesToEvaluate: ['Neutral'],
expectedPolicyEvaluation: 'Deny',
expectedPolicyEvaluation: {
verdict: 'Deny',
isImplicit: true,
},
},
{
policiesToEvaluate: ['Deny'],
expectedPolicyEvaluation: 'Deny',
expectedPolicyEvaluation: {
verdict: 'Deny',
isImplicit: false,
},
},
{
policiesToEvaluate: ['Allow', 'Allow'],
expectedPolicyEvaluation: 'Allow',
expectedPolicyEvaluation: {
verdict: 'Allow',
isImplicit: false,
},
},
{
policiesToEvaluate: ['Allow', 'Neutral'],
expectedPolicyEvaluation: 'Allow',
expectedPolicyEvaluation: {
verdict: 'Allow',
isImplicit: false,
},
},
{
policiesToEvaluate: ['Neutral', 'Allow'],
expectedPolicyEvaluation: 'Allow',
expectedPolicyEvaluation: {
verdict: 'Allow',
isImplicit: false,
},
},
{
policiesToEvaluate: ['Neutral', 'Neutral'],
expectedPolicyEvaluation: 'Deny',
expectedPolicyEvaluation: {
verdict: 'Deny',
isImplicit: true,
},
},
{
policiesToEvaluate: ['Allow', 'Deny'],
expectedPolicyEvaluation: 'Deny',
expectedPolicyEvaluation: {
verdict: 'Deny',
isImplicit: false,
},
},
{
policiesToEvaluate: ['AllowWithTagCondition'],
expectedPolicyEvaluation: 'NeedTagConditionEval',
expectedPolicyEvaluation: {
verdict: 'NeedTagConditionEval',
isImplicit: false,
},
},
{
policiesToEvaluate: ['Allow', 'AllowWithTagCondition'],
expectedPolicyEvaluation: 'Allow',
expectedPolicyEvaluation: {
verdict: 'Allow',
isImplicit: false,
},
},
{
policiesToEvaluate: ['DenyWithTagCondition'],
expectedPolicyEvaluation: 'Deny',
expectedPolicyEvaluation: {
verdict: 'Deny',
isImplicit: true,
},
},
{
policiesToEvaluate: ['Allow', 'DenyWithTagCondition'],
expectedPolicyEvaluation: 'NeedTagConditionEval',
expectedPolicyEvaluation: {
verdict: 'NeedTagConditionEval',
isImplicit: false,
},
},
{
policiesToEvaluate: ['AllowWithTagCondition', 'DenyWithTagCondition'],
expectedPolicyEvaluation: 'NeedTagConditionEval',
expectedPolicyEvaluation: {
verdict: 'NeedTagConditionEval',
isImplicit: false,
},
},
{
policiesToEvaluate: ['AllowWithTagCondition', 'DenyWithTagCondition', 'Deny'],
expectedPolicyEvaluation: 'Deny',
expectedPolicyEvaluation: {
verdict: 'Deny',
isImplicit: false,
},
},
{
policiesToEvaluate: ['DenyWithTagCondition', 'AllowWithTagCondition', 'Allow'],
expectedPolicyEvaluation: 'NeedTagConditionEval',
expectedPolicyEvaluation: {
verdict: 'NeedTagConditionEval',
isImplicit: false,
},
},
];
@ -1582,7 +1639,7 @@ describe('policyEvaluator', () => {
requestContext,
testCase.policiesToEvaluate.map(policyName => TestMatrixPolicies[policyName]),
log);
assert.strictEqual(result, testCase.expectedPolicyEvaluation);
assert.deepStrictEqual(result, testCase.expectedPolicyEvaluation);
});
});
});

View File

@ -111,6 +111,7 @@ describe('RequestContext', () => {
specificResource: 'specific-resource',
sslEnabled: true,
tokenIssueTime: null,
objectLockRetentionDays: null,
};
it('serialize()', () => {
assert.deepStrictEqual(JSON.parse(rc.serialize()), SerializedFields);