使用 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
函数用于引用在同一模板中创建的安全组的逻辑名称。
在第一个入口规则中,必须为 SourceSecurityGroupName
和 SourceSecurityGroupOwnerId
属性添加一个值。在第二个入口规则中,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 安全组:SGroup1
和 SGroup2
。允许在两个安全组之间通信的入口规则是使用 AWS::EC2::SecurityGroupIngress 资源创建的。SGroup1Ingress
为 SGroup1
建立了一个入口规则,允许来自源安全组 SGroup2
端口 80 上的传入 TCP 流量。SGroup2Ingress
为 SGroup2
建立了一个入口规则,允许来自源安全组 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
来获取负载均衡器源安全组的 OwnerAlias
。SourceSecurityGroupName
使用 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