AWS CloudFormationを使用してsecurity groupを作成した際に、アウトバウンドルールを全て拒否に設定するのにつまずいたので記事にします。
背景・目的
- VPCエンドポイント用のsecurity groupを作成
- インバウンドルールはAWS Lambdaに割り当てたsecurity groupからのHTTPS通信のみ許可
- アウトバウンドルールは全て拒否
期待した動作と実際の結果
アウトバウンドルールを全て拒否にしたかったため、以下のようにSecurityGroupEgressは指定せずにsecurity groupを作成しました。
SampleSecurityGroup:
Type: 'AWS::EC2::SecurityGroup'
Properties:
GroupName: sample-sg
GroupDescription: test
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '443'
ToPort: '443'
SourceSecurityGroupId: !Ref Lambda
アウトバウンドルールを指定していないため、ルールが空になることを期待して、デプロイしました。
しかし、AWSマネジメントコンソールから作成されたsecurity groupを確認してみると、 結果は期待と真逆で、全て許可に設定されていました。
実装ミスかと思い、慌ててコードを見返してみましたが、確かにSecurityGroupEgressは指定していませんでした。
原因の調査
原因はAWS CloudFormationの公式ドキュメントに記載がありました。
When you create a security group, if you do not add egress rules, we add egress rules that allow all outbound IPv4 and IPv6 traffic. Otherwise, we do not add them. After the security group is created, if you remove all egress rules that you added, we do not add egress rules, so no outbound traffic is allowed.
要するに、AWS CloudFormationを使用してsecurity groupを作成する際にアウトバウンドルールを設定していない場合は、全てのトラフィックを許可するアウトバウンドルールがデフォルトで追加される仕様ということでした。
解決方法
解決方法もAWS CloudFormationの公式ドキュメントに記載がありました。
Remove the default rule
When you specify a VPC security group, Amazon EC2 creates a default egress rule that allows egress traffic on all ports and IP protocols to any location. The default rule is removed only when you specify one or more egress rules. If you want to remove the default rule and limit egress traffic to just the localhost (127.0.0.1/32), use the following example.
sgwithoutegress:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Limits security group egress traffic
SecurityGroupEgress:
- CidrIp: 127.0.0.1/32
IpProtocol: "-1"
VpcId: !Ref myVPC
デフォルトのアウトバウンドルールは1つ以上アウトバウンドルールを指定した場合に削除されるので、ローカルホスト(127.0.0.1/32)のみ許可するアウトバウンドルールを設定すれば、削除できるとのことでした。
ローカルホストへの通信のみを許可するルールを追加することで、実質的にすべての外部通信を拒否できるということです。
最終的には以下のように指定することで解決しました。
SampleSecurityGroup:
Type: 'AWS::EC2::SecurityGroup'
Properties:
GroupName: sample-sg
GroupDescription: test
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '443'
ToPort: '443'
SourceSecurityGroupId: !Ref Lambda
SecurityGroupEgress:
- CidrIp: 127.0.0.1/32
IpProtocol: "-1"
学んだ教訓
今回はアウトバウンドルールを指定しなければ空になるだろうという思い込みが原因で、発生した事象でした。
新しいことを行う際は公式ドキュメントをしっかり参照し、最低でもデプロイ結果は必ず確認することが大切だと身に染みました。