[terraform] SSM Session Managerを使用してPrivate Subnet内のRDSにアクセスする

## はじめに

下記記事のリソース作成をterraformで行ってみました。
[SSM Session Managerを使用してPrivate Subnet内のRDSにアクセスする](https://qiita.com/shntaki/items/5ca5b2384cdbfde2fc9b)

## 事前準備

- RDSの認証情報をyaml形式でSSMパラメータストアに手動保存 

    ```yaml:test-rds
    db_name: postgres
    username: postgres
    password: 適当なパスワード
    ```

- EC2用のキーペアを手動作成
キーペア名：`test-keypair`

## VPC作成

```terraform:vpc.tf
resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"
  tags = {
    Name = "test-vpc"
  }
  enable_dns_hostnames = true
  enable_dns_support   = true
}

resource "aws_subnet" "private1" {
  vpc_id     = aws_vpc.main.id
  cidr_block = "10.0.0.0/24"
  tags = {
    Name = "test-private-subnet1"
  }
  availability_zone = "ap-northeast-1a"
}

resource "aws_subnet" "private2" {
  vpc_id     = aws_vpc.main.id
  cidr_block = "10.0.1.0/24"
  tags = {
    Name = "test-private-subnet2"
  }
  availability_zone = "ap-northeast-1c"
}
```

## VPCエンドポイント作成

```terraform:vpc_endpoint.tf
resource "aws_security_group" "vpce_sg" {
  name        = "vpce-sg"
  vpc_id      = aws_vpc.main.id
  description = "Security group for VPC Endpoints"
  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = [aws_subnet.private1.cidr_block, aws_subnet.private2.cidr_block]
  }
}

resource "aws_vpc_endpoint" "ssm" {
  vpc_id              = aws_vpc.main.id
  service_name        = "com.amazonaws.ap-northeast-1.ssm"
  vpc_endpoint_type   = "Interface"
  security_group_ids  = [aws_security_group.vpce_sg.id]
  private_dns_enabled = true

  tags = {
    "Name" = "test-ssm-vpe"
  }
}

resource "aws_vpc_endpoint" "ssmmessages" {
  vpc_id              = aws_vpc.main.id
  service_name        = "com.amazonaws.ap-northeast-1.ssmmessages"
  vpc_endpoint_type   = "Interface"
  security_group_ids  = [aws_security_group.vpce_sg.id]
  private_dns_enabled = true

  tags = {
    "Name" = "test-ssmmessages-vpe"
  }
}

resource "aws_vpc_endpoint_subnet_association" "ssm" {
  vpc_endpoint_id = aws_vpc_endpoint.ssm.id
  subnet_id       = aws_subnet.private1.id
}
resource "aws_vpc_endpoint_subnet_association" "ssmmessages" {
  vpc_endpoint_id = aws_vpc_endpoint.ssmmessages.id
  subnet_id       = aws_subnet.private1.id
}
```

## RDS作成

```terraform:rds.tf
data "aws_ssm_parameter" "rds_params" {
  name = "test-rds"
}

locals {
  rds_params = yamldecode(data.aws_ssm_parameter.rds_params.value)
}

resource "aws_db_subnet_group" "main" {
  name       = "test-subnet-group"
  subnet_ids = [aws_subnet.private1.id, aws_subnet.private2.id]
}

resource "aws_security_group" "rds_sg" {
  name   = "test-rds-sg"
  vpc_id = aws_vpc.main.id
  ingress {
    protocol    = "tcp"
    from_port   = 5432
    to_port     = 5432
    cidr_blocks = ["${aws_instance.main.private_ip}/32"]
  }

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

resource "aws_db_instance" "main" {
  identifier              = "test-rds"
  allocated_storage       = 20
  storage_type            = "gp3"
  engine                  = "postgres"
  engine_version          = "16.3"
  instance_class          = "db.t4g.micro"
  db_subnet_group_name    = aws_db_subnet_group.main.name
  password                = local.rds_params.password
  username                = local.rds_params.username
  backup_retention_period = 7
  multi_az                = false
  skip_final_snapshot     = true
  vpc_security_group_ids  = [aws_security_group.rds_sg.id]
}

```

## 踏み台EC2作成

```terraform:ec2.tf
resource "aws_security_group" "ec2_sg" {
  name   = "test-ec2-sg"
  vpc_id = aws_vpc.main.id
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
  tags = {
    Name = "test-ec2-sg"
  }
}

resource "aws_iam_role" "ec2_role" {
  name               = "test-ec2-role"
  assume_role_policy = data.aws_iam_policy_document.ec2_assume_role.json
}

data "aws_iam_policy_document" "ec2_assume_role" {
  statement {
    actions = ["sts:AssumeRole"]
    effect  = "Allow"
    principals {
      type        = "Service"
      identifiers = ["ec2.amazonaws.com"]
    }
  }
}

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

resource "aws_iam_instance_profile" "main" {
  name = "test-ec2-instance-profile"
  role = aws_iam_role.ec2_role.name
  depends_on = [aws_iam_role_policy_attachment.ec2_policy]
}

resource "aws_instance" "main" {
  ami           = "ami-0283b1f9e59025981"
  instance_type = "t4g.nano"
  key_name      = "test-keypair"

  subnet_id            = aws_subnet.private1.id
  iam_instance_profile = aws_iam_instance_profile.main.id

  vpc_security_group_ids = [aws_security_group.ec2_sg.id]

  root_block_device {
    volume_size = 8
    volume_type = "gp3"
  }

  tags = {
    Name = "test-ec2"
  }
}
```

以上。