0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

第11回 Terraform講座|Security Group

0
Posted at

― 「誰の通信を許可する?」をコードで考える ―

今回から、少し難しくなる。

ここまでは、

  • VPC → ネットワークを作る
  • Subnet → ネットワークを区切る
  • Route Table → 通信の行き先を決める
  • ALB → 負荷分散する
  • Listener → 通信を振り分ける
  • Target Group → 転送先を管理する
  • EC2 → 実際に仕事をするサーバー

というように、

「このAWSサービスは何をするのか?」

を中心に勉強してきた。

でも、Security Groupは少し違う。

Security Groupは、

「誰の通信を許可するのか?」

を決めるルールだからだ。


🔥 今の構成をもう一度確認

現在の構成はこうなっている。

Internet
│
▼
Internet Gateway
│
▼
ALB
│
▼
Listener
│
▼
Target Group
│
▼
EC2

ここで考えてみよう。

もしインターネットからEC2へ直接アクセスできてしまったら?

Internet
│
├────────→ ALB → EC2
│
└────────→ EC2

これってどうだろう?

当然、あまり良くない。

本来は、

Internet
↓
ALB
↓
EC2

という経路にしたい。

そこで登場するのが、

Security Group


🔐 Security Groupとは?

Security Groupは、ざっくり言えば

「この通信は通していい。この通信はダメ」

というルールを設定するもの。

イメージとしては、建物の入口にいる警備員。

      👮

Internet ─→ Security Group ─→ EC2

警備員が、

«「誰ですか?」»

と確認して、

«「ALBです」»

なら、

«「どうぞ」»

となる。

でも、

«「インターネットから直接来ました」»

なら、

«「帰ってください」»

となる。

もちろん実際のSecurity Groupが人間みたいに確認しているわけではないけど、考え方としてはかなり近い。


TerraformでSecurity Groupを作る

まずはALB用のSecurity Group。

resource "aws_security_group" "alb" {

}

これは、

ALBに適用するSecurity Groupを作る

という意味。


① name

name = "alb-sg"

Security Groupの名前。

今回は、

alb-sg

という名前を付ける。


② vpc_id

vpc_id = aws_vpc.main.id

ここで質問。

なぜSecurity Groupにも、

vpc_id

が必要なんだろう?

ポイントは、

Security GroupはVPCに所属する

ということ。

イメージすると、

VPC
│
├── ALB
│ └── ALB Security Group
│
└── EC2
└── EC2 Security Group

という関係。

だからTerraformでは、

«「このSecurity Groupは、このVPCに所属させてね」»

と指定する。


③ ingress

ここはかなり重要。

ingress {
}

"ingress" は、

入ってくる通信

を定義する。

例えば、

from_port = 80
to_port = 80
protocol = "tcp"

なら、

TCPの80番ポートへの通信

を許可する設定。


④ cidr_blocks

さらに、

cidr_blocks = ["0.0.0.0/0"]

とする。

これ、以前にも出てきた。

"0.0.0.0/0" は、

すべてのIPv4アドレス

を意味する。

つまり今回、

0.0.0.0/0
↓
世界中
↓
TCP 80番
↓
ALB

という通信を許可している。

ALBはインターネットからアクセスを受ける必要があるので、

Internet
↓
ALB : 80

という通信を許可する。


⑤ egress

今度はこちら。

egress {
}

"egress" は、

外へ出ていく通信

を定義する。

今回の設定は、

from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]

となっている。

ここで注意。

"protocol = "-1"" は、

すべてのプロトコル

を意味する。

つまり、

  • TCP
  • UDP
  • ICMP

などを含めて許可する設定。

そのため、

from_port = 0
to_port = 0

だから「ポート0しか通らない」という意味ではない。

"protocol = "-1"" の場合、ポート指定は実質的に無視される。

つまり、

すべての送信先への通信を許可する

という設定になる。


完成形

ここまでをまとめると、

resource "aws_security_group" "alb" {

name = "alb-sg"

vpc_id = aws_vpc.main.id

ingress {

from_port = 80

to_port = 80

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"]

}

}

これで、

「インターネットからALBの80番ポートへの通信を許可するSecurity Group」

が作れる。


🔥 今日の問題

ここからが本番。

Q1

なぜSecurity Groupにも、

vpc_id

が必要なの?


Q2

ingress

と

egress

の違いは?


Q3【今日一番重要】

ALBのSecurity Groupでは、

cidr_blocks = ["0.0.0.0/0"]

として、

世界中から80番ポートへの通信を許可している。

では、EC2にも、

cidr_blocks = ["0.0.0.0/0"]

を書いていいだろうか?

理由も考えてみよう。

ヒントは、

Internet
│
▼
ALB SG
「世界中から80番OK」
│
▼
EC2 SG
「???」
│
▼
EC2


🎯 今日の考え方

今回からは、

「このサービスは何をする?」

だけではなく、

「誰と誰を通信させる?」

という視点も重要になる。

例えば最終的には、

Internet
│
▼
ALB SG
「世界中から80番OK」
│
▼
EC2 SG
「ALBからだけOK」
│
▼
RDS SG
「EC2からだけOK」

という構成を目指す。

これは、

必要な通信だけを許可する

という考え方。

AWSで非常に重要な、

最小権限の原則

につながってくる。


📝 今回の回答

今回の回答はこちら。

コードの説明

«"resource "aws_security_group" "alb""
セキュリティグループを作ります»

«"name = "alb-sg""
alb-sgという名前»

«"vpc_id = aws_vpc.main.id"
メインVPC»

«"ingress"
入ってくる»

«"from_port = 80"
ポート80から»

«"to_port = 80"
ポート80へ»

«"protocol = "tcp""
TCPプロトコルの通信»

«"cidr_blocks = ["0.0.0.0/0"]"
すべて受け付けます»

«"egress"
出るときは»

«"protocol = "-1""
-1プロトコル»

«"cidr_blocks = ["0.0.0.0/0"]"
すべての通信が通る»


🔎 今回のレビュー

今回は、正直ちょっと難しかったと思う。

でも、躓いたところがかなり分かりやすい回だった。

そして、その躓き方自体が悪いわけじゃない。

Security Groupは今までのAWSサービスと違って、

「サービスの役割」ではなく「通信ルール」

を考える必要があるからだ。

では、一つずつ確認していこう。


コードレビュー

"resource "aws_security_group" "alb""

«セキュリティグループを作ります»

その通り。

100点!💯


"name = "alb-sg""

«alb-sgという名前»

これもOK。

100点!


"vpc_id = aws_vpc.main.id"

«メインVPC»

これも正しい。

ただし、ここは後のQ1にもつながる重要ポイント。

"vpc_id" は、

「どのVPCに所属するSecurity Groupなのか」

を指定している。


"ingress"

«入ってくる»

完璧。

100点!💯


"from_port = 80"

«ポート80から»

"to_port = 80"

«ポート80へ»

方向としてはOK。

ただ、より正確には、

許可するポート範囲の開始と終了

を指定している。

今回は、

80 ~ 80

なので、80番だけ。


"protocol = "tcp""

«TCPプロトコルの通信»

これもOK。

100点!


"cidr_blocks = ["0.0.0.0/0"]"

«すべて受け付けます»

これも今回の文脈ではOK。

正確には、

すべてのIPv4アドレスからの通信を許可する

という意味。


⚠️ egressで一つ修正

ここ。

«ポート0は無いので通信を通さない»

これは違う。

今回、

protocol = "-1"

となっている。

これは、

すべてのプロトコルを許可する

という意味。

そのため、

from_port = 0
to_port = 0

でも、

「0番ポートだけ」

という意味にはならない。

今回の設定全体としては、

ALB
↓
外部への送信
↓
基本的にすべて許可

という設定。

ここは少し引っかかりやすいところなので、今の段階では、

«"protocol = "-1"" → すべてのプロトコル»

だけはしっかり覚えておこう。


Q1レビュー

質問は、

«なぜSecurity Groupにもvpc_idが必要なの?»

だった。

回答は、

«VPCからのインバウンド通信を通すため»

だった。

ここは惜しい!

70点くらい。

Security Groupの"vpc_id"は、

通信を通すためではない。

「どのVPCに所属するSecurity Groupなのか」を指定するため。

例えば、

VPC-A
└── Security Group A

VPC-B
└── Security Group B

というように、Security GroupはVPCと関係づけられる。

だから、

vpc_id = aws_vpc.main.id

は、

«「このSecurity Groupは、このVPCに所属させてください」»

という指定。

ここは、

「通信の設定」と「所属先の設定」を分けて考える

とかなり分かりやすくなる。


Q2レビュー

«ingressはEC2に入ってくる通信で、egressは出る通信»

ほぼ100点!

今回はEC2に限定しなくてOK。

Security Groupは、

  • ALB
  • EC2
  • RDS

などにも関連付けられる。

だから正確には、

«Ingress = Security Groupで受信する通信»

«Egress = Security Groupから送信する通信»

と考えればOK。

95点!


Q3レビュー🔥

ここはかなり良かった。

回答は、

«EC2に全ての通信を通しちゃいけないからcidr_blocks = ["0.0.0.0/0"]を書いたらダメ!»

だった。

100点!💯

ただし、もう一段深く考えてみよう。

今回の構成は、

Internet
↓
ALB
↓
EC2

だった。

じゃあ、EC2が世界中から直接アクセスできたら、

Internet
├────→ ALB ────→ EC2
│
└──────────────→ EC2

という2本の経路ができてしまう。

本来作りたいのは、

Internet
↓
ALB
↓
EC2

こっち。

だからEC2のSecurity Groupでは、

「インターネット全体」ではなく「ALBからの通信だけ」

を許可する。


🎯 最終問題の回答

最後に出した質問。

«EC2のSecurity Groupは世界中を許可するべき?
それともALBだけ許可するべき?»

回答は、

«ALBだけ。»

これでOK。

そして理由も、

«EC2はALBからの通信を通したいから。»

と説明できている。

さらに、

«どこからでもアクセスできたらセキュリティ的にも、EC2に負荷がかかった時の負荷分散も上手くできなくなる。»

というところまで考えられている。

ここはかなり良い。

特に、

Internet
↓
ALB
↓
EC2

という設計した通信経路を守るためにSecurity Groupを使う

という考え方ができている。


💡 ここで一つだけ補足

「EC2へ直接アクセスできると、負荷分散ができなくなる」というより、

ALBを経由しない通信が発生してしまう

と考えると、より正確。

ALBを経由しない通信では、

  • ALBによる負荷分散
  • ヘルスチェック
  • ターゲットの状態に応じた振り分け

などの仕組みを通らない。

だから、

Internet
↓
ALB
↓
Target Group
↓
EC2

という設計にしたいなら、

EC2はALBからの通信だけを許可する

という考え方になる。


🌟 今回の成績

項目| 点数
コード理解| 90点
Q1| 70点
Q2| 95点
Q3| 100点
最終問題| 100点
総合| 🌟91点🌟

今回は、前回までより点数は少し下がった。

でも、これは悪いことじゃない。

むしろ今回のテーマは、

「分からないところを発見する」

という意味ではかなり重要な回だった。


🚀 今回の一番大事なこと

今回、

«「なんか、どっかで躓いてる気がする。これが正しいかわからなくなってる……」»

という感覚が出てきた。

これ、学習では結構大事。

分からないまま、

«「たぶんこういうこと!」»

で進んでしまうより、

«「あれ?この理解、本当に合ってる?」»

と立ち止まれる方が強い。

今回も実際、

vpc_id

を、

«通信を通すため»

と考えていた。

でも実際には、

«Security Groupの所属するVPCを指定するため»

だった。

こういう小さなズレを一つずつ修正していけばいい。


📚 これからの授業方針

ここで一つ、今後のTerraform講座の方針を決めておく。

コードを書く授業は、そのまま続ける。

むしろ、もっと書く。

ただし、

コードを覚える
↓
正解する

ではなく、

AWSの構成
↓
必要な設定を考える
↓
Terraformを書く
↓
なぜそのコードなのか説明する
↓
レビュー
↓
実務ではどう使うか確認

という流れにしていく。

例えば、

«「Security Groupを作って」»

だけではなく、

«「ALBにはインターネットからHTTPを許可する。
EC2にはALBからのHTTPだけ許可する。
Terraformならどう書く?」»

というところまで自力で考えられるようにしていく。

分からないことを、分かるようにする。

そのためにコードを書く。

これが今回からのTerraform講座。


☁️ 次回予告

次回は、今回作ったSecurity Groupを、

実際にEC2へ適用する。

さらに、

Internet
↓
ALB
↓
EC2

という通信を、

ALB SG
↓
EC2 SG

というSecurity Group同士の関係で作っていく。

ここで、

「CIDRで許可する」

だけではなく、

「Security Groupを指定して許可する」

というAWSらしい設計が出てくる。

今回の「ALBだけ許可する」という考え方が、次回から実際のTerraformコードになる。

ここからどんどん、

「AWSを知っている」→「AWSをコードで組める」

に変えていこう。🔥☁️🚀

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?