AWS IoT Coreのエラーアクション動作を確認する

IoT Coreのエラーアクション動作を確認します。
2022.11.15

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

AWS IoT Coreのルールアクションには、エラー発生時に動作するエラーアクションがあります。 このエラーアクションの動作を確認したい場合には、ひと工夫が必要です。 本記事では、ルールアクションを強制的に失敗させて、エラーアクションの動作を確認してみました。

おすすめの方

  • AWS IoT Coreのエラーアクションの動作を確認したい方
  • AWS IoT CoreをCloudFormationで作成したい方

IoT Coreのルールアクションを失敗させる方法

IoTルールアクションを失敗させるためには、IoTルールアクションにアタッチされているIAMロールを失敗する内容で試します。

  • Effect: AllowからDenyにする
  • Action: 関係ない内容にする
  • Resource: 関係ない内容にする

本記事では、Actionを関係ない内容にします。

IoT Ruleアクションとエラーアクションを作成する

CloudFormationテンプレート

前述したとおり、IoTルールアクション用のIAMロールの権限を「SNS」ではなく「DynamoDB」にしています。

iot.yaml

AWSTemplateFormatVersion: 2010-09-09
Description: IoT Rule Test

Resources:
  SampleTable:
    Type: AWS::DynamoDB::Table
    Properties:
      TableName: iot-rule-error-action-table
      BillingMode: PAY_PER_REQUEST
      AttributeDefinitions:
        - AttributeName: awsUuid
          AttributeType: S
        - AttributeName: awsTimestamp
          AttributeType: N
      KeySchema:
        - AttributeName: awsUuid
          KeyType: HASH
        - AttributeName: awsTimestamp
          KeyType: RANGE

  OkTopic:
    Type: AWS::SNS::Topic
    Properties:
      Subscription:
        - Endpoint: sample@example.com
          Protocol: email

  TestTopicRule:
    Type: AWS::IoT::TopicRule
    Properties:
      RuleName: test_sample_topic_rule
      TopicRulePayload:
        AwsIotSqlVersion: "2016-03-23"
        RuleDisabled: false
        Sql: >-
          SELECT
            * as payloads
          FROM
            'test/aaa'
        Actions:
          - Sns:
              TargetArn: !Ref OkTopic
              RoleArn: !GetAtt TestTopicRuleRole.Arn
        ErrorAction:
          DynamoDB:
            TableName: !Ref SampleTable
            HashKeyField: awsUuid
            HashKeyType: STRING
            HashKeyValue: ${newuuid()}
            RangeKeyField: awsTimestamp
            RangeKeyType: NUMBER
            RangeKeyValue: ${timestamp()}
            RoleArn: !GetAtt TestTopicRuleErrorRole.Arn

  TestTopicRuleRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: test-sample-topic-rule-role
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: iot.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        # 本来はSNS Publish権限を付与するべきだが、失敗させるために、SNS以外の権限を付与している
        - arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess

  TestTopicRuleErrorRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: test-sample-topic-rule-error-role
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: iot.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess

デプロイ

aws cloudformation deploy \
    --template-file iot.yaml \
    --stack-name IoT-Rule-Test-Stack \
    --capabilities CAPABILITY_NAMED_IAM \
    --no-fail-on-empty-changeset

エラーアクションの動作を確認する

IoT Coreにメッセージを送信する

トピック「test/aaa」に適当なメッセージを送信します。

任意のトピックにデータを送信する

CloudWatch LogsでIoT CoreのErrorログを確認する

Errorログがありました。通常のルールアクションが失敗しています。

{
    "timestamp": "2022-11-15 03:30:05.593",
    "logLevel": "ERROR",
    "traceId": "a7d6d7a5-55ba-465f-cbdc-9811649979c0",
    "accountId": "xxx",
    "status": "Failure",
    "eventType": "RuleExecution",
    "clientId": "iotconsole-xxx",
    "topicName": "test/aaa",
    "ruleName": "test_sample_topic_rule",
    "ruleAction": "SNSAction",
    "resources": {
        "TargetArn": "arn:aws:sns:ap-northeast-1:xxx:IoT-Rule-Test-Stack-OkTopic-YXI8X6qb4MbD"
    },
    "principalId": "xxx",
    "details": "User: arn:aws:sts::xxx:assumed-role/test-sample-topic-rule-role/OlNaFMWi is not authorized to perform: SNS:Publish on resource: arn:aws:sns:ap-northeast-1:xxx:IoT-Rule-Test-Stack-OkTopic-YXI8X6qb4MbD because no identity-based policy allows the SNS:Publish action (Service: AmazonSNS; Status Code: 403; Error Code: AuthorizationError; Request ID: e999d0c2-88ee-5d01-a70e-8b2f8113b1b3; Proxy: null)"
}

DynamoDBテーブルを確認する

IoT Coreのエラーアクションで保存されたデータがありました。

DynamoDBテーブルにデータが保存されている

{
 "awsUuid": "3ae9926b-830d-421e-bb10-7c1e83048802",
 "awsTimestamp": 1668483005471,
 "payload": {
  "base64OriginalPayload": "ewogICJtZXNzYWdlIjogIkFXUyBJb1Qg44Kz44Oz44K944O844Or44GL44KJ44Gu5oyo5ou2Igp9",
  "base64TransparentProperties": "eyJmb3JtYXRfaW5kaWNhdG9yIjoiVU5TUEVDSUZJRURfQllURVMifQ==",
  "clientId": "xxx",
  "cloudwatchTraceId": "a7d6d7a5-55ba-465f-cbdc-9811649979c0",
  "failures": [
   {
    "errorMessage": "Failed to publish SNS topic. The error received was User: arn:aws:sts::xxx:assumed-role/test-sample-topic-rule-role/OlNaFMWi is not authorized to perform: SNS:Publish on resource: arn:aws:sns:ap-northeast-1:xxx:IoT-Rule-Test-Stack-OkTopic-YXI8X6qb4MbD because no identity-based policy allows the SNS:Publish action (Service: AmazonSNS; Status Code: 403; Error Code: AuthorizationError; Request ID: e999d0c2-88ee-5d01-a70e-8b2f8113b1b3; Proxy: null). Message arrived on: test/aaa, Action: sns, Target Arn: arn:aws:sns:ap-northeast-1:xxx:IoT-Rule-Test-Stack-OkTopic-YXI8X6qb4MbD",
    "failedAction": "SNSAction",
    "failedResource": "arn:aws:sns:ap-northeast-1:xxx:IoT-Rule-Test-Stack-OkTopic-YXI8X6qb4MbD"
   }
  ],
  "ruleName": "test_sample_topic_rule",
  "topic": "test/aaa"
 }
}

「base64OriginalPayload」をBase64デコードすると、次の内容でした。

{
  "message": "AWS IoT コンソールからの挨拶"
}

さいごに

IoT Coreのエラーアクション動作を確認しました。すでに本番稼働しているシステムでIAMロールの権限を変更する場合は、タイミングやアフターケアなどに気をつけてください。

参考