1
0

More than 1 year has passed since last update.

AWS CDK(Typescript) で LambdaEdge を使う

Posted at

想定

  1. クロスリージョンスタック(複数リージョンのスタックを連携)
  2. NodejsFunctionを使っている(ts で書いたハンドラーをそのままデプロイできる construct)

結論

cdk.ts
#!/usr/bin/env node
import * as cdk from "aws-cdk-lib";
import "source-map-support/register";
import { LambdaEdgeStack } from "../lib/lambda-edge-stack";
import { SampleStack } from "../lib/sample-stack";

const app = new cdk.App();

const account = process.env.CDK_DEFAULT_ACCOUNT;

export const REGION = {
  VIRGINIA: "us-east-1",
  TOKYO: "ap-northeast-1",
};

const lambdaEdgeStack = new LambdaEdgeStack(app, LambdaEdgeStack.name, {
  env: { account, region: REGION.VIRGINIA },
  crossRegionReferences: true,
});

const sampleStack = new SampleStack(app, SampleStack.name, {
  env: { account, region: REGION.TOKYO },
  lambdaEdgeFunction: lambdaEdgeStack.function,
  crossRegionReferences: true,
});

sampleStack.addDependency(lambdaEdgeStack);
lambda-edge-stack.ts
import { Stack, StackProps } from "aws-cdk-lib";
import { CompositePrincipal, ManagedPolicy, Role, ServicePrincipal } from "aws-cdk-lib/aws-iam";
import { Runtime } from "aws-cdk-lib/aws-lambda";
import { NodejsFunction } from "aws-cdk-lib/aws-lambda-nodejs";
import { Construct } from "constructs";
import { join } from "path";

export class LambdaEdgeStack extends Stack {
  function: NodejsFunction;

  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    const role = new Role(this, "LambdaEdgeExecutionRole", {
      assumedBy: new CompositePrincipal(
        new ServicePrincipal("lambda.amazonaws.com"),
        new ServicePrincipal("edgelambda.amazonaws.com") // デフォルトで生成されるロールはこれがないので追加
      ),
      managedPolicies: [ManagedPolicy.fromAwsManagedPolicyName("service-role/AWSLambdaBasicExecutionRole")],
    });

    this.function = new NodejsFunction(this, NodejsFunction.name, {
      entry: join(__dirname, "./handler.ts"),
      handler: "handler",
      runtime: Runtime.NODEJS_18_X,
      awsSdkConnectionReuse: false, // このプロパティを`false`にしないと、`LambdaEdge`は環境変数は使えないよエラーを出す
      role,
    });
  }
}
handler.ts
import { Callback, CloudFrontRequestEvent, Context } from "aws-lambda";

export const handler = async (event: CloudFrontRequestEvent, context: Context, callback: Callback) => {
  console.log("hi mom")
};

ポイント

  1. lambda-edge-stack.tsawsSdkConnectionReuse: false
  2. cloudfront でのログ出力のためlambda-edge-stack.ts で ロールにedgelambda.amazonaws.comを付与必須

1 を true にすると lambdaEdge では環境変数は使えないエラーが出ます。
2 はデフォルトのロールも生成されるのですが、それだと ServicePrincipal にlambda.amazonaws.comしかないので、edgelambda.amazonaws.comを追加しないと

cdk デプロイ時に

Resource handler returned message: "Invalid request provided: AWS::CloudFront::Distribution: The function execution role must be assumable with edgelambda.amazonaws.com as well as lambda.amazonaws.com principals. Update the IAM role and try again.

というエラーが出るのでそのため新しくロールを作成しています。

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0