Compare commits
1 Commits
developmen
...
dev/ft/use
Author | SHA1 | Date |
---|---|---|
Rahul Padigela | 2c2626132d |
|
@ -293,13 +293,13 @@
|
|||
"description": "The request signature we calculated does not match the signature you provided."
|
||||
},
|
||||
"_comment" : {
|
||||
"note" : "This is an AWS S3 specific error. We are opting to use the more general 'ServiceUnavailable' error used throughout AWS (IAM/EC2) to have uniformity of error messages even though we are potentially compromising S3 compatibility.",
|
||||
"note" : "This is an AWS S3 specific error. We are opting to use the more general 'ServiceUnavailable' error used throughout AWS (IAM/EC2) to have uniformity of error messages even though we are potentially compromising S3 compatibility.",
|
||||
"ServiceUnavailable": {
|
||||
"code": 503,
|
||||
"description": "Reduce your request rate."
|
||||
}
|
||||
},
|
||||
"ServiceUnavailable": {
|
||||
"ServiceUnavailable": {
|
||||
"code": 503,
|
||||
"description": "The request has failed due to a temporary failure of the server."
|
||||
},
|
||||
|
@ -550,7 +550,7 @@
|
|||
"SecretKeyDoesNotExist": {
|
||||
"description": "secret key does not exist",
|
||||
"code": 5030
|
||||
},
|
||||
},
|
||||
"InvalidRegion": {
|
||||
"description": "Region was not provided or is not recognized by the system",
|
||||
"code": 5031
|
||||
|
@ -583,15 +583,15 @@
|
|||
"BadUrl": {
|
||||
"description": "url not ok",
|
||||
"code": 5038
|
||||
},
|
||||
},
|
||||
"BadClientIdList": {
|
||||
"description": "client id list not ok'",
|
||||
"code": 5039
|
||||
},
|
||||
},
|
||||
"BadThumbprintList": {
|
||||
"description": "thumbprint list not ok'",
|
||||
"code": 5040
|
||||
},
|
||||
},
|
||||
"BadObject": {
|
||||
"description": "Object not ok'",
|
||||
"code": 5041
|
||||
|
@ -600,12 +600,12 @@
|
|||
"BadRole": {
|
||||
"description": "role not ok",
|
||||
"code": 5042
|
||||
},
|
||||
},
|
||||
"_comment": "#### SamlpErrors ####",
|
||||
"BadSamlp": {
|
||||
"description": "samlp not ok",
|
||||
"code": 5043
|
||||
},
|
||||
},
|
||||
"BadMetadataDocument": {
|
||||
"description": "metadata document not ok",
|
||||
"code": 5044
|
||||
|
@ -671,5 +671,46 @@
|
|||
"NotEnoughMapsInConfig:": {
|
||||
"description": "NotEnoughMapsInConfig",
|
||||
"code": 400
|
||||
}
|
||||
},
|
||||
"_comment": "--------------------- Policies ---------------------",
|
||||
"InvalidPolicyJSON": {
|
||||
"description": "Policy contains JSON errors",
|
||||
"code": 400
|
||||
},
|
||||
"InvalidPolicyVersion": {
|
||||
"description": "Version field must be a valid string",
|
||||
"code": 400
|
||||
},
|
||||
"InvalidPolicyEffect": {
|
||||
"description": "Invalid value for Effect",
|
||||
"code": 400
|
||||
},
|
||||
"InvalidPolicyAction": {
|
||||
"description": "Invalid service prefix for Action",
|
||||
"code": 400
|
||||
},
|
||||
"InvalidPolicyResource": {
|
||||
"description": "Invalid value for Resource",
|
||||
"code": 400
|
||||
},
|
||||
"MissingPolicyVersion": {
|
||||
"description": "Missing required field Version",
|
||||
"code": 400
|
||||
},
|
||||
"MissingPolicyStatement": {
|
||||
"description": "Missing required field Statement",
|
||||
"code": 400
|
||||
},
|
||||
"MissingPolicyAction": {
|
||||
"description": "Missing required field Action",
|
||||
"code": 400
|
||||
},
|
||||
"MissingPolicyEffect": {
|
||||
"description": "Missing required field Effect",
|
||||
"code": 400
|
||||
},
|
||||
"MissingPolicyResource": {
|
||||
"description": "Missing required field Resource",
|
||||
"code": 400
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
'use strict'; // eslint-disable-line strict
|
||||
|
||||
const Ajv = require('ajv');
|
||||
const userPolicySchema = require('./userPolicySchema');
|
||||
const errors = require('../errors');
|
||||
|
||||
const ajValidate = new Ajv({ allErrors: true });
|
||||
// compiles schema to functions and caches them for all cases
|
||||
const userPolicyValidate = ajValidate.compile(userPolicySchema);
|
||||
|
||||
// parse ajv errors and build list of erros
|
||||
function _parseErrors(ajvErrors) {
|
||||
let parsedErr;
|
||||
ajvErrors.some(err => {
|
||||
const resource = err.dataPath.replace('.', '');
|
||||
if (err.keyword === 'required' && err.params) {
|
||||
const field = err.params.missingProperty;
|
||||
if (field === 'Version') {
|
||||
parsedErr = errors.MissingPolicyVersion;
|
||||
} else if (field === 'Statement') {
|
||||
parsedErr = errors.MissingPolicyStatement;
|
||||
} else if (field === 'Action') {
|
||||
parsedErr = errors.MissingPolicyAction;
|
||||
} else if (field === 'Effect') {
|
||||
parsedErr = errors.MissingPolicyEffect;
|
||||
} else if (field === 'Resource') {
|
||||
parsedErr = errors.MissingPolicyResource;
|
||||
} else {
|
||||
parsedErr = errors.InvalidPolicyDocument;
|
||||
}
|
||||
} else if (err.keyword === 'minItems' && resource === 'Statement') {
|
||||
parsedErr = errors.InvalidPolicyStatement;
|
||||
} else if (err.keyword === 'pattern') {
|
||||
parsedErr = errors.InvalidPolicyDocument;
|
||||
} else if (err.keyword === 'type') {
|
||||
// skip if it's Statement as it does not have enough
|
||||
// error context
|
||||
if (resource === 'Version') {
|
||||
parsedErr = errors.PolicyInvalidVersion;
|
||||
}
|
||||
} else {
|
||||
parsedErr = errors.InvalidPolicyDocument;
|
||||
}
|
||||
return parsedErr instanceof Error;
|
||||
});
|
||||
return parsedErr;
|
||||
}
|
||||
|
||||
|
||||
// parse JSON safely without throwing an exception
|
||||
function _safeJSONParse(s) {
|
||||
let res;
|
||||
try {
|
||||
res = JSON.parse(s);
|
||||
} catch (e) {
|
||||
return e;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
// validates policy using the validation schema
|
||||
function _validatePolicy(type, policy) {
|
||||
if (type === 'user') {
|
||||
const parseRes = _safeJSONParse(policy);
|
||||
if (parseRes instanceof Error) {
|
||||
return { error: errors.PolicyInvalidJSON, valid: false };
|
||||
}
|
||||
userPolicyValidate(parseRes);
|
||||
if (userPolicyValidate.errors) {
|
||||
return { error: _parseErrors(userPolicyValidate.errors),
|
||||
valid: false };
|
||||
}
|
||||
return { error: null, valid: true };
|
||||
}
|
||||
// todo: add support for resource policies
|
||||
return { error: errors.NotImplemented, valid: false };
|
||||
}
|
||||
/**
|
||||
* @typedef ValidationResult
|
||||
* @type Object
|
||||
* @property {Array|null} error - list of validation errors or null
|
||||
* @property {Bool} valid - true/false depending on the validation result
|
||||
*/
|
||||
/**
|
||||
* Validates user policy
|
||||
* @param {String} policy - policy json
|
||||
* @returns {Object} - returns object with properties error and value
|
||||
* @returns {ValidationResult} - result of the validation
|
||||
*/
|
||||
function validateUserPolicy(policy) {
|
||||
return _validatePolicy('user', policy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates resource policy
|
||||
* @param {String} policy - policy json
|
||||
* @returns {Object} - returns object with properties error and value
|
||||
* @returns {ValidationResult} - result of the validation
|
||||
*/
|
||||
function validateResourcePolicy(policy) {
|
||||
return _validatePolicy('resource', policy);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
validateUserPolicy,
|
||||
validateResourcePolicy,
|
||||
};
|
|
@ -0,0 +1,401 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"type": "object",
|
||||
"title": "AWS Policy schema.",
|
||||
"description": "This schema describes user policy per AWS policy grammar rules",
|
||||
"definitions": {
|
||||
"actionItem": {
|
||||
"type": "string",
|
||||
"pattern": "^[^*:]+:([^:])+|^\\*{1}$"
|
||||
},
|
||||
"resourceItem": {
|
||||
"type": "string",
|
||||
"pattern": "^\\*|arn:aws(:(\\*{1}|[a-z0-9\\*\\-]{2,})*){2}:.*$"
|
||||
},
|
||||
"conditions": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"StringEquals": {
|
||||
"type": "object"
|
||||
},
|
||||
"StringNotEquals": {
|
||||
"type": "object"
|
||||
},
|
||||
"StringEqualsIgnoreCase": {
|
||||
"type": "object"
|
||||
},
|
||||
"StringNotEqualsIgnoreCase": {
|
||||
"type": "object"
|
||||
},
|
||||
"StringLike": {
|
||||
"type": "object"
|
||||
},
|
||||
"StringNotLike": {
|
||||
"type": "object"
|
||||
},
|
||||
"NumericEquals": {
|
||||
"type": "object"
|
||||
},
|
||||
"NumericNotEquals": {
|
||||
"type": "object"
|
||||
},
|
||||
"NumericLessThan": {
|
||||
"type": "object"
|
||||
},
|
||||
"NumericLessThanEquals": {
|
||||
"type": "object"
|
||||
},
|
||||
"NumericGreaterThan": {
|
||||
"type": "object"
|
||||
},
|
||||
"NumericGreaterThanEquals": {
|
||||
"type": "object"
|
||||
},
|
||||
"DateEquals": {
|
||||
"type": "object"
|
||||
},
|
||||
"DateNotEquals": {
|
||||
"type": "object"
|
||||
},
|
||||
"DateLessThan": {
|
||||
"type": "object"
|
||||
},
|
||||
"DateLessThanEquals": {
|
||||
"type": "object"
|
||||
},
|
||||
"DateGreaterThan": {
|
||||
"type": "object"
|
||||
},
|
||||
"DateGreaterThanEquals": {
|
||||
"type": "object"
|
||||
},
|
||||
"Bool": {
|
||||
"type": "object"
|
||||
},
|
||||
"BinaryEquals": {
|
||||
"type": "object"
|
||||
},
|
||||
"IpAddress": {
|
||||
"type": "object"
|
||||
},
|
||||
"NotIpAddress": {
|
||||
"type": "object"
|
||||
},
|
||||
"ArnEquals": {
|
||||
"type": "object"
|
||||
},
|
||||
"ArnNotEquals": {
|
||||
"type": "object"
|
||||
},
|
||||
"ArnLike": {
|
||||
"type": "object"
|
||||
},
|
||||
"ArnNotLike": {
|
||||
"type": "object"
|
||||
},
|
||||
"Null": {
|
||||
"type": "object"
|
||||
},
|
||||
"StringEqualsIfExists": {
|
||||
"type": "object"
|
||||
},
|
||||
"StringNotEqualsIfExists": {
|
||||
"type": "object"
|
||||
},
|
||||
"StringEqualsIgnoreCaseIfExists": {
|
||||
"type": "object"
|
||||
},
|
||||
"StringNotEqualsIgnoreCaseIfExists": {
|
||||
"type": "object"
|
||||
},
|
||||
"StringLikeIfExists": {
|
||||
"type": "object"
|
||||
},
|
||||
"StringNotLikeIfExists": {
|
||||
"type": "object"
|
||||
},
|
||||
"NumericEqualsIfExists": {
|
||||
"type": "object"
|
||||
},
|
||||
"NumericNotEqualsIfExists": {
|
||||
"type": "object"
|
||||
},
|
||||
"NumericLessThanIfExists": {
|
||||
"type": "object"
|
||||
},
|
||||
"NumericLessThanEqualsIfExists": {
|
||||
"type": "object"
|
||||
},
|
||||
"NumericGreaterThanIfExists": {
|
||||
"type": "object"
|
||||
},
|
||||
"NumericGreaterThanEqualsIfExists": {
|
||||
"type": "object"
|
||||
},
|
||||
"DateEqualsIfExists": {
|
||||
"type": "object"
|
||||
},
|
||||
"DateNotEqualsIfExists": {
|
||||
"type": "object"
|
||||
},
|
||||
"DateLessThanIfExists": {
|
||||
"type": "object"
|
||||
},
|
||||
"DateLessThanEqualsIfExists": {
|
||||
"type": "object"
|
||||
},
|
||||
"DateGreaterThanIfExists": {
|
||||
"type": "object"
|
||||
},
|
||||
"DateGreaterThanEqualsIfExists": {
|
||||
"type": "object"
|
||||
},
|
||||
"BoolIfExists": {
|
||||
"type": "object"
|
||||
},
|
||||
"BinaryEqualsIfExists": {
|
||||
"type": "object"
|
||||
},
|
||||
"IpAddressIfExists": {
|
||||
"type": "object"
|
||||
},
|
||||
"NotIpAddressIfExists": {
|
||||
"type": "object"
|
||||
},
|
||||
"ArnEqualsIfExists": {
|
||||
"type": "object"
|
||||
},
|
||||
"ArnNotEqualsIfExists": {
|
||||
"type": "object"
|
||||
},
|
||||
"ArnLikeIfExists": {
|
||||
"type": "object"
|
||||
},
|
||||
"ArnNotLikeIfExists": {
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"Version": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"2012-10-17"
|
||||
]
|
||||
},
|
||||
"Statement": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": [
|
||||
"array"
|
||||
],
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"Sid": {
|
||||
"type": "string",
|
||||
"pattern": "[a-zA-Z0-9]+"
|
||||
},
|
||||
"Effect": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Allow",
|
||||
"Deny"
|
||||
]
|
||||
},
|
||||
"Action": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/definitions/actionItem"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/actionItem"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"NotAction": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/definitions/actionItem"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/actionItem"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"Resource": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/definitions/resourceItem"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/resourceItem"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"NotResource": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/definitions/resourceItem"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/resourceItem"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"Condition": {
|
||||
"$ref": "#/definitions/conditions"
|
||||
}
|
||||
},
|
||||
"oneOf": [
|
||||
{
|
||||
"required": [
|
||||
"Effect",
|
||||
"Action",
|
||||
"Resource"
|
||||
]
|
||||
}, {
|
||||
"required": [
|
||||
"Effect",
|
||||
"Action",
|
||||
"NotResource"
|
||||
]
|
||||
}, {
|
||||
"required": [
|
||||
"Effect",
|
||||
"NotAction",
|
||||
"Resource"
|
||||
]
|
||||
}, {
|
||||
"required": [
|
||||
"Effect",
|
||||
"NotAction",
|
||||
"NotResource"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": [
|
||||
"object"
|
||||
],
|
||||
"properties": {
|
||||
"Sid": {
|
||||
"type": "string",
|
||||
"pattern": "[a-zA-Z0-9]+"
|
||||
},
|
||||
"Effect": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Allow",
|
||||
"Deny"
|
||||
]
|
||||
},
|
||||
"Action": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/definitions/actionItem"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/actionItem"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"NotAction": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/definitions/actionItem"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/actionItem"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"Resource": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/definitions/resourceItem"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/resourceItem"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"NotResource": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/definitions/resourceItem"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/resourceItem"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"Condition": {
|
||||
"$ref": "#/definitions/conditions"
|
||||
}
|
||||
},
|
||||
"oneOf": [
|
||||
{
|
||||
"required": [
|
||||
"Action",
|
||||
"Effect",
|
||||
"Resource"
|
||||
]
|
||||
}, {
|
||||
"required": [
|
||||
"Action",
|
||||
"Effect",
|
||||
"NotResource"
|
||||
]
|
||||
}, {
|
||||
"required": [
|
||||
"Effect",
|
||||
"NotAction",
|
||||
"Resource"
|
||||
]
|
||||
}, {
|
||||
"required": [
|
||||
"Effect",
|
||||
"NotAction",
|
||||
"NotResource"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"Version",
|
||||
"Statement"
|
||||
]
|
||||
}
|
|
@ -10,10 +10,11 @@
|
|||
"author": "Giorgio Regni",
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/scality/Arsenal/issues"
|
||||
"url": "https://github.com/scality/Arsenal/issues"
|
||||
},
|
||||
"homepage": "https://github.com/scality/Arsenal#readme",
|
||||
"dependencies": {
|
||||
"ajv": "^4.1.3",
|
||||
"utf8": "~2.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -0,0 +1,240 @@
|
|||
'use strict'; // eslint-disable-line strict
|
||||
|
||||
const assert = require('assert');
|
||||
const policyValidator = require('../../../lib/policy/policyValidator');
|
||||
const errors = require('../../../lib/errors');
|
||||
const validateUserPolicy = policyValidator.validateUserPolicy;
|
||||
const successRes = { error: null, valid: true };
|
||||
const samplePolicy = {
|
||||
Version: '2012-10-17',
|
||||
Statement: {
|
||||
Sid: 'FooBar1234',
|
||||
Effect: 'Allow',
|
||||
Action: 's3:PutObject',
|
||||
Resource: 'arn:aws:s3:::my_bucket/uploads/widgetco/*',
|
||||
Condition: { NumericLessThanEquals: { 's3:max-keys': '10' } },
|
||||
},
|
||||
};
|
||||
let policy;
|
||||
|
||||
function failRes(error) {
|
||||
return { error, valid: false };
|
||||
}
|
||||
|
||||
function check(input, expected) {
|
||||
const result = validateUserPolicy(JSON.stringify(input));
|
||||
assert.deepStrictEqual(result, expected);
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
policy = JSON.parse(JSON.stringify(samplePolicy));
|
||||
});
|
||||
|
||||
describe('Policies validation - Invalid JSON', () => {
|
||||
it('should return error for invalid JSON', () => {
|
||||
const result = validateUserPolicy('{"Version":"2012-10-17",' +
|
||||
'"Statement":{"Effect":"Allow""Action":"s3:PutObject",' +
|
||||
'"Resource":"arn:aws:s3*"}}');
|
||||
assert.deepStrictEqual(result, failRes(errors.PolicyInvalidJSON));
|
||||
});
|
||||
});
|
||||
|
||||
describe('Policies validation - Version', () => {
|
||||
it('should validate with version date 2012-10-17', () => {
|
||||
check(policy, successRes);
|
||||
});
|
||||
|
||||
it('should return error for other dates', () => {
|
||||
policy.Version = '2012-11-17';
|
||||
check(policy, failRes(errors.InvalidPolicyDocument));
|
||||
});
|
||||
|
||||
it('should return error if Version field is missing', () => {
|
||||
policy.Version = undefined;
|
||||
check(policy, failRes(errors.MissingPolicyVersion));
|
||||
});
|
||||
});
|
||||
|
||||
describe('Policies validation - Statement', () => {
|
||||
it('should succeed for a valid object', () => {
|
||||
check(policy, successRes);
|
||||
});
|
||||
|
||||
it('should succeed for a valid array', () => {
|
||||
policy.Statement = [
|
||||
{
|
||||
Effect: 'Allow',
|
||||
Action: 's3:PutObject',
|
||||
Resource: 'arn:aws:s3:::my_bucket/uploads/widgetco/*',
|
||||
},
|
||||
{
|
||||
Effect: 'Deny',
|
||||
Action: 's3:DeleteObject',
|
||||
Resource: 'arn:aws:s3:::my_bucket/uploads/widgetco/*',
|
||||
},
|
||||
];
|
||||
check(policy, successRes);
|
||||
});
|
||||
|
||||
it('should return an error for undefined', () => {
|
||||
policy.Statement = undefined;
|
||||
check(policy, failRes(errors.MissingPolicyStatement));
|
||||
});
|
||||
|
||||
it('should return an error for an empty list', () => {
|
||||
policy.Statement = [];
|
||||
check(policy, failRes(errors.InvalidPolicyDocument));
|
||||
});
|
||||
|
||||
it('should return an error for an empty object', () => {
|
||||
policy.Statement = {};
|
||||
check(policy, failRes(errors.MissingPolicyAction));
|
||||
});
|
||||
|
||||
it('should return an error for missing a required field - Action', () => {
|
||||
delete policy.Statement.Action;
|
||||
check(policy, failRes(errors.MissingPolicyAction));
|
||||
});
|
||||
|
||||
it('should return an error for missing a required field - Effect', () => {
|
||||
delete policy.Statement.Effect;
|
||||
check(policy, failRes(errors.MissingPolicyEffect));
|
||||
});
|
||||
|
||||
it('should return an error for missing a required field - Resource', () => {
|
||||
delete policy.Statement.Resource;
|
||||
check(policy, failRes(errors.MissingPolicyResource));
|
||||
});
|
||||
|
||||
it('should return an error for missing multiple required fields', () => {
|
||||
delete policy.Statement.Effect;
|
||||
delete policy.Statement.Resource;
|
||||
check(policy, failRes(errors.MissingPolicyEffect));
|
||||
});
|
||||
|
||||
it('should succeed with optional fields missing - Sid, Condition', () => {
|
||||
delete policy.Statement.Sid;
|
||||
delete policy.Statement.Condition;
|
||||
check(policy, successRes);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Policies validation - Statement::Sid_block', () => {
|
||||
it('should succeed if Sid is any alphanumeric string', () => {
|
||||
check(policy, successRes);
|
||||
});
|
||||
|
||||
it('should fail if Sid is not a string', () => {
|
||||
policy.Statement.Sid = 1234;
|
||||
check(policy, failRes(errors.InvalidPolicyDocument));
|
||||
});
|
||||
});
|
||||
|
||||
describe('Policies validation - Statement::Effect_block', () => {
|
||||
it('should succeed for Allow', () => {
|
||||
check(policy, successRes);
|
||||
});
|
||||
|
||||
it('should succeed for Deny', () => {
|
||||
policy.Statement.Effect = 'Deny';
|
||||
check(policy, successRes);
|
||||
});
|
||||
|
||||
it('should fail for strings other than Allow/Deny', () => {
|
||||
policy.Statement.Effect = 'Reject';
|
||||
check(policy, failRes(errors.InvalidPolicyDocument));
|
||||
});
|
||||
|
||||
it('should fail if Effect is not a string', () => {
|
||||
policy.Statement.Effect = 1;
|
||||
check(policy, failRes(errors.InvalidPolicyDocument));
|
||||
});
|
||||
});
|
||||
|
||||
describe('Policies validation - Statement::Action_block', () => {
|
||||
it('should succeed for foo:bar', () => {
|
||||
policy.Statement.Action = 'foo:bar';
|
||||
check(policy, successRes);
|
||||
});
|
||||
|
||||
it('should succeed for foo:*', () => {
|
||||
policy.Statement.Action = 'foo:*';
|
||||
check(policy, successRes);
|
||||
});
|
||||
|
||||
it('should succeed for *', () => {
|
||||
policy.Statement.Action = '*';
|
||||
check(policy, successRes);
|
||||
});
|
||||
|
||||
it('should fail for **', () => {
|
||||
policy.Statement.Action = '**';
|
||||
check(policy, failRes(errors.InvalidPolicyDocument));
|
||||
});
|
||||
|
||||
it('should fail for foobar', () => {
|
||||
policy.Statement.Action = 'foobar';
|
||||
check(policy, failRes(errors.InvalidPolicyDocument));
|
||||
});
|
||||
});
|
||||
|
||||
describe('Policies validation - Statement::Resource_block', () => {
|
||||
it('should succeed for arn:aws:s3:::*', () => {
|
||||
policy.Statement.Resource = 'arn:aws:s3:::*';
|
||||
check(policy, successRes);
|
||||
});
|
||||
|
||||
it('should succeed for arn:aws:s3:::test/home/${aws:username}', () => {
|
||||
policy.Statement.Resource = 'arn:aws:s3:::test/home/${aws:username}';
|
||||
check(policy, successRes);
|
||||
});
|
||||
|
||||
it('should succeed for arn:aws:ec2:us-west-1:1234qwerty:volume/*', () => {
|
||||
policy.Statement.Resource = 'arn:aws:ec2:us-west-1:1234qwerty:volume/*';
|
||||
check(policy, successRes);
|
||||
});
|
||||
|
||||
it('should succeed for *', () => {
|
||||
policy.Statement.Resource = '*';
|
||||
check(policy, successRes);
|
||||
});
|
||||
|
||||
it('should fail for ec2:us-west-1:1234qwerty:volume/*', () => {
|
||||
policy.Statement.Resource = 'ec2:us-west-1:1234qwerty:volume/*';
|
||||
check(policy, failRes(errors.InvalidPolicyDocument));
|
||||
});
|
||||
});
|
||||
|
||||
describe('Policies validation - Statement::Condition_block', () => {
|
||||
it('should succeed for single Condition', () => {
|
||||
check(policy, successRes);
|
||||
});
|
||||
|
||||
it('should succeed for multiple Conditions', () => {
|
||||
policy.Statement.Condition = {
|
||||
StringNotLike: { 's3:prefix': ['Development/*'] },
|
||||
Null: { 's3:prefix': false },
|
||||
};
|
||||
check(policy, successRes);
|
||||
});
|
||||
|
||||
it('should fail when Condition is not an Object', () => {
|
||||
policy.Statement.Condition = 'NumericLessThanEquals';
|
||||
check(policy, failRes(errors.InvalidPolicyDocument));
|
||||
});
|
||||
|
||||
it('should fail for an invalid Condition', () => {
|
||||
policy.Statement.Condition = {
|
||||
SomethingLike: { 's3:prefix': ['Development/*'] },
|
||||
};
|
||||
check(policy, failRes(errors.InvalidPolicyDocument));
|
||||
});
|
||||
|
||||
it('should fail when one of the multiple conditions is invalid', () => {
|
||||
policy.Statement.Condition = {
|
||||
Null: { 's3:prefix': false },
|
||||
SomethingLike: { 's3:prefix': ['Development/*'] },
|
||||
};
|
||||
check(policy, failRes(errors.InvalidPolicyDocument));
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue