EC2 Instance Connect EndpointでEC2の踏み台サーバーを作ってみる

## 概要
RDSを仕事で本格的に触る機会が増え、自宅でも検証など実施したくEC2で踏み台サーバー(いわゆるBastion)を作ってみたいと思いました。
検証する際はpublicなRDSではなくPrivateなRDSでいろいろ弄りたい。
(別にpublicなRDSならendpointさえ分かれば接続できる)
ただできるだけお金はかけたくなく、PrivateなEC2、かつローカルのLinuxからアクセスして作業することはできないかと調べていたところ「EC2 Instance Connect Endpoint」というものがあることを知りました。
しかも料金は無料！

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/connect-with-ec2-instance-connect-endpoint.html

こちらの記事を参考にterraformを利用して構築してみたいと思います。

https://blog.denet.co.jp/ec2-instance-connect-endpoint/

https://blog.denet.co.jp/aws-cli-ec2-instance-connect-endpoint/

この記事はそのメモやまとめです。
すでに設定済みの項目がいくつかある。
試行錯誤しながらやったので、手順として不要かもしれない。**あくまでメモ用。**

# 必要なリソースとterraformでも記載方法
必要なリソースは
- ECIエンドポイント用SG
- EC2用SG
- EICエンドポイント(VPC endpoint)
- EC2

で実現できるようです。

terraformについては

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_instance_connect_endpoint#availability_zone

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group#security_groups

あたりを使えばできそうですね。
terraformに落とし込むに当たりこちらを参考にもしました。

https://dev.classmethod.jp/articles/ec2-instance-connect-endpoint-by-terraform/


# terraformで実装
試行錯誤して最終的には以下のようになりました。
```terraform:ec2_bastion.tf
# EIC Endpoint SG
resource "aws_security_group" "bastion_eci" {
  vpc_id = aws_vpc.vpc.id
  name   = "bastion_for_eci_allow_ssh"
  egress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

# Bastion ec2 SG
resource "aws_security_group" "bastion_ec2" {
  vpc_id = aws_vpc.vpc.id
  name   = "bastion_for_ec2_allow_ssh_from_eci"
  ingress {
    from_port       = 22
    to_port         = 22
    protocol        = "tcp"
    security_groups = [aws_security_group.bastion_eci.id]
  }

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

# EC2 Instance Connect Endpoint
resource "aws_ec2_instance_connect_endpoint" "for_bastion_eic" {
  subnet_id          = aws_subnet.subnet_public_AZa.id
  security_group_ids = [aws_security_group.bastion_eci.id]
  preserve_client_ip = true
}

# Amazon Linuxの最新AMIを取得
data "aws_ami" "amazon-linux-2" {
  most_recent = true #最新版を指定
  owners      = ["amazon"]
  filter {
    name   = "owner-alias"
    values = ["amazon"]
  }
  filter {
    name   = "name"
    values = ["amzn2-ami-hvm-*-x86_64-gp2"]
  }
}

# bastion ec2
resource "aws_instance" "bastion" {
  ami                    = data.aws_ami.amazon-linux-2.id # Amazon Linux 2
  instance_type          = "t3.nano"
  subnet_id              = aws_subnet.subnet_private_AZa.id # private subnet
  vpc_security_group_ids = [aws_security_group.bastion_ec2.id]
  tags = {
    Name = "bastion-ec2"
  }
  lifecycle {
    ignore_changes = [
      ami,
    ]
  }
}
```
appyします。
ここでつまずき。
terraformのaws providersが古く、`aws_ec2_instance_connect_endpoint`を認識できなかった。
以下のように最新のproviderを指定して上げることで回避することができました。
```terraform:requirements.tf
  required_version = ">= 0.15"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "5.19.0"
    }
  }
}
```

# 接続してみる(コンソール)
EC2 →　instanceを選択して「接続」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185852/125b717b-61d0-8c65-0d23-08e9167f9e5d.png)

繋がった！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/185852/e98224cd-2ebc-eb31-c04f-4ae5323863b9.png)
(どうでもいいけどEC2ってでかでかと出てきていた記憶あるのですが今は鳩？になっているのですね)

# 接続してみる(ターミナル)
```bash
aws ec2-instance-connect ssh --instance-id i-xxxxxxx --connection-type eice --region ap-northeast-1
```
ここでつまずき2。

```bash
~ via 🐍 v3.10.8 
at 16:55:17 ⬢ [Docker] ❯ aws-vault exec xxxxx -- aws ec2-instance-connect ssh --instance-id i-xxxxxx

usage: aws [options] <command> <subcommand> [<subcommand> ...] [parameters]
To see help text, you can run:

  aws help
  aws <command> help
  aws <command> <subcommand> help

aws: error: argument operation: Invalid choice, valid choices are:

send-ssh-public-key                      | send-serial-console-ssh-public-key      
help                                    
```
コマンドが認識されていないので、多分aws cliが古いのではと予想。
```bash
~ via 🐍 v3.10.8 
at 16:57:31 ⬢ [Docker] ❯ aws --version
aws-cli/2.7.14 Python/3.9.11 Linux/5.10.16.3-microsoft-standard-WSL2 exe/x86_64.almalinux.8 prompt/off

~ via 🐍 v3.10.8 
at 17:02:01 ⬢ [Docker] ❯ 
```
予想通り古かった。
最新に更新する。

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-install.html

```bash
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install --update
```
versionを確認してみる。
```bash
~ via 🐍 v3.10.8 
at 18:07:07 ⬢ [Docker] ❯ aws --version
aws-cli/2.13.22 Python/3.11.5 Linux/5.10.16.3-microsoft-standard-WSL2 exe/x86_64.almalinux.8 prompt/off

~ via 🐍 v3.10.8 
at 18:07:09 ⬢ [Docker] ❯ 
```
新しくなっているので再度実行。

```bash
~ via 🐍 v3.10.8 
at 18:07:09 ⬢ [Docker] ❯ aws ec2-instance-connect ssh --instance-id i-xxxxxx --connection-type eice --region ap-northeast-1
Last login: Fri Sep 29 09:01:50 2023 from 88.15.62.130.shared.user.transix.jp
   ,     #_
   ~\_  ####_        Amazon Linux 2
  ~~  \_#####\
  ~~     \###|       AL2 End of Life is 2025-06-30.
  ~~       \#/ ___
   ~~       V~' '->
    ~~~         /    A newer version of Amazon Linux is available!
      ~~._.   _/
         _/ _/       Amazon Linux 2023, GA and supported until 2028-03-15.
       _/m/'           https://aws.amazon.com/linux/amazon-linux-2023/

[ec2-user@ip-10-0-10-62 ~]$ 
```
繋がった！

# ハマったところとか
- ツールなどのversion upしていなかったのでソレが原因で躓く場面がちょいちょいあった
- terraformｄやろうとするとそこについても調べなくてはならないので、時間がかかってします

# 次やりたいこと
- privateなRDSを作成してみて今回の方法を利用して接続をしてみる