如何在 CloudFormation 中正确外部化 SecurityGroupEgress 和 SecurityGroupIngress

How correctly externalize SecurityGroupEgress and SecurityGroupIngress in CloudFormation

使用下面的 CloudFormation 模板,我可以通过 SSH 连接到 EC2 实例。

PublicSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
        GroupName: PublicSecurityGroup
        GroupDescription: Public Security Group
        VpcId:
            Ref: Vpc
        SecurityGroupEgress:
            - IpProtocol: "-1"
                FromPort: 0
                ToPort: 65535
                CidrIp: 0.0.0.0/0
        SecurityGroupIngress:
            - IpProtocol: tcp
                FromPort: 22
                ToPort: 22
                CidrIp: 0.0.0.0/0
PublicEc2Instance:
    Type: AWS::EC2::Instance
    Properties:
        ImageId:
            Ref: ImageId
        InstanceType:
            Ref: InstanceType
        KeyName:
            Ref: KeyName
        SecurityGroupIds:
            - Fn::GetAtt:
                    - PublicSecurityGroup
                    - GroupId
        SubnetId:
            Ref: PublicSubnet
        Tags:
            - Key: Name
                Value: PublicEc2Instance

当我将 SecurityGroup 定义更改为以下结构时

PublicSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
        GroupName: PublicSecurityGroup
        GroupDescription: Public Security Group
        VpcId:
            Ref: Vpc
PublicOutboundRule1:
    Type: AWS::EC2::SecurityGroupEgress
    Properties:
        GroupId: !Ref PublicSecurityGroup
        SourceSecurityGroupId: !Ref PublicSecurityGroup
        IpProtocol: "-1"
        FromPort: 0
        ToPort: 65535
PublicInboundRule1:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
        GroupId: !Ref PublicSecurityGroup
        SourceSecurityGroupId: !Ref PublicSecurityGroup
        IpProtocol: tcp
        FromPort: 22
        ToPort: 22

我无法再在 EC2 实例中使用 SSH。

为什么 SecurityGroupEgressSecurityGroupIngress 的外部化会阻止对 EC2 的 SSH 访问?

谢谢!

您将入口规则中的流量限制为以下行中的 PublicSecurityGroupSourceSecurityGroupId: !Ref PublicSecurityGroup 而不是 SourceSecurityGroupId 指定您在上面的 yaml 片段中使用的 CIDR 块:

PublicSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
        GroupName: PublicSecurityGroup
        GroupDescription: Public Security Group
        VpcId:
            Ref: Vpc
PublicOutboundRule1:
    Type: AWS::EC2::SecurityGroupEgress
    Properties:
        GroupId: !Ref PublicSecurityGroup
        IpProtocol: "-1"
        FromPort: 0
        ToPort: 65535
        CidrIp: 0.0.0.0/0

PublicInboundRule1:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
        GroupId: !Ref PublicSecurityGroup
        IpProtocol: tcp
        FromPort: 22
        ToPort: 22
        CidrIp: 0.0.0.0/0

请注意,我也从您的 Egress 规则中删除了 SourceSecurityGroupId,因为 Egress 规则不期望源,它们期望目的地(其他 SG、CIDR 块),因为它们就是出口 :)。

您没有在 AWS::EC2::SecurityGroup 和 AWS::EC2::SecurityGroupIngress/AWS::EC2::SecurityGroupEgress

之间建立正确的关系

在您的第一个描述中,您允许从任何位置访问 22 端口: SecurityGroupIngress: - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: 0.0.0.0/0

但是在您的第二个定义中,您定义的是仅从同一安全组访问端口 22,因为参数 SourceSecurityGroupId 指定了允许访问的 Amazon EC2 安全组的 ID,而您希望从 0.0.0.0 授予访问权限/, 不一样:

SourceSecurityGroupId: !Ref PublicSecurityGroup IpProtocol: tcp FromPort: 22 ToPort: 22

您需要删除 SourceSecurityGroupId 参数