AWS CDK: Get IoT Rule Resource by ARN

0

I have a Stack A with an IoT Rule and its Arn.

In another Stack B, I want to get this IoT Rule and add a action to it. I don't want to add the action in Stack A, because the rule references to a Lambda Function, that is created in Stack B.

For a lot of resources, there is a "fromArn"-Function. But it seems like there is none for an IoT Rule.

How can I make this work?

Thank you very much!

1 Answer
0

There are a couple of ways to approach this. You will need to follow a few steps. AWS CloudFormation does not provide a direct "fromArn" function for IoT rules but you can accomplish this using AWS CDK (Cloud Development Kit) or by directly using the AWS SDK.

Here is one way of accomplishing this by using AWS CDK:

  1. Create the IoT Rule in Stack A and make note of the ARN.

  2. In Stack B, you can then use the AWS CDK to import the IoT Rule by its ARN and then add an action to it.

I have provided an example below:

 from aws_cdk import core.
 from aws_cdk.aws_iot import CfnTopicRule

 class StackA(core.Stack):
       def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
             super().__init__(scope, id, **kwargs)
    
            # Create IoT Rule
            self.iot_rule = CfnTopicRule(self, "MyIoTRule",
                                                            rule_name="MyIoTRule",
                                                            topic_rule_payload={
                                                                   "sql": "SELECT * FROM 'some/topic'",
                                                                  "actions": []
                                                            })

           core.CfnOutput(self, "IoTRuleArn", value=self.iot_rule.attr_arn)


 class StackB(core.Stack):
      def __init__(self, scope: core.Construct, id: str, iot_rule_arn: str, **kwargs) -> None:
            super().__init__(scope, id, **kwargs)
    
            # Add action to IoT Rule
           CfnTopicRule(self, "MyIoTRuleWithAction",
                                   rule_name="MyIoTRule",
                                   topic_rule_payload={
                                           "sql": "SELECT * FROM 'some/topic'",
                                           "actions": [
                                                 {
                                                         "lambda": {
                                                                 "functionArn": "arn:aws:lambda:region:account-id:function:MyFunction"
                                                          }
                                              }
                                    ]
                              })
    
 app = core.App()
 stack_a = StackA(app, "StackA")
 stack_b = StackB(app, "StackB", iot_rule_arn=stack_a.iot_rule.attr_arn)
 app.synth()

If you prefer to use CloudFormation templates directly, you would need to use custom resources or Lambda-backed custom resources to update the IoT Rule. Here is one way of accomplishing this with AWS SDK.

  1. You can use a Lambda function to modify the IoT Rule from Stack B Here is an example.

    Resources:
       UpdateIoTRule:
          Type: "AWS::Lambda::Function"
           Properties:
             Handler: index.handler
            Role: arn:aws:iam::account-id:role/service-role/role-name
            Code:
                 ZipFile: |
                     import boto3
                     import cfnresponse
    
                    def handler(event, context):
                           client = boto3.client('iot')
                           try:
                                 response = client.replace_topic_rule(
                                        ruleName='MyIoTRule',
                                        topicRulePayload={
                                               'sql': "SELECT * FROM 'some/topic'",
                                               'actions': [
                                                     {
                                                            'lambda': {
                                                                   'functionArn': 'arn:aws:lambda:region:account-id:function:MyFunction'
                                                            }
                                                }
                                        ]
                              }
                      )
                     cfnresponse.send(event, context, cfnresponse.SUCCESS, {})
                except Exception as e:
                    cfnresponse.send(event, context, cfnresponse.FAILED, {'Message': str(e)})
        Runtime: python3.8
    

In your Stack B template, invoke this Lambda function:

 Resources:
   UpdateIoTRuleCustomResource:
         Type: Custom::UpdateIoTRule
         Properties:
            ServiceToken: !GetAtt UpdateIoTRule.Arn

Both AWS CDK and AWS SDK allow you to manage and update your IoT rules across stacks. AWS CDK provides a clean and programmatic way to handle this task while the AWS SDK and CloudFormation custom resources offer a more traditional approach.

For more details on this topic, refer to the following:

AWS CDK Developer Guide

AWS CDK Python Reference Documentation

AWS CDK IoT Module

AWS SDK for Python (Boto3) Documentation

AWS CloudFormation Custom Resources

[AWS Lambda Function in CloudFormation

AWS
answered 4 months ago
  • Hi! Thanks for you help! But I do not fully understand. You created the argument "iot_rule_arn" for the constructor in StackB, but I can't see using it. Am I missing something?

    By the way: I'm using TypeScript, but I guess it's fully translatable, isn't it?

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions