Cloudformation custom resource failing

0

Below CloudFormation template has started failing in the last 2 days. It uses the cfn-response and NodeJS10 runtime. Appreciate your inputs. The cfn-response success/ failure is not being sent by the lambda and template is stuck for 3 hours. Has there been any change to the SDK?

AWSTemplateFormatVersion: '2010-09-09'

Description: ENI extraction template for API Gateway VPC Endpoint

Parameters:
  VPCId:
    Type: AWS::EC2::VPC::Id
    Description: VPC for the Lambda and VPC endpoint
  SecurityGroupIds:
    Type: List<AWS::EC2::SecurityGroup::Id>
    Description: Security group Ids for the Lambda and VPC endpoint
  SubnetIds:
    Type: List<AWS::EC2::Subnet::Id>
    Description: Subnet Ids for the Lambda

Resources:

  # Get the VPCe ENI IPs using custom resource
  GetPrivateIPsRole:
    Type: AWS::IAM::Role
    Properties:
      Path: "/"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: "Allow"
            Principal:
              Service: "lambda.amazonaws.com"
            Action:
              - "sts:AssumeRole"
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
      Policies:
        - PolicyName: "GetPrivateIPs"
          PolicyDocument:
            Statement:
              - Action:
                  - "ec2:DescribeNetworkInterfaces"
                  - "ec2:CreateNetworkInterface"
                  - "ec2:DeleteNetworkInterface"
                  - "ec2:DescribeInstances"
                  - "ec2:AttachNetworkInterface"
                Effect: "Allow"
                Resource: "*"

  GetPrivateIPsLambda:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        ZipFile: |
          const AWS = require('aws-sdk');
          const response = require('cfn-response');

          exports.handler = function(event, context) {

            console.log("============================================================");
            console.log(event);
            console.log("============================================================");

            var networkInterfaceIdsList = event.ResourceProperties.NetworkInterfaceIds;
            var ec2 = new AWS.EC2();
            var params = {
              NetworkInterfaceIds: networkInterfaceIdsList
            };
            ec2.describeNetworkInterfaces(params, function(err, data) {
              if (err) {
                var responseData = {}
                responseData["IP0"] = "Fail";
                responseData["IP1"] = "Fail";
                responseData["IP2"] = "Fail";
                response.send(event, context, response.FAILED, responseData);
              } // an error occurred
              else {
                var networkInterfaceIPs = [];
                data.NetworkInterfaces.forEach(function getNetworkInterfaceIPs(item, index){
                  var ip = item.PrivateIpAddress;
                  networkInterfaceIPs.push(ip)
                });
                var responseData = {}
                responseData["IP0"] = networkInterfaceIPs[0];
                responseData["IP1"] = networkInterfaceIPs[1];
                responseData["IP2"] = networkInterfaceIPs[2];
                response.send(event, context, response.SUCCESS, responseData);
              }// successful response
            });
          };
      VpcConfig:
        SecurityGroupIds: !Ref SecurityGroupIds
        SubnetIds: !Ref SubnetIds
      Handler: index.handler
      Description: Extract the VPCe ENI private IPs
      Role: !GetAtt GetPrivateIPsRole.Arn
      Runtime: nodejs10.x
      Timeout: 60

  # Get the VPCe private IPs for the NLB target group
  GetPrivateIPs:
    Type: Custom::GetPrivateIPs
    Properties:
      ServiceToken: !GetAtt GetPrivateIPsLambda.Arn
      NetworkInterfaceIds: !GetAtt ApiGatewayVPCEndpoint.NetworkInterfaceIds

  ApiGatewayVPCEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      VpcEndpointType: Interface
      VpcId: !Ref VPCId
      SubnetIds: !Ref SubnetIds
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.execute-api'
      SecurityGroupIds: !Ref SecurityGroupIds
      PrivateDnsEnabled: false


AWS
Suraj
asked 3 years ago1712 views
1 Answer
0
Accepted Answer

Added a DependsOn just in caes and extended the timeout (as VPC Lambda can take longer)...

Worked as expected with an S3 Gateway Endpoint and EC2 Interface Endpoint in Private Subnets:

AWSTemplateFormatVersion: '2010-09-09'
Description: ENI extraction template for API Gateway VPC Endpoint
Parameters:
  VPCId:
    Type: AWS::EC2::VPC::Id
    Description: VPC for the Lambda and VPC endpoint
    Default: "vpc-xxxxx"
  SecurityGroupIds:
    Type: List<AWS::EC2::SecurityGroup::Id>
    Description: Security group Ids for the Lambda and VPC endpoint
    Default: "sg-xxxx"
  SubnetIds:
    Type: List<AWS::EC2::Subnet::Id>
    Description: Subnet Ids for the Lambda
    Default: "subnet-xxxx, subnet-yyyy"

Resources:

  # Get the VPCe ENI IPs using custom resource
  GetPrivateIPsRole:
    Type: AWS::IAM::Role
    Properties:
      Path: "/"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: "Allow"
            Principal:
              Service: "lambda.amazonaws.com"
            Action:
              - "sts:AssumeRole"
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
      Policies:
        - PolicyName: "GetPrivateIPs"
          PolicyDocument:
            Statement:
              - Action:
                  - "ec2:DescribeNetworkInterfaces"
                  - "ec2:CreateNetworkInterface"
                  - "ec2:DeleteNetworkInterface"
                  - "ec2:DescribeInstances"
                  - "ec2:AttachNetworkInterface"
                Effect: "Allow"
                Resource: "*"

  GetPrivateIPsLambda:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        ZipFile: |
          const AWS = require('aws-sdk');
          const response = require('cfn-response');

          exports.handler = function(event, context) {

            console.log("============================================================");
            console.log(event);
            console.log("============================================================");

            var networkInterfaceIdsList = event.ResourceProperties.NetworkInterfaceIds;
            var ec2 = new AWS.EC2();
            var params = {
              NetworkInterfaceIds: networkInterfaceIdsList
            };
            ec2.describeNetworkInterfaces(params, function(err, data) {
              if (err) {
                var responseData = {}
                responseData["IP0"] = "Fail";
                responseData["IP1"] = "Fail";
                responseData["IP2"] = "Fail";
                response.send(event, context, response.FAILED, responseData);
              } // an error occurred
              else {
                var networkInterfaceIPs = [];
                data.NetworkInterfaces.forEach(function getNetworkInterfaceIPs(item, index){
                  var ip = item.PrivateIpAddress;
                  networkInterfaceIPs.push(ip)
                });
                var responseData = {}
                responseData["IP0"] = networkInterfaceIPs[0];
                responseData["IP1"] = networkInterfaceIPs[1];
                responseData["IP2"] = networkInterfaceIPs[2];
                response.send(event, context, response.SUCCESS, responseData);
              }// successful response
            });
          };
      VpcConfig:
        SecurityGroupIds: !Ref SecurityGroupIds
        SubnetIds: !Ref SubnetIds
      Handler: index.handler
      Description: Extract the VPCe ENI private IPs
      Role: !GetAtt GetPrivateIPsRole.Arn
      Runtime: nodejs10.x
      Timeout: 360

  # Get the VPCe private IPs for the NLB target group
  GetPrivateIPs:
    Type: Custom::GetPrivateIPs
    DependsOn: [ApiGatewayVPCEndpoint]
    Properties:
      ServiceToken: !GetAtt GetPrivateIPsLambda.Arn
      NetworkInterfaceIds: !GetAtt ApiGatewayVPCEndpoint.NetworkInterfaceIds

  ApiGatewayVPCEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      VpcEndpointType: Interface
      VpcId: !Ref VPCId
      SubnetIds: !Ref SubnetIds
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.execute-api'
      SecurityGroupIds: !Ref SecurityGroupIds
      PrivateDnsEnabled: false
AWS
EXPERT
Raphael
answered 3 years ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions