首页 > 解决方案 > 尽管调用权限配置得当,但 Cognito “PreSignUp 调用因配置而失败”

问题描述

我目前有一个配置为触发预注册 lambda 的 Cognito 用户池。现在我正在设置登台环境,并且我在 dev 上具有完全相同的设置(可以工作)。我知道这是一样的,因为我是用相同的 terraform 文件创建两个环境。

我已经将调用权限与 lambda 函数相关联,这通常是导致此错误消息的原因。两种环境中的一切看起来都一样,除了当我尝试从新的登台环境注册新用户时收到“PreSignUp 调用因配置失败” 。

AWS 是否需要太长时间才能使权限缓存失效?到目前为止,我只能相信这是来自 AWS 的错误...

有任何想法吗!?

标签: amazon-web-servicesamazon-cognito

解决方案


似乎存在竞争条件,第一次部署时未附加权限。

我能够用 cloudformation 重现这一点。

两次部署具有相同配置的堆栈似乎可以“修复”权限问题。

我实际上在权限附件上添加了 10 秒的延迟,它解决了我的第一个部署问题......

我希望这对遇到此问题的其他人有所帮助。

    # Hack to fix Cloudformation bug
    # AWS::Lambda::Permission will not attach correctly on first deployment unless "delay" is used
    # DependsOn & every other thing did not work... ¯\_(ツ)_/¯
    CustomResourceDelay:
      Type: Custom::Delay
      DependsOn:
        - PostConfirmationLambdaFunction
        - CustomMessageLambdaFunction
        - CognitoUserPool
      Properties:
        ServiceToken: !GetAtt CustomResourceDelayFunction.Arn
        SecondsToWait: 10
    CustomResourceDelayFunctionRole:
      Type: AWS::IAM::Role
      Properties:
        AssumeRolePolicyDocument:
          Version: '2012-10-17'
          Statement: [{ "Effect":"Allow","Principal":{"Service":["lambda.amazonaws.com"]},"Action":["sts:AssumeRole"] }]
        Policies:
          - PolicyName: !Sub "${AWS::StackName}-delay-lambda-logs"
            PolicyDocument:
              Version: '2012-10-17'
              Statement:
                - Effect: Allow
                  Action: [ logs:CreateLogGroup, logs:CreateLogStream, logs:PutLogEvents ]
                  Resource: !Sub arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${AWS::StackName}*:*
    CustomResourceDelayFunction:
      Type: AWS::Lambda::Function
      Properties:
        Handler: index.handler
        Description: Wait for N seconds custom resource for stack debounce
        Timeout: 120
        Role: !GetAtt CustomResourceDelayFunctionRole.Arn
        Runtime: nodejs12.x
        Code:
          ZipFile: |
            const { send, SUCCESS } = require('cfn-response')
            exports.handler = (event, context, callback) => {
              if (event.RequestType !== 'Create') {
                return send(event, context, SUCCESS)
              }
              const timeout = (event.ResourceProperties.SecondsToWait || 10) * 1000
              setTimeout(() => send(event, context, SUCCESS), timeout)
            }

    # ------------------------- Roles & Permissions for cognito resources ---------------------------
    CognitoTriggerPostConfirmationInvokePermission:
      Type: AWS::Lambda::Permission
      ## CustomResourceDelay needed to property attach permission
      DependsOn: [ CustomResourceDelay ]
      Properties:
        Action: lambda:InvokeFunction
        FunctionName: !GetAtt PostConfirmationLambdaFunction.Arn
        Principal: cognito-idp.amazonaws.com
        SourceArn: !GetAtt CognitoUserPool.Arn

推荐阅读