Logo
Published on

CDK: IoT Rule does not invoke Lambda function

Authors
  • avatar
    Name
    Bobbie Couhbor
    Twitter

Stumbled on this one the other day! I tried to provision an AWS IoT rule in CDK that had an AWS Lambda function to invoke as its action but it wouldn't (and didn't throw any errors), unless i manually edited the IoT rule and chose the $LATEST version for the Lambda function. Turns out, you need a permission construct to provide the appropriate permissions.

new CfnPermission(this, "permission", {
    action: "lambda:InvokeFunction",
    functionName: fn.functionArn,
    principal: "iot.amazonaws.com",
    sourceArn: rule.attrArn
})

So a full deployment would look something like this:

import * as cdk from 'aws-cdk-lib';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as rule from 'aws-cdk-lib/aws-iot'
import * as path from 'path';
import { Construct } from 'constructs';

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

    const lambdaFn = new lambda.Function(this, 'lambdaFn', {
      runtime: lambda.Runtime.PYTHON_3_12,
      handler: 'index.handler',
      code: lambda.Code.fromAsset(path.join(__dirname, 'lambdaFn')),
      architecture: lambda.Architecture.ARM_64,
    });

    const IoTRule = new rule.CfnTopicRule(this, 'IoTRule', {
      topicRulePayload: {
        actions: [
          {
            lambda: {
              functionArn: lambdaFn.functionArn
            },
          },
        ],
        sql: "SELECT * FROM 'payload'"
      }
    })

    const permission = new lambda.CfnPermission(this, "permission", {
      action: "lambda:invokeFunction",
      functionName: lambdaFn.functionArn,
      principal: "iot.amazonaws.com",
      sourceArn: IoTRule.attrArn
    })

  }
}

Note, i haven't actually tested this, but i assume it works. :)

Credit to Olivier Pichon for spotting this one, https://github.com/aws/aws-cdk/issues/12772