頑張るときはいつも今

自称エンジニアのゴリラです。日々精進。

【AWS】TerraformでVPC構築からEC2を動作させてみた#2(セキュリティグループ、ネットワークACL)

何をやるか

  • 昨日の記事の続きで、Terraformを使って下記のような構成のAWSインフラを作成する。
    • 単一AZにパブリックサブネットとプライベートサブネットを構築
    • プライベートサブネットのEC2にはMYSQLをインストールして、パブリックサブネットのEC2からのみアクセスできるようにする
    • NAT GWをパブリックサブネットに配置して開発者がSSH接続できるようにする

f:id:wa_football_1120:20191222142939j:plain

  • 現状下記の実装が完了ずみ。

    • VPCの作成
    • パブリックサブネット、プライベートサブネットの作成
      • ルートテーブルの作成とアタッチ
    • IGWをパブリックサブネットに配置
    • NAT GWをパブリックサブネットに配置
  • 今日はセキュリティグループネットワークACLを作成する。

予備知識(前回の記事にも書いたかも)

セキュリティグループとは

  • EC2ELBRDSなどのインスタンス単位に設定できるファイアウォール的な役割
  • インバウンド、アウトバウンド両方のルールを設定することができる
    • ステートフルのため、インバウンドで許可した通信の応答パケットはアウトバウンドのルールに関わらず許可される
  • VPCを作成した際には、デフォルトで1つセキュリティグループが作成される
    • インスタンス作成時にセキュリティグループを指定しない場合はこのデフォルトグループが適用される
    • デフォルトのセキュリティグループのルールは下記の通り
      • 同じセキュリティグループからのインバウンド通信は全て許可
      • 同じセキュリティグループ外(インターネットを含む)からのインバウンと通信は全て拒否

f:id:wa_football_1120:20191222150222j:plain

ネットワークACLとは

クラスメソッドさん技術ブログ

  • サブネットごとに通信制御するためのファイアウォール
  • セキュリティグループと異なりステートレスACL
    • 戻りのルールも追加しないと通信が成立しない
  • ルール番号が小さい順から適用される
  • デフォルトでは、インバウンド・アウトバウンド全て許可されている

f:id:wa_football_1120:20191222152513j:plain

Terraformの実装

セキュリティグループ実装

パブリックサブネット側のEC2

パブリックサブネット側のEC2はウェブサーバとして動作させる想定のため、通信要件は下記とする。

  • 任意の送信元からHTTPHTTPSの通信を許可する(Inbound)
  • 特定のIPアドレスからSSHの通信を許可する(Inbound)

他サーバにも適用できるように、SSH接続用のセキュリティグループ(ssh-sg)とWebサーバ用のセキュリティグループ(web-sg)に分けて表のようになった。

web-sg(インバウンド)

タイプ プロトコル ポート範囲 送信元
HTTP TCP 80 0.0.0.0/0
HTTPS TCP 443 0.0.0.0/0

web-sg(アウトバウンド)

  • 今回は全て許可(DBの通信はプライベートサブネット側のEC2で設定)

ssh-sg(インバウンド)

タイプ プロトコル ポート範囲 送信元
SSH TCP 22 開発者のIP

プライベートサブネット側のEC2

プライベート側のEC2はDBサーバとして動作させる想定のため、通信要件は下記

  • web-sgからのMySQLの通信を許可する
  • NAT Gateway経由でのSSH接続も想定しているため先に作成したssh-sgもアタッチする予定

db-sg(インバウンド)

タイプ プロトコル ポート範囲 送信元
Mysq/Aurora TCP 3306 web-sg

web-sg

セキュリティグループ作成

  • aws_security_groupでリソースを作成
  • vpc_idには前回作成したモジュールのoutput値を使う
variable "vpc_id" {}

################################################
# Security Group for public subnet EC2
################################################

# web-sg
resource "aws_security_group" "example_web_sg" {
    name    = "web-sg"
    vpc_id  = "${var.vpc_id}"
}

ルール作成

  • aws_security_group_ruleでリソースを作成
  • typeはインバウンドかアウトバウンドを選ぶ項目
    • ingressはインバウンドルール
    • egressはアウトバウンドルール
  • protocolは文字通りプロトコルHTTPHTTPS共にtcpを利用
  • from_portto_portは開始ポートと終了ポートらしい(Request時の宛先ポートとResponse時の送信元ポート的な位置付け??)
  • cidr_blocksは送信元のIPアドレス
  • security_group_idで作成したセキュリティグループと関連付けをする
esource "aws_security_group_rule" "ingress_http" {
    type              = "ingress"
    from_port         = 80
    to_port           = 80
    protocol          = "tcp"
    cidr_blocks       = [ "0.0.0.0/0" ]
    description       = "HTTP Full Open"
    security_group_id = "${aws_security_group.example_web_sg.id}"
}
resource "aws_security_group_rule" "ingress_https" {
    type              = "ingress"
    from_port         = 443
    to_port           = 443
    protocol          = "tcp"
    cidr_blocks       = ["0.0.0.0/0"]
    description       = "HTTPS Full Open"
    security_group_id = "${aws_security_group.example_web_sg.id}"
}
resource "aws_security_group_rule" "egress_all" {
    type              = "egress"
    from_port         = 0
    to_port           = 0
    protocol          = "-1"
    cidr_blocks       = ["0.0.0.0/0"]
    security_group_id = "${aws_security_group.example_web_sg.id}"
}

ssh-sg

セキュリティグループの作成

詳しい説明は前述のため省略

resource "aws_security_group" "example_ssh_sg" {
    name    = "ssh-sg"
    vpc_id  = "${var.vpc_id}"
}

ルールの作成

resource "aws_security_group_rule" "ingress_ssh" {
    type              = "ingress"
    from_port         = 22
    to_port           = 22
    protocol          = "tcp"
    cidr_blocks       = ["Your IP"]
    security_group_id = "${aws_security_group.example_ssh_sg.id}"
}
resource "aws_security_group_rule" "egress_ssh" {
    type              = "egress"
    from_port         = 0
    to_port           = 0
    protocol          = "-1"
    cidr_blocks       = ["Your IP"]
    security_group_id = "${aws_security_group.example_ssh_sg.id}"
}

db-sg

セキュリティグループの作成

詳しい説明は前述のため省略

resource "aws_security_group" "example_db_sg" {
    name   = "db-sg"
    vpc_id = "${var.vpc_id}"
}

ルールの作成

  • source_security_group_idで送信元のセキュリティグループを指定する
resource "aws_security_group_rule" "ingress_db" {
    type                     = "ingress"
    from_port                = 3306
    to_port                  = 3306
    protocol                 = "tcp"
    source_security_group_id = "${aws_security_group.example_web_sg.id}"
    security_group_id        = "${aws_security_group.example_db_sg.id}"
}
resource "aws_security_group_rule" "egress_db" {
    type                     = "ingress"
    from_port                = 0
    to_port                  = 0
    protocol                 = "-1"
    cidr_blocks              = ["0.0.0.0/0"]
    security_group_id        = "${aws_security_group.example_db_sg.id}"
}

output

  • 次のインスタンス作成時にセキュリティグループのIDが必要になるため別ファイルで作成
output "web_sg_id" {
    value = "${aws_security_group.example_web_sg.id}"
}

output "ssh_sg_id" {
    value = "${aws_security_group.example_ssh_sg.id}"
}

output "db_sg_id" {
    value = "${aws_security_group.example_db_sg.id}"
}

適用結果

  • terraform initterraform planterraform applyを適用していく
  • コンソールを確認してセキュリティグループとルールが作成されていたら完了!!

感想

  • セキュリティグループとネットワークACLを使い分ける自身がない
    • セキュリティグループはホワイトリスト方式でネットワークACLブラックリスト方式と覚えておけばいい??
    • あとはそもそもサブネット間の通信を限定する