diff --git a/CHANGELOG.md b/CHANGELOG.md index aaf0d67c9..6c961fabc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,16 +5,28 @@ 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.2.0] - 2023-04-24 +## [6.2.1] - 2023-08-03 + +### Fixed + +- Template fails to deploy unless demo UI is enabled [#499](https://github.com/aws-solutions/serverless-image-handler/issues/499) +- Thumbor requests of images without a file extension would fail +- CloudFormation template description was not being generated + +### Changed + +- Upgraded build requirement to Node 16 + +## [6.2.0] - 2023-08-01 ### Added -+ Add `cdk-helper` module to help with packaging cdk generated assets in solutions internal pipelines -+ Use [DefaultStackSynthesizer](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.DefaultStackSynthesizer.html) with different configurations to generate template for `cdk deploy` and on internal solutions pipeline -+ Add esbuild bundler for lambda functions using `NodejsFunction`, reference [aws_lambda_nodejs](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda_nodejs-readme.html) -+ Refactor pipeline scripts -+ Changes semver dependency version to 7.5.2 for github reported vulnerability CVE-2022-25883 -+ Changes word-wrap dependency version to aashutoshrathi/word-wrap for github reported vulnerability CVE-2023-26115 +- Add `cdk-helper` module to help with packaging cdk generated assets in solutions internal pipelines +- Use [DefaultStackSynthesizer](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.DefaultStackSynthesizer.html) with different configurations to generate template for `cdk deploy` and on internal solutions pipeline +- Add esbuild bundler for lambda functions using `NodejsFunction`, reference [aws_lambda_nodejs](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda_nodejs-readme.html) +- Refactor pipeline scripts +- Changes semver dependency version to 7.5.2 for github reported vulnerability CVE-2022-25883 +- Changes word-wrap dependency version to aashutoshrathi/word-wrap for github reported vulnerability CVE-2023-26115 ## [6.1.2] - 2023-04-14 diff --git a/README.md b/README.md index 0e55135f8..64524e0c4 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ In addition to the AWS Solutions Constructs, the solution uses AWS CDK directly ## Prerequisites for Customization - [AWS Command Line Interface](https://aws.amazon.com/cli/) -- Node.js 14.x +- Node.js 16.x or later ### 1. Clone the repository diff --git a/source/constructs/bin/constructs.ts b/source/constructs/bin/constructs.ts index b3baf434d..0999d2005 100644 --- a/source/constructs/bin/constructs.ts +++ b/source/constructs/bin/constructs.ts @@ -19,9 +19,12 @@ if (DIST_OUTPUT_BUCKET && SOLUTION_NAME && VERSION) }); const app = new App(); +const solutionDisplayName = "Serverless Image Handler"; +const description = `(${app.node.tryGetContext("solutionId")}) - ${solutionDisplayName}. Version ${VERSION ?? app.node.tryGetContext("solutionVersion")}`; // eslint-disable-next-line no-new new ServerlessImageHandlerStack(app, "ServerlessImageHandlerStack", { synthesizer: synthesizer, + description: description, solutionId: app.node.tryGetContext("solutionId"), solutionVersion: app.node.tryGetContext("solutionVersion"), solutionName: app.node.tryGetContext("solutionName"), diff --git a/source/constructs/cdk.json b/source/constructs/cdk.json index 0ab0ad0c9..d0d468589 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-6.2.0", + "solutionVersion": "custom-v6.2.1", "solutionName": "serverless-image-handler" } } \ No newline at end of file diff --git a/source/constructs/lib/common-resources/custom-resources/custom-resource-construct.ts b/source/constructs/lib/common-resources/custom-resources/custom-resource-construct.ts index e0e5a2a82..f350eae79 100644 --- a/source/constructs/lib/common-resources/custom-resources/custom-resource-construct.ts +++ b/source/constructs/lib/common-resources/custom-resources/custom-resource-construct.ts @@ -7,12 +7,13 @@ import { Function as LambdaFunction, Runtime } from "aws-cdk-lib/aws-lambda"; import { NodejsFunction } from "aws-cdk-lib/aws-lambda-nodejs"; import { Bucket, IBucket } from "aws-cdk-lib/aws-s3"; import { BucketDeployment, Source as S3Source } from "aws-cdk-lib/aws-s3-deployment"; -import { ArnFormat, Aws, CfnCondition, CfnResource, CustomResource, Duration, Lazy, Stack } from "aws-cdk-lib"; +import { ArnFormat, Aspects, Aws, CfnCondition, CfnResource, CustomResource, Duration, Lazy, Stack } from "aws-cdk-lib"; import { Construct } from "constructs"; import { addCfnSuppressRules } from "../../../utils/utils"; import { SolutionConstructProps } from "../../types"; import { CommonResourcesProps, Conditions } from "../common-resources-construct"; +import { ConditionAspect } from "../../../utils/aspects"; export interface CustomResourcesConstructProps extends CommonResourcesProps { readonly conditions: Conditions; @@ -179,10 +180,11 @@ export class CustomResourcesConstruct extends Construct { public setupCopyWebsiteCustomResource(props: SetupCopyWebsiteCustomResourceProps) { // Stage static assets for the front-end from the local /* eslint-disable no-new */ - new BucketDeployment(this, "DeployWebsite", { + const bucketDeployment = new BucketDeployment(this, "DeployWebsite", { sources: [S3Source.asset(path.join(__dirname, "../../../../demo-ui"))], destinationBucket: props.hostingBucket, }); + Aspects.of(bucketDeployment).add(new ConditionAspect(this.conditions.deployUICondition)); } public setupPutWebsiteConfigCustomResource(props: SetupPutWebsiteConfigCustomResourceProps) { diff --git a/source/constructs/lib/serverless-image-stack.ts b/source/constructs/lib/serverless-image-stack.ts index e49231153..f92104947 100644 --- a/source/constructs/lib/serverless-image-stack.ts +++ b/source/constructs/lib/serverless-image-stack.ts @@ -4,7 +4,7 @@ import { PriceClass } from "aws-cdk-lib/aws-cloudfront"; import { Aspects, CfnMapping, CfnOutput, CfnParameter, Stack, StackProps, Tags } from "aws-cdk-lib"; import { Construct } from "constructs"; -import { SuppressLambdaFunctionCfnRulesAspect } from "../utils/aspects"; +import { ConditionAspect, SuppressLambdaFunctionCfnRulesAspect } from "../utils/aspects"; import { BackEnd } from "./back-end/back-end-construct"; import { CommonResources } from "./common-resources/common-resources-construct"; import { FrontEndConstruct as FrontEnd } from "./front-end/front-end-construct"; @@ -199,6 +199,8 @@ export class ServerlessImageHandlerStack extends Stack { commonResources.customResources.setupCopyWebsiteCustomResource({ hostingBucket: frontEnd.websiteHostingBucket, }); + const singletonFunction = this.node.findChild("Custom::CDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C"); + Aspects.of(singletonFunction).add(new ConditionAspect(commonResources.conditions.deployUICondition)); commonResources.customResources.setupPutWebsiteConfigCustomResource({ hostingBucket: frontEnd.websiteHostingBucket, diff --git a/source/constructs/package.json b/source/constructs/package.json index bfa6874a4..d76def7c5 100644 --- a/source/constructs/package.json +++ b/source/constructs/package.json @@ -1,6 +1,6 @@ { "name": "constructs", - "version": "6.2.0", + "version": "6.2.1", "description": "Serverless Image Handler Constructs", "license": "Apache-2.0", "bin": { diff --git a/source/constructs/test/__snapshots__/constructs.test.ts.snap b/source/constructs/test/__snapshots__/constructs.test.ts.snap index a6965a38b..94ac68192 100644 --- a/source/constructs/test/__snapshots__/constructs.test.ts.snap +++ b/source/constructs/test/__snapshots__/constructs.test.ts.snap @@ -350,7 +350,7 @@ exports[`Serverless Image Handler Stack Snapshot 1`] = ` "Solutions:ApplicationType": "AWS-Solutions", "Solutions:SolutionID": "S0ABC", "Solutions:SolutionName": "sih", - "Solutions:SolutionVersion": "v6.2.0", + "Solutions:SolutionVersion": "v6.2.1", }, }, "Type": "AWS::ServiceCatalogAppRegistry::Application", @@ -1150,9 +1150,9 @@ exports[`Serverless Image Handler Stack Snapshot 1`] = ` "S3Bucket": { "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}", }, - "S3Key": "a0b1a27ff795cbf91cf437968a83823da180d2a071ab88a08eaadde821211f8a.zip", + "S3Key": "82f1ba8dc3b6177b733d951f282f5451925f6fb067ddd9626328d91468b7c9fc.zip", }, - "Description": "sih (v6.2.0): Performs image edits and manipulations", + "Description": "sih (v6.2.1): Performs image edits and manipulations", "Environment": { "Variables": { "AUTO_WEBP": { @@ -1419,13 +1419,13 @@ exports[`Serverless Image Handler Stack Snapshot 1`] = ` }, "S3Key": "1d9c0f7ba21ae4df4d9f33af092ffe6bf4c806ea06398e947419c4e7f091d52b.zip", }, - "Description": "sih (v6.2.0): Custom resource", + "Description": "sih (v6.2.1): Custom resource", "Environment": { "Variables": { "AWS_NODEJS_CONNECTION_REUSE_ENABLED": "1", "RETRY_SECONDS": "5", "SOLUTION_ID": "S0ABC", - "SOLUTION_VERSION": "v6.2.0", + "SOLUTION_VERSION": "v6.2.1", }, }, "Handler": "index.handler", @@ -1575,6 +1575,7 @@ exports[`Serverless Image Handler Stack Snapshot 1`] = ` "UpdateReplacePolicy": "Delete", }, "CommonResourcesCustomResourcesDeployWebsiteAwsCliLayerBC025F39": { + "Condition": "CommonResourcesDeployDemoUICondition308D3B09", "Properties": { "Content": { "S3Bucket": { @@ -1587,6 +1588,7 @@ exports[`Serverless Image Handler Stack Snapshot 1`] = ` "Type": "AWS::Lambda::LayerVersion", }, "CommonResourcesCustomResourcesDeployWebsiteCustomResourceECB9B136": { + "Condition": "CommonResourcesDeployDemoUICondition308D3B09", "DeletionPolicy": "Delete", "Properties": { "DestinationBucketName": { @@ -1730,6 +1732,7 @@ exports[`Serverless Image Handler Stack Snapshot 1`] = ` "Type": "AWS::IAM::Policy", }, "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756C81C01536": { + "Condition": "CommonResourcesDeployDemoUICondition308D3B09", "DependsOn": [ "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRoleDefaultPolicy88902FDF", "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265", @@ -1788,6 +1791,7 @@ exports[`Serverless Image Handler Stack Snapshot 1`] = ` "Type": "AWS::Lambda::Function", }, "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRole89A01265": { + "Condition": "CommonResourcesDeployDemoUICondition308D3B09", "Properties": { "AssumeRolePolicyDocument": { "Statement": [ @@ -1825,6 +1829,7 @@ exports[`Serverless Image Handler Stack Snapshot 1`] = ` "Type": "AWS::IAM::Role", }, "CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756CServiceRoleDefaultPolicy88902FDF": { + "Condition": "CommonResourcesDeployDemoUICondition308D3B09", "Properties": { "PolicyDocument": { "Statement": [ @@ -1924,7 +1929,7 @@ exports[`Serverless Image Handler Stack Snapshot 1`] = ` "applicationType": "AWS-Solutions", "solutionID": "S0ABC", "solutionName": "sih", - "version": "v6.2.0", + "version": "v6.2.1", }, "Description": "Attribute group for solution information", "Name": { diff --git a/source/constructs/test/constructs.test.ts b/source/constructs/test/constructs.test.ts index 420c373ab..75c76691b 100644 --- a/source/constructs/test/constructs.test.ts +++ b/source/constructs/test/constructs.test.ts @@ -12,7 +12,7 @@ test("Serverless Image Handler Stack Snapshot", () => { const stack = new ServerlessImageHandlerStack(app, "TestStack", { solutionId: "S0ABC", solutionName: "sih", - solutionVersion: "v6.2.0", + solutionVersion: "v6.2.1", }); const template = Template.fromStack(stack); diff --git a/source/custom-resource/package.json b/source/custom-resource/package.json index be9f1f8de..7b5f537c9 100644 --- a/source/custom-resource/package.json +++ b/source/custom-resource/package.json @@ -1,6 +1,6 @@ { "name": "custom-resource", - "version": "6.2.0", + "version": "6.2.1", "private": true, "description": "Serverless Image Handler custom resource", "license": "Apache-2.0", diff --git a/source/image-handler/image-request.ts b/source/image-handler/image-request.ts index 4180356f9..372339705 100644 --- a/source/image-handler/image-request.ts +++ b/source/image-handler/image-request.ts @@ -344,7 +344,7 @@ export class ImageRequest { } else if (definedEnvironmentVariables) { // use rewrite function then thumbor mappings return RequestTypes.CUSTOM; - } else if (matchThumbor1.test(path) && matchThumbor2.test(path) && matchThumbor3.test(path)) { + } else if (matchThumbor1.test(path) && (matchThumbor2.test(path) || matchThumbor3.test(path))) { // use thumbor mappings return RequestTypes.THUMBOR; } else { diff --git a/source/image-handler/package.json b/source/image-handler/package.json index 1aca72be7..50ba065fe 100644 --- a/source/image-handler/package.json +++ b/source/image-handler/package.json @@ -1,6 +1,6 @@ { "name": "image-handler", - "version": "6.2.0", + "version": "6.2.1", "private": true, "description": "A Lambda function for performing on-demand image edits and manipulations.", "license": "Apache-2.0", diff --git a/source/image-handler/test/image-request/parse-request-type.spec.ts b/source/image-handler/test/image-request/parse-request-type.spec.ts index 0759bd8f7..34fb2d0c0 100644 --- a/source/image-handler/test/image-request/parse-request-type.spec.ts +++ b/source/image-handler/test/image-request/parse-request-type.spec.ts @@ -109,4 +109,17 @@ describe("parseRequestType", () => { }); } }); + + it("Should pass if a path is provided without an extension", () => { + // Arrange + const event = { path: "/image" }; + + // Act + const imageRequest = new ImageRequest(s3Client, secretProvider); + const result = imageRequest.parseRequestType(event); + + // Assert + const expectedResult = RequestTypes.THUMBOR; + expect(result).toEqual(expectedResult); + }); }); diff --git a/source/package.json b/source/package.json index d875e707b..9d86a441b 100644 --- a/source/package.json +++ b/source/package.json @@ -1,6 +1,6 @@ { "name": "source", - "version": "6.2.0", + "version": "6.2.1", "private": true, "description": "ESLint and prettier dependencies to be used within the solution", "license": "Apache-2.0", diff --git a/source/solution-utils/package.json b/source/solution-utils/package.json index 1c5294047..88236a8e8 100644 --- a/source/solution-utils/package.json +++ b/source/solution-utils/package.json @@ -1,6 +1,6 @@ { "name": "solution-utils", - "version": "6.2.0", + "version": "6.2.1", "private": true, "description": "Utilities to be used within this solution", "license": "Apache-2.0",