【爆速】TerraformでプライベートサブネットのEC2へSession Managerからアクセス可能な環境を構築する: VPCエンドポイント編

AWS

2024.5.22

Topics

はじめに

こんにちは、Shunです!

EC2を使った検証をする際に、プライベートサブネットにEC2を立てて、VPCエンドポイントを作るなど毎回環境を構築するのは面倒くさいですよね!
そこで、爆速かつセキュアにEC2を検証するTerraformテンプレートをご紹介します!

VPCエンドポイントではなく、NATゲートウェイを使った環境を作りたい方はこちら!

関連記事
【爆速】TerraformでプライベートサブネットのEC2へSession Managerからアクセス可能な環境を構築する: NAT Gateway編

爆速で、CloudFront + S3の静的サイトホスティング環境を作りたい方はこちら!

関連記事
【爆速】CloudFormationでCloudFront+S3環境を5分以内に構築

構築するアーキテクチャ

今回、構築するシステム構成図です。
Session Managerからアクセスするために、VPCエンドポイントを構築します。

terraformファイル構成

今回使用するtfファイルは以下の構成になっています。

├─ provider.tf
├─ vpc.tf
└─ ec2.tf

1.providers.tf

locals内の変数を書き換えるだけで、利用可能です。

locals {
  aws_id      = "[アカウントID]"
  name_prefix = "[名前]"
  region      = "[リージョン]"
  Environment = "[環境名]"
}


terraform {
  required_version = "~> 1.7.0"
  backend "s3" {
    key            = "[S3のkey]"
    bucket         = "[バケット名]"
    region         = "[リージョン]"
  }

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

variable "vpc" {
  description = "Parameter for VPC"
  type        = string
  default     = "10.0.0.0/16"
}

variable "private_subnet" {
  description = "Parameter for private subnet"
  type        = string
  default     = "10.0.128.0/24"
}

variable "default_instance_type" {
  default = "t2.micro"
}

2. vpc.tf

vpc.tfでは、3つのことを実施しています。

  • VPC、サブネットなどネットワークの構築
  • VPCエンドポイントの作成
####################
# vpc
####################
resource "aws_vpc" "main" {
  cidr_block           = var.vpc
  enable_dns_hostnames = true
  enable_dns_support   = true
  tags = {
    Name = "${local.name_prefix}-${local.Environment}-vpc"
  }
}

####################
# subnet
####################
# プライベートサブネット作成
resource "aws_subnet" "private_1a" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = var.private_subnet
  availability_zone = "ap-northeast-1a"
  tags = {
    Name = "${local.name_prefix}-${local.Environment}-private-1a"
  }
}

####################
# route table
####################
# private_ルートテーブル作成
resource "aws_route_table" "private_1a" {
  vpc_id = aws_vpc.main.id
  tags = {
    Name = "${local.name_prefix}-${local.Environment}-private-1a"
  }
}

# private_ルートテーブル紐づけ
resource "aws_route_table_association" "private_1a" {
  subnet_id      = aws_subnet.private_1a.id
  route_table_id = aws_route_table.private_1a.id
}

####################
# vpc endpoint
####################
resource "aws_vpc_endpoint" "ssm" {
  vpc_id              = aws_vpc.main.id
  service_name        = "com.amazonaws.${local.region}.ssm"
  vpc_endpoint_type   = "Interface"
  security_group_ids  = [aws_security_group.main.id]
  subnet_ids          = [aws_subnet.private_1a.id]
  private_dns_enabled = true

  tags = {
    Name = "${local.name_prefix}-${local.Environment}-vpc-endpoint"
  }
}

resource "aws_vpc_endpoint" "ec2messages" {
  vpc_id              = aws_vpc.main.id
  service_name        = "com.amazonaws.${local.region}.ec2messages"
  vpc_endpoint_type   = "Interface"
  security_group_ids  = [aws_security_group.main.id]
  subnet_ids          = [aws_subnet.private_1a.id]
  private_dns_enabled = true

  tags = {
    Name = "${local.name_prefix}-${local.Environment}-vpc-endpoint"
  }
}

resource "aws_vpc_endpoint" "ssmmessages" {
  vpc_id              = aws_vpc.main.id
  service_name        = "com.amazonaws.${local.region}.ssmmessages"
  vpc_endpoint_type   = "Interface"
  security_group_ids  = [aws_security_group.main.id]
  subnet_ids          = [aws_subnet.private_1a.id]
  private_dns_enabled = true

  tags = {
    Name = "${local.name_prefix}-${local.Environment}-vpc-endpoint"
  }
}

3. ec2.tf

ec2.tfでは、3つのことを実施しています。

  • 最新のAmazon LinuxのAMIを取得し、EC2を構築
  • Session Managerを使用するためのIAMを作成し、EC2へ付与
####################
# ami
####################
data "aws_ami" "latest_amazon_linux2" {
  most_recent = true
  owners      = ["amazon"]

  filter {
    name   = "name"
    values = ["amzn2-ami-hvm-*-x86_64-gp2"]
  }
}

####################
# ec2
####################
resource "aws_instance" "main" {
  instance_type          = var.default_instance_type
  ami                    = data.aws_ami.latest_amazon_linux2.id
  subnet_id              = aws_subnet.private_1a.id
  vpc_security_group_ids = [aws_security_group.main.id]
  iam_instance_profile   = aws_iam_instance_profile.example_profile.name
  root_block_device {
    volume_size           = 8
    volume_type           = "gp3"
    iops                  = 3000
    throughput            = 125
    delete_on_termination = true

    # EBSのNameタグ
    tags = {
      Name = "${local.name_prefix}-${local.Environment}"
    }
  }
  lifecycle {
    ignore_changes = [
      ami,
    ]
  }

  tags = {
    Name = "${local.name_prefix}-${local.Environment}"
  }
}

####################
# security group
####################
resource "aws_security_group" "main" {
  name   = "${local.name_prefix}-${local.Environment}-sg"
  vpc_id = aws_vpc.main.id
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
  
  ingress {
    from_port   = 443
    to_port     = 443
    protocol  = "tcp"
    cidr_blocks = [
      "10.0.0.0/16"
    ]
  }

  tags = {
    Name = "${local.name_prefix}-${local.Environment}-sg"
  }
}


####################
# ec2 iam role
####################
# インスタンスプロファイルを作成
resource "aws_iam_instance_profile" "example_profile" {
  name = "${local.name_prefix}-${local.Environment}-ssm"
  role = aws_iam_role.ssm_role.name
}

resource "aws_iam_role" "ssm_role" {
  name               = "${local.name_prefix}-${local.Environment}-ssm"
  assume_role_policy = data.aws_iam_policy_document.assume_role.json
}

data "aws_iam_policy_document" "assume_role" {
  statement {
    actions = ["sts:AssumeRole"]

    principals {
      type        = "Service"
      identifiers = ["ec2.amazonaws.com"]
    }
  }
}


resource "aws_iam_role_policy_attachment" "ssm_managed_instance_core" {
  role       = aws_iam_role.ssm_role.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}

環境構築

今回は、CloudShellを用いて、Terraformを実行します。
CloudShellを開き、以下のコマンドを入力し、Terraformをインストールします。

$ cd ~
$ git clone https://github.com/tfutils/tfenv.git ~/.tfenv
$ mkdir -p ~/.local/bin/
$ sudo ln -s ~/.tfenv/bin/* ~/.local/bin/
$ tfenv install 1.7.0
$ tfenv use 1.7.0

続いて、CloudShell内に適当なディレクトリを作成し、今回ご紹介したtfファイルを配置します。
作成したディクトリ配下へ移動し、以下のコマンドを入力します。

$ terraform init
$ terraform fmt
$ terraform plan

問題なければ、以下のコマンドを実行し、環境へデプロイします。

$ terraform apply 

これで環境構築は完了です。

疎通確認

マネジメントコンソールからEC2の画面を開きます。
設定したインスタンスを選択し、セッションマネージャーから接続をします。

以下のように接続ができれば完了です!

さいごに

今回の記事では、プライベートサブネットのEC2へSession Managerからアクセス可能なTerraformテンプレートをご紹介しました!

このテンプレートを使用することで、爆速でセキュアな環境でEC2を利用することができます!
是非、テンプレートを活用し、セキュアなEC2ライフを送ってください!

最後まで読んでいただきありがとうございます!

テックブログ新着情報のほか、AWSやGoogle Cloudに関するお役立ち情報を配信中!

Shun

週8バスケしたいです。Google Cloud11冠、2024 AWS All Cert

Recommends

こちらもおすすめ

Special Topics

注目記事はこちら