为什么我的CloudWatch规则触发但不调用我的lambda功能?

发布于 2025-01-30 23:06:40 字数 2036 浏览 3 评论 0 原文

我已经使用CDK创建了lambda函数。

在我的Java应用程序中,我通过编程方式创建一个CloudWatch事件规则,其目标通过其ARN指向该函数。

CloudWatch规则被触发,但未能调用lambda。当我手动将CloudWatch规则添加为AWS控制台的lambda触发器时,该函数确实会被调用。

CDK代码

private createPregameEventsLambda(props: InfraStackProps) {
        const lambdaEnvVars = {
            'Domain': props.stage,
            'Region': props.region,
            'ResourceNamePrefix': props.resourceNamePrefix
        };

        const pregameEventsLambda = new Lambda(this, "PregameEvents-Lambda", {
            ...props,
            name: LambdaConfig.PREGAME_EVENTS_LAMBDA.name,
            handler: LambdaConfig.PREGAME_EVENTS_LAMBDA.handler,
            environment: {
                variables: lambdaEnvVars
            },
            role: this.lambdaExecutionRole
        }).getFunction()
}

Java应用程序:

public void createCloudWatchRule(final LiveEventIdRelationInfo info) {
        final String smpId = info.getSmpId();
        final Date date = new Date(startTime);
        final Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        calendar.setTimeZone(TimeZone.getTimeZone("GMT+0"));
        final String cronExpression =  getCronExpression(calendar);

        final PutRuleRequest putRuleRequest = new PutRuleRequest()
                .withScheduleExpression(cronExpression)
                .withName(ruleName);
        cloudWatchEventClient.putRule(putRuleRequest);

        final Target target = new Target()
                .withId(LAMBDA_TARGET_ID)
                .withArn(functionArn)
                .withInput(jsonString);
        final PutTargetsRequest putTargetsRequest = new PutTargetsRequest()
                .withRule(ruleName)
                .withTargets(target);
        cloudWatchEventClient.putTargets(putTargetsRequest);
    }

控制台显示创建的规则具有正确的lambda arn,但仍未被调用。

是否有 InvokeFunction 我需要添加到CDK代码的权限?

我是否缺少权限?

I have created a Lambda function using the CDK.

In my Java application, I am programmatically creating a CloudWatch Event Rule with a target pointing to the function via its ARN.

The CloudWatch rule gets triggered but it fails to invoke the Lambda. When I manually add the CloudWatch rule as a trigger for the Lambda from AWS Console, the function does get invoked.

CDK code

private createPregameEventsLambda(props: InfraStackProps) {
        const lambdaEnvVars = {
            'Domain': props.stage,
            'Region': props.region,
            'ResourceNamePrefix': props.resourceNamePrefix
        };

        const pregameEventsLambda = new Lambda(this, "PregameEvents-Lambda", {
            ...props,
            name: LambdaConfig.PREGAME_EVENTS_LAMBDA.name,
            handler: LambdaConfig.PREGAME_EVENTS_LAMBDA.handler,
            environment: {
                variables: lambdaEnvVars
            },
            role: this.lambdaExecutionRole
        }).getFunction()
}

Java application:

public void createCloudWatchRule(final LiveEventIdRelationInfo info) {
        final String smpId = info.getSmpId();
        final Date date = new Date(startTime);
        final Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        calendar.setTimeZone(TimeZone.getTimeZone("GMT+0"));
        final String cronExpression =  getCronExpression(calendar);

        final PutRuleRequest putRuleRequest = new PutRuleRequest()
                .withScheduleExpression(cronExpression)
                .withName(ruleName);
        cloudWatchEventClient.putRule(putRuleRequest);

        final Target target = new Target()
                .withId(LAMBDA_TARGET_ID)
                .withArn(functionArn)
                .withInput(jsonString);
        final PutTargetsRequest putTargetsRequest = new PutTargetsRequest()
                .withRule(ruleName)
                .withTargets(target);
        cloudWatchEventClient.putTargets(putTargetsRequest);
    }

Console shows that the Rule created has the correct Lambda ARN but it still does not get invoked.

Is there an InvokeFunction permission I need to add to the CDK code?

Am I missing permissions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

余罪 2025-02-06 23:06:40

是否有 InvokeFunction 我需要添加到CDK代码?

不,这与您的CDK代码无关,因为您在CDK代码之外创建了一个新的EventBridge(CloudWatch)规则。您不是使用CDK创建规则,因此它不是正确的位置。

您的lambda功能缺少基于资源的IAM策略,该策略授予EventBridge&特别是您创建的规则,以调用它。

因为您正在创建规则& Target 通过编程,您还需要使用 在您的Java应用程序中。

除其他外, addpermission 允许您设置一个调用该功能的AWS资源的源ARN。这将是Eventbridge规则的Arn。

这不是必需的 ,但是如果您未指定源,请注意,其他帐户可能会在其帐户中配置资源以调用您的lambda函数。因此,我建议始终设置源

将上述应用于您的代码, CloudWatchEventClient.putrule(putrulerequest); 实际上将返回https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/eventbridge/eventbridge/model/model/putruleresponse.html“ rel =“ norofollow norefollow norefoller” >通过 dulearn()方法,

final PutRuleResponse response = cloudWatchEventClient.putRule(putRuleRequest);
final String ruleArn = response.ruleArn();

即捕获了此值后,创建&发送 授予必要的许可。

这应该使用Java 2.x的AWS SDK来工作:

public void createCloudWatchRule(final LiveEventIdRelationInfo info) {
    ...
    final PutRuleRequest putRuleRequest = new PutRuleRequest()
            .withScheduleExpression(cronExpression)
            .withName(ruleName);

    final PutRuleResponse response = cloudWatchEventClient.putRule(putRuleRequest);
    final String ruleArn = response.ruleArn();

    final Target target = new Target()
            .withId(LAMBDA_TARGET_ID)
            .withArn(functionArn)
            .withInput(jsonString);
    final PutTargetsRequest putTargetsRequest = new PutTargetsRequest()
            .withRule(ruleName)
            .withTargets(target);
    cloudWatchEventClient.putTargets(putTargetsRequest);

    final AddPermissionRequest addPermissionRequest = new AddPermissionRequest()
        .withFunctionName(functionArn)
        .withStatementId("sid-" + LAMBDA_TARGET_ID)
        .withAction("lambda:InvokeFunction")
        .withPrincipal("events.amazonaws.com")
        .withSourceArn(ruleArn)
        .build();
    
    lambdaClient.addPermission(addPermissionRequest);
}

如果您使用AWS SDK用于Java 1.x,则适用相同的概念 - 会有较小的语法差异,但会引用上述链接与V1 Docs,并且您'将能够轻松弄清楚。

Is there an InvokeFunction permission I need to add to the CDK code?

No, this isn't related to your CDK code, since you're creating a new EventBridge (CloudWatch) rule outside of your CDK code. You're not creating the rule using the CDK so it's not the right place to look.

Your Lambda function is missing a resource-based IAM policy, which grants EventBridge & specifically your created rule, to invoke it.

Since you're creating the rule & target programmatically, you will also need to grant this permission programmatically using AddPermission & the LambdaClient in your Java application.

Among other things, AddPermission allows you to set a source ARN which is the ARN of the AWS resource that invokes the function. This would be the ARN of the EventBridge rule.

This is not required however if you do not specify the source, do note that other accounts could potentially configure resources in their account to invoke your Lambda function. As such, I'd recommend always setting the source ARN.

Applying the above to your code, cloudWatchEventClient.putRule(putRuleRequest); will actually return the ARN of the created rule in the PutRuleReponse via the ruleArn() method i.e.

final PutRuleResponse response = cloudWatchEventClient.putRule(putRuleRequest);
final String ruleArn = response.ruleArn();

Once you have this value captured, create & send a AddPermissionRequest to grant the necessary permission.

This should work using the AWS SDK for Java 2.x:

public void createCloudWatchRule(final LiveEventIdRelationInfo info) {
    ...
    final PutRuleRequest putRuleRequest = new PutRuleRequest()
            .withScheduleExpression(cronExpression)
            .withName(ruleName);

    final PutRuleResponse response = cloudWatchEventClient.putRule(putRuleRequest);
    final String ruleArn = response.ruleArn();

    final Target target = new Target()
            .withId(LAMBDA_TARGET_ID)
            .withArn(functionArn)
            .withInput(jsonString);
    final PutTargetsRequest putTargetsRequest = new PutTargetsRequest()
            .withRule(ruleName)
            .withTargets(target);
    cloudWatchEventClient.putTargets(putTargetsRequest);

    final AddPermissionRequest addPermissionRequest = new AddPermissionRequest()
        .withFunctionName(functionArn)
        .withStatementId("sid-" + LAMBDA_TARGET_ID)
        .withAction("lambda:InvokeFunction")
        .withPrincipal("events.amazonaws.com")
        .withSourceArn(ruleArn)
        .build();
    
    lambdaClient.addPermission(addPermissionRequest);
}

If you're using AWS SDK for Java 1.x, the same concepts apply - there will be minor syntax differences but cross reference the above links with the v1 docs and you'll be able to easily figure it out.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文