TerraformでセキュリティグループIDをソースに指定したセキュリティグループを作成する
セキュリティグループを作成するときに、インバウンドのソースとして別のセキュリティグループIDを指定する方法はとても便利です。
よく使うのは、AWSで踏み台サーバを用意してアプリケーションサーバにはその踏み台サーバ経由でしかsshできないようにする場合です。
踏み台サーバには特定の(社内などの)IPからしかsshできないようなセキュリティグループを設定し、アプリケーションサーバにはそのセキュリティグループIDがソースであるsshのみを許可するようにします。
CIDRブロック単位だと許可範囲が広いですし、IPだと変更があったときにセキュリティグループの設定も修正する必要があるので、セキュリティグループIDをソースに指定するやり方は便利です。
さて、この方法でセキュリティグループを作成するにあたってTerraformを使おうとした場合、少し悩みました。
以降のTerraformはv0.12.12で動作確認しています。
仮に踏み台サーバはどこからでもsshできて大丈夫だとして、そのようなセキュリティグループを作成する場合は以下のようなTerraformになります。
provider "aws" { region = "ap-northeast-1" } resource "aws_security_group" "bastion" { name = "bastion" description = "Security Group for bastion" ingress { from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } }
これはこれで問題ないのですが、今回作成したセキュリティグループをソースに指定してセキュリティグループを作成する方法に少し悩みました。
公式によると、aws_security_groupリソースのingressブロックで取りうる要素は以下の通りで、それっぽい指定箇所はありません。 www.terraform.io
要素 | 説明 |
---|---|
cidr_blocks | (Optional) List of CIDR blocks. |
ipv6_cidr_blocks | (Optional) List of IPv6 CIDR blocks. |
prefix_list_ids | (Optional) List of prefix list IDs. |
from_port | (Required) The start port (or ICMP type number if protocol is "icmp") |
protocol | (Required) The protocol. If you select a protocol of "-1" (semantically equivalent to "all", which is not a valid value here), you must specify a "from_port" and "to_port" equal to 0. If not icmp, tcp, udp, or "-1" use the protocol number |
security_groups | (Optional) List of security group Group Names if using EC2-Classic, or Group IDs if using a VPC. |
self | (Optional) If true, the security group itself will be added as a source to this ingress rule. |
to_port | (Required) The end range port (or ICMP code if protocol is "icmp"). |
description | (Optional) Description of this ingress rule. |
というわけで、よくよく調べると、aws_security_group_ruleリソースで指定ができるようです。 www.terraform.io
要素 | 説明 |
---|---|
source_security_group_id | (Optional) The security group id to allow access to/from, depending on the type. Cannot be specified with cidr_blocks and self. |
最終的に、以下のようになります。
provider "aws" { region = "ap-northeast-1" } resource "aws_security_group" "bastion" { name = "bastion" description = "Security Group for bastion" ingress { from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } } resource "aws_security_group" "application" { name = "application" description = "Security Group for application" egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } } resource "aws_security_group_rule" "application_from_bastion" { type = "ingress" to_port = 22 protocol = "tcp" source_security_group_id = aws_security_group.bastion.id from_port = 22 security_group_id = aws_security_group.application.id }