From c2736fe5bb89f48e71dcdb9dd2250ef17b0db201 Mon Sep 17 00:00:00 2001 From: PChol22 Date: Fri, 13 May 2022 16:10:43 +0200 Subject: [PATCH] Create limited-versions-number rule --- package.json | 2 +- src/guardian/index.js | 2 + .../limited-number-of-versions/index.js | 66 +++++++++++++++++++ .../limited-number-of-versions.MD | 12 ++++ yarn.lock | 18 ++--- 5 files changed, 90 insertions(+), 10 deletions(-) create mode 100644 src/guardian/rules/best_practices/limited-number-of-versions/index.js create mode 100644 src/guardian/rules/best_practices/limited-number-of-versions/limited-number-of-versions.MD diff --git a/package.json b/package.json index 1149ba91..1358a2c4 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "sls-dev-tools": "./lib/index.js" }, "dependencies": { - "aws-sdk": "^2.655.0", + "aws-sdk": "2.1124.0", "blessed": "^0.1.81", "blessed-contrib": "^4.8.17", "chalk": "^4.0.0", diff --git a/src/guardian/index.js b/src/guardian/index.js index 944e659c..48187d34 100644 --- a/src/guardian/index.js +++ b/src/guardian/index.js @@ -7,6 +7,7 @@ import NoMaximumTimeout from "./rules/best_practices/no-max-timeout"; import NoMaximumMemory from "./rules/best_practices/no-max-memory"; import NoIdenticalCode from "./rules/best_practices/no-identical-code"; import NoSharedRoles from "./rules/best_practices/no-shared-roles"; +import LimitedNumberOfVersions from "./rules/best_practices/limited-number-of-versions"; import { getAWSCredentials, getStackResources, @@ -43,6 +44,7 @@ class GuardianCI { NoMaximumMemory, NoIdenticalCode, NoSharedRoles, + LimitedNumberOfVersions, ]; this.failingChecks = []; diff --git a/src/guardian/rules/best_practices/limited-number-of-versions/index.js b/src/guardian/rules/best_practices/limited-number-of-versions/index.js new file mode 100644 index 00000000..a34162c4 --- /dev/null +++ b/src/guardian/rules/best_practices/limited-number-of-versions/index.js @@ -0,0 +1,66 @@ +class LimitedNumberOfVersions { + constructor(AWS, stackName, stackFunctions) { + this.name = "limited-number-of-versions"; + this.AWS = AWS; + this.stackName = stackName; + this.stackFunctions = stackFunctions; + this.result = false; + this.failingResources = []; + this.failureMessage = + "The following functions have a number of deployed versions greater than 3"; + this.rulePage = + "See (https://m33.notion.site/Serverless-Sustainability-Audit-a36847289fd64339a60e40bc5aa63092) for impact."; + this.lambda = new AWS.Lambda(); + } + + // Given the name of a lambda, returns its number of versions (excluding $Latest) + async getNumberOfLambdaVersions(FunctionName) { + const lambdaVersions = await this.lambda + .listVersionsByFunction({ + FunctionName, + }) + .promise(); + return lambdaVersions.Versions.length - 1; + } + + async run() { + try { + const functionsWithCount = await Promise.all( + this.stackFunctions.map(async (lambda) => { + const numberOfVersions = await this.getNumberOfLambdaVersions( + lambda.FunctionName + ); + return { + functionArn: lambda.FunctionArn, + numberOfVersions, + }; + }) + ); + + const functionsWithTooManyVersions = functionsWithCount.reduce( + (acc, current) => + current.numberOfVersions > 3 ? [...acc, current] : acc, + [] + ); + + this.failingResources = functionsWithTooManyVersions.map( + (lambdaWithCount) => ({ + arn: lambdaWithCount.functionArn, + numberOfVersions: lambdaWithCount.numberOfVersions, + }) + ); + + if (functionsWithTooManyVersions.length > 0) { + this.result = false; + } else { + this.result = true; + } + } catch (e) { + console.error(e); + this.result = false; + } + return this.result; + } +} + +export default LimitedNumberOfVersions; diff --git a/src/guardian/rules/best_practices/limited-number-of-versions/limited-number-of-versions.MD b/src/guardian/rules/best_practices/limited-number-of-versions/limited-number-of-versions.MD new file mode 100644 index 00000000..b9d66825 --- /dev/null +++ b/src/guardian/rules/best_practices/limited-number-of-versions/limited-number-of-versions.MD @@ -0,0 +1,12 @@ +# Functions should have less than 3 versions + +It is most of the time useless to keep more than 3 online versions for your lambdas. +Storing useless data has a negative impact on teh environment. (For more info, see https://www.notion.so/m33/Serverless-Sustainability-Audit-a36847289fd64339a60e40bc5aa63092?p=a0471b2c407144fe839150326ed804d8) + +AWS Lambda service furthermore has limited storage space, which can be easily reached if you keep every single version of your lambdas. + +--- + +## Suggested Actions + +- Use [serverless-prune-versions](https://github.com/manwaring/serverless-prune-versions) to regularly prune the versions of the affected lambdas diff --git a/yarn.lock b/yarn.lock index cab67d16..219b8c50 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1689,15 +1689,15 @@ atob@^2.1.2: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== -aws-sdk@^2.655.0: - version "2.855.0" - resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.855.0.tgz#2788e2655d8e2eecfc9d86acafd13d872725e73a" - integrity sha512-u1lO75V82E4REeu0Pt3RE1Kg2CdtUoMgMnyR02cUxdWnoTBpdSlwvz2X2U0VEGW2oYzeJJYp0N0H1sgSRnv8vg== +aws-sdk@2.1124.0: + version "2.1124.0" + resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1124.0.tgz#350550b973f210b092a45184036659251d7cbd1e" + integrity sha512-LIj2EmvduQmyjpSLoDPe2TvRBrGWhJKlCuC7lungN4f+qYPOfVWg6/c9GdP99W0q5p2IqhDkCmQ/ZZBpO1Z/Fg== dependencies: buffer "4.9.2" events "1.1.1" ieee754 "1.1.13" - jmespath "0.15.0" + jmespath "0.16.0" querystring "0.2.0" sax "1.2.1" url "0.10.3" @@ -4382,10 +4382,10 @@ jest@^26.6.3: import-local "^3.0.2" jest-cli "^26.6.3" -jmespath@0.15.0: - version "0.15.0" - resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.15.0.tgz#a3f222a9aae9f966f5d27c796510e28091764217" - integrity sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc= +jmespath@0.16.0: + version "0.16.0" + resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.16.0.tgz#b15b0a85dfd4d930d43e69ed605943c802785076" + integrity sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw== "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0"