From 55d24fe712c08013fa7217c6837e3dd35a66fa39 Mon Sep 17 00:00:00 2001 From: Simon Krol Date: Mon, 9 Sep 2024 16:22:46 -0400 Subject: [PATCH] Update to version 6.3.0 (#573) --- CHANGELOG.md | 26 +- NOTICE | 10 + README.md | 6 +- VERSION.txt | 2 +- .../asset-packager/index.ts | 1 - .../cdk-solution-helper/package-lock.json | 9 +- deployment/run-unit-tests.sh | 2 + source/constructs/cdk.json | 2 +- .../lib/back-end/back-end-construct.ts | 34 +- .../constructs/lib/serverless-image-stack.ts | 12 +- source/constructs/package-lock.json | 246 +- source/constructs/package.json | 9 +- .../__snapshots__/constructs.test.ts.snap | 499 +- source/constructs/test/constructs.test.ts | 14 +- source/custom-resource/package-lock.json | 13 +- source/custom-resource/package.json | 2 +- source/demo-ui/package-lock.json | 4 +- source/demo-ui/package.json | 2 +- source/image-handler/index.ts | 64 +- source/image-handler/package-lock.json | 13 +- source/image-handler/package.json | 2 +- source/image-handler/test/index.spec.ts | 118 + source/metrics-utils/.npmignore | 6 + source/metrics-utils/index.ts | 5 + source/metrics-utils/jest.config.js | 14 + .../lambda/helpers/client-helper.ts | 35 + .../lambda/helpers/metrics-helper.ts | 212 + source/metrics-utils/lambda/helpers/types.ts | 64 + source/metrics-utils/lambda/index.ts | 60 + source/metrics-utils/lib/query-builders.ts | 68 + source/metrics-utils/lib/solutions-metrics.ts | 119 + source/metrics-utils/package-lock.json | 6443 +++++++++++++++++ source/metrics-utils/package.json | 30 + .../test/lambda/helpers/client-helper.spec.ts | 70 + .../lambda/helpers/metrics-helper.spec.ts | 188 + .../metrics-utils/test/lambda/index.spec.ts | 108 + .../test/lib/solutions-metrics.spec.ts | 186 + source/package-lock.json | 13 +- source/package.json | 5 +- source/solution-utils/package-lock.json | 13 +- source/solution-utils/package.json | 2 +- 41 files changed, 8563 insertions(+), 168 deletions(-) create mode 100644 source/metrics-utils/.npmignore create mode 100644 source/metrics-utils/index.ts create mode 100644 source/metrics-utils/jest.config.js create mode 100644 source/metrics-utils/lambda/helpers/client-helper.ts create mode 100644 source/metrics-utils/lambda/helpers/metrics-helper.ts create mode 100644 source/metrics-utils/lambda/helpers/types.ts create mode 100644 source/metrics-utils/lambda/index.ts create mode 100644 source/metrics-utils/lib/query-builders.ts create mode 100644 source/metrics-utils/lib/solutions-metrics.ts create mode 100644 source/metrics-utils/package-lock.json create mode 100644 source/metrics-utils/package.json create mode 100644 source/metrics-utils/test/lambda/helpers/client-helper.spec.ts create mode 100644 source/metrics-utils/test/lambda/helpers/metrics-helper.spec.ts create mode 100644 source/metrics-utils/test/lambda/index.spec.ts create mode 100644 source/metrics-utils/test/lib/solutions-metrics.spec.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 755f3c8c7..df91a206b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,15 +5,32 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [6.3.0] - 2024-09-09 + +### Added + +- Additional anonymized metrics system to help understand how the solution is being used, identify areas of improvement, and drive future roadmap decisions. + +### Changed + +- Cdk update to 2.151.0 +- Default log retention to 180 days +- Cache-control header on fallback images to use (in order of priority), fallback image metadata, header provided in image request, and default cache control [#563](https://github.com/aws-solutions/serverless-image-handler/issues/563) + +### Security + +- Upgraded micromatch to v4.0.8 for vulnerability CVE-2024-4067 + ## [6.2.7] - 2024-08-19 -### Security -- Upgraded axios to v1.7.4 for vulnerability CVE-2024-39338 +### Security +- Upgraded axios to v1.7.4 for vulnerability CVE-2024-39338 ## [6.2.6] - 2024-06-27 ### Added + - StackId tag to CloudFrontLoggingBucket and its bucket name as a CfnOutput [#529](https://github.com/aws-solutions/serverless-image-handler/issues/529) - Test case to verify UTF-8 support in object key [#320](https://github.com/aws-solutions/serverless-image-handler/pull/320) - Test cases to verify crop functionality [#459](https://github.com/aws-solutions/serverless-image-handler/pull/459) @@ -23,6 +40,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Support for 8-bit depth AVIF image type inference [#360](https://github.com/aws-solutions/serverless-image-handler/issues/360) ### Changed + - Decreased permissions allotted to CustomResource Lambda and ImageHandler Lambda - cdk update to 2.124.0 - aws-solutions-constructs update to 2.51.0 @@ -32,18 +50,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Modified JPEG SOI marker parsing to only check first 2 bytes [#429] ### Security + - Upgraded follow-redirects to v1.15.6 for vulnerability CVE-2024-28849 - Upgraded braces to v3.0.3 for vulnerability CVE-2024-4068 ### Removed + - Unused CopyS3Assets custom resource ### Fixed + - Some error messages indicating incorrect file types - Solution version and id not being passed to Backend Lambda - Thumbor-style URL matching being overly permissive - ## [6.2.5] - 2024-01-03 ### Fixed diff --git a/NOTICE b/NOTICE index 0dec45df1..8bc497dde 100644 --- a/NOTICE +++ b/NOTICE @@ -55,3 +55,13 @@ ts-jest under the Massachusetts Institute of Technology (MIT) license ts-node under the Massachusetts Institute of Technology (MIT) license typescript under the Apache License 2.0 uuid under the Massachusetts Institute of Technology (MIT) license +@aws-sdk/client-cloudwatch under the Apache License 2.0 +@aws-sdk/client-cloudwatch-logs under the Apache License 2.0 +@aws-sdk/client-sqs under the Apache License 2.0 +@aws-solutions-constructs/aws-eventbridge-lambda under the Apache License 2.0 +@aws-solutions-constructs/aws-lambda-sqs-lambda under the Apache License 2.0 +@types/aws-lambda under the Massachusetts Institute of Technology (MIT) license +esbuild under the Massachusetts Institute of Technology (MIT) license +@aws-cdk/aws-servicecatalogappregistry-alpha under the Apache License 2.0 +@types/adm-zip under the Massachusetts Institute of Technology (MIT) license +prettier under the Massachusetts Institute of Technology (MIT) license diff --git a/README.md b/README.md index 56b417c67..3a638b771 100644 --- a/README.md +++ b/README.md @@ -105,8 +105,10 @@ This solution collects anonymous operational metrics to help AWS improve the qua - [@Fjool](https://github.com/Fjool) for [#489](https://github.com/aws-solutions/serverless-image-handler/pull/489) - [@fvsnippets](https://github.com/fvsnippets) for [#373](https://github.com/aws-solutions/serverless-image-handler/pull/373), [#380](https://github.com/aws-solutions/serverless-image-handler/pull/380) - [@ccchapman](https://github.com/ccchapman) for [#490](https://github.com/aws-solutions/serverless-image-handler/pull/490) -- [@bennet-esyoil][https://github.com/bennet-esyoil] for [#521](https://github.com/aws-solutions/serverless-image-handler/pull/521) -- [@vaniyokk][https://github.com/vaniyokk] for [#511](https://github.com/aws-solutions/serverless-image-handler/pull/511) +- [@bennet-esyoil](https://github.com/bennet-esyoil) for [#521](https://github.com/aws-solutions/serverless-image-handler/pull/521) +- [@vaniyokk](https://github.com/vaniyokk) for [#511](https://github.com/aws-solutions/serverless-image-handler/pull/511) +- [@nicolasbuch](https://github.com/nicolasbuch) for [#569](https://github.com/aws-solutions/serverless-image-handler/pull/569) +- [@mrnonz](https://github.com/mrnonz) for [#567](https://github.com/aws-solutions/serverless-image-handler/pull/567) # License diff --git a/VERSION.txt b/VERSION.txt index c404f1a68..e7e42a4b5 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -6.2.7 \ No newline at end of file +6.3.0 \ No newline at end of file diff --git a/deployment/cdk-solution-helper/asset-packager/index.ts b/deployment/cdk-solution-helper/asset-packager/index.ts index 18e572f59..8c70652f3 100644 --- a/deployment/cdk-solution-helper/asset-packager/index.ts +++ b/deployment/cdk-solution-helper/asset-packager/index.ts @@ -4,7 +4,6 @@ */ import { CDKAssetPackager } from "./asset-packager"; -import path from "path"; export async function handler(cdkAssetFolderPath: string | undefined, outputPath: string | undefined) { if (!cdkAssetFolderPath || !outputPath) throw new Error("undefined input path"); diff --git a/deployment/cdk-solution-helper/package-lock.json b/deployment/cdk-solution-helper/package-lock.json index f8b88f293..220bebb26 100644 --- a/deployment/cdk-solution-helper/package-lock.json +++ b/deployment/cdk-solution-helper/package-lock.json @@ -3260,12 +3260,13 @@ "dev": true }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, + "license": "MIT", "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { diff --git a/deployment/run-unit-tests.sh b/deployment/run-unit-tests.sh index e1bc1f41f..0d0da6cc9 100755 --- a/deployment/run-unit-tests.sh +++ b/deployment/run-unit-tests.sh @@ -35,6 +35,7 @@ template_dir="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd cdk_dir="$template_dir/../source/constructs" image_handler_dir="$template_dir/../source/image-handler" custom_resource_dir="$template_dir/../source/custom-resource" +metrics_utils_dir="$template_dir/../source/metrics-utils" coverage_reports_top_path="$template_dir/../source/test/coverage-reports" headline "[Tests] Run unit tests" @@ -42,6 +43,7 @@ declare -a packages=( "$cdk_dir" "$image_handler_dir" "$custom_resource_dir" + "$metrics_utils_dir" ) for package in "${packages[@]}"; do cd "$package" diff --git a/source/constructs/cdk.json b/source/constructs/cdk.json index b8b9ea6a0..ea124a5ef 100644 --- a/source/constructs/cdk.json +++ b/source/constructs/cdk.json @@ -2,7 +2,7 @@ "app": "npx ts-node --prefer-ts-exts bin/constructs.ts", "context": { "solutionId": "SO0023", - "solutionVersion": "custom-v6.2.7", + "solutionVersion": "custom-v6.3.0", "solutionName": "serverless-image-handler" } } \ No newline at end of file diff --git a/source/constructs/lib/back-end/back-end-construct.ts b/source/constructs/lib/back-end/back-end-construct.ts index b1d5d616e..cf8d62785 100644 --- a/source/constructs/lib/back-end/back-end-construct.ts +++ b/source/constructs/lib/back-end/back-end-construct.ts @@ -21,18 +21,21 @@ import { Runtime } from "aws-cdk-lib/aws-lambda"; import { NodejsFunction } from "aws-cdk-lib/aws-lambda-nodejs"; import { LogGroup, RetentionDays } from "aws-cdk-lib/aws-logs"; import { IBucket } from "aws-cdk-lib/aws-s3"; -import { ArnFormat, Aws, Duration, Lazy, Stack } from "aws-cdk-lib"; +import { ArnFormat, Aspects, Aws, CfnCondition, Duration, Fn, Lazy, Stack } from "aws-cdk-lib"; import { Construct } from "constructs"; import { CloudFrontToApiGatewayToLambda } from "@aws-solutions-constructs/aws-cloudfront-apigateway-lambda"; import { addCfnSuppressRules } from "../../utils/utils"; import { SolutionConstructProps } from "../types"; import * as api from "aws-cdk-lib/aws-apigateway"; +import { SolutionsMetrics, ExecutionDay } from "metrics-utils"; +import { ConditionAspect } from "../../utils/aspects"; export interface BackEndProps extends SolutionConstructProps { readonly solutionVersion: string; readonly solutionId: string; readonly solutionName: string; + readonly sendAnonymousStatistics: CfnCondition; readonly secretsManagerPolicy: Policy; readonly logsBucket: IBucket; readonly uuid: string; @@ -230,5 +233,34 @@ export class BackEnd extends Construct { imageHandlerCloudFrontApiGatewayLambda.apiGateway.node.tryRemoveChild("Endpoint"); // we don't need the RestApi endpoint in the outputs this.domainName = imageHandlerCloudFrontApiGatewayLambda.cloudFrontWebDistribution.distributionDomainName; + + const shortLogRetentionCondition: CfnCondition = new CfnCondition(this, "ShortLogRetentionCondition", { + expression: Fn.conditionOr( + Fn.conditionEquals(props.logRetentionPeriod.toString(), "1"), + Fn.conditionEquals(props.logRetentionPeriod.toString(), "3"), + Fn.conditionEquals(props.logRetentionPeriod.toString(), "5") + ), + }); + const solutionsMetrics = new SolutionsMetrics(this, "SolutionMetrics", { + uuid: props.uuid, + executionDay: Fn.conditionIf( + shortLogRetentionCondition.logicalId, + ExecutionDay.DAILY, + ExecutionDay.MONDAY + ).toString(), + }); + solutionsMetrics.addLambdaInvocationCount(imageHandlerLambdaFunction.functionName); + solutionsMetrics.addLambdaBilledDurationMemorySize([imageHandlerLogGroup], "BilledDurationMemorySizeQuery"); + solutionsMetrics.addCloudFrontMetric( + imageHandlerCloudFrontApiGatewayLambda.cloudFrontWebDistribution.distributionId, + "Requests" + ); + + solutionsMetrics.addCloudFrontMetric( + imageHandlerCloudFrontApiGatewayLambda.cloudFrontWebDistribution.distributionId, + "BytesDownloaded" + ); + + Aspects.of(solutionsMetrics).add(new ConditionAspect(props.sendAnonymousStatistics)); } } diff --git a/source/constructs/lib/serverless-image-stack.ts b/source/constructs/lib/serverless-image-stack.ts index ebf50161c..f1a68d3c7 100644 --- a/source/constructs/lib/serverless-image-stack.ts +++ b/source/constructs/lib/serverless-image-stack.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { PriceClass } from "aws-cdk-lib/aws-cloudfront"; -import { Aspects, CfnMapping, CfnOutput, CfnParameter, Stack, StackProps, Tags } from "aws-cdk-lib"; +import { Aspects, CfnCondition, CfnMapping, CfnOutput, CfnParameter, Fn, Stack, StackProps, Tags } from "aws-cdk-lib"; import { Construct } from "constructs"; import { ConditionAspect, SuppressLambdaFunctionCfnRulesAspect } from "../utils/aspects"; import { BackEnd } from "./back-end/back-end-construct"; @@ -72,7 +72,7 @@ export class ServerlessImageHandlerStack extends Stack { "1827", "3653", ], - default: "1", + default: "180", }); const autoWebPParameter = new CfnParameter(this, "AutoWebPParameter", { @@ -138,10 +138,13 @@ export class ServerlessImageHandlerStack extends Stack { Version: props.solutionVersion, }, }, - lazy: true, + lazy: false, }); const anonymousUsage = `${solutionMapping.findInMap("Config", "AnonymousUsage")}`; + const sendAnonymousStatistics = new CfnCondition(this, "SendAnonymousStatistics", { + expression: Fn.conditionEquals(anonymousUsage, "Yes"), + }); const solutionConstructProps: SolutionConstructProps = { corsEnabled: corsEnabledParameter.valueAsString, @@ -175,6 +178,7 @@ export class ServerlessImageHandlerStack extends Stack { solutionId: props.solutionId, solutionName: props.solutionName, secretsManagerPolicy: commonResources.secretsManagerPolicy, + sendAnonymousStatistics, logsBucket: commonResources.logsBucket, uuid: commonResources.customResources.uuid, cloudFrontPriceClass: cloudFrontPriceClassParameter.valueAsString, @@ -326,7 +330,7 @@ export class ServerlessImageHandlerStack extends Stack { new CfnOutput(this, "CloudFrontLoggingBucket", { value: commonResources.logsBucket.bucketName, description: "Amazon S3 bucket for storing CloudFront access logs.", - }) + }); Aspects.of(this).add(new SuppressLambdaFunctionCfnRulesAspect()); Tags.of(this).add("SolutionId", props.solutionId); diff --git a/source/constructs/package-lock.json b/source/constructs/package-lock.json index eb2fbdd49..91eb1bc28 100644 --- a/source/constructs/package-lock.json +++ b/source/constructs/package-lock.json @@ -1,14 +1,15 @@ { "name": "constructs", - "version": "6.2.7", + "version": "6.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "constructs", - "version": "6.2.7", + "version": "6.3.0", "license": "Apache-2.0", "dependencies": { + "metrics-utils": "file:../metrics-utils", "sharp": "^0.32.6" }, "bin": { @@ -22,8 +23,8 @@ "@aws-solutions-constructs/core": "2.51.0", "@types/jest": "^29.5.6", "@types/node": "^20.10.4", - "aws-cdk": "^2.124.0", - "aws-cdk-lib": "^2.124.0", + "aws-cdk": "^2.151.0", + "aws-cdk-lib": "^2.151.0", "constructs": "^10.3.0", "esbuild": "^0.19.10", "jest": "^29.7.0", @@ -32,6 +33,27 @@ "typescript": "^5.3.3" } }, + "../metrics-utils": { + "version": "0.1.0", + "dependencies": { + "@aws-sdk/client-cloudwatch": "^3.637.0", + "@aws-sdk/client-cloudwatch-logs": "^3.637.0", + "@aws-sdk/client-sqs": "^3.637.0", + "@aws-solutions-constructs/aws-eventbridge-lambda": "^2.59.0", + "@aws-solutions-constructs/aws-lambda-sqs-lambda": "^2.59.0", + "@types/aws-lambda": "^8.10.143", + "axios": "^1.7.4", + "esbuild": "^0.23.1" + }, + "devDependencies": { + "@types/jest": "^29.5.12", + "@types/node": "20.4.5", + "aws-cdk-lib": "^2.151.0", + "constructs": "^10.0.0", + "jest": "^29.6.2", + "ts-jest": "^29.2.0" + } + }, "node_modules/@ampproject/remapping": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", @@ -58,10 +80,11 @@ "dev": true }, "node_modules/@aws-cdk/asset-node-proxy-agent-v6": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v6/-/asset-node-proxy-agent-v6-2.0.1.tgz", - "integrity": "sha512-DDt4SLdLOwWCjGtltH4VCST7hpOI5DzieuhGZsBpZ+AgJdSI2GCjklCXm0GCTwJG/SolkL5dtQXyUKgg9luBDg==", - "dev": true + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v6/-/asset-node-proxy-agent-v6-2.0.3.tgz", + "integrity": "sha512-twhuEG+JPOYCYPx/xy5uH2+VUsIEhPTzDY0F1KuB+ocjWWB/KEDiOVL19nHvbPCB6fhWnkykXEMJ4HHcKvjtvg==", + "dev": true, + "license": "Apache-2.0" }, "node_modules/@aws-cdk/aws-servicecatalogappregistry-alpha": { "version": "2.118.0-alpha.0", @@ -1952,10 +1975,11 @@ } }, "node_modules/@types/jest": { - "version": "29.5.6", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.6.tgz", - "integrity": "sha512-/t9NnzkOpXb4Nfvg17ieHE6EeSjDS2SGSpNYfoLbUAeL/EOueU/RSdOWFpfQTXBEM7BguYW1XQ0EbM+6RlIh6w==", + "version": "29.5.12", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", + "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", "dev": true, + "license": "MIT", "dependencies": { "expect": "^29.0.0", "pretty-format": "^29.0.0" @@ -2080,10 +2104,11 @@ } }, "node_modules/aws-cdk": { - "version": "2.124.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.124.0.tgz", - "integrity": "sha512-kUOfqwIAaTEx4ZozojZEhWa8G+O9KU+P0tERtDVmTw9ip4QXNMwTTkjj/IPtoH8qfXGdeibTQ9MJwRvHOR8kXQ==", + "version": "2.151.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.151.0.tgz", + "integrity": "sha512-+pM3mTXjzZk44U5q+jaji5Y1X8J2c4ro8szqm2V/Wwa+xXCsJfVwJYiQbstSZkOz6ondfgkrJKtx6EzaodxRNw==", "dev": true, + "license": "Apache-2.0", "bin": { "cdk": "bin/cdk" }, @@ -2095,9 +2120,9 @@ } }, "node_modules/aws-cdk-lib": { - "version": "2.124.0", - "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.124.0.tgz", - "integrity": "sha512-K/Tey8TMw30GO6UD0qb19CPhBMZhleGshz520ZnbDUJwNfFtejwZOnpmRMOdUP9f4tHc5BrXl1VGsZtXtUaGhg==", + "version": "2.151.0", + "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.151.0.tgz", + "integrity": "sha512-SIzzOGSYO+s1f+y2zyGKK8wH5JmN+nkrGOL28iHzmx9lXK0NaT0+d5sjTbzLo2C8iogzbR91yGnIKze0GzZXHg==", "bundleDependencies": [ "@balena/dockerignore", "case", @@ -2108,22 +2133,25 @@ "punycode", "semver", "table", - "yaml" + "yaml", + "mime-types" ], "dev": true, + "license": "Apache-2.0", "dependencies": { "@aws-cdk/asset-awscli-v1": "^2.2.202", "@aws-cdk/asset-kubectl-v20": "^2.1.2", - "@aws-cdk/asset-node-proxy-agent-v6": "^2.0.1", + "@aws-cdk/asset-node-proxy-agent-v6": "^2.0.3", "@balena/dockerignore": "^1.0.2", "case": "1.6.3", "fs-extra": "^11.2.0", - "ignore": "^5.3.0", + "ignore": "^5.3.1", "jsonschema": "^1.4.1", + "mime-types": "^2.1.35", "minimatch": "^3.1.2", "punycode": "^2.3.1", - "semver": "^7.5.4", - "table": "^6.8.1", + "semver": "^7.6.2", + "table": "^6.8.2", "yaml": "1.10.2" }, "engines": { @@ -2135,20 +2163,18 @@ }, "node_modules/aws-cdk-lib/node_modules/@balena/dockerignore": { "version": "1.0.2", - "dev": true, "inBundle": true, "license": "Apache-2.0" }, "node_modules/aws-cdk-lib/node_modules/ajv": { - "version": "8.12.0", - "dev": true, + "version": "8.16.0", "inBundle": true, "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "uri-js": "^4.4.1" }, "funding": { "type": "github", @@ -2157,7 +2183,6 @@ }, "node_modules/aws-cdk-lib/node_modules/ansi-regex": { "version": "5.0.1", - "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -2166,7 +2191,6 @@ }, "node_modules/aws-cdk-lib/node_modules/ansi-styles": { "version": "4.3.0", - "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -2181,7 +2205,6 @@ }, "node_modules/aws-cdk-lib/node_modules/astral-regex": { "version": "2.0.0", - "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -2190,13 +2213,11 @@ }, "node_modules/aws-cdk-lib/node_modules/balanced-match": { "version": "1.0.2", - "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/aws-cdk-lib/node_modules/brace-expansion": { "version": "1.1.11", - "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -2206,7 +2227,6 @@ }, "node_modules/aws-cdk-lib/node_modules/case": { "version": "1.6.3", - "dev": true, "inBundle": true, "license": "(MIT OR GPL-3.0-or-later)", "engines": { @@ -2215,7 +2235,6 @@ }, "node_modules/aws-cdk-lib/node_modules/color-convert": { "version": "2.0.1", - "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -2227,31 +2246,26 @@ }, "node_modules/aws-cdk-lib/node_modules/color-name": { "version": "1.1.4", - "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/aws-cdk-lib/node_modules/concat-map": { "version": "0.0.1", - "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/aws-cdk-lib/node_modules/emoji-regex": { "version": "8.0.0", - "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/aws-cdk-lib/node_modules/fast-deep-equal": { "version": "3.1.3", - "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/aws-cdk-lib/node_modules/fs-extra": { "version": "11.2.0", - "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -2265,13 +2279,11 @@ }, "node_modules/aws-cdk-lib/node_modules/graceful-fs": { "version": "4.2.11", - "dev": true, "inBundle": true, "license": "ISC" }, "node_modules/aws-cdk-lib/node_modules/ignore": { - "version": "5.3.0", - "dev": true, + "version": "5.3.1", "inBundle": true, "license": "MIT", "engines": { @@ -2280,7 +2292,6 @@ }, "node_modules/aws-cdk-lib/node_modules/is-fullwidth-code-point": { "version": "3.0.0", - "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -2289,13 +2300,11 @@ }, "node_modules/aws-cdk-lib/node_modules/json-schema-traverse": { "version": "1.0.0", - "dev": true, "inBundle": true, "license": "MIT" }, "node_modules/aws-cdk-lib/node_modules/jsonfile": { "version": "6.1.0", - "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -2307,7 +2316,6 @@ }, "node_modules/aws-cdk-lib/node_modules/jsonschema": { "version": "1.4.1", - "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -2316,25 +2324,30 @@ }, "node_modules/aws-cdk-lib/node_modules/lodash.truncate": { "version": "4.4.2", - "dev": true, "inBundle": true, "license": "MIT" }, - "node_modules/aws-cdk-lib/node_modules/lru-cache": { - "version": "6.0.0", - "dev": true, + "node_modules/aws-cdk-lib/node_modules/mime-db": { + "version": "1.52.0", "inBundle": true, - "license": "ISC", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/aws-cdk-lib/node_modules/mime-types": { + "version": "2.1.35", + "inBundle": true, + "license": "MIT", "dependencies": { - "yallist": "^4.0.0" + "mime-db": "1.52.0" }, "engines": { - "node": ">=10" + "node": ">= 0.6" } }, "node_modules/aws-cdk-lib/node_modules/minimatch": { "version": "3.1.2", - "dev": true, "inBundle": true, "license": "ISC", "dependencies": { @@ -2346,7 +2359,6 @@ }, "node_modules/aws-cdk-lib/node_modules/punycode": { "version": "2.3.1", - "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -2355,7 +2367,6 @@ }, "node_modules/aws-cdk-lib/node_modules/require-from-string": { "version": "2.0.2", - "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -2363,13 +2374,9 @@ } }, "node_modules/aws-cdk-lib/node_modules/semver": { - "version": "7.5.4", - "dev": true, + "version": "7.6.2", "inBundle": true, "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, "bin": { "semver": "bin/semver.js" }, @@ -2379,7 +2386,6 @@ }, "node_modules/aws-cdk-lib/node_modules/slice-ansi": { "version": "4.0.0", - "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -2396,7 +2402,6 @@ }, "node_modules/aws-cdk-lib/node_modules/string-width": { "version": "4.2.3", - "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -2410,7 +2415,6 @@ }, "node_modules/aws-cdk-lib/node_modules/strip-ansi": { "version": "6.0.1", - "dev": true, "inBundle": true, "license": "MIT", "dependencies": { @@ -2421,8 +2425,7 @@ } }, "node_modules/aws-cdk-lib/node_modules/table": { - "version": "6.8.1", - "dev": true, + "version": "6.8.2", "inBundle": true, "license": "BSD-3-Clause", "dependencies": { @@ -2438,7 +2441,6 @@ }, "node_modules/aws-cdk-lib/node_modules/universalify": { "version": "2.0.1", - "dev": true, "inBundle": true, "license": "MIT", "engines": { @@ -2447,22 +2449,14 @@ }, "node_modules/aws-cdk-lib/node_modules/uri-js": { "version": "4.4.1", - "dev": true, "inBundle": true, "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } }, - "node_modules/aws-cdk-lib/node_modules/yallist": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, "node_modules/aws-cdk-lib/node_modules/yaml": { "version": "1.10.2", - "dev": true, "inBundle": true, "license": "ISC", "engines": { @@ -3035,6 +3029,22 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/electron-to-chromium": { "version": "1.4.536", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.536.tgz", @@ -3221,6 +3231,39 @@ "bser": "2.1.1" } }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -3588,6 +3631,32 @@ "node": ">=8" } }, + "node_modules/jake": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", + "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jake/node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" + }, "node_modules/jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", @@ -4279,13 +4348,18 @@ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, + "node_modules/metrics-utils": { + "resolved": "../metrics-utils", + "link": true + }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, + "license": "MIT", "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -5162,12 +5236,14 @@ } }, "node_modules/ts-jest": { - "version": "29.1.1", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", - "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", + "version": "29.2.4", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.4.tgz", + "integrity": "sha512-3d6tgDyhCI29HlpwIq87sNuI+3Q6GLTTCeYRHCs7vDz+/3GCMwEtV9jezLyl4ZtnBgx00I7hm8PCP8cTksMGrw==", "dev": true, + "license": "MIT", "dependencies": { "bs-logger": "0.x", + "ejs": "^3.1.10", "fast-json-stable-stringify": "2.x", "jest-util": "^29.0.0", "json5": "^2.2.3", @@ -5180,10 +5256,11 @@ "ts-jest": "cli.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" }, "peerDependencies": { "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0", "@jest/types": "^29.0.0", "babel-jest": "^29.0.0", "jest": "^29.0.0", @@ -5193,6 +5270,9 @@ "@babel/core": { "optional": true }, + "@jest/transform": { + "optional": true + }, "@jest/types": { "optional": true }, diff --git a/source/constructs/package.json b/source/constructs/package.json index 56ca21146..e078459bb 100644 --- a/source/constructs/package.json +++ b/source/constructs/package.json @@ -1,6 +1,6 @@ { "name": "constructs", - "version": "6.2.7", + "version": "6.3.0", "description": "Serverless Image Handler Constructs", "license": "Apache-2.0", "author": { @@ -28,8 +28,8 @@ "@aws-solutions-constructs/core": "2.51.0", "@types/jest": "^29.5.6", "@types/node": "^20.10.4", - "aws-cdk": "^2.124.0", - "aws-cdk-lib": "^2.124.0", + "aws-cdk": "^2.151.0", + "aws-cdk-lib": "^2.151.0", "constructs": "^10.3.0", "esbuild": "^0.19.10", "jest": "^29.7.0", @@ -44,6 +44,7 @@ "semver": "7.5.4" }, "dependencies": { - "sharp": "^0.32.6" + "sharp": "^0.32.6", + "metrics-utils": "file:../metrics-utils" } } diff --git a/source/constructs/test/__snapshots__/constructs.test.ts.snap b/source/constructs/test/__snapshots__/constructs.test.ts.snap index 20d19453d..78ae817de 100644 --- a/source/constructs/test/__snapshots__/constructs.test.ts.snap +++ b/source/constructs/test/__snapshots__/constructs.test.ts.snap @@ -3,6 +3,34 @@ exports[`Serverless Image Handler Stack Snapshot 1`] = ` { "Conditions": { + "BackEndShortLogRetentionCondition72EA1A33": { + "Fn::Or": [ + { + "Fn::Equals": [ + { + "Ref": "LogRetentionPeriodParameter", + }, + "1", + ], + }, + { + "Fn::Equals": [ + { + "Ref": "LogRetentionPeriodParameter", + }, + "3", + ], + }, + { + "Fn::Equals": [ + { + "Ref": "LogRetentionPeriodParameter", + }, + "5", + ], + }, + ], + }, "CommonResourcesDeployDemoUICondition308D3B09": { "Fn::Equals": [ { @@ -35,6 +63,27 @@ exports[`Serverless Image Handler Stack Snapshot 1`] = ` "Yes", ], }, + "SendAnonymousStatistics": { + "Fn::Equals": [ + { + "Fn::FindInMap": [ + "Solution", + "Config", + "AnonymousUsage", + ], + }, + "Yes", + ], + }, + }, + "Mappings": { + "Solution": { + "Config": { + "AnonymousUsage": "Yes", + "SolutionId": "S0ABC", + "Version": "v6.3.0", + }, + }, }, "Metadata": { "AWS::CloudFormation::Interface": { @@ -312,7 +361,7 @@ exports[`Serverless Image Handler Stack Snapshot 1`] = ` "1827", "3653", ], - "Default": "1", + "Default": "180", "Description": "This solution automatically logs events to Amazon CloudWatch. Select the amount of time for CloudWatch logs from this solution to be retained (in days).", "Type": "Number", }, @@ -359,7 +408,7 @@ exports[`Serverless Image Handler Stack Snapshot 1`] = ` "Solutions:ApplicationType": "AWS-Solutions", "Solutions:SolutionID": "S0ABC", "Solutions:SolutionName": "sih", - "Solutions:SolutionVersion": "v6.2.7", + "Solutions:SolutionVersion": "v6.3.0", }, }, "Type": "AWS::ServiceCatalogAppRegistry::Application", @@ -1228,13 +1277,12 @@ exports[`Serverless Image Handler Stack Snapshot 1`] = ` }, "S3Key": "Omitted to remove snapshot dependency on hash", }, - "Description": "sih (v6.2.7): Performs image edits and manipulations", + "Description": "sih (v6.3.0): Performs image edits and manipulations", "Environment": { "Variables": { "AUTO_WEBP": { "Ref": "AutoWebPParameter", }, - "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", "CORS_ENABLED": { "Ref": "CorsEnabledParameter", }, @@ -1262,7 +1310,7 @@ exports[`Serverless Image Handler Stack Snapshot 1`] = ` "Ref": "SecretsManagerKeyParameter", }, "SOLUTION_ID": "S0ABC", - "SOLUTION_VERSION": "v6.2.7", + "SOLUTION_VERSION": "Omitted to remove snapshot dependency on solution version", "SOURCE_BUCKETS": { "Ref": "SourceBucketsParameter", }, @@ -1361,10 +1409,442 @@ exports[`Serverless Image Handler Stack Snapshot 1`] = ` }, "Type": "AWS::CloudFront::OriginRequestPolicy", }, + "BackEndSolutionMetricsBilledDurationMemorySizeQuery39F16D58": { + "Condition": "SendAnonymousStatistics", + "Properties": { + "LogGroupNames": [ + { + "Ref": "BackEndImageHandlerLogGroupA0941EEC", + }, + ], + "Name": { + "Fn::Join": [ + "", + [ + { + "Ref": "AWS::StackName", + }, + "-BilledDurationMemorySizeQuery", + ], + ], + }, + "QueryString": "stats sum(@billedDuration) as AWSLambdaBilledDuration, max(@memorySize) as AWSLambdaMemorySize", + }, + "Type": "AWS::Logs::QueryDefinition", + }, + "BackEndSolutionMetricsEventbridgeRuleToLambdaEventsRule05009025": { + "Condition": "SendAnonymousStatistics", + "Properties": { + "ScheduleExpression": { + "Fn::Join": [ + "", + [ + "cron(0 23 ? * ", + { + "Fn::If": [ + "BackEndShortLogRetentionCondition72EA1A33", + "*", + "MON", + ], + }, + " *)", + ], + ], + }, + "State": "ENABLED", + "Targets": [ + { + "Arn": { + "Fn::GetAtt": [ + "BackEndSolutionMetricsMetricsLambdaF4FA4AF7", + "Arn", + ], + }, + "Id": "Target0", + "InputTransformer": { + "InputPathsMap": { + "detail-type": "$.detail-type", + "time": "$.time", + }, + "InputTemplate": { + "Fn::Join": [ + "", + [ + "{"detail-type": , "time":