aws / aws-cdk

The AWS Cloud Development Kit is a framework for defining cloud infrastructure in code
https://aws.amazon.com/cdk
Apache License 2.0
11.59k stars 3.89k forks source link

apigwv2: AuthorizerPayloadFormatVersion not a field in HttpLambdaAuthorizerProps #21492

Open elad-asaf opened 2 years ago

elad-asaf commented 2 years ago

Describe the feature

The HttpLambdaAuthorizerProps includes a response type field, however, you can't choose the IAM response type and set the version of the payload format as 2.0. The IAM payload 2.0 behaves a bit differently than 1.0, as described here: https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-lambda-authorizer.html#http-api-lambda-authorizer.payload-format-response It would be great to be able to set this as a prop in HttpLambdaAuthorizerProps.

Use Case

APIGW deployment using CDK would be much smoother with this.

Proposed Solution

No response

Other Information

No response

Acknowledgements

CDK version used

2.35.0

Environment details (OS name and version, etc.)

Ubuntu 20.04

montoyan877 commented 8 months ago

Any solution to this? I'm in the same

yasamoka commented 2 months ago

In case the PR is not (yet) accepted, for anyone facing this issue, you can use the lower-level HttpAuthorizer construct that is used internally for HttpLambdaAuthorizer (here and here). Here is a full example:

import {
  aws_apigatewayv2 as apigateway,
  aws_ecr as ecr,
  aws_lambda as lambda,
  Names,
  Stack,
  StackProps,
} from "aws-cdk-lib";
import {
  AuthorizerPayloadVersion,
  HttpAuthorizer,
  HttpAuthorizerType,
} from "aws-cdk-lib/aws-apigatewayv2";
import { Construct } from "constructs";
import * as ecrdeploy from "cdk-ecr-deployment";
import { DockerImageAsset } from "aws-cdk-lib/aws-ecr-assets";
import { IFunction } from "aws-cdk-lib/aws-lambda";
import { ServicePrincipal } from "aws-cdk-lib/aws-iam";

export class CdkStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    const repo = new ecr.Repository(this, "repo");

    const dummyImage = new DockerImageAsset(this, "dummy-image", {
      assetName: "dummy-image",
      directory: "../dummy",
    });

    const ecrDeployment = new ecrdeploy.ECRDeployment(
      this,
      "ecr-deployment",
      {
        src: new ecrdeploy.DockerImageName(dummyImage.imageUri),
        dest: new ecrdeploy.DockerImageName(
          `${repo.repositoryUri}:latest`
        ),
      }
    );

    const api = new apigateway.HttpApi(this, "api");

    const lambdaFunction = new lambda.Function(this, "lambda", {
      runtime: lambda.Runtime.FROM_IMAGE,
      code: lambda.Code.fromEcrImage(repo),
      handler: lambda.Handler.FROM_IMAGE,
    });

    lambdaFunction.node.addDependency(ecrDeployment);

    const authorizer = new HttpAuthorizer(this, "authorizer", {
      httpApi: api,
      identitySource: [
        '$request.header.Authorization',
      ],
      type: HttpAuthorizerType.LAMBDA,
      enableSimpleResponses: false,
      payloadFormatVersion: AuthorizerPayloadVersion.VERSION_2_0,
      authorizerUri: lambdaAuthorizerArn(lambdaFunction),
    });

    lambdaFunction.addPermission(
      `${Names.nodeUniqueId(authorizer.node)}-Permission`,
      {
        scope: api,
        principal: new ServicePrincipal("apigateway.amazonaws.com"),
        sourceArn: this.formatArn({
          service: "execute-api",
          resource: api.apiId,
          resourceName: `authorizers/${authorizer.authorizerId}`,
        }),
      }
    );
  }
}

function lambdaAuthorizerArn(handler: IFunction) {
  return `arn:${Stack.of(handler).partition}:apigateway:${Stack.of(handler).region
    }:lambda:path/2015-03-31/functions/${handler.functionArn}/invocations`;
}

Alternatively, you can copy the contents of lambda.ts from the PR (here), remove HttpLambdaResponseType, and just use the new version of HttpLambdaAuthorizer you now have, which also implements the required IHttpRouteAuthorizer interface, in your stack. This may be the only option if you want to attach authorizers to separate routes.

tombeuckelaere commented 1 month ago

@yasamoka Thanks for providing an example with a lower level L2 construct. I'm also impacted by this issue for AWS CDK .NET which I previously solved by creating an CfnAuthorizer. This lead me however to constructing other L1 constructs as well because L1 and L2 don't mix which is a pitty. I'm happily expecting the release of your pending PR 😇 . And thanks for the efforts you've already made.

Tobias243 commented 1 month ago

I also stumbled over this, thanks for putting in the effort.