ダメなパターン
これを
resource "aws_security_group" "test" {
name = "test"
vpc_id = "${aws_vpc.test.id}"
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["x.x.x.x/32"]
}
}
こう変えると
resource "aws_security_group" "test" {
name = "test"
vpc_id = "${aws_vpc.test.id}"
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
- cidr_blocks = ["x.x.x.x/32"]
+ cidr_blocks = ["x.x.x.x/32","y.y.y.y/32"]
}
}
ログが次のように出て、なんか diff が怪しい。1回 ingress を全部消して、再度全部作ってるような。
aws_security_group.test: Modifying...
ingress.2293169953.cidr_blocks.#: "1" => "0"
2016/10/27 18:33:14 [DEBUG] apply: aws_security_group.test: executing Apply
ingress.2293169953.cidr_blocks.0: "x.x.x.x/32" => ""
ingress.2293169953.from_port: "22" => "0"
ingress.2293169953.protocol: "tcp" => ""
ingress.2293169953.security_groups.#: "0" => "0"
ingress.2293169953.self: "0" => "0"
ingress.2293169953.to_port: "22" => "0"
ingress.3838495408.cidr_blocks.#: "0" => "2"
ingress.3838495408.cidr_blocks.0: "" => "x.x.x.x/32"
ingress.3838495408.cidr_blocks.1: "" => "y.y.y.y/32"
ingress.3838495408.from_port: "" => "22"
ingress.3838495408.protocol: "" => "tcp"
ingress.3838495408.security_groups.#: "0" => "0"
ingress.3838495408.self: "" => "0"
ingress.3838495408.to_port: "" => "22"
TF_LOG=DEBUG をつけて実行すると以下のようにログが出て、Revoke & Authorize している感じ。
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: 2016/10/27 18:33:15 [DEBUG] Revoking security group {
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: Description: "Managed by Terraform",
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: GroupName: "test",
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: IpPermissions: [{
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: FromPort: 22,
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: IpProtocol: "tcp",
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: IpRanges: [{
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: CidrIp: "x.x.x.x/32"
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: }],
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: ToPort: 22
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: }],
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: } ingress rule: []*ec2.IpPermission{{
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: FromPort: 22,
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: IpProtocol: "tcp",
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: IpRanges: [{
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: CidrIp: "x.x.x.x/32"
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: }],
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: ToPort: 22
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: }}
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: 2016/10/27 18:33:15 [DEBUG] Authorizing security group {
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: Description: "Managed by Terraform",
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: GroupName: "test",
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: IpPermissions: [{
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: FromPort: 22,
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: IpProtocol: "tcp",
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: IpRanges: [{
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: CidrIp: "x.x.x.x/32"
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: }],
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: ToPort: 22
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: }],
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: } ingress rule: []*ec2.IpPermission{{
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: FromPort: 22,
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: IpProtocol: "tcp",
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: IpRanges: [{
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: CidrIp: "x.x.x.x/32"
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: },{
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: CidrIp: "y.y.y.y/32"
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: }],
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: ToPort: 22
2016/10/27 18:33:15 [DEBUG] terraform-provider-aws: }}
// TODO: We need to handle partial state better in the in-between
// in this update.
// TODO: It'd be nicer to authorize before removing, but then we have
// to deal with complicated unrolling to get individual CIDR blocks
// to avoid authorizing already authorized sources. Removing before
// adding is easier here, and Terraform should be fast enough to
// not have service issues.
とあり、TODO になっている。Terraform は充分に早いからサービスISSUEは起こらないんじゃないかな(意訳)とのことだが ...
安全安心なパターン
aws_security_group_rule を使う
resource "aws_security_group" "test" {
name = "test"
vpc_id = "${aws_vpc.test.id}"
}
resource "aws_security_group_rule" "test_rule_1" {
security_group_id = "${aws_security_group.test.id}"
type = "ingress"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["x.x.x.x/32"]
}
+resource "aws_security_group_rule" "test_rule_2" {
+ security_group_id = "${aws_security_group.test.id}"
+ type = "ingress"
+ from_port = 22
+ to_port = 22
+ protocol = "tcp"
+ cidr_blocks = ["y.y.y.y/32"]
+}
これなら追加だけになる。ログは以下。
2016/10/27 18:40:29 [DEBUG] apply: aws_security_group_rule.test_rule2: executing Apply
aws_security_group_rule.test: Creating...
cidr_blocks.#: "" => "1"
cidr_blocks.0: "" => "y.y.y.y/32"
from_port: "" => "22"
protocol: "" => "tcp"
self: "" => "0"
2016/10/27 18:40:30 [DEBUG] terraform-provider-aws: 2016/10/27 18:40:30 [DEBUG] Authorizing security group sg-66d6231b Ingress rule: {
2016/10/27 18:40:30 [DEBUG] terraform-provider-aws: FromPort: 22,
2016/10/27 18:40:30 [DEBUG] terraform-provider-aws: IpProtocol: "tcp",
2016/10/27 18:40:30 [DEBUG] terraform-provider-aws: IpRanges: [{
2016/10/27 18:40:30 [DEBUG] terraform-provider-aws: CidrIp: "y.y.y.y/32"
2016/10/27 18:40:30 [DEBUG] terraform-provider-aws: }],
2016/10/27 18:40:30 [DEBUG] terraform-provider-aws: ToPort: 22
2016/10/27 18:40:30 [DEBUG] terraform-provider-aws: }
2016/10/27 18:40:30 [DEBUG] terraform-provider-aws: 2016/10/27 18:40:30 [DEBUG] Found rule for Security Group Rule (sgrule-3952629376): {
2016/10/27 18:40:30 [DEBUG] terraform-provider-aws: FromPort: 22,
2016/10/27 18:40:30 [DEBUG] terraform-provider-aws: IpProtocol: "tcp",
2016/10/27 18:40:30 [DEBUG] terraform-provider-aws: IpRanges: [{
2016/10/27 18:40:30 [DEBUG] terraform-provider-aws: CidrIp: "x.x.x.x/32"
2016/10/27 18:40:30 [DEBUG] terraform-provider-aws: },{
2016/10/27 18:40:30 [DEBUG] terraform-provider-aws: CidrIp: "y.y.y.y/32"
2016/10/27 18:40:30 [DEBUG] terraform-provider-aws: }],
2016/10/27 18:40:30 [DEBUG] terraform-provider-aws: ToPort: 22
2016/10/27 18:40:30 [DEBUG] terraform-provider-aws: }
注意点は、from_port, to_port が同じだからと cidr_blocks の配列要素に追加しようとすると、destory & add になってしまう点。つまり、以下はダメ。aws_security_group_rule を別途用意すべき。
resource "aws_security_group" "test" {
name = "test"
vpc_id = "${aws_vpc.test.id}"
}
resource "aws_security_group_rule" "test_rule_1" {
security_group_id = "${aws_security_group.test.id}"
type = "ingress"
from_port = 22
to_port = 22
protocol = "tcp"
- cidr_blocks = ["x.x.x.x/32"]
+ cidr_blocks = ["x.x.x.x/32","y.y.y.y/32"]
}
セキュリティグループの瞬断について考察 (追記)
セキュリティグループの ingress または egress からエントリを削除すると新規接続が弾かれるようになるが、すでに開いている接続が切られるわけではないことを確認した。
なので、「ダメなパターン」でも Revoke してから Authorize するまでの短い時間に新規接続が来たorをする場合にのみ問題となる。TCPであれば 少し待って(Linuxならデフォルト1秒)再接続するので、この少しを許容できるかという点と、UDPの送信失敗を許容できるかという点が論点になるだろう。
まぁ、aws_security_group_rule
を使っておくほうが安全というのは間違いない。