Compare commits
3 Commits
developmen
...
fix/mapUsa
Author | SHA1 | Date |
---|---|---|
Rahul Padigela | 3f24a118c5 | |
Rahul Padigela | f2d2840e40 | |
Rahul Padigela | f018879a37 |
|
@ -4,6 +4,7 @@ const substituteVariables = require('./utils/variables.js');
|
|||
const handleWildcards = require('./utils/wildcards.js').handleWildcards;
|
||||
const conditions = require('./utils/conditions.js');
|
||||
const findConditionKey = conditions.findConditionKey;
|
||||
const setupConditionKey = conditions.setupConditionKey;
|
||||
const convertConditionOperator = conditions.convertConditionOperator;
|
||||
const checkArnMatch = require('./utils/checkArnMatch.js');
|
||||
|
||||
|
@ -103,6 +104,7 @@ function meetConditions(requestContext, statementCondition, log) {
|
|||
// operators as keys
|
||||
const operators = Object.keys(statementCondition);
|
||||
const length = operators.length;
|
||||
const map = setupConditionKey(requestContext);
|
||||
for (let i = 0; i < length; i ++) {
|
||||
const operator = operators[i];
|
||||
const hasIfExistsCondition = operator.endsWith('IfExists');
|
||||
|
@ -137,8 +139,7 @@ function meetConditions(requestContext, statementCondition, log) {
|
|||
// condition has "ForAnyValue" or "ForAllValues".
|
||||
// (see http://docs.aws.amazon.com/IAM/latest/UserGuide/
|
||||
// reference_policies_multi-value-conditions.html)
|
||||
const keyBasedOnRequestContext =
|
||||
findConditionKey(key, requestContext);
|
||||
const keyBasedOnRequestContext = findConditionKey(key, map);
|
||||
// Handle IfExists and negation operators
|
||||
if ((keyBasedOnRequestContext === undefined ||
|
||||
keyBasedOnRequestContext === null) &&
|
||||
|
|
|
@ -6,34 +6,28 @@ const handleWildcards = require('./wildcards.js').handleWildcards;
|
|||
const checkArnMatch = require('./checkArnMatch.js');
|
||||
const conditions = {};
|
||||
|
||||
/**
|
||||
* findConditionKey finds the value of a condition key based on requestContext
|
||||
* @param {string} key - condition key name
|
||||
* @param {RequestContext} requestContext - info sent with request
|
||||
* @return {string} condition key value
|
||||
*/
|
||||
conditions.findConditionKey = (key, requestContext) => {
|
||||
conditions.setupConditionKey = requestContext => {
|
||||
// TODO: Consider combining with findVariable function if no benefit
|
||||
// to keeping separate
|
||||
const headers = requestContext.getHeaders();
|
||||
const query = requestContext.getQuery();
|
||||
const requesterInfo = requestContext.getRequesterInfo();
|
||||
|
||||
const map = new Map();
|
||||
const map = {};
|
||||
// Possible AWS Condition keys (http://docs.aws.amazon.com/IAM/latest/
|
||||
// UserGuide/reference_policies_elements.html#AvailableKeys)
|
||||
|
||||
// aws:CurrentTime – Used for date/time conditions
|
||||
// (see Date Condition Operators).
|
||||
map.set('aws:CurrentTime', new Date().toISOString());
|
||||
map['aws:CurrentTime'] = new Date().toISOString();
|
||||
// aws:EpochTime – Used for date/time conditions
|
||||
// (see Date Condition Operators).
|
||||
map.set('aws:EpochTime', Date.now().toString());
|
||||
map['aws:EpochTime'] = Date.now().toString();
|
||||
// aws:TokenIssueTime – Date/time that temporary security
|
||||
// credentials were issued (see Date Condition Operators).
|
||||
// Only present in requests that are signed using temporary security
|
||||
// credentials.
|
||||
map.set('aws:TokenIssueTime', requestContext.getTokenIssueTime());
|
||||
map['aws:TokenIssueTime'] = requestContext.getTokenIssueTime();
|
||||
// aws:MultiFactorAuthPresent – Used to check whether MFA was used
|
||||
// (see Boolean Condition Operators).
|
||||
// Note: This key is only present if MFA was used. So, the following
|
||||
|
@ -43,104 +37,111 @@ conditions.findConditionKey = (key, requestContext) => {
|
|||
// Instead use:
|
||||
// "Condition" :
|
||||
// { "Null" : { "aws:MultiFactorAuthPresent" : true } }
|
||||
map.set('aws:MultiFactorAuthPresent',
|
||||
requestContext.getMultiFactorAuthPresent());
|
||||
map['aws:MultiFactorAuthPresent'] =
|
||||
requestContext.getMultiFactorAuthPresent();
|
||||
// aws:MultiFactorAuthAge – Used to check how many seconds since
|
||||
// MFA credentials were issued. If MFA was not used,
|
||||
// this key is not present
|
||||
map.set('aws:MultiFactorAuthAge', requestContext.getMultiFactorAuthAge());
|
||||
map['aws:MultiFactorAuthAge'] = requestContext.getMultiFactorAuthAge();
|
||||
// aws:principaltype states whether the principal is an account,
|
||||
// user, federated, or assumed role
|
||||
// Note: Docs for conditions have "PrincipalType" but simulator
|
||||
// and docs for variables have lowercase
|
||||
map.set('aws:principaltype', requesterInfo.principaltype);
|
||||
map['aws:principaltype'] = requesterInfo.principaltype;
|
||||
// aws:Referer – Used to check who referred the client browser to
|
||||
// the address the request is being sent to. Only supported by some
|
||||
// services, such as S3. Value comes from the referer header in the
|
||||
// HTTPS request made to AWS.
|
||||
map.set('aws:referer', headers.referer);
|
||||
map['aws:referer'] = headers.referer;
|
||||
// aws:SecureTransport – Used to check whether the request was sent
|
||||
// using SSL (see Boolean Condition Operators).
|
||||
map.set('aws:SecureTransport',
|
||||
requestContext.getSslEnabled() ? 'true' : 'false');
|
||||
map['aws:SecureTransport'] =
|
||||
requestContext.getSslEnabled() ? 'true' : 'false';
|
||||
// aws:SourceArn – Used check the source of the request,
|
||||
// using the ARN of the source. N/A here.
|
||||
map.set('aws:SourceArn', undefined);
|
||||
map['aws:SourceArn'] = undefined;
|
||||
// aws:SourceIp – Used to check the requester's IP address
|
||||
// (see IP Address Condition Operators)
|
||||
map.set('aws:SourceIp', requestContext.getRequesterIp());
|
||||
map['aws:SourceIp'] = requestContext.getRequesterIp();
|
||||
// aws:SourceVpc – Used to restrict access to a specific
|
||||
// AWS Virtual Private Cloud. N/A here.
|
||||
map.set('aws:SourceVpc', undefined);
|
||||
map['aws:SourceVpc'] = undefined;
|
||||
// aws:SourceVpce – Used to limit access to a specific VPC endpoint
|
||||
// N/A here
|
||||
map.set('aws:SourceVpce', undefined);
|
||||
map['aws:SourceVpce'] = undefined;
|
||||
// aws:UserAgent – Used to check the requester's client app.
|
||||
// (see String Condition Operators)
|
||||
map.set('aws:UserAgent', headers['user-agent']);
|
||||
map['aws:UserAgent'] = headers['user-agent'];
|
||||
// aws:userid – Used to check the requester's unique user ID.
|
||||
// (see String Condition Operators)
|
||||
map.set('aws:userid', requesterInfo.userid);
|
||||
map['aws:userid'] = requesterInfo.userid;
|
||||
// aws:username – Used to check the requester's friendly user name.
|
||||
// (see String Condition Operators)
|
||||
map.set('aws:username', requesterInfo.username);
|
||||
map['aws:username'] = requesterInfo.username;
|
||||
// Possible condition keys for S3:
|
||||
// s3:x-amz-acl is acl request for bucket or object put request
|
||||
map.set('s3:x-amz-acl', headers['x-amz-acl']);
|
||||
map['s3:x-amz-acl'] = headers['x-amz-acl'];
|
||||
// s3:x-amz-grant-PERMISSION (where permission can be:
|
||||
// read, write, read-acp, write-acp or full-control)
|
||||
// Value is the value of that header (ex. id of grantee)
|
||||
map.set('s3:x-amz-grant-read', headers['x-amz-grant-read']);
|
||||
map.set('s3:x-amz-grant-write', headers['x-amz-grant-write']);
|
||||
map.set('s3:x-amz-grant-read-acp', headers['x-amz-grant-read-acp']);
|
||||
map.set('s3:x-amz-grant-write-acp', headers['x-amz-grant-write-acp']);
|
||||
map.set('s3:x-amz-grant-full-control', headers['x-amz-grant-full-control']);
|
||||
map['s3:x-amz-grant-read'] = headers['x-amz-grant-read'];
|
||||
map['s3:x-amz-grant-write'] = headers['x-amz-grant-write'];
|
||||
map['s3:x-amz-grant-read-acp'] = headers['x-amz-grant-read-acp'];
|
||||
map['s3:x-amz-grant-write-acp'] = headers['x-amz-grant-write-acp'];
|
||||
map['s3:x-amz-grant-full-control'] = headers['x-amz-grant-full-control'];
|
||||
// s3:x-amz-copy-source is x-amz-copy-source header if applicable on
|
||||
// a put object
|
||||
map.set('s3:x-amz-copy-source', headers['x-amz-copy-source']);
|
||||
map['s3:x-amz-copy-source'] = headers['x-amz-copy-source'];
|
||||
// s3:x-amz-metadata-directive is x-amz-metadata-directive header if
|
||||
// applicable on a put object copy. Determines whether metadata will
|
||||
// be copied from original object or replaced. Values or "COPY" or
|
||||
// "REPLACE". Default is "COPY"
|
||||
map.set('s3:x-amz-metadata-directive', headers['metadata-directive']);
|
||||
map['s3:x-amz-metadata-directive'] = headers['metadata-directive'];
|
||||
// s3:x-amz-server-side-encryption -- Used to require that object put
|
||||
// use server side encryption. Value is the encryption algo such as
|
||||
// "AES256"
|
||||
map.set('s3:x-amz-server-side-encryption',
|
||||
headers['x-amz-server-side-encryption']);
|
||||
map['s3:x-amz-server-side-encryption'] =
|
||||
headers['x-amz-server-side-encryption'];
|
||||
// s3:x-amz-storage-class -- x-amz-storage-class header value
|
||||
// (STANDARD, etc.)
|
||||
map.set('s3:x-amz-storage-class', headers['x-amz-storage-class']);
|
||||
map['s3:x-amz-storage-class'] = headers['x-amz-storage-class'];
|
||||
// s3:VersionId -- version id of object
|
||||
map.set('s3:VersionId', headers['x-amz-version-id']);
|
||||
map['s3:VersionId'] = headers['x-amz-version-id'];
|
||||
// s3:LocationConstraint -- Used to restrict creation of bucket
|
||||
// in certain region. Only applicable for CreateBucket
|
||||
map.set('s3:LocationConstraint', requestContext.getLocationConstraint());
|
||||
map['s3:LocationConstraint'] = requestContext.getLocationConstraint();
|
||||
// s3:delimiter is delimiter for listing request
|
||||
map.set('s3:delimiter', query.delimiter);
|
||||
map['s3:delimiter'] = query.delimiter;
|
||||
// s3:max-keys is max-keys for listing request
|
||||
map.set('s3:max-keys', query['max-keys']);
|
||||
map['s3:max-keys'] = query['max-keys'];
|
||||
// s3:prefix is prefix for listing request
|
||||
map.set('s3:prefix', query.prefix);
|
||||
map['s3:prefix'] = query.prefix;
|
||||
// s3 auth v4 additional condition keys
|
||||
// (See http://docs.aws.amazon.com/AmazonS3/latest/API/
|
||||
// bucket-policy-s3-sigv4-conditions.html)
|
||||
// s3:signatureversion -- Either "AWS" for v2 or
|
||||
// "AWS4-HMAC-SHA256" for v4
|
||||
map.set('s3:signatureversion', requestContext.getSignatureVersion());
|
||||
map['s3:signatureversion'] = requestContext.getSignatureVersion();
|
||||
// s3:authType -- Method of authentication: either "REST-HEADER",
|
||||
// "REST-QUERY-STRING" or "POST"
|
||||
map.set('s3:authType', requestContext.getAuthType());
|
||||
map['s3:authType'] = requestContext.getAuthType();
|
||||
// s3:signatureAge is the length of time, in milliseconds,
|
||||
// that a signature is valid in an authenticated request. So,
|
||||
// can use this to limit the age to less than 7 days
|
||||
map.set('s3:signatureAge', requestContext.getSignatureAge());
|
||||
map['s3:signatureAge'] = requestContext.getSignatureAge();
|
||||
// s3:x-amz-content-sha256 - Valid value is "UNSIGNED-PAYLOAD"
|
||||
// so can use this in a deny policy to deny any requests that do not
|
||||
// have a signed payload
|
||||
map.set('s3:x-amz-content-sha256', headers['x-amz-content-sha256']);
|
||||
return map.get(key);
|
||||
map['s3:x-amz-content-sha256'] = headers['x-amz-content-sha256'];
|
||||
return map;
|
||||
};
|
||||
/**
|
||||
* findConditionKey finds the value of a condition key based on requestContext
|
||||
* @param {string} key - condition key name
|
||||
* @param {map} map - map object
|
||||
* @return {string} condition key value
|
||||
*/
|
||||
conditions.findConditionKey = (key, map) => map[key];
|
||||
|
||||
|
||||
// Wildcards are allowed in certain string comparison and arn comparisons
|
||||
|
|
|
@ -8,59 +8,62 @@
|
|||
// the string operators (StringEquals, StringLike, StringNotLike, etc.)
|
||||
// or the ARN operators (ArnEquals, ArnLike, etc.).
|
||||
|
||||
/**
|
||||
* findVariable finds the value of a variable based on the requestContext
|
||||
* @param {string} variable - variable name
|
||||
* @param {RequestContext} requestContext - info sent with request
|
||||
* @return {string} variable value
|
||||
*/
|
||||
function findVariable(variable, requestContext) {
|
||||
// See http://docs.aws.amazon.com/IAM/latest/UserGuide/
|
||||
// reference_policies_variables.html
|
||||
function setupVariable(requestContext) {
|
||||
const map = {};
|
||||
const headers = requestContext.getHeaders();
|
||||
const query = requestContext.getQuery();
|
||||
const requesterInfo = requestContext.getRequesterInfo();
|
||||
|
||||
const map = new Map();
|
||||
// HACK!! - this should be fixed properly
|
||||
const requesterInfo = requestContext.getRequesterInfo() || {};
|
||||
// aws:CurrentTime can be used for conditions
|
||||
// that check the date and time.
|
||||
map.set('aws:CurrentTime', new Date().toISOString());
|
||||
map['aws:CurrentTime'] = new Date().toISOString();
|
||||
// aws:EpochTime for use with date/time conditions
|
||||
map.set('aws:EpochTime', Date.now());
|
||||
map['aws:EpochTime'] = Date.now();
|
||||
// aws:TokenIssueTime is date and time that temp security credentials
|
||||
// were issued. can be used with date/time conditions.
|
||||
// this key is only available in requests that are signed using
|
||||
// temporary security credentials.
|
||||
map.set('aws:TokenIssueTime', requestContext.getTokenIssueTime());
|
||||
map['aws:TokenIssueTime'] = requestContext.getTokenIssueTime();
|
||||
// aws:principaltype states whether the principal is an account,
|
||||
// user, federated, or assumed role
|
||||
map.set('aws:principaltype', requesterInfo.principaltype);
|
||||
map['aws:principaltype'] = requesterInfo.principaltype;
|
||||
// aws:SecureTransport is boolean value that represents whether the
|
||||
// request was sent using SSL
|
||||
map.set('aws:SecureTransport',
|
||||
requestContext.getSslEnabled() ? 'true' : 'false');
|
||||
map['aws:SecureTransport'] =
|
||||
requestContext.getSslEnabled() ? 'true' : 'false';
|
||||
// aws:SourceIp is requester's IP address, for use with IP address
|
||||
// conditions
|
||||
map.set('aws:SourceIp', requestContext.getRequesterIp());
|
||||
map['aws:SourceIp'] = requestContext.getRequesterIp();
|
||||
// aws:UserAgent is information about the requester's client application
|
||||
map.set('aws:UserAgent', headers['user-agent']);
|
||||
map['aws:UserAgent'] = headers['user-agent'];
|
||||
// aws:userid is unique ID for the current user
|
||||
map.set('aws:userid', requesterInfo.userid);
|
||||
map['aws:userid'] = requesterInfo.userid;
|
||||
// aws:username is friendly name of the current user
|
||||
map.set('aws:username', requesterInfo.username);
|
||||
map['aws:username'] = requesterInfo.username;
|
||||
// ec2:SourceInstanceARN is the Amazon EC2 instance from which the
|
||||
// request was made. Present only when the request comes from an Amazon
|
||||
// EC2 instance using an IAM role associated with an EC2
|
||||
// instance profile. N/A here.
|
||||
map.set('ec2:SourceInstanceARN', undefined);
|
||||
map['ec2:SourceInstanceARN'] = undefined;
|
||||
// s3 - specific:
|
||||
// s3:prefix is prefix for listing request
|
||||
map.set('s3:prefix', query.prefix);
|
||||
map['s3:prefix'] = query.prefix;
|
||||
// s3:max-keys is max-keys for listing request
|
||||
map.set('s3:max-keys', query['max-keys']);
|
||||
map['s3:max-keys'] = query['max-keys'];
|
||||
// s3:x-amz-acl is acl request for bucket or object put request
|
||||
map.set('s3:x-amz-acl', query['x-amz-acl']);
|
||||
return map.get(variable);
|
||||
map['s3:x-amz-acl'] = query['x-amz-acl'];
|
||||
return map;
|
||||
}
|
||||
/**
|
||||
* findVariable finds the value of a variable based on the requestContext
|
||||
* @param {string} variable - variable name
|
||||
* @param {object} map - map object
|
||||
* @return {string} variable value
|
||||
*/
|
||||
function findVariable(variable, map) {
|
||||
// See http://docs.aws.amazon.com/IAM/latest/UserGuide/
|
||||
// reference_policies_variables.html
|
||||
return map[variable];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -73,6 +76,7 @@ function findVariable(variable, requestContext) {
|
|||
function substituteVariables(string, requestContext) {
|
||||
const arr = string.split('');
|
||||
let startOfVariable = arr.indexOf('$');
|
||||
const map = setupVariable(requestContext);
|
||||
while (startOfVariable > -1) {
|
||||
if (arr[startOfVariable + 1] !== '{') {
|
||||
startOfVariable = arr.indexOf('$', startOfVariable + 1);
|
||||
|
@ -89,7 +93,7 @@ function substituteVariables(string, requestContext) {
|
|||
// undefined, leave the original string '${whatever}'.
|
||||
// This also means that ${*}, ${?} and ${$} will remain as they are
|
||||
// here and will be converted as part of the wildcard transformation
|
||||
const value = findVariable(variableContent, requestContext);
|
||||
const value = findVariable(variableContent, map);
|
||||
// Length of item being replaced is the variable content plus ${}
|
||||
let replacingLength = variableContent.length + 3;
|
||||
if (value !== undefined) {
|
||||
|
|
Loading…
Reference in New Issue