UNPKG

aws-lager

Version:

AWS Lambda / API Gateway / Endpoint Router

147 lines (133 loc) 4.6 kB
'use strict'; var _ = require('lodash'); var AWS = require('aws-sdk'); var Promise = require('bluebird'); var fs = require('fs'); var nameGenerator = require('./name_generator'); var policyHelperFn = require('./policy_helper'); AWS.config.apiVersions = { iam: '2010-05-08' }; /** * Constructor function * @param Object options */ var policyBuilder = function(options) { this.environment = options.environment; this.pathPrefix = '/' + (this.environment ? this.environment + '/' : ''); this.iam = new AWS.IAM(); this.policyHelper = policyHelperFn(this.iam); }; /* istanbul ignore next */ /** * Deploy all policies in a directory * @param String path * @return Promise */ policyBuilder.prototype.deployAll = function(path) { // Retrieve policy configuration directories var policyPaths = _.map(fs.readdirSync(path), function(dirName) { return path + '/' + dirName; }); // Run the functions in serie return Promise.mapSeries(policyPaths, this.deploy.bind(this)); }; /* istanbul ignore next */ /** * Deploy a policy configuration * @param String pathToPolicy * @return Promise */ policyBuilder.prototype.deploy = function(pathToPolicy) { var policyName = nameGenerator(pathToPolicy, this.environment); var policyDocument = fs.readFileSync(pathToPolicy).toString(); console.log(' * Deploying policy ' + policyName); var params = { PathPrefix: this.pathPrefix, OnlyAttached: false, Scope: 'Local' }; return this.policyHelper.getPolicyByName(policyName, params) .then(function(currentPolicy) { if (!currentPolicy) { // If the policy could not be found, create it console.log(' * The policy does not exist yet'); var params = { PolicyDocument: policyDocument, PolicyName: policyName, Description: 'Policy generated by LAGER', Path: this.pathPrefix }; return Promise.promisify(this.iam.createPolicy.bind(this.iam))(params); } else { // If the policy already exists, we update it if necessary console.log(' * The policy already exists'); var params = { PolicyArn: currentPolicy.Arn, VersionId: currentPolicy.DefaultVersionId }; return Promise.promisify(this.iam.getPolicyVersion.bind(this.iam))(params) .then(function(data) { if (unescape(data.PolicyVersion.Document) === policyDocument) { console.log(' * The policy is already up-to-date'); return Promise.resolve(currentPolicy); } else { console.log(' * The policy must be updated'); return this.updatePolicy(currentPolicy.Arn, policyDocument); } }); } }.bind(this)); }; /** * Update a policy taking car of the limit of 5 versions * Deletes the version that has the smallest ID and is not set as default * @param String policyArn * @param String policyDocument * @return Promise */ policyBuilder.prototype.updatePolicy = function(policyArn, policyDocument) { return Promise.promisify(this.iam.listPolicyVersions.bind(this.iam))({ PolicyArn: policyArn }) .then(function(data) { if (data.Versions.length < 5) { // If the policy has less than 5 versions, we can create a new version return this.createPolicyVersion(policyArn, policyDocument); } else { // If the policy already has 5 versions, we have to delete the oldest one // Look for the smallest version number console.log(' * 5 versions exist already'); var minVersion = _.reduce(data.Versions, function(result, value, key) { if (value.IsDefaultVersion || value.VersionId > result) { return result; } return value.VersionId; }, Infinity); console.log(' * Deleting version ' + minVersion); var params = { PolicyArn: policyArn, VersionId: minVersion }; return Promise.promisify(this.iam.deletePolicyVersion.bind(this.iam))(params) .then(function() { return this.createPolicyVersion(policyArn, policyDocument); }); } }); }; /** * Create a policy version * @param String policyArn * @param String policyDocument * @return Promise */ policyBuilder.prototype.createPolicyVersion = function(policyArn, policyDocument) { // @TODO We should SetAsDefault only once the deployment is performed console.log(' * Creating a new version'); var params = { PolicyArn: policyArn, PolicyDocument: policyDocument, SetAsDefault: true }; return Promise.promisify(this.iam.createPolicyVersion.bind(this.iam))(params); }; module.exports = policyBuilder;