Skip to content

Commit

Permalink
Merge pull request #1199 from awslabs/bump/2.69.0
Browse files Browse the repository at this point in the history
chore(release): 2.69.0
  • Loading branch information
biffgaut authored Sep 11, 2024
2 parents 4679aa4 + c09ebf4 commit 636e41d
Show file tree
Hide file tree
Showing 20 changed files with 2,816 additions and 208 deletions.
1 change: 1 addition & 0 deletions .viperlightignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ source/patterns/@aws-solutions-constructs/aws-cloudfront-apigateway/test/integ.c
source/patterns/@aws-solutions-constructs/aws-apigateway-dynamodb/test/integ.apiddb-apigateway-dynamodb-existing-table.expected.json:60
CODE_OF_CONDUCT.md:4
CONTRIBUTING.md:244
SECURITY.md:2
source/patterns/@aws-solutions-constructs/core/test/step-function-helper.test.ts:107
source/patterns/@aws-solutions-constructs/aws-kinesisstreams-gluejob/test/test.kinesisstream-gluejob.test.ts:126
source/patterns/@aws-solutions-constructs/aws-lambda-sqs/test/integ.lamsqs-deployFunction.expected.json:112
Expand Down
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

## [2.69.0](https://github.com/awslabs/aws-solutions-constructs/compare/v2.68.0...v2.69.0) (2024-09-11)

Built on CDK v2.154.1

### Features

* **aws-openapigateway-lambda:** update construct to allow specifying an inline api definition ([#1190](https://github.com/awslabs/aws-solutions-constructs/issues/1190)) ([b1baf59](https://github.com/awslabs/aws-solutions-constructs/commit/b1baf59c13d6270cd1e32dcaed7dae3c6b302087))

## [2.68.0](https://github.com/awslabs/aws-solutions-constructs/compare/v2.67.1...v2.68.0) (2024-08-28)

Built on CDK v2.154.1
Expand Down Expand Up @@ -218,7 +226,7 @@ Built on CDK v2.111.0
### Bug Fixes

* **aws-apigateway-sqs:** Remove /message path when delete method is not allowed ([#1030](https://github.com/awslabs/aws-solutions-constructs/issues/1030)) ([f772200](https://github.com/awslabs/aws-solutions-constructs/commit/f772200d6885cf0e0030239ce6f7511cdb2814d6))
=======


## [2.47.0](https://github.com/aws-solutions-constructs-team/aws-solutions-constructs-test/compare/v2.14.0...v2.47.0) (2023-11-27)

Expand Down
3 changes: 3 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### Reporting Security Issues
We take all security reports seriously. When we receive such reports, we will investigate and subsequently address any potential vulnerabilities as quickly as possible. If you discover a potential security issue in this project, please notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/) or directly via email to [AWS Security](mailto:[email protected]). Please do not create a public GitHub issue in this project.

2 changes: 1 addition & 1 deletion source/lerna.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
"./patterns/@aws-solutions-constructs/*"
],
"rejectCycles": "true",
"version": "2.68.0"
"version": "2.69.0"
}
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ new OpenApiGatewayToLambda(this, "OpenApiGatewayToLambda", OpenApiGatewayToLambd
|apiDefinitionBucket?|[`s3.IBucket`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.IBucket.html)|S3 Bucket where the OpenAPI spec file is located. When specifying this property, `apiDefinitionKey` must also be specified.|
|apiDefinitionKey?|`string`|S3 Object name of the OpenAPI spec file. When specifying this property, `apiDefinitionBucket` must also be specified.|
|apiDefinitionAsset?|[`aws_s3_assets.Asset`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3_assets.Asset.html)|Local file asset of the OpenAPI spec file.|
|apiDefinitionJson?|any|OpenAPI specification represented in a JSON object to be embedded in the CloudFormation template. IMPORTANT - Including the spec in the template introduces a risk of the template growing too big, but there are some use cases that require an embedded spec. Unless your use case explicitly requires an embedded spec you should pass your spec as an S3 asset.|
|apiIntegrations|`ApiIntegration[]`|One or more key-value pairs that contain an id for the api integration and either an existing lambda function or an instance of the LambdaProps. Please see the `Overview of how the OpenAPI file transformation works` section below for more usage details.|
|logGroupProps?|[`logs.LogGroupProps`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_logs.LogGroupProps.html)|User provided props to override the default props for for the CloudWatchLogs LogGroup.|

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,58 +11,18 @@
* and limitations under the License.
*/

import { Aws } from 'aws-cdk-lib';
import * as cdk from "aws-cdk-lib";
import { Construct } from 'constructs';
import * as apigateway from 'aws-cdk-lib/aws-apigateway';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as logs from 'aws-cdk-lib/aws-logs';
import * as iam from 'aws-cdk-lib/aws-iam';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as defaults from '@aws-solutions-constructs/core';
import * as resources from '@aws-solutions-constructs/resources';
import { RestApiBaseProps } from 'aws-cdk-lib/aws-apigateway';
import { Asset } from 'aws-cdk-lib/aws-s3-assets';

/**
* The ApiIntegration interface is used to correlate a user-specified id with either a existing lambda function or set of lambda props.
*
* See the 'Overview of how the OpenAPI file transformation works' section of the README.md for more details on its usage.
*/
export interface ApiIntegration {
/**
* Id of the ApiIntegration, used to correlate this lambda function to the api integration in the open api definition.
*
* Note this is not a CDK Construct ID, and is instead a client defined string used to map the resolved lambda resource with the OpenAPI definition.
*/
readonly id: string;
/**
* The Lambda function to associate with the API method in the OpenAPI file matched by id.
*
* One and only one of existingLambdaObj or lambdaFunctionProps must be specified, any other combination will cause an error.
*/
readonly existingLambdaObj?: lambda.Function;
/**
* Properties for the Lambda function to create and associate with the API method in the OpenAPI file matched by id.
*
* One and only one of existingLambdaObj or lambdaFunctionProps must be specified, any other combination will cause an error.
*/
readonly lambdaFunctionProps?: lambda.FunctionProps;
}

/**
* Helper object to map an ApiIntegration id to its resolved lambda.Function. This type is exposed as a property on the instantiated construct.
*/
export interface ApiLambdaFunction {
/**
* Id of the ApiIntegration, used to correlate this lambda function to the api integration in the open api definition.
*/
readonly id: string;
/**
* The instantiated lambda.Function.
*/
readonly lambdaFunction: lambda.Function;
}
import { ApiIntegration, CheckOpenApiProps, ApiLambdaFunction, ObtainApiDefinition } from './openapi-helper';
// openapi-helper is on its way to core, so these interfaces must be exported here
export { ApiIntegration, ApiLambdaFunction } from './openapi-helper';

export interface OpenApiGatewayToLambdaProps {
/**
Expand All @@ -77,6 +37,13 @@ export interface OpenApiGatewayToLambdaProps {
* Local file asset of the OpenAPI spec file.
*/
readonly apiDefinitionAsset?: Asset;
/**
* OpenAPI specification represented in a JSON object to be embedded in the CloudFormation template.
* IMPORTANT - Including the spec in the template introduces a risk of the template growing too big, but
* there are some use cases that require an embedded spec. Unless your use case explicitly requires an embedded spec
* you should pass your spec as an S3 asset.
*/
readonly apiDefinitionJson?: any;
/**
* One or more key-value pairs that contain an id for the api integration
* and either an existing lambda function or an instance of the LambdaProps.
Expand Down Expand Up @@ -144,10 +111,7 @@ export class OpenApiGatewayToLambda extends Construct {

constructor(scope: Construct, id: string, props: OpenApiGatewayToLambdaProps) {
super(scope, id);
CheckOpenapiProps(props);

const apiDefinitionBucket = props.apiDefinitionBucket ?? props.apiDefinitionAsset?.bucket;
const apiDefinitionKey = props.apiDefinitionKey ?? props.apiDefinitionAsset?.s3ObjectKey;
CheckOpenApiProps(props);

// store a counter to be able to uniquely name lambda functions to avoid naming collisions
let lambdaCounter = 0;
Expand All @@ -169,45 +133,27 @@ export class OpenApiGatewayToLambda extends Construct {
}
});

// Map each id and lambda function pair to the required format for the template writer custom resource
const apiIntegrationUris = this.apiLambdaFunctions.map(apiLambdaFunction => {
// the placeholder string that will be replaced in the OpenAPI Definition
const uriPlaceholderString = apiLambdaFunction.id;
// the endpoint URI of the backing lambda function, as defined in the API Gateway extensions for OpenAPI here:
// https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-swagger-extensions-integration.html
const uriResolvedValue = `arn:${Aws.PARTITION}:apigateway:${Aws.REGION}:lambda:path/2015-03-31/functions/${apiLambdaFunction.lambdaFunction.functionArn}/invocations`;

return {
id: uriPlaceholderString,
value: uriResolvedValue
};
});

// This custom resource will overwrite the string placeholders in the openapi definition with the resolved values of the lambda URIs
const apiDefinitionWriter = resources.createTemplateWriterCustomResource(this, 'Api', {
// CheckAlbProps() has confirmed the existence of these values
templateBucket: apiDefinitionBucket!,
templateKey: apiDefinitionKey!,
templateValues: apiIntegrationUris,
timeout: props.internalTransformTimeout ?? cdk.Duration.minutes(1),
memorySize: props.internalTransformMemorySize ?? 1024
const definition = ObtainApiDefinition(this, {
tokenToFunctionMap: this.apiLambdaFunctions,
apiDefinitionBucket: props.apiDefinitionBucket,
apiDefinitionKey: props.apiDefinitionKey,
apiDefinitionAsset: props.apiDefinitionAsset,
apiJsonDefinition: props.apiDefinitionJson,
internalTransformTimeout: props.internalTransformTimeout,
internalTransformMemorySize: props.internalTransformMemorySize
});

const specRestApiResponse = defaults.CreateSpecRestApi(this, {
...props.apiGatewayProps,
apiDefinition: apigateway.ApiDefinition.fromBucket(
apiDefinitionWriter.s3Bucket,
apiDefinitionWriter.s3Key
)
apiDefinition: definition
}, props.logGroupProps);

this.apiGateway = specRestApiResponse.api;
this.apiGatewayCloudWatchRole = specRestApiResponse.role;
this.apiGatewayLogGroup = specRestApiResponse.logGroup;

// Redeploy the API any time the incoming API definition changes (from asset or s3 object)
this.apiGateway.latestDeployment?.addToLogicalId(apiDefinitionKey);

// Redeploy the API any time a decoupled (non-inline) API definition changes (from asset or s3 object)
this.apiGateway.latestDeployment?.addToLogicalId(props.apiDefinitionKey ?? props.apiDefinitionAsset?.s3ObjectKey);
this.apiLambdaFunctions.forEach(apiLambdaFunction => {
// Redeploy the API any time one of the lambda functions changes
this.apiGateway.latestDeployment?.addToLogicalId(apiLambdaFunction.lambdaFunction.functionArn);
Expand All @@ -219,32 +165,3 @@ export class OpenApiGatewayToLambda extends Construct {
});
}
}

function CheckOpenapiProps(props: OpenApiGatewayToLambdaProps) {

let errorMessages = '';
let errorFound = false;

if (props.apiDefinitionAsset && (props.apiDefinitionBucket || props.apiDefinitionKey)) {
errorMessages += 'Either apiDefinitionBucket/apiDefinitionKey or apiDefinitionAsset must be specified, but not both\n';
errorFound = true;
}

const apiDefinitionBucket = props.apiDefinitionBucket ?? props.apiDefinitionAsset?.bucket;
const apiDefinitionKey = props.apiDefinitionKey ?? props.apiDefinitionAsset?.s3ObjectKey;

if (apiDefinitionBucket === undefined || apiDefinitionKey === undefined) {
errorMessages += 'Either apiDefinitionBucket/apiDefinitionKey or apiDefinitionAsset must be specified\n';
errorFound = true;
}

if (props.apiIntegrations === undefined || props.apiIntegrations.length < 1) {
errorMessages += 'At least one ApiIntegration must be specified in the apiIntegrations property\n';
errorFound = true;
}

if (errorFound) {
throw new Error(errorMessages);
}

}
Loading

0 comments on commit 636e41d

Please sign in to comment.