diff --git a/src/guardian/index.js b/src/guardian/index.js index 2b165d24..e250b41a 100644 --- a/src/guardian/index.js +++ b/src/guardian/index.js @@ -1,6 +1,8 @@ -import NoDefaultMemory from './rules/best_practices/no-default-memory' import chalk from 'chalk'; +import NoDefaultMemory from './rules/best_practices/no-default-memory' +import { getStackResources } from "../services/stackResources"; + const infoLog = chalk.greenBright; const titleLog = chalk.greenBright.underline.bold; const fail = chalk.redBright; @@ -19,7 +21,48 @@ class GuardianCI { } this.AWS = AWS; this.stackName = stackName; + this.checksToRun = [NoDefaultMemory]; + this.failingChecks = []; + + + this.resourceIDs = [] + this.allFunctions = [] + this.stackFunctions = [] + } + + + async getAllLambdaFunctions() { + const lambda = new this.AWS.Lambda(); + let marker; + let allFunctions = []; + while (true){ + const functions = await lambda.listFunctions({Marker: marker, MaxItems: 50}).promise() + allFunctions = [...allFunctions, ...functions.Functions] + if(!functions.NextMarker){ + break; + } + marker = functions.NextMarker + } + return allFunctions; + } + + async getStackFunctionResouceIDs() { + const cloudformation = new this.AWS.CloudFormation(); + const stackResources = await getStackResources(this.stackName, cloudformation); + const lambdaFunctionResources = stackResources.StackResourceSummaries.filter( + (res) => { + return res.ResourceType === "AWS::Lambda::Function"; + } + ); + return lambdaFunctionResources.map(lambda => lambda.PhysicalResourceId); } + + async initResources() { + this.resourceIDs = await this.getStackFunctionResouceIDs(); + this.allFunctions = await this.getAllLambdaFunctions(); + this.stackFunctions = this.allFunctions.filter(lambda => this.resourceIDs.includes(lambda.FunctionName)); + } + async runChecks() { console.log(chalk.greenBright(` ‗‗‗‗‗‗‗‗‗‗‗‗‗‗‗†‗‗‗‗‗‗‗‗‗‗‗‗‗‗ @@ -37,23 +80,38 @@ class GuardianCI { if (this.exitCode != 0) { return; } + console.group(titleLog(" > Running checks")) - const check1 = new NoDefaultMemory(this.AWS, this.stackName) - process.stdout.write(infoLog(` > ${check1.name}... `)); - const check1Result = await check1.run(); - console.log(check1Result ? "✅" : "❌") + + console.log("Analysing Resources...") + await this.initResources() + for (const Check of this.checksToRun) { + const check = new Check(this.AWS, this.stackName, this.stackFunctions) + process.stdout.write(infoLog(` > ${check.name}... `)); + const checkResult = await check.run(); + console.log(checkResult ? "✅" : "❌") + if (!checkResult) { + this.failingChecks = [...this.failingChecks, check] + } + } console.groupEnd() - if(!check1Result) { + if(this.failingChecks.length > 0) { console.group(chalk.blueBright.underline(failTitleLog(" > Failing Checks"))) - console.log(fail(check1.name)); - console.log(fail(check1.failureMessage)); - console.log(infoLog(check1.rulePage)); - console.table(check1.failingResources); - console.groupEnd() } - if(!check1Result) { + let overallResult = true; + this.failingChecks.forEach(failingCheck => { + console.log(fail(failingCheck.name)); + console.log(failingCheck.failureMessage); + console.log(failingCheck.rulePage); + console.table(failingCheck.failingResources); + console.groupEnd() + overallResult = false; + }) + console.groupEnd() + + if(!overallResult) { this.exitCode = 1; } diff --git a/src/guardian/rules/best_practices/no-default-memory/index.js b/src/guardian/rules/best_practices/no-default-memory/index.js index 352e0a6b..36f90c0a 100644 --- a/src/guardian/rules/best_practices/no-default-memory/index.js +++ b/src/guardian/rules/best_practices/no-default-memory/index.js @@ -1,40 +1,14 @@ -import { getStackResources } from "../../../../services/stackResources"; - class NoDefaultMemory { - constructor(AWS, stackName) { + constructor(AWS, stackName, stackFunctions) { this.name = "no-default-memory" this.AWS = AWS; this.stackName = stackName; + this.stackFunctions = stackFunctions + this.result; this.defaultMemory = 1024; this.failingResources = []; this.failureMessage = "The following functions have their memory set as default." this.rulePage = "See (https://github.com/Theodo-UK/sls-dev-tools/blob/guardian-ci/src/guardian/rules/best_practices/no-default-memory/no-default-memory.MD) for impact and how to to resolve." - } - - async getAllLambdaFunctions() { - const lambda = new this.AWS.Lambda(); - let marker; - let allFunctions = []; - while (true){ - const functions = await lambda.listFunctions({Marker: marker, MaxItems: 50}).promise() - allFunctions = [...allFunctions, ...functions.Functions] - if(!functions.NextMarker){ - break; - } - marker = functions.NextMarker - } - return allFunctions; - } - - async getStackFunctionResouceIDs() { - const cloudformation = new this.AWS.CloudFormation(); - const stackResources = await getStackResources(this.stackName, cloudformation); - const lambdaFunctionResources = stackResources.StackResourceSummaries.filter( - (res) => { - return res.ResourceType === "AWS::Lambda::Function"; - } - ); - return lambdaFunctionResources.map(lambda => lambda.PhysicalResourceId); } hasDefaultMemory(lambdaFunction) { @@ -43,24 +17,21 @@ class NoDefaultMemory { async run() { try { - const resourceIDs = await this.getStackFunctionResouceIDs(); - const allFunctions = await this.getAllLambdaFunctions(); - const stackFunctions = allFunctions.filter(lambda => resourceIDs.includes(lambda.FunctionName)); - - const defautlMemFunctions = stackFunctions.reduce((acc, current) => this.hasDefaultMemory(current) ? [...acc, current] : acc, []); + const defautlMemFunctions = this.stackFunctions.reduce((acc, current) => this.hasDefaultMemory(current) ? [...acc, current] : acc, []); this.failingResources = defautlMemFunctions.map(lambda => ({arn: lambda.FunctionArn, memory: lambda.MemorySize})); if(defautlMemFunctions.length > 0) { - return false + this.result = false; } else { - return true; + this.result = true; } } catch (e) { console.error(e) - return false; + this.result = false; } + return this.result; } }