diff --git a/examples/cdk/functions/common/getUuid.ts b/examples/cdk/functions/common/getUuid.ts new file mode 100644 index 0000000000..eb567314bd --- /dev/null +++ b/examples/cdk/functions/common/getUuid.ts @@ -0,0 +1,22 @@ +import { logger } from './powertools'; +import { getParameter } from '@aws-lambda-powertools/parameters/ssm'; +import { randomUUID } from 'node:crypto'; +import { default as request } from 'phin'; + +export const getUuid = async (): Promise => { + const uuidApiUrl = await getParameter('/app/uuid-api-url'); + if (!uuidApiUrl) { + // create uuid locally + logger.warn('No uuid-api-url parameter found, creating uuid locally'); + + return randomUUID(); + } else { + // Request a sample random uuid from a webservice + const res = await request<{ uuid: string }>({ + url: uuidApiUrl, + parse: 'json', + }); + + return res.body.uuid; + } +}; diff --git a/examples/cdk/functions/common/powertools.ts b/examples/cdk/functions/common/powertools.ts index 0b5a768326..01949a91ac 100644 --- a/examples/cdk/functions/common/powertools.ts +++ b/examples/cdk/functions/common/powertools.ts @@ -1,8 +1,7 @@ import { Logger } from '@aws-lambda-powertools/logger'; import { Metrics } from '@aws-lambda-powertools/metrics'; import { Tracer } from '@aws-lambda-powertools/tracer'; - -const awsLambdaPowertoolsVersion = '1.5.0'; +import { PT_VERSION } from '@aws-lambda-powertools/commons/lib/version'; const defaultValues = { region: process.env.AWS_REGION || 'N/A', @@ -14,7 +13,7 @@ const logger = new Logger({ ...defaultValues, logger: { name: '@aws-lambda-powertools/logger', - version: awsLambdaPowertoolsVersion, + version: PT_VERSION, }, }, }); diff --git a/examples/cdk/functions/get-all-items.ts b/examples/cdk/functions/get-all-items.ts index a0b69aa0ff..d0b1acb4b8 100644 --- a/examples/cdk/functions/get-all-items.ts +++ b/examples/cdk/functions/get-all-items.ts @@ -1,17 +1,17 @@ +import { injectLambdaContext } from '@aws-lambda-powertools/logger'; +import { logMetrics } from '@aws-lambda-powertools/metrics'; +import { captureLambdaHandler } from '@aws-lambda-powertools/tracer'; +import { ScanCommand } from '@aws-sdk/lib-dynamodb'; +import middy from '@middy/core'; import { APIGatewayProxyEvent, APIGatewayProxyResult, Context, } from 'aws-lambda'; -import middy from '@middy/core'; import { tableName } from './common/constants'; -import { logger, tracer, metrics } from './common/powertools'; -import { logMetrics } from '@aws-lambda-powertools/metrics'; -import { injectLambdaContext } from '@aws-lambda-powertools/logger'; -import { captureLambdaHandler } from '@aws-lambda-powertools/tracer'; import { docClient } from './common/dynamodb-client'; -import { ScanCommand } from '@aws-sdk/lib-dynamodb'; -import { default as request } from 'phin'; +import { getUuid } from './common/getUuid'; +import { logger, metrics, tracer } from './common/powertools'; /* * @@ -45,12 +45,7 @@ const getAllItemsHandler = async ( awsRequestId: context.awsRequestId, }); - // Request a sample random uuid from a webservice - const res = await request<{ uuid: string }>({ - url: 'https://httpbin.org/uuid', - parse: 'json', - }); - const { uuid } = res.body; + const uuid = await getUuid(); // Logger: Append uuid to each log statement logger.appendKeys({ uuid }); diff --git a/examples/cdk/functions/get-by-id.ts b/examples/cdk/functions/get-by-id.ts index db536b3f23..9ad13fcb2f 100644 --- a/examples/cdk/functions/get-by-id.ts +++ b/examples/cdk/functions/get-by-id.ts @@ -1,14 +1,14 @@ +import { LambdaInterface } from '@aws-lambda-powertools/commons'; +import { GetCommand } from '@aws-sdk/lib-dynamodb'; import { APIGatewayProxyEvent, APIGatewayProxyResult, Context, } from 'aws-lambda'; import { tableName } from './common/constants'; -import { logger, tracer, metrics } from './common/powertools'; -import { LambdaInterface } from '@aws-lambda-powertools/commons'; import { docClient } from './common/dynamodb-client'; -import { GetCommand } from '@aws-sdk/lib-dynamodb'; -import { default as request } from 'phin'; +import { getUuid } from './common/getUuid'; +import { logger, metrics, tracer } from './common/powertools'; /* * @@ -28,14 +28,7 @@ import { default as request } from 'phin'; class Lambda implements LambdaInterface { @tracer.captureMethod() public async getUuid(): Promise { - // Request a sample random uuid from a webservice - const res = await request<{ uuid: string }>({ - url: 'https://httpbin.org/uuid', - parse: 'json', - }); - const { uuid } = res.body; - - return uuid; + return getUuid(); } @tracer.captureLambdaHandler({ captureResponse: false }) // by default the tracer would add the response as metadata on the segment, but there is a chance to hit the 64kb segment size limit. Therefore set captureResponse: false diff --git a/examples/cdk/functions/put-item.ts b/examples/cdk/functions/put-item.ts index c51b37c094..b686244d2f 100644 --- a/examples/cdk/functions/put-item.ts +++ b/examples/cdk/functions/put-item.ts @@ -1,14 +1,14 @@ +import { PutCommand } from '@aws-sdk/lib-dynamodb'; import { APIGatewayProxyEvent, APIGatewayProxyResult, Context, } from 'aws-lambda'; +import type { Subsegment } from 'aws-xray-sdk-core'; import { tableName } from './common/constants'; -import { logger, tracer, metrics } from './common/powertools'; import { docClient } from './common/dynamodb-client'; -import { PutCommand } from '@aws-sdk/lib-dynamodb'; -import { default as request } from 'phin'; -import type { Subsegment } from 'aws-xray-sdk-core'; +import { getUuid } from './common/getUuid'; +import { logger, metrics, tracer } from './common/powertools'; /** * @@ -59,12 +59,7 @@ export const handler = async ( awsRequestId: context.awsRequestId, }); - // Request a sample random uuid from a webservice - const res = await request<{ uuid: string }>({ - url: 'https://httpbin.org/uuid', - parse: 'json', - }); - const { uuid } = res.body; + const uuid = await getUuid(); // Logger: Append uuid to each log statement logger.appendKeys({ uuid }); diff --git a/examples/cdk/functions/uuid.ts b/examples/cdk/functions/uuid.ts new file mode 100644 index 0000000000..58e017dbea --- /dev/null +++ b/examples/cdk/functions/uuid.ts @@ -0,0 +1,8 @@ +import { randomUUID } from 'node:crypto'; + +exports.handler = async (_event) => { + return { + statusCode: 200, + body: JSON.stringify(randomUUID()), + }; +}; diff --git a/examples/cdk/package.json b/examples/cdk/package.json index aba33bb7a1..d5c5454281 100644 --- a/examples/cdk/package.json +++ b/examples/cdk/package.json @@ -25,9 +25,12 @@ "*.js": "npm run lint-fix" }, "devDependencies": { + "@aws-lambda-powertools/commons": "^1.11.1", "@aws-lambda-powertools/logger": "^1.11.1", "@aws-lambda-powertools/metrics": "^1.11.1", + "@aws-lambda-powertools/parameters": "^1.11.1", "@aws-lambda-powertools/tracer": "^1.11.1", + "@aws-sdk/client-ssm": "^3.360.0", "@aws-sdk/lib-dynamodb": "^3.360.0", "@types/aws-lambda": "^8.10.109", "@types/jest": "^29.2.4", diff --git a/examples/cdk/src/example-stack.ts b/examples/cdk/src/example-stack.ts index e79efc42b8..179f86149b 100644 --- a/examples/cdk/src/example-stack.ts +++ b/examples/cdk/src/example-stack.ts @@ -1,13 +1,14 @@ -import { Stack, StackProps, Duration } from 'aws-cdk-lib'; -import { Construct } from 'constructs'; -import { Table, BillingMode, AttributeType } from 'aws-cdk-lib/aws-dynamodb'; +import { Duration, Stack, StackProps } from 'aws-cdk-lib'; +import { LambdaIntegration, RestApi } from 'aws-cdk-lib/aws-apigateway'; +import { AttributeType, BillingMode, Table } from 'aws-cdk-lib/aws-dynamodb'; +import { LayerVersion, Runtime, Tracing } from 'aws-cdk-lib/aws-lambda'; import { NodejsFunction, NodejsFunctionProps, } from 'aws-cdk-lib/aws-lambda-nodejs'; -import { Runtime, Tracing, LayerVersion } from 'aws-cdk-lib/aws-lambda'; import { RetentionDays } from 'aws-cdk-lib/aws-logs'; -import { RestApi, LambdaIntegration } from 'aws-cdk-lib/aws-apigateway'; +import { StringParameter } from 'aws-cdk-lib/aws-ssm'; +import { Construct } from 'constructs'; const commonProps: Partial = { runtime: Runtime.NODEJS_18_X, @@ -37,6 +38,8 @@ export class CdkAppStack extends Stack { public constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); + const uuidApi = new UuidApi(this, 'uuid-api'); + const table = new Table(this, 'Table', { billingMode: BillingMode.PAY_PER_REQUEST, partitionKey: { @@ -51,7 +54,7 @@ export class CdkAppStack extends Stack { 'powertools-layer', `arn:aws:lambda:${ Stack.of(this).region - }:094274105915:layer:AWSLambdaPowertoolsTypeScript:6` + }:094274105915:layer:AWSLambdaPowertoolsTypeScript:16` ) ); @@ -76,12 +79,20 @@ export class CdkAppStack extends Stack { entry: './functions/get-by-id.ts', handler: 'handler', }); + + uuidApi.apiUrlParam.grantRead(getByIdFn); + uuidApi.apiUrlParam.grantRead(putItemFn); + uuidApi.apiUrlParam.grantRead(getAllItemsFn); + getByIdFn.addEnvironment('SAMPLE_TABLE', table.tableName); table.grantReadData(getByIdFn); const api = new RestApi(this, 'items-api', { restApiName: 'Items Service', description: 'This service serves items.', + deployOptions: { + tracingEnabled: true, + }, }); const itemPutIntegration = new LambdaIntegration(putItemFn); @@ -95,3 +106,32 @@ export class CdkAppStack extends Stack { item.addMethod('GET', itemIntegration); } } + +class UuidApi extends Construct { + public readonly apiUrlParam: StringParameter; + public constructor(scope: Construct, id: string) { + super(scope, id); + + const uuidFn = new NodejsFunction(this, 'UuidFn', { + runtime: Runtime.NODEJS_18_X, + entry: './functions/uuid.ts', + }); + + const api = new RestApi(this, 'uuid-api', { + restApiName: 'UUID Service', + description: 'This service serves UUIDs.', + deployOptions: { + tracingEnabled: true, + }, + }); + + const uuidIntegration = new LambdaIntegration(uuidFn); + const uuid = api.root.addResource('uuid'); + uuid.addMethod('GET', uuidIntegration); + + this.apiUrlParam = new StringParameter(this, 'uuid-api-url', { + parameterName: '/app/uuid-api-url', + stringValue: `${api.url}/uuid`, + }); + } +} diff --git a/examples/cdk/tests/cdk-app.test.ts b/examples/cdk/tests/cdk-app.test.ts index f67fce3d66..83ebfe2105 100644 --- a/examples/cdk/tests/cdk-app.test.ts +++ b/examples/cdk/tests/cdk-app.test.ts @@ -5,5 +5,5 @@ import * as CdkApp from '../src/example-stack'; test('CDK code synthesize', () => { const app = new cdk.App(); const stack = new CdkApp.CdkAppStack(app, 'MyTestStack'); - Template.fromStack(stack).resourceCountIs('AWS::Lambda::Function', 4); // The stack has 4 functions: 3 for the example, and 1 for the log retention that is deployed by CDK + Template.fromStack(stack).resourceCountIs('AWS::Lambda::Function', 5); // The stack has 4 functions: 3 for the example, and 1 for the log retention that is deployed by CDK }); diff --git a/examples/sam/package.json b/examples/sam/package.json index 65f00d0543..9a35d20c62 100644 --- a/examples/sam/package.json +++ b/examples/sam/package.json @@ -26,7 +26,6 @@ "@types/node": "18.11.17", "@typescript-eslint/eslint-plugin": "^5.46.1", "@typescript-eslint/parser": "^5.46.1", - "esbuild": "^0.16.9", "eslint": "^8.30.0", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^3.5.2", @@ -40,9 +39,12 @@ "@aws-lambda-powertools/logger": "^1.11.1", "@aws-lambda-powertools/metrics": "^1.11.1", "@aws-lambda-powertools/tracer": "^1.11.1", + "@aws-lambda-powertools/parameters": "^1.11.1", "@aws-sdk/client-dynamodb": "^3.360.0", + "@aws-sdk/client-ssm": "^3.360.0", "@aws-sdk/lib-dynamodb": "^3.360.0", "@middy/core": "^3.6.2", + "esbuild": "^0.18.14", "phin": "^3.7.0" } } diff --git a/examples/sam/src/common/getUuid.ts b/examples/sam/src/common/getUuid.ts new file mode 100644 index 0000000000..eb567314bd --- /dev/null +++ b/examples/sam/src/common/getUuid.ts @@ -0,0 +1,22 @@ +import { logger } from './powertools'; +import { getParameter } from '@aws-lambda-powertools/parameters/ssm'; +import { randomUUID } from 'node:crypto'; +import { default as request } from 'phin'; + +export const getUuid = async (): Promise => { + const uuidApiUrl = await getParameter('/app/uuid-api-url'); + if (!uuidApiUrl) { + // create uuid locally + logger.warn('No uuid-api-url parameter found, creating uuid locally'); + + return randomUUID(); + } else { + // Request a sample random uuid from a webservice + const res = await request<{ uuid: string }>({ + url: uuidApiUrl, + parse: 'json', + }); + + return res.body.uuid; + } +}; diff --git a/examples/sam/src/common/powertools.ts b/examples/sam/src/common/powertools.ts index 0b5a768326..01949a91ac 100644 --- a/examples/sam/src/common/powertools.ts +++ b/examples/sam/src/common/powertools.ts @@ -1,8 +1,7 @@ import { Logger } from '@aws-lambda-powertools/logger'; import { Metrics } from '@aws-lambda-powertools/metrics'; import { Tracer } from '@aws-lambda-powertools/tracer'; - -const awsLambdaPowertoolsVersion = '1.5.0'; +import { PT_VERSION } from '@aws-lambda-powertools/commons/lib/version'; const defaultValues = { region: process.env.AWS_REGION || 'N/A', @@ -14,7 +13,7 @@ const logger = new Logger({ ...defaultValues, logger: { name: '@aws-lambda-powertools/logger', - version: awsLambdaPowertoolsVersion, + version: PT_VERSION, }, }, }); diff --git a/examples/sam/src/get-all-items.ts b/examples/sam/src/get-all-items.ts index a0b69aa0ff..b0e3ec9ae6 100644 --- a/examples/sam/src/get-all-items.ts +++ b/examples/sam/src/get-all-items.ts @@ -11,7 +11,7 @@ import { injectLambdaContext } from '@aws-lambda-powertools/logger'; import { captureLambdaHandler } from '@aws-lambda-powertools/tracer'; import { docClient } from './common/dynamodb-client'; import { ScanCommand } from '@aws-sdk/lib-dynamodb'; -import { default as request } from 'phin'; +import { getUuid } from './common/getUuid'; /* * @@ -45,12 +45,7 @@ const getAllItemsHandler = async ( awsRequestId: context.awsRequestId, }); - // Request a sample random uuid from a webservice - const res = await request<{ uuid: string }>({ - url: 'https://httpbin.org/uuid', - parse: 'json', - }); - const { uuid } = res.body; + const uuid = await getUuid(); // Logger: Append uuid to each log statement logger.appendKeys({ uuid }); diff --git a/examples/sam/src/get-by-id.ts b/examples/sam/src/get-by-id.ts index db536b3f23..9ad13fcb2f 100644 --- a/examples/sam/src/get-by-id.ts +++ b/examples/sam/src/get-by-id.ts @@ -1,14 +1,14 @@ +import { LambdaInterface } from '@aws-lambda-powertools/commons'; +import { GetCommand } from '@aws-sdk/lib-dynamodb'; import { APIGatewayProxyEvent, APIGatewayProxyResult, Context, } from 'aws-lambda'; import { tableName } from './common/constants'; -import { logger, tracer, metrics } from './common/powertools'; -import { LambdaInterface } from '@aws-lambda-powertools/commons'; import { docClient } from './common/dynamodb-client'; -import { GetCommand } from '@aws-sdk/lib-dynamodb'; -import { default as request } from 'phin'; +import { getUuid } from './common/getUuid'; +import { logger, metrics, tracer } from './common/powertools'; /* * @@ -28,14 +28,7 @@ import { default as request } from 'phin'; class Lambda implements LambdaInterface { @tracer.captureMethod() public async getUuid(): Promise { - // Request a sample random uuid from a webservice - const res = await request<{ uuid: string }>({ - url: 'https://httpbin.org/uuid', - parse: 'json', - }); - const { uuid } = res.body; - - return uuid; + return getUuid(); } @tracer.captureLambdaHandler({ captureResponse: false }) // by default the tracer would add the response as metadata on the segment, but there is a chance to hit the 64kb segment size limit. Therefore set captureResponse: false diff --git a/examples/sam/src/get-uuid.ts b/examples/sam/src/get-uuid.ts new file mode 100644 index 0000000000..58e017dbea --- /dev/null +++ b/examples/sam/src/get-uuid.ts @@ -0,0 +1,8 @@ +import { randomUUID } from 'node:crypto'; + +exports.handler = async (_event) => { + return { + statusCode: 200, + body: JSON.stringify(randomUUID()), + }; +}; diff --git a/examples/sam/src/put-item.ts b/examples/sam/src/put-item.ts index 27ca35f06c..aab7116602 100644 --- a/examples/sam/src/put-item.ts +++ b/examples/sam/src/put-item.ts @@ -1,14 +1,14 @@ +import { PutCommand } from '@aws-sdk/lib-dynamodb'; import { APIGatewayProxyEvent, APIGatewayProxyResult, Context, } from 'aws-lambda'; +import type { Subsegment } from 'aws-xray-sdk-core'; import { tableName } from './common/constants'; -import { logger, tracer, metrics } from './common/powertools'; import { docClient } from './common/dynamodb-client'; -import { PutCommand } from '@aws-sdk/lib-dynamodb'; -import { default as request } from 'phin'; -import type { Subsegment } from 'aws-xray-sdk-core'; +import { logger, metrics, tracer } from './common/powertools'; +import { getUuid } from './common/getUuid'; /** * @@ -61,13 +61,7 @@ export const handler = async ( awsRequestId: context.awsRequestId, }); - // Request a sample random uuid from a webservice - const res = await request<{ uuid: string }>({ - url: 'https://httpbin.org/uuid', - parse: 'json', - }); - const { uuid } = res.body; - + const uuid = await getUuid(); // Logger: Append uuid to each log statement logger.appendKeys({ uuid }); diff --git a/examples/sam/template.yaml b/examples/sam/template.yaml index e44c619096..46e18f412e 100644 --- a/examples/sam/template.yaml +++ b/examples/sam/template.yaml @@ -11,6 +11,22 @@ Description: >- # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/transform-section-structure.html Transform: AWS::Serverless-2016-10-31 +Parameters: + apiGatewayName: + Type: String + Default: uuid-api + apiGatewayStageName: + Type: String + AllowedPattern: '[a-z0-9]+' + Default: dev + apiGatewayHTTPMethod: + Type: String + Default: GET + lambdaFunctionName: + Type: String + AllowedPattern: '[a-zA-Z0-9]+[a-zA-Z0-9-]+[a-zA-Z0-9]+' + Default: uuid-lambda + # Global configuration that all Functions inherit # https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-specification-template-anatomy-globals.html Globals: @@ -37,6 +53,8 @@ Resources: # Give Create/Read/Update/Delete Permissions to the SampleTable - DynamoDBReadPolicy: TableName: !Ref SampleTable + - SSMParameterWithSlashPrefixReadPolicy: + ParameterName: !Ref uuidApiUrlParameter Tracing: Active Environment: Variables: @@ -53,7 +71,7 @@ Resources: Properties: Path: / Method: GET - Metadata: + Metadata: # Manage esbuild properties BuildMethod: esbuild BuildProperties: @@ -76,6 +94,9 @@ Resources: # Give Create/Read/Update/Delete Permissions to the SampleTable - DynamoDBReadPolicy: TableName: !Ref SampleTable + # add ssm:getParameter permission to the function + - SSMParameterWithSlashPrefixReadPolicy: + ParameterName: !Ref uuidApiUrlParameter Tracing: Active Environment: Variables: @@ -92,7 +113,7 @@ Resources: Properties: Path: /{id} Method: GET - Metadata: + Metadata: # Manage esbuild properties BuildMethod: esbuild BuildProperties: @@ -105,6 +126,53 @@ Resources: EntryPoints: - src/get-by-id.ts + # This is a Lambda function config associated with the source code: get-uuid.js + getUuidFunction: + Type: AWS::Serverless::Function + Properties: + Handler: src/get-uuid.handler + Description: A simple example includes a HTTP get method to get a UUID. + Tracing: Active + FunctionName: !Ref lambdaFunctionName + Role: !GetAtt lambdaIAMRole.Arn + Environment: + Variables: + POWERTOOLS_SERVICE_NAME: items-store + POWERTOOLS_METRICS_NAMESPACE: PowertoolsSAMExample + LOG_LEVEL: Debug + # add ssm:getParameter permission to the function + Policies: + - SSMParameterWithSlashPrefixReadPolicy: + ParameterName: !Ref uuidApiUrlParameter + Events: + Api: + Type: Api + Properties: + Path: / + Method: GET + RestApiId: !Ref apiGateway + Metadata: + # Manage esbuild properties + BuildMethod: esbuild + BuildProperties: + Minify: true + Target: "ES2020" + Sourcemap: true + External: + - "uuid" + EntryPoints: + - src/get-uuid.ts + + # create ssm parameter with the value of the uuid api url + uuidApiUrlParameter: + Type: AWS::SSM::Parameter + Properties: + Name: /app/uuid-api-url + Type: String + Description: "Example parameter for UUID API URL" + Value: !Sub "https://${apiGateway}.execute-api.${AWS::Region}.amazonaws.com/${apiGatewayStageName}/" + + # This is a Lambda function config associated with the source code: put-item.js putItemFunction: Type: AWS::Serverless::Function @@ -115,6 +183,8 @@ Resources: # Give Create/Read/Update/Delete Permissions to the SampleTable - DynamoDBCrudPolicy: TableName: !Ref SampleTable + - SSMParameterWithSlashPrefixReadPolicy: + ParameterName: !Ref uuidApiUrlParameter Tracing: Active Environment: Variables: @@ -131,7 +201,7 @@ Resources: Properties: Path: / Method: POST - Metadata: + Metadata: # Manage esbuild properties BuildMethod: esbuild BuildProperties: @@ -141,7 +211,7 @@ Resources: External: - "@aws-sdk/lib-dynamodb" - "@aws-sdk/client-dynamodb" - EntryPoints: + EntryPoints: - src/put-item.ts # DynamoDB table to store item: {id: , name: } @@ -152,14 +222,75 @@ Resources: Name: id Type: String - Api: + apiGateway: Type: AWS::ApiGateway::RestApi Properties: - Name: !Sub ${AWS::StackName}-api - Description: "Example API" + Name: !Sub ${AWS::StackName}-uuid-api + Description: "Example API for UUID generation" + + apiGatewayDeployment: + Type: AWS::ApiGateway::Deployment + DependsOn: + - apiGatewayRootMethod + Properties: + RestApiId: !Ref apiGateway + StageName: !Ref apiGatewayStageName + + apiGatewayRootMethod: + Type: AWS::ApiGateway::Method + Properties: + AuthorizationType: NONE # NOSONAR + HttpMethod: !Ref apiGatewayHTTPMethod + Integration: + IntegrationHttpMethod: POST + Type: AWS_PROXY + Uri: !Sub + - arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${lambdaArn}/invocations + - lambdaArn: !GetAtt getUuidFunction.Arn + ResourceId: !GetAtt apiGateway.RootResourceId + RestApiId: !Ref apiGateway + + lambdaApiGatewayInvoke: + Type: AWS::Lambda::Permission + Properties: + Action: lambda:InvokeFunction + FunctionName: !GetAtt getUuidFunction.Arn + Principal: apigateway.amazonaws.com + SourceArn: !Sub arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${apiGateway}/${apiGatewayStageName}/*/ + lambdaIAMRole: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: + - Action: + - sts:AssumeRole + Effect: Allow + Principal: + Service: + - lambda.amazonaws.com + Policies: + - PolicyDocument: + Version: 2012-10-17 + Statement: + - Action: + - logs:CreateLogGroup + - logs:CreateLogStream + - logs:PutLogEvents + Effect: Allow + Resource: + - !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${lambdaFunctionName}:* + PolicyName: lambda + + lambdaLogGroup: + Type: AWS::Logs::LogGroup + Properties: + LogGroupName: !Sub /aws/lambda/${lambdaFunctionName} + RetentionInDays: 1 Outputs: - WebEndpoint: - Description: "API Gateway endpoint URL for Prod stage" - Value: !Sub "https://${Api}.execute-api.${AWS::Region}.amazonaws.com/Prod/" + + UuidWebEndpoint: + Description: "API Gateway endpoint URL for UUID endpoint" + Value: !Sub "https://${apiGateway}.execute-api.${AWS::Region}.amazonaws.com/dev/" \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index d9d180d8ae..f6cd0e5fd2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -297,9 +297,12 @@ "cdk-app": "bin/cdk-app.js" }, "devDependencies": { + "@aws-lambda-powertools/commons": "^1.11.1", "@aws-lambda-powertools/logger": "^1.11.1", "@aws-lambda-powertools/metrics": "^1.11.1", + "@aws-lambda-powertools/parameters": "^1.11.1", "@aws-lambda-powertools/tracer": "^1.11.1", + "@aws-sdk/client-ssm": "^3.360.0", "@aws-sdk/lib-dynamodb": "^3.360.0", "@types/aws-lambda": "^8.10.109", "@types/jest": "^29.2.4", @@ -339,10 +342,13 @@ "dependencies": { "@aws-lambda-powertools/logger": "^1.11.1", "@aws-lambda-powertools/metrics": "^1.11.1", + "@aws-lambda-powertools/parameters": "^1.11.1", "@aws-lambda-powertools/tracer": "^1.11.1", "@aws-sdk/client-dynamodb": "^3.360.0", + "@aws-sdk/client-ssm": "^3.360.0", "@aws-sdk/lib-dynamodb": "^3.360.0", "@middy/core": "^3.6.2", + "esbuild": "^0.18.14", "phin": "^3.7.0" }, "devDependencies": { @@ -351,7 +357,6 @@ "@types/node": "18.11.17", "@typescript-eslint/eslint-plugin": "^5.46.1", "@typescript-eslint/parser": "^5.46.1", - "esbuild": "^0.16.9", "eslint": "^8.30.0", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^3.5.2", @@ -362,12 +367,63 @@ "typescript": "^4.9.4" } }, + "examples/sam/node_modules/@esbuild/linux-arm64": { + "version": "0.18.15", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.15.tgz", + "integrity": "sha512-BWncQeuWDgYv0jTNzJjaNgleduV4tMbQjmk/zpPh/lUdMcNEAxy+jvneDJ6RJkrqloG7tB9S9rCrtfk/kuplsQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, "examples/sam/node_modules/@types/node": { "version": "18.11.17", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.17.tgz", "integrity": "sha512-HJSUJmni4BeDHhfzn6nF0sVmd1SMezP7/4F0Lq+aXzmp2xm9O7WXrUtHW/CHlYVtZUbByEvWidHqRtcJXGF2Ng==", "dev": true }, + "examples/sam/node_modules/esbuild": { + "version": "0.18.15", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.15.tgz", + "integrity": "sha512-3WOOLhrvuTGPRzQPU6waSDWrDTnQriia72McWcn6UCi43GhCHrXH4S59hKMeez+IITmdUuUyvbU9JIp+t3xlPQ==", + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.18.15", + "@esbuild/android-arm64": "0.18.15", + "@esbuild/android-x64": "0.18.15", + "@esbuild/darwin-arm64": "0.18.15", + "@esbuild/darwin-x64": "0.18.15", + "@esbuild/freebsd-arm64": "0.18.15", + "@esbuild/freebsd-x64": "0.18.15", + "@esbuild/linux-arm": "0.18.15", + "@esbuild/linux-arm64": "0.18.15", + "@esbuild/linux-ia32": "0.18.15", + "@esbuild/linux-loong64": "0.18.15", + "@esbuild/linux-mips64el": "0.18.15", + "@esbuild/linux-ppc64": "0.18.15", + "@esbuild/linux-riscv64": "0.18.15", + "@esbuild/linux-s390x": "0.18.15", + "@esbuild/linux-x64": "0.18.15", + "@esbuild/netbsd-x64": "0.18.15", + "@esbuild/openbsd-x64": "0.18.15", + "@esbuild/sunos-x64": "0.18.15", + "@esbuild/win32-arm64": "0.18.15", + "@esbuild/win32-ia32": "0.18.15", + "@esbuild/win32-x64": "0.18.15" + } + }, "layers": { "version": "1.11.1", "license": "MIT-0", @@ -939,7 +995,6 @@ "version": "3.360.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-ssm/-/client-ssm-3.360.0.tgz", "integrity": "sha512-VpykmgTlXeoCpOZFuvRuanJTJHa0OGrN84t2/07xAY1oxii0O+/ZH7/lcENpJAm9CJH1a/64smE/vVW4d0TFiw==", - "dev": true, "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", @@ -986,7 +1041,6 @@ }, "node_modules/@aws-sdk/client-ssm/node_modules/uuid": { "version": "8.3.2", - "dev": true, "license": "MIT", "bin": { "uuid": "dist/bin/uuid" @@ -2715,6 +2769,126 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@esbuild/android-arm": { + "version": "0.18.15", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.15.tgz", + "integrity": "sha512-wlkQBWb79/jeEEoRmrxt/yhn5T1lU236OCNpnfRzaCJHZ/5gf82uYx1qmADTBWE0AR/v7FiozE1auk2riyQd3w==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.18.15", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.15.tgz", + "integrity": "sha512-NI/gnWcMl2kXt1HJKOn2H69SYn4YNheKo6NZt1hyfKWdMbaGadxjZIkcj4Gjk/WPxnbFXs9/3HjGHaknCqjrww==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.18.15", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.15.tgz", + "integrity": "sha512-FM9NQamSaEm/IZIhegF76aiLnng1kEsZl2eve/emxDeReVfRuRNmvT28l6hoFD9TsCxpK+i4v8LPpEj74T7yjA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.18.15", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.15.tgz", + "integrity": "sha512-XmrFwEOYauKte9QjS6hz60FpOCnw4zaPAb7XV7O4lx1r39XjJhTN7ZpXqJh4sN6q60zbP6QwAVVA8N/wUyBH/w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.18.15", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.15.tgz", + "integrity": "sha512-bMqBmpw1e//7Fh5GLetSZaeo9zSC4/CMtrVFdj+bqKPGJuKyfNJ5Nf2m3LknKZTS+Q4oyPiON+v3eaJ59sLB5A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.18.15", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.15.tgz", + "integrity": "sha512-LoTK5N3bOmNI9zVLCeTgnk5Rk0WdUTrr9dyDAQGVMrNTh9EAPuNwSTCgaKOKiDpverOa0htPcO9NwslSE5xuLA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.18.15", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.15.tgz", + "integrity": "sha512-62jX5n30VzgrjAjOk5orYeHFq6sqjvsIj1QesXvn5OZtdt5Gdj0vUNJy9NIpjfdNdqr76jjtzBJKf+h2uzYuTQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.18.15", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.15.tgz", + "integrity": "sha512-dT4URUv6ir45ZkBqhwZwyFV6cH61k8MttIwhThp2BGiVtagYvCToF+Bggyx2VI57RG4Fbt21f9TmXaYx0DeUJg==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@esbuild/linux-arm64": { "version": "0.16.10", "cpu": [ @@ -2730,6 +2904,201 @@ "node": ">=12" } }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.18.15", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.15.tgz", + "integrity": "sha512-JPXORvgHRHITqfms1dWT/GbEY89u848dC08o0yK3fNskhp0t2TuNUnsrrSgOdH28ceb1hJuwyr8R/1RnyPwocw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.18.15", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.15.tgz", + "integrity": "sha512-kArPI0DopjJCEplsVj/H+2Qgzz7vdFSacHNsgoAKpPS6W/Ndh8Oe24HRDQ5QCu4jHgN6XOtfFfLpRx3TXv/mEg==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.18.15", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.15.tgz", + "integrity": "sha512-b/tmngUfO02E00c1XnNTw/0DmloKjb6XQeqxaYuzGwHe0fHVgx5/D6CWi+XH1DvkszjBUkK9BX7n1ARTOst59w==", + "cpu": [ + "mips64el" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.18.15", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.15.tgz", + "integrity": "sha512-KXPY69MWw79QJkyvUYb2ex/OgnN/8N/Aw5UDPlgoRtoEfcBqfeLodPr42UojV3NdkoO4u10NXQdamWm1YEzSKw==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.18.15", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.15.tgz", + "integrity": "sha512-komK3NEAeeGRnvFEjX1SfVg6EmkfIi5aKzevdvJqMydYr9N+pRQK0PGJXk+bhoPZwOUgLO4l99FZmLGk/L1jWg==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.18.15", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.15.tgz", + "integrity": "sha512-632T5Ts6gQ2WiMLWRRyeflPAm44u2E/s/TJvn+BP6M5mnHSk93cieaypj3VSMYO2ePTCRqAFXtuYi1yv8uZJNA==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.18.15", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.15.tgz", + "integrity": "sha512-MsHtX0NgvRHsoOtYkuxyk4Vkmvk3PLRWfA4okK7c+6dT0Fu4SUqXAr9y4Q3d8vUf1VWWb6YutpL4XNe400iQ1g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.18.15", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.15.tgz", + "integrity": "sha512-djST6s+jQiwxMIVQ5rlt24JFIAr4uwUnzceuFL7BQT4CbrRtqBPueS4GjXSiIpmwVri1Icj/9pFRJ7/aScvT+A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.18.15", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.15.tgz", + "integrity": "sha512-naeRhUIvhsgeounjkF5mvrNAVMGAm6EJWiabskeE5yOeBbLp7T89tAEw0j5Jm/CZAwyLe3c67zyCWH6fsBLCpw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.18.15", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.15.tgz", + "integrity": "sha512-qkT2+WxyKbNIKV1AEhI8QiSIgTHMcRctzSaa/I3kVgMS5dl3fOeoqkb7pW76KwxHoriImhx7Mg3TwN/auMDsyQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.18.15", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.15.tgz", + "integrity": "sha512-HC4/feP+pB2Vb+cMPUjAnFyERs+HJN7E6KaeBlFdBv799MhD+aPJlfi/yk36SED58J9TPwI8MAcVpJgej4ud0A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.18.15", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.15.tgz", + "integrity": "sha512-ovjwoRXI+gf52EVF60u9sSDj7myPixPxqzD5CmkEUmvs+W9Xd0iqISVBQn8xcx4ciIaIVlWCuTbYDOXOnOL44Q==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.18.15", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.15.tgz", + "integrity": "sha512-imUxH9a3WJARyAvrG7srLyiK73XdX83NXQkjKvQ+7vPh3ZxoLrzvPkQKKw2DwZ+RV2ZB6vBfNHP8XScAmQC3aA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@eslint/eslintrc": { "version": "1.4.0", "dev": true,