Instantly share code, notes, and snippets.
Created
August 8, 2017 09:25
-
Star
(1)
1
You must be signed in to star a gist -
Fork
(0)
0
You must be signed in to fork a gist
-
Save ravituvar/b309c3ce43c2822e9f14e7711f225315 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const jwt = require('jsonwebtoken'); | |
const region = 'us-east-1'; | |
exports.handler = function(event, context) { | |
jwt.verify(event.authorizationToken, secret, function(err, payload) { | |
if(err) { | |
context.fail("Unauthorized"); | |
} else { | |
var principalId = payload.sub; | |
var apiOptions = {}; | |
var tmp = event.methodArn.split(':'); | |
var apiGatewayArnTmp = tmp[5].split('/'); | |
var awsAccountId = tmp[4]; | |
apiOptions.region = tmp[3]; | |
apiOptions.restApiId = apiGatewayArnTmp[0]; | |
apiOptions.stage = apiGatewayArnTmp[1]; | |
var method = apiGatewayArnTmp[2]; | |
var resource = '/'; | |
if (apiGatewayArnTmp[3]) { | |
resource += apiGatewayArnTmp[3]; | |
} | |
var policy = new AuthPolicy(principalId, awsAccountId, apiOptions); | |
policy.allowAllMethods(); | |
context.succeed(policy.build()); | |
} | |
}); | |
}; | |
function AuthPolicy(principal, awsAccountId, apiOptions) { | |
this.awsAccountId = awsAccountId; | |
this.principalId = principal; | |
this.version = "2012-10-17"; | |
this.pathRegex = new RegExp('^[/.a-zA-Z0-9-\*]+$'); | |
this.allowMethods = []; | |
this.denyMethods = []; | |
if (!apiOptions || !apiOptions.restApiId) { | |
this.restApiId = "*"; | |
} else { | |
this.restApiId = apiOptions.restApiId; | |
} | |
if (!apiOptions || !apiOptions.region) { | |
this.region = "*"; | |
} else { | |
this.region = apiOptions.region; | |
} | |
if (!apiOptions || !apiOptions.stage) { | |
this.stage = "*"; | |
} else { | |
this.stage = apiOptions.stage; | |
} | |
}; | |
AuthPolicy.HttpVerb = { | |
GET : "GET", | |
POST : "POST", | |
PUT : "PUT", | |
PATCH : "PATCH", | |
HEAD : "HEAD", | |
DELETE : "DELETE", | |
OPTIONS : "OPTIONS", | |
ALL : "*" | |
}; | |
AuthPolicy.prototype = (function() { | |
var addMethod = function(effect, verb, resource, conditions) { | |
if (verb != "*" && !AuthPolicy.HttpVerb.hasOwnProperty(verb)) { | |
throw new Error("Invalid HTTP verb " + verb + ". Allowed verbs in AuthPolicy.HttpVerb"); | |
} | |
if (!this.pathRegex.test(resource)) { | |
throw new Error("Invalid resource path: " + resource + ". Path should match " + this.pathRegex); | |
} | |
var cleanedResource = resource; | |
if (resource.substring(0, 1) == "/") { | |
cleanedResource = resource.substring(1, resource.length); | |
} | |
var resourceArn = "arn:aws:execute-api:" + | |
this.region + ":" + | |
this.awsAccountId + ":" + | |
this.restApiId + "/" + | |
this.stage + "/" + | |
verb + "/" + | |
cleanedResource; | |
if (effect.toLowerCase() == "allow") { | |
this.allowMethods.push({ | |
resourceArn: resourceArn, | |
conditions: conditions | |
}); | |
} else if (effect.toLowerCase() == "deny") { | |
this.denyMethods.push({ | |
resourceArn: resourceArn, | |
conditions: conditions | |
}) | |
} | |
}; | |
var getEmptyStatement = function(effect) { | |
effect = effect.substring(0, 1).toUpperCase() + effect.substring(1, effect.length).toLowerCase(); | |
var statement = {}; | |
statement.Action = "execute-api:Invoke"; | |
statement.Effect = effect; | |
statement.Resource = []; | |
return statement; | |
}; | |
var getStatementsForEffect = function(effect, methods) { | |
var statements = []; | |
if (methods.length > 0) { | |
var statement = getEmptyStatement(effect); | |
for (var i = 0; i < methods.length; i++) { | |
var curMethod = methods[i]; | |
if (curMethod.conditions === null || curMethod.conditions.length === 0) { | |
statement.Resource.push(curMethod.resourceArn); | |
} else { | |
var conditionalStatement = getEmptyStatement(effect); | |
conditionalStatement.Resource.push(curMethod.resourceArn); | |
conditionalStatement.Condition = curMethod.conditions; | |
statements.push(conditionalStatement); | |
} | |
} | |
if (statement.Resource !== null && statement.Resource.length > 0) { | |
statements.push(statement); | |
} | |
} | |
return statements; | |
}; | |
return { | |
constructor: AuthPolicy, | |
allowAllMethods: function() { | |
addMethod.call(this, "allow", "*", "*", null); | |
}, | |
denyAllMethods: function() { | |
addMethod.call(this, "deny", "*", "*", null); | |
}, | |
allowMethod: function(verb, resource) { | |
addMethod.call(this, "allow", verb, resource, null); | |
}, | |
denyMethod : function(verb, resource) { | |
addMethod.call(this, "deny", verb, resource, null); | |
}, | |
allowMethodWithConditions: function(verb, resource, conditions) { | |
addMethod.call(this, "allow", verb, resource, conditions); | |
}, | |
denyMethodWithConditions : function(verb, resource, conditions) { | |
addMethod.call(this, "deny", verb, resource, conditions); | |
}, | |
build: function() { | |
if ((!this.allowMethods || this.allowMethods.length === 0) && | |
(!this.denyMethods || this.denyMethods.length === 0)) { | |
throw new Error("No statements defined for the policy"); | |
} | |
var policy = {}; | |
policy.principalId = this.principalId; | |
var doc = {}; | |
doc.Version = this.version; | |
doc.Statement = []; | |
doc.Statement = doc.Statement.concat(getStatementsForEffect.call(this, "Allow", this.allowMethods)); | |
doc.Statement = doc.Statement.concat(getStatementsForEffect.call(this, "Deny", this.denyMethods)); | |
policy.policyDocument = doc; | |
return policy; | |
} | |
}; | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
var https = require('https');
exports.handler = function (event, context) {
var options = {
hostname: process.env.AuthHostName,
port: process.env.AuthPort,
path: process.env.AuthPath,
headers: {
'Authorization': event.authorizationToken
}
};
https.get(options, function (result) {
if(result.statusCode==200){
var principalId = "AuthTokenPrincipal";
var apiOptions = {};
var tmp = event.methodArn.split(':');
var apiGatewayArnTmp = tmp[5].split('/');
var awsAccountId = tmp[4];
apiOptions.region = tmp[3];
apiOptions.restApiId = apiGatewayArnTmp[0];
apiOptions.stage = apiGatewayArnTmp[1];
var method = apiGatewayArnTmp[2];
var resource = '/';
if (apiGatewayArnTmp[3]) {
resource += apiGatewayArnTmp[3];
}
var policy = new AuthPolicy(principalId, awsAccountId, apiOptions);
policy.allowAllMethods();
context.succeed(policy.build());
}else{
context.fail("Unauthorized");
}
}).on('error', function (err) {
context.fail("Unauthorized");
});
};
function AuthPolicy(principal, awsAccountId, apiOptions) {
this.awsAccountId = awsAccountId;
this.principalId = principal;
this.version = "2012-10-17";
this.pathRegex = new RegExp('^[/.a-zA-Z0-9-*]+$');
this.allowMethods = [];
this.denyMethods = [];
};
AuthPolicy.HttpVerb = {
GET: "GET",
POST: "POST",
PUT: "PUT",
PATCH: "PATCH",
HEAD: "HEAD",
DELETE: "DELETE",
OPTIONS: "OPTIONS",
ALL: "*"
};
AuthPolicy.prototype = (function () {
var addMethod = function (effect, verb, resource, conditions) {
if (verb != "*" && !AuthPolicy.HttpVerb.hasOwnProperty(verb)) {
throw new Error("Invalid HTTP verb " + verb + ". Allowed verbs in AuthPolicy.HttpVerb");
}
})();