【问题标题】:AWS Textract StartDocumentAnalysis function not publishing a message to the SNS TopicAWS Textract StartDocumentAnalysis 函数未向 SNS 主题发布消息
【发布时间】:2019-11-05 18:51:05
【问题描述】:

我正在使用 AWS Textract,我想分析一个多页文档,因此我必须使用异步选项,所以我首先使用了 startDocumentAnalysisfunction,我得到了一个 JobId 作为返回,但它需要触发一个我设置的 SNS 主题收到消息时触发的函数。

这些是我的无服务器文件和处理程序文件。

provider:
  name: aws
  runtime: nodejs8.10
  stage: dev
  region: us-east-1
  iamRoleStatements:
    - Effect: "Allow"
      Action:
       - "s3:*"
      Resource: { "Fn::Join": ["", ["arn:aws:s3:::${self:custom.secrets.IMAGE_BUCKET_NAME}", "/*" ] ] }
    - Effect: "Allow"
      Action:
        - "sts:AssumeRole"
        - "SNS:Publish"
        - "lambda:InvokeFunction"
        - "textract:DetectDocumentText"
        - "textract:AnalyzeDocument"
        - "textract:StartDocumentAnalysis"
        - "textract:GetDocumentAnalysis"
      Resource: "*"

custom:
  secrets: ${file(secrets.${opt:stage, self:provider.stage}.yml)}

functions:
  routes:
    handler: src/functions/routes/handler.run
    events:
      - s3:
          bucket: ${self:custom.secrets.IMAGE_BUCKET_NAME}
          event: s3:ObjectCreated:*

  textract:
    handler: src/functions/routes/handler.detectTextAnalysis
    events:
      - sns: "TextractTopic"

resources:
  Resources:
    TextractTopic:
        Type: AWS::SNS::Topic
        Properties:
          DisplayName: "Start Textract API Response"
          TopicName: TextractResponseTopic

Handler.js

module.exports.run = async (event) => {
  const uploadedBucket = event.Records[0].s3.bucket.name;
  const uploadedObjetct = event.Records[0].s3.object.key;

  var params = {
    DocumentLocation: {
      S3Object: {
        Bucket: uploadedBucket,
        Name: uploadedObjetct
      }
    },
    FeatureTypes: [
      "TABLES", 
      "FORMS"
    ],
    NotificationChannel: {
      RoleArn: 'arn:aws:iam::<accont-id>:role/qvalia-ocr-solution-dev-us-east-1-lambdaRole', 
      SNSTopicArn: 'arn:aws:sns:us-east-1:<accont-id>:TextractTopic'
    }
  };

  let textractOutput = await new Promise((resolve, reject) => {
    textract.startDocumentAnalysis(params, function(err, data) {
      if (err) reject(err); 
      else resolve(data);
    });
  });
}

我手动向主题发布了一条 sns 消息,然后它正在触发当前具有此功能的 textract lambda,

module.exports.detectTextAnalysis = async (event) => {
  console.log('SNS Topic isssss Generated');
  console.log(event.Records[0].Sns.Message);
};

我有什么错误以及为什么文本 startDocumentAnalysis 没有发布消息并使其触发 lambda?

注意:在使用 startTextAnalysis 函数之前我没有使用 startDocumentTextDetection,尽管在此之前没有必要调用它。

【问题讨论】:

  • qvalia-ocr-solution-dev-us-east-1-lambdaRole 是否有足够的权限通过 SNS 发布?
  • 我也在 amazon textract 工作,SNS 发布大约一周前还在工作,现在不行了。我有一个应用程序,我没有在发布中更改任何内容,现在它已损坏。开发者一定已经破坏了它,因为它仍然是开放预览。
  • @griff4594 我也有同样的问题,我很想弄清楚这是怎么回事。感谢您的评论
  • @griff4594 我注意到,如果在推送到 SNS 的角色中使用允许所有策略,它会起作用。我不知道我忘记了什么权限才能让它工作
  • @RubenJGarcia 我的工作是因为我使用的 IAM 角色不允许在受信任的关系中专门使用 Textract。 { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": [ "lambda.amazonaws.com", "textract.amazonaws.com" ] }, "Action": "sts:AssumeRole" } ] }

标签: amazon-web-services aws-lambda aws-sdk aws-sdk-nodejs amazon-textract


【解决方案1】:

确保您与所使用角色的信任关系:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": [
          "lambda.amazonaws.com",
          "textract.amazonaws.com"
        ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

【讨论】:

  • 这个答案并结合确保我同时拥有“sts:AssumeRole”和“sns:Publish”权限对我有用。谢谢!
【解决方案2】:

SNS 主题名称必须是 AmazonTextract

最后你的 arn 应该是这样的:

arn:aws:sns:us-east-2:111111111111:AmazonTextract

【讨论】:

  • 是的,如果您使用 aws 托管策略“AmazonTextractServiceRole”,则资源限制为“arn:aws:sns:*:*:AmazonTextract*”,这意味着您的 SNS 主题名称必须至少“AmazonTextract”开头
【解决方案3】:

通过将 Lambda 执行资源添加到我的 serverless.yml 文件中,我能够直接通过无服务器框架实现此功能:

resources:
  Resources:
    IamRoleLambdaExecution:
      Type: AWS::IAM::Role
      Properties:
        AssumeRolePolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Principal:
                Service:
                  - lambda.amazonaws.com
                  - textract.amazonaws.com
              Action: sts:AssumeRole

然后我只是在启动Textract文档分析时使用了Serverless生成的相同角色(用于lambda函数)作为通知通道角色参数:

感谢this post 为我指明了正确的方向!

【讨论】:

    【解决方案4】:

    对于在 TypeScript 中使用 CDK 的任何人,您都需要像往常一样将 Lambda 作为 ServicePrincipal 添加到 Lambda 执行角色。接下来访问执行角色的assumeRolePolicy,调用addStatements方法。

    基本执行角色,无需任何额外语句(稍后添加)

      this.executionRole = new iam.Role(this, 'ExecutionRole', {
        assumedBy: new ServicePrincipal('lambda.amazonaws.com'),
      });
    

    接下来,将 Textract 添加为额外的 ServicePrincipal

      this.executionRole.assumeRolePolicy?.addStatements(
        new PolicyStatement({
          principals: [
            new ServicePrincipal('textract.amazonaws.com'),
          ],
          actions: ['sts:AssumeRole']
        })
      );
    

    另外,确保执行角色对目标 SNS 主题拥有完全权限(注意主题已创建并通过 fromTopicArn 方法访问)

     const stmtSNSOps = new PolicyStatement({
        effect: iam.Effect.ALLOW,
        actions: [
          "SNS:*"
        ],
        resources: [
          this.textractJobStatusTopic.topicArn
        ]
      });
    

    将策略语句添加到全局策略(在活动堆栈中)

     this.standardPolicy = new iam.Policy(this, 'Policy', {
        statements: [
          ...
          stmtSNSOps, 
          ...
        ]
      });
    

    最后,将策略附加到执行角色

      this.executionRole.attachInlinePolicy(this.standardPolicy);
    

    【讨论】:

      【解决方案5】:

      如果您的存储桶已加密,则应授予 kms 权限,否则它将不起作用

      【讨论】:

      • 您能否具体说明您指的是哪些 KMS 操作?
      猜你喜欢
      • 2020-07-08
      • 1970-01-01
      • 2021-02-15
      • 2021-05-06
      • 2016-03-05
      • 2019-03-19
      • 1970-01-01
      • 1970-01-01
      • 2021-10-18
      相关资源
      最近更新 更多