使用 Amazon CloudFormation 管理安全组 - Amazon CloudFormation
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

使用 Amazon CloudFormation 管理安全组

以下代码段演示了如何使用 Amazon CloudFormation 管理安全组和 Amazon EC2 实例,从而控制对 Amazon 资源的访问权限。

将 Amazon EC2 实例与安全组关联

以下示例代码段演示了如何使用 Amazon CloudFormation 将 Amazon EC2 实例与默认的 Amazon VPC 安全组关联起来。

将 Amazon EC2 实例与默认 VPC 安全组关联

以下代码段创建了一个 Amazon VPC、一个 VPC 内的子网和一个 Amazon EC2 实例。VPC 是使用 AWS::EC2::VPC 资源创建的。VPC 的 IP 地址范围在较大的模板中定义并由 MyVPCCIDRRange 参数引用。

子网是使用 AWS::EC2:: Subnet 资源在 VPC 中创建的。子网与 VPC 关联,后者被引用为 MyVPC

使用 AWS::EC2::Instance 资源在 VPC 和子网内启动 EC2 实例。此资源指定用于启动实例的亚马逊机器映像(AMI)、实例将在其中运行的子网以及要与该实例关联的安全组。Fn::FindInMap 函数用于从模板中定义的 AWSRegionToAMI 映射检索值,以确定 AWS::EC2::Instance 资源的 ImageId

安全组 ID 是使用 Fn::GetAtt 函数获取的,该函数从 MyVPC 资源中检索默认安全组。

该实例位于代码段中定义的 MySubnet 资源中。

使用 Amazon CloudFormation 创建 VPC 时,Amazon 会在 VPC 中自动创建默认资源,包括默认安全组。但是,当您在 Amazon CloudFormation 模板中定义 VPC 时,可能无法在创建模板时访问这些默认资源的 ID。要访问和使用模板中指定的默认资源,您可以使用内置函数,例如 Fn::GetAtt。此函数允许您使用由 Amazon CloudFormation 自动创建的默认资源。

JSON

"MyVPC": { "Type": "AWS::EC2::VPC", "Properties": { "CidrBlock": { "Ref": "MyVPCCIDRRange" }, "EnableDnsSupport": false, "EnableDnsHostnames": false, "InstanceTenancy": "default" } }, "MySubnet": { "Type": "AWS::EC2::Subnet", "Properties": { "CidrBlock": { "Ref": "MyVPCCIDRRange" }, "VpcId": { "Ref": "MyVPC" } } }, "MyInstance": { "Type": "AWS::EC2::Instance", "Properties": { "ImageId": { "Fn::FindInMap": [ "AWSRegionToAMI", { "Ref": "AWS::Region" }, "64" ] }, "SecurityGroupIds": [ { "Fn::GetAtt": [ "MyVPC", "DefaultSecurityGroup" ] } ], "SubnetId": { "Ref": "MySubnet" } } }

YAML

MyVPC: Type: AWS::EC2::VPC Properties: CidrBlock: Ref: MyVPCCIDRRange EnableDnsSupport: false EnableDnsHostnames: false InstanceTenancy: default MySubnet: Type: AWS::EC2::Subnet Properties: CidrBlock: Ref: MyVPCCIDRRange VpcId: Ref: MyVPC MyInstance: Type: AWS::EC2::Instance Properties: ImageId: Fn::FindInMap: - AWSRegionToAMI - Ref: AWS::Region - "64" SecurityGroupIds: - Fn::GetAtt: - MyVPC - DefaultSecurityGroup SubnetId: Ref: MySubnet

创建带有附加卷和安全组的 Amazon EC2 实例

以下代码段使用从指定 AMI 启动的 AWS::EC2::Instance 资源创建 Amazon EC2 实例。该实例与一个安全组关联,该安全组使用 AWS::EC2::SecurityGroup 资源允许来自指定 IP 地址端口 22 上的传入 SSH 流量。它使用 AWS::EC2::Volume 资源创建一个 100GB 的 Amazon EBS 卷。根据 GetAtt 函数的指定,这个卷在与实例相同的可用区中创建,并安装到 /dev/sdh 设备上的实例。

有关创建 Amazon EBS 卷的更多信息,请参阅创建 Amazon EBS 卷

JSON

"Ec2Instance": { "Type": "AWS::EC2::Instance", "Properties": { "SecurityGroups": [ { "Ref": "InstanceSecurityGroup" } ], "ImageId": "ami-1234567890abcdef0" } }, "InstanceSecurityGroup": { "Type": "AWS::EC2::SecurityGroup", "Properties": { "GroupDescription": "Enable SSH access via port 22", "SecurityGroupIngress": [ { "IpProtocol": "tcp", "FromPort": "22", "ToPort": "22", "CidrIp": "192.0.2.0/24" } ] } }, "NewVolume": { "Type": "AWS::EC2::Volume", "Properties": { "Size": "100", "AvailabilityZone": { "Fn::GetAtt": [ "Ec2Instance", "AvailabilityZone" ] } } }, "MountPoint": { "Type": "AWS::EC2::VolumeAttachment", "Properties": { "InstanceId": { "Ref": "Ec2Instance" }, "VolumeId": { "Ref": "NewVolume" }, "Device": "/dev/sdh" } }

YAML

Ec2Instance: Type: AWS::EC2::Instance Properties: SecurityGroups: - !Ref InstanceSecurityGroup ImageId: ami-1234567890abcdef0 InstanceSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Enable SSH access via port 22 SecurityGroupIngress: - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: 192.0.2.0/24 NewVolume: Type: AWS::EC2::Volume Properties: Size: 100 AvailabilityZone: !GetAtt [Ec2Instance, AvailabilityZone] MountPoint: Type: AWS::EC2::VolumeAttachment Properties: InstanceId: !Ref Ec2Instance VolumeId: !Ref NewVolume Device: /dev/sdh

使用入口规则创建安全组

以下示例代码段演示了如何使用 Amazon CloudFormation 配置具有特定入口规则的安全组。

使用入口规则创建安全组以允许 SSH 和 HTTP 访问

以下代码段描述了两个使用 AWS::EC2::SecurityGroup 资源的安全组入口规则。第一个入口规则允许从名为 MyAdminSecurityGroup 的现有安全组访问 SSH(端口 22),该安全组由账号为 1111-2222-3333 的 Amazon 账户所有。第二个入口规则允许从名为 MySecurityGroupCreatedInCFN 的另一个安全组访问 HTTP(端口 80),该安全组是在同一个模板中创建的。Ref 函数用于引用在同一模板中创建的安全组的逻辑名称。

在第一个入口规则中,必须为 SourceSecurityGroupNameSourceSecurityGroupOwnerId 属性添加一个值。在第二个入口规则中,MySecurityGroupCreatedInCFNTemplate 引用了在同一个模板中创建的另一个安全组。验证逻辑名称 MySecurityGroupCreatedInCFNTemplate 是否与您在较大模板中指定的安全组资源的实际逻辑名称相匹配。

有关安全组的更多信息,请参阅适用于 Linux 实例的 Amazon EC2 安全组适用于 Windows 实例的 Amazon EC2 安全组

JSON

"SecurityGroup": { "Type": "AWS::EC2::SecurityGroup", "Properties": { "GroupDescription": "Allow connections from specified source security group", "SecurityGroupIngress": [ { "IpProtocol": "tcp", "FromPort": "22", "ToPort": "22", "SourceSecurityGroupName": "MyAdminSecurityGroup", "SourceSecurityGroupOwnerId": "1111-2222-3333" }, { "IpProtocol": "tcp", "FromPort": "80", "ToPort": "80", "SourceSecurityGroupName": { "Ref": "MySecurityGroupCreatedInCFNTemplate" } } ] } }

YAML

SecurityGroup: Type: 'AWS::EC2::SecurityGroup' Properties: GroupDescription: Allow connections from specified source security group SecurityGroupIngress: - IpProtocol: tcp FromPort: '22' ToPort: '22' SourceSecurityGroupName: MyAdminSecurityGroup SourceSecurityGroupOwnerId: '1111-2222-3333' - IpProtocol: tcp FromPort: '80' ToPort: '80' SourceSecurityGroupName: Ref: MySecurityGroupCreatedInCFNTemplate

使用入口规则创建安全组以允许来自指定 CIDR 范围的 HTTP 和 SSH 访问

以下代码段为具有两个入站规则的 Amazon EC2 实例创建了一个安全组。入站规则允许来自指定 CIDR 范围指定端口上的传入 TCP 流量。AWS::EC2::SecurityGroup 资源用于指定规则。您必须为每个规则指定一个协议。对于 TCP,您必须指定端口或端口范围。如果未指定源安全组或 CIDR 范围,堆栈虽会成功启动,但规则不会应用于安全组。

有关安全组的更多信息,请参阅适用于 Linux 实例的 Amazon EC2 安全组适用于 Windows 实例的 Amazon EC2 安全组

JSON

"ServerSecurityGroup": { "Type": "AWS::EC2::SecurityGroup", "Properties": { "GroupDescription": "Allow connections from specified CIDR ranges", "SecurityGroupIngress": [ { "IpProtocol": "tcp", "FromPort": "80", "ToPort": "80", "CidrIp": "192.0.2.0/24" }, { "IpProtocol": "tcp", "FromPort": "22", "ToPort": "22", "CidrIp": "192.0.2.0/24" } ] } }

YAML

ServerSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Allow connections from specified CIDR ranges SecurityGroupIngress: - IpProtocol: tcp FromPort: 80 ToPort: 80 CidrIp: 192.0.2.0/24 - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: 192.0.2.0/24

使用入口规则创建交叉引用安全组

以下代码段使用 AWS::EC2::SecurityGroup 资源创建两个 Amazon EC2 安全组:SGroup1SGroup2。允许在两个安全组之间通信的入口规则是使用 AWS::EC2::SecurityGroupIngress 资源创建的。SGroup1IngressSGroup1 建立了一个入口规则,允许来自源安全组 SGroup2 端口 80 上的传入 TCP 流量。SGroup2IngressSGroup2 建立了一个入口规则,允许来自源安全组 SGroup1 端口 80 上的传入 TCP 流量。

JSON

"SGroup1": { "Type": "AWS::EC2::SecurityGroup", "Properties": { "GroupDescription": "EC2 instance access" } }, "SGroup2": { "Type": "AWS::EC2::SecurityGroup", "Properties": { "GroupDescription": "EC2 instance access" } }, "SGroup1Ingress": { "Type": "AWS::EC2::SecurityGroupIngress", "Properties": { "GroupName": { "Ref": "SGroup1" }, "IpProtocol": "tcp", "ToPort": "80", "FromPort": "80", "SourceSecurityGroupName": { "Ref": "SGroup2" } } }, "SGroup2Ingress": { "Type": "AWS::EC2::SecurityGroupIngress", "Properties": { "GroupName": { "Ref": "SGroup2" }, "IpProtocol": "tcp", "ToPort": "80", "FromPort": "80", "SourceSecurityGroupName": { "Ref": "SGroup1" } } }

YAML

SGroup1: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: EC2 Instance access SGroup2: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: EC2 Instance access SGroup1Ingress: Type: AWS::EC2::SecurityGroupIngress Properties: GroupName: !Ref SGroup1 IpProtocol: tcp ToPort: 80 FromPort: 80 SourceSecurityGroupName: !Ref SGroup2 SGroup2Ingress: Type: AWS::EC2::SecurityGroupIngress Properties: GroupName: !Ref SGroup2 IpProtocol: tcp ToPort: 80 FromPort: 80 SourceSecurityGroupName: !Ref SGroup1

使用安全组入口规则创建弹性负载均衡器

以下模板在指定的可用区中创建了 AWS::ElasticLoadBalancing::LoadBalancer 资源。AWS::ElasticLoadBalancing::LoadBalancer 资源配置为在端口 80 上侦听 HTTP 流量,并将请求定向到端口 80 上的实例。弹性负载均衡器负责对实例间传入的 HTTP 流量进行负载均衡。

此外,此模板将生成一个与负载均衡器关联的 AWS::EC2::SecurityGroup 资源。此安全组是使用单个入口规则(描述为 ELB ingress group)创建的,该规则允许端口 80 上的传入 TCP 流量。此入口规则的来源是使用从负载均衡器资源检索属性的 Fn::GetAtt 函数定义的。SourceSecurityGroupOwnerId 使用 Fn::GetAtt 来获取负载均衡器源安全组的 OwnerAliasSourceSecurityGroupName 使用 Fn::Getatt 来获取 ELB 源安全组的 GroupName

此设置可确保 ELB 和实例之间的安全通信。

有关负载均衡的更多信息,请参阅 Elastic Load Balancing 用户指南

JSON

{ "AWSTemplateFormatVersion": "2010-09-09", "Resources": { "MyELB": { "Type": "AWS::ElasticLoadBalancing::LoadBalancer", "Properties": { "AvailabilityZones": [ "aa-example-1a" ], "Listeners": [ { "LoadBalancerPort": "80", "InstancePort": "80", "Protocol": "HTTP" } ] } }, "MyELBIngressGroup": { "Type": "AWS::EC2::SecurityGroup", "Properties": { "GroupDescription": "ELB ingress group", "SecurityGroupIngress": [ { "IpProtocol": "tcp", "FromPort": 80, "ToPort": 80, "SourceSecurityGroupOwnerId": { "Fn::GetAtt": [ "MyELB", "SourceSecurityGroup.OwnerAlias" ] }, "SourceSecurityGroupName": { "Fn::GetAtt": [ "MyELB", "SourceSecurityGroup.GroupName" ] } } ] } } } }

YAML

AWSTemplateFormatVersion: '2010-09-09' Resources: MyELB: Type: 'AWS::ElasticLoadBalancing::LoadBalancer' Properties: AvailabilityZones: - aa-example-1a Listeners: - LoadBalancerPort: '80' InstancePort: '80' Protocol: HTTP MyELBIngressGroup: Type: 'AWS::EC2::SecurityGroup' Properties: GroupDescription: ELB ingress group SecurityGroupIngress: - IpProtocol: tcp FromPort: '80' ToPort: '80' SourceSecurityGroupOwnerId: Fn::GetAtt: - MyELB - SourceSecurityGroup.OwnerAlias SourceSecurityGroupName: Fn::GetAtt: - MyELB - SourceSecurityGroup.GroupName