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
ESPERTO
posta 4 anni fa1108 visualizzazioni
1 Risposta
0
Risposta accettata

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
ESPERTO
Raphael
con risposta 4 anni fa
  • 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.

Accesso non effettuato. Accedi per postare una risposta.

Una buona risposta soddisfa chiaramente la domanda, fornisce un feedback costruttivo e incoraggia la crescita professionale del richiedente.

Linee guida per rispondere alle domande