首页 > 解决方案 > 如何在 CloudFormation 模板中引用现有安全组

问题描述

我正在尝试创建一个 CF 模板来部署 Lambda 函数。我想将它分配给名为“default”的安全组。

我的 CF 模板如下所示:

LambdaFunction:
  Type: AWS::Lambda::Function
  Properties:
    VpcConfig:
      SecurityGroupIds:
        - sg-085XXXXXXXX

我可以使用它的 ID 分配这个特定的安全组。但我想引用 SG 名称“default”而不是 SG id ,因为我想将我的 Lambda 部署在不同的 AWS 账户中。有没有办法获取现有安全组的 id 并在 CF 模板中使用它。

标签: amazon-web-servicesamazon-cloudformation

解决方案


不幸的是,您不能按名称引用安全组。您可以编写一个自定义资源来查找资源名称并输出 Id。

可以在此处找到 反向设置的示例: https ://aws.amazon.com/blogs/mt/four-ways-to-retrieve-any-aws-service-property-using-aws-cloudformation-part-1 /

它实际上创建了一个自定义资源,其输入是安全组 ID,输出是安全组名称。

模板:

AWSTemplateFormatVersion: '2010-09-09'
Parameters: 
  vpcID: 
    Type: AWS::EC2::VPC::Id
    Description: Enter VPC Id

Resources:
  CfnEC2SecurityGroup: 
    Type: 'AWS::EC2::SecurityGroup' 
    Properties: 
      GroupDescription: CFN2 Security Group Description
      VpcId: !Ref vpcID

  LambdaBasicExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
        - Effect: Allow
          Principal:
            Service: lambda.amazonaws.com
          Action: sts:AssumeRole
      Path: /
      Policies:
        - PolicyName: CustomLambdaEC2DescribePolicy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Resource: arn:aws:logs:*:*:*
              - Effect: Allow
                Action:
                  - ec2:DescribeSecurityGroups
                Resource: '*'

  CustomSGResource:
    Type: AWS::CloudFormation::CustomResource
    Properties:
      ServiceToken: !GetAtt 'CustomFunction.Arn'
      ResourceRef: !Ref 'CfnEC2SecurityGroup'

  CustomFunction:
    Type: AWS::Lambda::Function
    Properties:
      Handler: index.lambda_handler
      Description: "Retrieves EC2 Security group name"
      Timeout: 30
      Role: !GetAtt 'LambdaBasicExecutionRole.Arn'
      Runtime: python3.7
      Code:
        ZipFile: |
          import json
          import logging
          import cfnresponse
          import boto3
          
          logger = logging.getLogger()
          logger.setLevel(logging.INFO)

          def lambda_handler(event, context):
            logger.info('got event {}'.format(event))  
            try: 
              responseData = {}
              if event['RequestType'] == 'Delete':
                logger.info('Incoming RequestType: Delete operation') 
                cfnresponse.send(event, context, cfnresponse.SUCCESS, {})
              if event['RequestType'] in ["Create", "Update"]:                      
                # 1. retrieve resource reference ID or Name
                ResourceRef=event['ResourceProperties']['ResourceRef']
                # 2. retrieve boto3 client    
                client = boto3.client('ec2')
                # 3. Invoke describe/retrieve function using ResourceRef
                response = client.describe_security_groups(GroupIds=[ResourceRef])
                # 4. Parse and return required attributes 
                responseData = {}
                responseData['SecurityGroup-Name']= response.get('SecurityGroups')[0].get('GroupName')
                logger.info('Retrieved SecurityGroup-Name!')
                cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData)
              else:
                logger.info('Unexpected RequestType!') 
                cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData)
            except Exception as err:
              logger.error(err)
              responseData = {"Data": str(err)}
              cfnresponse.send(event,context,cfnresponse.FAILED,responseData)
            return              
Outputs:
  SecurityGroupID:
    Description: Security Group ID
    Value: !Ref CfnEC2SecurityGroup
  SecurityGroupName:
    Description: Security Group Name from the custom resource
    Value: !GetAtt 'CustomSGResource.SecurityGroup-Name'

博文逐步解释了模板。

您需要反转 lambda 的逻辑,以便它按名称查找安全组,然后返回 Id。


推荐阅读