简体   繁体   English

如何从 arn 导入现有的 lambda 并将 SQS 添加为事件源? 放大

[英]How to import existing lambda from arn and add SQS as event source? Amplify

I'm trying to create an SNS topic that an SQS queue subscribes to which acts as an event source for a Lambda function.我正在尝试创建一个 SQS 队列订阅的 SNS 主题,该主题充当 Lambda function 的事件源。 I'm trying to do this with the amplify cdk integration.我正在尝试通过放大 cdk 集成来做到这一点。 However, there seems to be some problem when trying to reference the function which results in a permission problem.但是,在尝试引用 function 时似乎存在一些问题,这会导致权限问题。

CREATE_FAILED fetchMetadataSqsEventSourcesqsqueue2144E8FE AWS::Lambda::EventSourceMapping Fri May 06 2022 17:20:15 GMT+0200 (Central European Summer Time) Resource handler returned message: "Invalid request provided: The provided execution role does not have permissions to call ReceiveMessage on SQS (Service: Lambda, Status Code: 400, Request ID: 2b3147b0-8f59-4c35-8f0f-b7c29a45f139, Extended Request ID: null)" (RequestToken: c03cf5fb-283b-6d83-93c0-f7ee018338cd, HandlerErrorCode: InvalidRequest) CREATE_FAILED fetchMetadataSqsEventSourcesqsqueue2144E8FE AWS::Lambda::EventSourceMapping Fri May 06 2022 17:20:15 GMT+0200 (Central European Summer Time) 资源处理程序返回消息:“提供的请求无效:提供的执行角色无权在 SQS 上调用 ReceiveMessage (服务:Lambda,状态代码:400,请求 ID:2b3147b0-8f59-4c35-8f0f-b7c29a45f139,扩展请求 ID:空)“(RequestHandlerToken:c03cf5fb-283b-6d83-93c0-f7ee018338)cd:

Here's my code这是我的代码

import * as AmplifyHelpers from "@aws-amplify/cli-extensibility-helper"
import * as iam from "@aws-cdk/aws-iam"
import * as lambda from "@aws-cdk/aws-lambda"
import { SqsEventSource } from "@aws-cdk/aws-lambda-event-sources"
import * as sns from "@aws-cdk/aws-sns"
import * as subs from "@aws-cdk/aws-sns-subscriptions"
import * as sqs from "@aws-cdk/aws-sqs"
import * as cdk from "@aws-cdk/core"
import { Duration } from "@aws-cdk/core"

import { AmplifyDependentResourcesAttributes } from "../../types/amplify-dependent-resources-ref"

export class cdkStack extends cdk.Stack {
  constructor(
    scope: cdk.Construct,
    id: string,
    props?: cdk.StackProps,
    amplifyResourceProps?: AmplifyHelpers.AmplifyResourceProps
  ) {
    super(scope, id, props)

    /* Do not remove - Amplify CLI automatically injects the current deployment environment in this input parameter */
    new cdk.CfnParameter(this, "env", {
      type: "String",
      description: "Current Amplify CLI env name",
    })
    /* AWS CDK code goes here - learn more: https://docs.aws.amazon.com/cdk/latest/guide/home.html */

    // Example 1: Set up an SQS queue with an SNS topic

    const amplifyProjectInfo = AmplifyHelpers.getProjectInfo()
    const sqsQueueResourceNamePrefix = `sqs-queue-${amplifyProjectInfo.projectName}`
    const queue = new sqs.Queue(this, "sqs-queue", {
      queueName: `${sqsQueueResourceNamePrefix}-${cdk.Fn.ref("env")}`,
      visibilityTimeout: Duration.seconds(30), // default,
      receiveMessageWaitTime: Duration.seconds(20), // default
    })

    // 👇create sns topic
    const snsTopicResourceNamePrefix = `sns-topic-${amplifyProjectInfo.projectName}`
    const topic = new sns.Topic(this, "sns-topic", {
      topicName: `${snsTopicResourceNamePrefix}-${cdk.Fn.ref("env")}`,
    })

    // 👇 subscribe queue to topic
    topic.addSubscription(new subs.SqsSubscription(queue))
    new cdk.CfnOutput(this, "snsTopicArn", {
      value: topic.topicArn,
      description: "The arn of the SNS topic",
    })

    const dependencies: AmplifyDependentResourcesAttributes =
      AmplifyHelpers.addResourceDependency(
        this,
        amplifyResourceProps.category,
        amplifyResourceProps.resourceName,
        [
          {
            category: "function", // api, auth, storage, function, etc.
            resourceName: "fetchMetadata", // find the resource at "amplify/backend/<category>/<resourceName>"
          } /* add more dependencies as needed */,
        ]
      )

    const fetchMetadataFnArn = cdk.Fn.ref(
      dependencies.function.fetchMetadata.Arn
    )

    const lambdaRole = new iam.Role(this, "Role", {
      assumedBy: new iam.ServicePrincipal("lambda.amazonaws.com"),
      description: "Example role...",
    })

    queue.grantConsumeMessages(lambdaRole)

    let fn = lambda.Function.fromFunctionAttributes(this, "fetchMetadata", {
      role: lambdaRole,
      functionArn: fetchMetadataFnArn,
    })

    queue.grantConsumeMessages(fn)

    const eventSource = new SqsEventSource(queue)
    fn.addEventSource(eventSource)
  }
}

Here's a snippet of the generated CloudFormation code, it seems like there might be an issue with the arn?这是生成的 CloudFormation 代码的片段,似乎 arn 可能存在问题? 在此处输入图像描述

You are close, but have 1 or 2 problems.您很接近,但有 1 或 2 个问题。 CDK requires two ARNs from the imported Lambda: (1) the Function execution Role's ARN and (2) the Function ARN. CDK 需要来自导入的 Lambda 的两个 ARN:(1) Function 执行角色的 ARN 和 (2) Function ARN。 You provide them with lambda.Function.fromFunctionAttributes .您为他们提供lambda.Function.fromFunctionAttributes

(1) Function execution Role ARN : You definitely have a problem here. (1) Function 执行角色 ARN : 你这里肯定有问题。 You need a reference the imported Lambda's existing execution Role via its ARN.您需要通过其 ARN 引用导入的 Lambda 的现有执行Role You have created a new Role , which is not going to work.您创建了一个新的Role ,但它不起作用。 Instead, "import" the existing role with iam.Role.fromRoleArn A typical way to get a Role ARN is to export it as a CloudFormation output and import it into cdkStack :相反,使用iam.Role.fromRoleArn “导入”现有角色 获取角色 ARN 的典型方法是将其导出为CloudFormation output并将其导入cdkStack

const fn = lambda.Function.fromFunctionAttributes(this, `FetchMetadata`, {
  role: iam.Role.fromRoleArn(
    this,
    'ImportedRole',
    cdk.Fn.importValue('NameOfStackExportWithTheRoleARN')
  ),
  functionArn: fetchMetadataFnArn,
});

If the imported Lambda was not created with CloudFormation, a SSM Parameter Store Parameter would be a way to pass cdkStack the Role's ARN.如果导入的 Lambda 不是使用 CloudFormation 创建的,则SSM 参数存储参数将是向cdkStack传递角色 ARN 的一种方式。 Or hardcode it.或者硬编码。

(2) Function ARN : You may have a problem here. (2) Function ARN :您可能在这里遇到问题。 I am not familiar with the Amplify helpers.我不熟悉 Amplify 助手。 You can diagnose whether fetchMetadataFnArn is correctly resolving by temporarily adding a CfnOutput to cdkStack :您可以通过临时将CfnOutput cdkStack诊断fetchMetadataFnArn是否正确解析:

new cdk.CfnOutput(this, 'JustCheckingWhetherTheFunctionArnIsReolvingOK', {
  value: fetchMetadataFnArn,
});

CDK prints these outputs to the console at deploy-time. CDK 在部署时将这些输出打印到控制台。 Check to see if the ARN is what you expect.检查 ARN 是否符合您的预期。

Once you get the imported ARNs right, CDK can create the AWS::SQS::QueuePolicy and AWS::Lambda::EventSourceMapping it needs to wire the Lambda to the Queue.正确导入 ARN 后,CDK 可以创建AWS::SQS::QueuePolicyAWS::Lambda::EventSourceMapping ,它需要将 Lambda 连接到队列。


NB You can delete queue.grantConsumeMessages(lambdaRole) and queue.grantConsumeMessages(fn) .注意您可以删除queue.grantConsumeMessages(lambdaRole)queue.grantConsumeMessages(fn) They are redundant.它们是多余的。 fn.addEventSource(eventSource) makes the grant under the hood. fn.addEventSource(eventSource)在后台进行授权。

The ideal approach to reference the ARN of the lambda function created via Amplify into CDK is to use the below approach assuming you are using AWS CDK v2将通过 Amplify 创建的 lambda function 的 ARN 引用到 CDK 的理想方法是使用以下方法,假设您使用的是 AWS CDK v2

 const importFunction:AmplifyDependentResourcesAttributes = AmplifyHelpers.addResourceDependency(this, 
  amplifyResourceProps.category, 
  amplifyResourceProps.resourceName, 
  [
    {category: 'function', resourceName: <Name of the function>},
  ]
);
const arn=cdk.Fn.ref(retVal.function.<function_name>.Arn);

This part should replace below part in your code to get the ARN此部分应替换代码中的以下部分以获取 ARN

cdk.Fn.ref(
  dependencies.function.fetchMetadata.Arn
)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM