How to programmatically register a lambda listener rule to an ALB?

Viewed 2590

Given that ALB Lambda integration is not currently supported by Cloudformation, I am trying to write a simple script to create a target group, register the lambda to the target group and then point a listener rule to that target group.

This works when I do it by the user interface however my attempts to register the lambda target to the target group fail (both in python script and cli):

botocore.exceptions.ClientError: An error occurred (AccessDenied) when calling the RegisterTargets operation: elasticloadbalancing principal does not have permission to invoke <LAMBDA ARN> from target group <TARGET GROUP ARN>

Below is the python script which does this:

import boto3
import os

environment = os.environ['ENV']
cloudformation = boto3.resource('cloudformation')
elb = boto3.client('elbv2')

stack = cloudformation.Stack('boomerang')

output = [x for x in stack.outputs if x['ExportName'] == 'boomerang-beacon-lambda'][0]
beacon_arn = output['OutputValue']

response = elb.create_target_group(
  TargetType='lambda',
  Name='public-%s-boomerang-beacon' % environment
)

target_group_arn = response['TargetGroups'][0]['TargetGroupArn']

elb.register_targets(
  TargetGroupArn=target_group_arn,
  Targets=[
    {
      'Id': beacon_arn
    },
  ]
)

Thank you

2 Answers

You will have to create add a lambda function permission to allow the elasticloadbalancing principal to invoke your lambda function. With CloudFormation you can add the following resource to make it work.

  LambdaFunctionPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName: !GetAtt LambdaTargetFunction.Arn
      Principal: elasticloadbalancing.amazonaws.com
      SourceArn: !Ref TargetGroup

More information on the Lambda Add Permission functionality can be found here: https://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html

'''
Below function uses boto3 to add permission to lambda function and then register it to TargetGroup 
'''

def addLambdaPermission():
        clientLambda = boto3.client('lambda',aws_access_key_id=ACCESS_KEY,aws_secret_access_key=SECRET_KEY,region_name=REGION)
        response = clientLambda.add_permission(
                Action='lambda:InvokeFunction',
                FunctionName=lambda_name,
                Principal='elasticloadbalancing.amazonaws.com',
                StatementId='registerTargetPermission',
        )
        print('Permissions added')

addLambdaPermission()

response = client.register_targets(
    TargetGroupArn= TGArn,
    Targets=[
        {
            'Id': lambda_arn,
        },
    ],
)

print('Lambda registered with TG')
Related