TerraformでSecurity Groupを作成


この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので十分ご注意ください。

皆様こんにちは。
今回はTerraformを利用して、AWSで高可用性アーキテクトの構築をしていきます。
ALB、EC2、RDS、EFSのセキュリティグループ(以下SG)を作成し、各SGの設定内容についても記事にしています。

1.高可用性アーキテクト構築目次

目次はこちら

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

セキュリティグループは仮想ファイアウォールとして機能し、関連付けられたリソースに到達および離れるトラフィックを制御します。例えば、セキュリティグループを EC2 インスタンスに関連付けると、インスタンスのインバウンドトラフィックとアウトバウンドトラフィックが制御されます。

セキュリティグループを使用してリソースへのトラフィックを制御する

SGは、EC2やELB、RDSなど、インスタンス単位の通信制御に利用します。インスタンスには少なくとも1つのSGをアタッチする必要があります。
通信制御としては、インバウンド(内向き、外部からVPCへ)とアウトバウンド(外向き、内部から外部へ)の制御ができます。

類似サービスとしては、「ネットワークACL」があります。
SGとネットワークACLの違いについては下記にまとめています。

項目 セキュリティグループ ネットワークACL
適用範囲 インスタンス単位 サブネット単位
デフォルト動作 インバウンド:すべて拒否
アウトバウンド:すべて許可
インバウンド:すべて許可
アウトバウンド:すべて許可
ルールの評価 全てのルールが適用 ルールの番号順で適用
ステータス ステートフル ステートレス

ステートフルなら以前の状態を保持したまま以後の処理に役立てますが、ステートレスでは以前の状態を保持せずにその都度の処理を要求します。

3.セキュリティグループ構成図

  1. ALB用のものはRoute53のパブリックホストゾーンからのトラフィックを受け入れる必要があるので、ソースは0.0.0.0/0とします。通信は暗号化されている必要があるのでタイプはHTTPSにします。
    パブリックホストゾーンには、トラフィックをインターネットでどのようにルーティングするかを指定するレコードが含まれています

  2. EC2用のものはALBからのトラフィックを受け入れる必要がありますのでソースはALB用のSGを指定します。VPC内部の通信は暗号化されている必要がないのでタイプはHTTPにします。また、自分のPCよりEC2インスタンスと通信するために、SSHでソースはMYIPを指定します。

  3. RDS用のものはEC2に対するDBサーバーとして扱います。EC2からのトラフィックを受け入れる必要がありますのでソースはEC2用のSGを指定します。タイプはDBにMYSQLを使用するのでMYSQL/Auroraを選びます。

  4. EFS用のものはEC2のWordpressインストールファイルを共有するために使用するので、EEC2からのトラフィックを受け入れる必要があります。ソースはEC2用のSGを指定し、タイプNFSを選びます。
    NFSとは、主にUNIX系OSで利用される分散ファイルシステム、および、そのための通信規約(プロトコル)です。

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

ALB、EC2、RDS、EFS用に4つのSGを作成していきます。
SG全体のソースコードは下記の通りです。

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

#--------------------------------------
# higa-ALB-sgの作成
#----------------------------------------
resource "aws_security_group" "higa-ALB-sg" {
  name        = "higa-ALB-sg"
  description = "higa-ALB-sg"
  vpc_id      = aws_vpc.higa-vpc.id

  //HTTP
  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" は "all" と同等
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  //HTTPS
  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  egress {
    from_port = 0
    to_port   = 0
    #protocol    = "-1" は "all" と同等
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "higa-ALB-sg"
  }

}

#--------------------------------------
# higa-ec2-sgの作成
#----------------------------------------
resource "aws_security_group" "higa-ec2-sg" {
  name        = "higa-ec2-sg"
  description = "higa-ec2-sg"
  vpc_id      = aws_vpc.higa-vpc.id
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "higa-ec2-sg"
  }
}

//80番ポート(http)許可のインバウンドルール
resource "aws_security_group_rule" "inbound_http" {
  type      = "ingress"
  from_port = 80
  to_port   = 80
  protocol  = "tcp"
  //higa-ALB-sgが紐づくリソースにアクセス許可
  source_security_group_id = aws_security_group.higa-ALB-sg.id

  //ec2セキュリティグループに紐付け
  security_group_id = aws_security_group.higa-ec2-sg.id
}

//22番ポート(ssh)許可のインバウンドルール
resource "aws_security_group_rule" "inbound_ssh" {
  type      = "ingress"
  from_port = 22
  to_port   = 22
  protocol  = "tcp"

  //ソースにマイIPを指定
  cidr_blocks = ["133.32.128.179/32"]

  //ec2セキュリティグループに紐付け
  security_group_id = aws_security_group.higa-ec2-sg.id
}

#--------------------------------------
# higa-RDS-sgの作成
#----------------------------------------
resource "aws_security_group" "higa-RDS-sg" {
  name        = "higa-RDS-sg"
  description = "higa-RDS-sg"
  vpc_id      = aws_vpc.higa-vpc.id
  ingress {
    from_port = 3306
    to_port   = 3306
    protocol  = "tcp"
    //ec2セキュリティグループが紐づくリソースにアクセス許可
    security_groups = [aws_security_group.higa-ec2-sg.id]
  }
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "higa-RDS-sg"
  }
}

#--------------------------------------
# higa-EFS-sgの作成
#----------------------------------------
resource "aws_security_group" "higa-EFS-sg" {
  name        = "higa-EFS-sg"
  description = "higa-EFS-sg"
  vpc_id      = aws_vpc.higa-vpc.id
  ingress {
    from_port = 2049
    to_port   = 2049
    protocol  = "tcp"
    //ec2セキュリティグループが紐づくリソースにアクセス許可
    security_groups = [aws_security_group.higa-ec2-sg.id]
  }
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "higa-EFS-sg"
  }
}

4-1.ALB用のSG作成

ALBのSGは下記のコードで作成します。(5~47行目)

#----------------------------------------
# higa-ALB-sgの作成
#----------------------------------------
resource "aws_security_group" "higa-ALB-sg" {
  name        = "higa-ALB-sg"
  description = "higa-ALB-sg"
  vpc_id      = aws_vpc.higa-vpc.id

  //HTTP
  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" は "all" と同等
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  //HTTPS
  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  egress {
    from_port = 0
    to_port   = 0
    #protocol    = "-1" は "all" と同等
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "higa-ALB-sg"
  }

}

設定項目は下記の通りです。

使用するオプション 設定値 説明
name higa-ALB-sg セキュリティグループ名
description higa-ALB-sg 説明
vpc_id aws_vpc.higa-vpc.id VPCの指定
tags Name = "higa-ALB-sg" Nameの表記を設定
設定項目 設定値 説明
タイプ HTTP
HTTPS
httpは一時的にhttpでアクセスするため設定(HTTPS構築後に削除します)
httpsは通信を暗号化するため設定
ポート 80
443
アクセスを許可したいプロトコルのポート範囲を入力
プロトコル TCP プロトコルを入力

protocol = "-1"は「all」と同等の意味を表します。つまり、すべて許可しています。

4-2.EC2用のSG作成

EC2のSGは下記のコードで作成します。(49~94行目)

#----------------------------------------
# higa-ec2-sgの作成
#----------------------------------------
resource "aws_security_group" "higa-ec2-sg" {
  name        = "higa-ec2-sg"
  description = "higa-ec2-sg"
  vpc_id      = aws_vpc.higa-vpc.id
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "higa-ec2-sg"
  }
}

//80番ポート(http)許可のインバウンドルール
resource "aws_security_group_rule" "inbound_http" {
  type      = "ingress"
  from_port = 80
  to_port   = 80
  protocol  = "tcp"
  //higa-ALB-sgが紐づくリソースにアクセス許可
  source_security_group_id = aws_security_group.higa-ALB-sg.id

  //ec2セキュリティグループに紐付け
  security_group_id = aws_security_group.higa-ec2-sg.id
}

//22番ポート(ssh)許可のインバウンドルール
resource "aws_security_group_rule" "inbound_ssh" {
  type      = "ingress"
  from_port = 22
  to_port   = 22
  protocol  = "tcp"

  //ソースにマイIPを指定
  cidr_blocks = ["133.32.128.179/32"]

  //ec2セキュリティグループに紐付け
  security_group_id = aws_security_group.higa-ec2-sg.id
}

設定項目は下記の通りです。

使用するオプション 設定値 説明
name higa-ec2-sg セキュリティグループ名
description higa-ec2-sg 説明
vpc_id aws_vpc.higa-vpc.id VPCの指定
tags Name = "higa-ec2-sg" Nameの表記を設定
設定項目 設定値 説明
タイプ HTTP
SSH
httpではALBのSGのみを許可
sshでは自分のIPからのみ接続を許可
ポート 80
22
アクセスを許可したいプロトコルのポート範囲を入力
プロトコル TCP プロトコルを入力

4-3.RDS用のSG作成

RDSのSGは下記のコードで作成します。(96~120行目)

#----------------------------------------
# higa-RDS-sgの作成
#----------------------------------------
resource "aws_security_group" "higa-RDS-sg" {
  name        = "higa-RDS-sg"
  description = "higa-RDS-sg"
  vpc_id      = aws_vpc.higa-vpc.id
  ingress {
    from_port = 3306
    to_port   = 3306
    protocol  = "tcp"
    //ec2セキュリティグループが紐づくリソースにアクセス許可
    security_groups = [aws_security_group.higa-ec2-sg.id]
  }
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "higa-RDS-sg"
  }
}

設定項目は下記の通りです。

使用するオプション 設定値 説明
name higa-RDS-sg 説明
description higa-RDS-sg セキュリティグループ名
vpc_id aws_vpc.higa-vpc.id VPCの指定
tags Name = "higa-RDS-sg" Nameの表記を設定
設定項目 設定値 説明
タイプ MYSQL/Aurora EC2のSGのみを許可
ポート 3306 アクセスを許可したいプロトコルのポート範囲を入力
プロトコル TCP プロトコルを入力

4-4.EFS用のSG作成

EFSのSGは下記のコードで作成します。(122~146行目)

#----------------------------------------
# higa-EFS-sgの作成
#----------------------------------------
resource "aws_security_group" "higa-EFS-sg" {
  name        = "higa-EFS-sg"
  description = "higa-EFS-sg"
  vpc_id      = aws_vpc.higa-vpc.id
  ingress {
    from_port = 2049
    to_port   = 2049
    protocol  = "tcp"
    //ec2セキュリティグループが紐づくリソースにアクセス許可
    security_groups = [aws_security_group.higa-ec2-sg.id]
  }
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "higa-EFS-sg"
  }
}

設定項目は下記の通りです。

使用するオプション 設定値 説明
name higa-EFS-sg セキュリティグループ名
description higa-EFS-sg 説明
vpc_id aws_vpc.higa-vpc.id VPCの指定
tags Name = "higa-EFS-sg" Nameの表記を設定
設定項目 設定値 説明
タイプ NFS EC2のSGのみを許可
ポート 2049 アクセスを許可したいプロトコルのポート範囲を入力
プロトコル TCP プロトコルを入力

5.疎通確認

作成したEC2インスタンス(TerraformによるEC2作成方法)を起動させて、疎通確認を行います。
「自分のWindows PC」から「EC2インスタンス(higa-ec2-1)」に接続できるか確認します。
疎通確認はPowerShellで行います。

①.SSHの疎通確認を下記コマンドで確認します。

Test-NetConnection [作成したEC2のパブリックIPv4] -port 22

SSHは自分のIPアドレスを受け入れているので成功しました。

②.HTTPの疎通確認を下記コマンドで確認します。

Test-NetConnection [作成したEC2のパブリックIPv4] -port 80

HTTPはALBからの通信以外は失敗するはずなので、上記の通り失敗しました。

疎通確認からEC2のSGが正常に動作していることが確認できました。

コマンドプロンプトとPowerShellの違い

簡単に説明すると、PowerShellはコマンドプロンプトの上位互換です。
PowerShellは従来のコマンドプロンプトよりも複雑ですが、それと同時に非常にパワフルな機能も備わっています。

下記に比較した表をまとめました。

説明 Powershell コマンドプロンプト
特徴 コマンドプロンプトの後期機能。Windows7移行で標準機能(無料) 初期Windowsから標準機能(無料)
機能 高機能。原則として「コマンドプロンプト」の機能はほとんど使える 貧弱
使い分け 複雑な処理を行いたい場合 簡単な処理を行いたい場合(cp,cdコマンド等)

6.苦労した点

疎通確認を行う際、初めはTera termでsshログインをして実行しようとしたのですが、Test-NetConnectionコマンドを実行したところ、「Test-NetConnection: command not found」と表示されてしまい、悩んでいました。

PowerShellでTest-NetConnectionコマンドを実行することで疎通確認ができました。

7.まとめ

SGの設定ではIPアドレスの指定だけでなく、他のSGを指定できるところがすごいと思いました。
また、TerraformでSGを作成するにあたって、SG用のファイルで管理することで、SGの設定項目が分かりやすいと感じました。

8.参考文献

Last modified: 2022-06-24

Author