ALB/Lambda CloudFormation circular dependency

0

I'm trying to create a CFn stack including a Lambda function being called by ALB. Part of this requires giving permission for the ALB to invoke the Lambda function.

However, when I do this in CloudFormation I get an error:

API: elasticloadbalancingv2:RegisterTargets elasticloadbalancing principal does not have permission to invoke <Lambda ARN> from target group <ALB Target Group ARN>

This is happening because CFn is creating the ALB target group before the permission is being created. Normally, I'd put a DependsOn in the target group definition so that but when I do that CFN tells me that there is a circular dependency - and there is because the permission references both the Lambda function and the target group.

I could remove the reference to the target group from the permission (and indeed this does fix the problem) but doing so would allow anything in the account to invoke the function (please correct me if I'm wrong here).

Is there a way around this? Briefest CFn template below:

AWSTemplateFormatVersion: "2010-09-09"

Resources:
    ALB:
        Type: "AWS::ElasticLoadBalancingV2::LoadBalancer"
        Properties:
            Name: "test-alb"
            Scheme: "internal"
            Type: "application"
            Subnets: 
              - "subnet-01c47f76"
              - "subnet-957eecf0"

    ALBListener:
        Type: "AWS::ElasticLoadBalancingV2::Listener"
        Properties:
            LoadBalancerArn: !Ref ALB
            Port: 80
            Protocol: "HTTP"
            DefaultActions: 
              - 
                Type: "forward"
                ForwardConfig: 
                    TargetGroups:
                      - TargetGroupArn: !Ref ALBTargetGroup

    ALBLambdaPermission:
        DependsOn:
          - LambdaFunction
        Type: AWS::Lambda::Permission
        Properties:
            FunctionName: !GetAtt LambdaFunction.Arn
            Action: lambda:InvokeFunction
            Principal: elasticloadbalancing.amazonaws.com
            SourceArn: !Ref ALBTargetGroup

    ALBTargetGroup:
        DependsOn: ALBLambdaPermission
        Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
        Properties:
            HealthCheckPath: "/"
            TargetType: "lambda"
            Targets: 
              - 
                Id: !GetAtt LambdaFunction.Arn

    LambdaRole:
      Type: AWS::IAM::Role
      Properties:
        AssumeRolePolicyDocument:
          Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Principal:
                Service:
                  - lambda.amazonaws.com
              Action:
                - sts:AssumeRole
        ManagedPolicyArns:
          - !Sub "arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"


    LambdaFunction:
        Type: "AWS::Lambda::Function"
        Properties:
            FunctionName: "alb-test-lambda"
            Handler: "index.lambda_handler"
            Code: 
              ZipFile: |
                def lambda_handler(event, context):
                    return  {
                        "statusCode": 200,
                        "body": "Hello from Lambda!",
                        "headers": {
                            "Content-Type": "text/html"
                        }
                    }
            Role: !GetAtt LambdaRole.Arn
            Runtime: "python3.6"
profile pictureAWS
전문가
질문됨 4년 전1108회 조회
1개 답변
0
수락된 답변

The trick for these cases is to build (one of) the ARN as a string rather than a reference, thus breaking the circular dependency. In your case, if you break the SourceArn and use a wildcard, it should work:

    ALBLambdaPermission:
        DependsOn:
          - LambdaFunction
        Type: AWS::Lambda::Permission
        Properties:
            FunctionName: !GetAtt LambdaFunction.Arn
            Action: lambda:InvokeFunction
            Principal: elasticloadbalancing.amazonaws.com
            SourceArn: !Sub "arn:aws:elasticloadbalancing:${AWS::Region}:${AWS::AccountId}:targetgroup/Bingo/*" # Rather than !Ref ALBTargetGroup

    ALBTargetGroup:
        DependsOn: ALBLambdaPermission
        Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
        Properties:
            HealthCheckPath: "/"
            Name: "Bingo"
            TargetType: "lambda"
            Targets: 
              - 
                Id: !GetAtt LambdaFunction.Arn
AWS
전문가
Raphael
답변함 4년 전
  • This solution didn't seem to work for me. When I view the Lambda in the console it shows an error and the trigger isn't registered. I read somewhere that AWS::Lambda::Permission doesn't support wildcards.

로그인하지 않았습니다. 로그인해야 답변을 게시할 수 있습니다.

좋은 답변은 질문에 명확하게 답하고 건설적인 피드백을 제공하며 질문자의 전문적인 성장을 장려합니다.

질문 답변하기에 대한 가이드라인

관련 콘텐츠