Search code examples
amazon-web-servicesaws-lambdaamazon-snsamazon-textract

How does NotificationChannel from the function StartExpenseAnalysisCommand of Amazon Textract works? AmazonTextract unable to publish msg to SNS


Good afternoon,

I am working with this service StartExpenseAnalysisCommand where there is a parameter that I am interested in using called NotificationChannel, where I pass my TopicArn (SNS), so basically my function is the following:

   const command = new StartExpenseAnalysisCommand({
      DocumentLocation: {
        S3Object: {
          Bucket: fileObj.s3.bucket.name,
          Name: fileObj.s3.object.key,
        },
      },
      NotificationChannel: {
        SNSTopicArn: process.env.SNS_TOPIC_ARN,
        RoleArn: process.env.ROLE_ARN,
      },
    });
    const response = await textractClient.send(command);

To explain what I want to do:

  • I have this Lambda Function that start StartExpenseAnalysisCommand. After completion, it is suppose to publish to the SNSTopicArn I created in NotificationChannel with the JobID.
  • This will publish to the SNS sending the JobId, and triggers my second Lambda Function, which will receive the event and extract the data with GetExpenseAnalysisCommand.

The issue I am facing is that it never triggers when I process the first function. I already confirmed that it receives the JobId and also confirmed that it is subscribed, but it never publish it.

Subscription

I also tried publishing a message manually from the aws console, and it works, it triggers the lambda function, so the problem might be with the NotificationChannel.

Manual publish

This is my serverless.yml where I also defined the permissions required for it which are sns:Publish and lambda:InvokeFunction:


provider:
  name: aws
  runtime: nodejs18.x
  memorySize: 128
  region: ${env:AWS_REGION}
  stage: ${opt:stage,'dev'}
  environment:
    # APP
    APP_STAGE: ${env:APP_STAGE}
    APP_SERVICE_NAME: ${env:APP_SERVICE_NAME}
    AWS_SQS_QUEUE_URL: !Ref MySQSQueue
    AWS_ACCOUNT_ID: ${env:AWS_ACCOUNT_ID}
    DEVELOPMENT_PATH: ${env:DEVELOPMENT_PATH}
    EXCHANGE_RATE_API: ${env:EXCHANGE_RATE_API}
    MESSAGING_QUEUE: ${env:MESSAGING_QUEUE}
    SNS_TOPIC_ARN: ${env:SNS_TOPIC_ARN}
    ROLE_ARN: ${env:ROLE_ARN}
    # SNS_TOPIC_ARN: !GetAtt AmazonTextractMyTopicName.TopicArn
    # ROLE_ARN: arn:aws:iam::${env:AWS_ACCOUNT_ID}:role/${env:APP_SERVICE_NAME}-${env:APP_STAGE}-${env:AWS_REGION}-lambdaRole
  iam:
    role:
      statements:
        - Effect: Allow
          Action:
            - sqs:SendMessage
            - sqs:ReceiveMessage
            - sqs:DeleteMessage
          Resource: !GetAtt MySQSQueue.Arn
        - Effect: Allow
          Action:
            - textract:StartExpenseAnalysis
            - textract:GetExpenseAnalysis
          Resource: "*"
        - Effect: Allow
          Action:
            - s3:GetObject
            - s3:PutObject
          Resource: "*"
        - Effect: Allow
          Action:
            - sns:Publish
          Resource: !GetAtt AmazonTextractMyTopicName.TopicArn
        - Effect: Allow
          Action:
            - lambda:InvokeFunction
          Resource: "*"

functions:
  startExpenseAnalysisJob:
    handler: src/functions/startExpenseAnalysisJob.handler
    timeout: 180
    maximumRetryAttempts: 0
    events:
      - sqs:
          arn: !GetAtt MySQSQueue.Arn
          batchSize: 1
  processExpenseAnalysisJob:
    handler: src/functions/processExpenseAnalysisJob.handler
    events:
      - sns:
          arn: !GetAtt AmazonTextractMyTopicName.TopicArn
          topicName: AmazonTextractMyTopicName-${self:provider.stage}

resources:
  Resources:
    # Official Docs https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sqs-queues.html
    MySQSQueue:
      Type: AWS::SQS::Queue
      Properties:
        QueueName: SQS-${self:provider.stage}
        VisibilityTimeout: 360

    AmazonTextractMyTopicName:
      Type: AWS::SNS::Topic
      Properties:
        TopicName: AmazonTextractMyTopicName-${self:provider.stage}

custom:
  serverless-offline-sqs:
    autoCreate: true
    apiVersion: "2012-11-05"
    endpoint: http://0.0.0.0:9324
    region: ${self:provider.region}
    accessKeyId: root
    secretAccessKey: root
    skipCacheInvalidation: false

Also, should I use subscribe my SQS to the topic? Right now I am just having my second Lambda with a trigger event with only SNS.


Solution

  • I solved the issue, following this guide: docs.aws.amazon.com/textract/latest/dg/api-async-roles.html

    Follow this part: Giving Amazon Textract Access to Your Amazon SNS Topic. the step 14, where you should find the trust policy and add it to your role (In the aws console) select your role => Find Trust Relationship => Edit Trust Policy.

    The problem I had was related to the permissions, specifically in the trust relationships part.

    Thank you, hope this helps for those who works with this.