LoginSignup
16
13

More than 3 years have passed since last update.

SAMでSQSをイベントソースとするLambdaを構築

Posted at

しようとしたら失敗したので備忘録的に解決策を残しておこうと思いました。

AWS曰く

このクールなコードでビルドできるよ!
とのこと。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Example of processing messages on an SQS queue with Lambda
Resources:
  MySQSQueueFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: handler
      Runtime: runtime
      Events:
        MySQSEvent:
          Type: SQS
          Properties:
            Queue: !GetAtt MySqsQueue.Arn
            BatchSize: 10
  MySqsQueue:
    Type: AWS::SQS::Queue

出典:AWS SAM Template for an Amazon SQS Application

そして失敗

エラー1:LambdaがSQSを呼ぶ権限がない

謎のエラーを吐いてCloudFormationが失敗に終わる。

The provided execution role does not have permissions to call ReceiveMessage on SQS (Service: AWSLambda; Status Code: 400; Error Code: InvalidParameterValueException

Lambdaに設定したロールには AWSLambdaSQSQueueExecutionRole が付いている。
つまりIAMロールには(おそらく)問題がない。

なぜ失敗する?

解決1:SQSにも権限の設定をする

冷静に考えたら、コンソールからキューを作る時も権限をいじった気がする。
というわけで、下記を追加する事で上述のエラーは出なくなった。

  MySqsQueuePolicy: 
    Type: AWS::SQS::QueuePolicy
    Properties: 
      PolicyDocument: 
        Id: !Ref MySqsQueue
        Statement: 
          - Sid: QueuePolicy-MySqsQueue
            Effect: Allow
            Principal: "*"
            Action: "SQS:*"
            Resource: 
              Fn::GetAtt:
              - MySqsQueue
              - Arn
      Queues:
        - !Ref MySqsQueue

エラー2:キューの可視性タイムアウトがLambdaのタイムアウトより短い

エラー1が解決したら、今度はこれが出るようになった。
コンソールから設定する時はあなたそんな事言わなかったじゃない。

Queue visibility timeout: 30 seconds is less than Function timeout: 60 seconds

解決2:可視性タイムアウトを伸ばす

明示的に指定しないとdefaultで30秒になるらしいので、キューのPropertiesにVisibilityTimeoutを設定する。
※Lambdaのタイムアウトを明示的に60秒にしていたので、もしかしたらその設定の影響かもしれない。

  MySqsQueue: 
    Type: AWS::SQS::Queue
    Properties: 
      VisibilityTimeout: 60

結論

SQSキューポリシーと、可視性タイムアウトの設定をするとうまくいきました。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Example of processing messages on an SQS queue with Lambda
Resources:
  MySQSQueueFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: handler
      Runtime: runtime
      Timeout: 60
      Events:
        MySQSEvent:
          Type: SQS
          Properties:
            Queue: !GetAtt MySqsQueue.Arn
            BatchSize: 10
  MySqsQueue:
    Type: AWS::SQS::Queue
    Properties: 
      VisibilityTimeout: 60
  MySqsQueuePolicy: 
    Type: AWS::SQS::QueuePolicy
    Properties: 
      PolicyDocument: 
        Id: !Ref MySqsQueue
        Statement: 
          - Sid: QueuePolicy-MySqsQueue
            Effect: Allow
            Principal: "*"
            Action: "SQS:*"
            Resource: 
              Fn::GetAtt:
              - MySqsQueue
              - Arn
      Queues:
        - !Ref MySqsQueue

蛇足

実はこの前段階でCloudFormationの実行ロールにSQSの権限が無かった事により一度失敗している。
CodeStarを使っているため、自動で作成されるロールに何の疑問も持たなかった事が原因ですね。私は悲しい。

16
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
13