👏

セキュアなEC2インスタンスをTerraformで作成する

2022/08/30に公開

最初に

以下の条件を満たすEC2インスタンスを作成したかった。

  • ちょっとした作業をするときにすぐ作成/削除できる
  • インターネットへの接続が可能
  • インスタンスがインターネットからアクセスできない
  • インスタンスへのログイン時にIAMユーザを利用した認証をしたい
    • MFAを強制するとより安全

意外とそういうコードがGitHub上で見つからず、自分用にTerraformコードを書き、数ヶ月運用して問題なさそうだったので公開する。

https://github.com/tomoyamachi/terraform-private-ec2-ssm

構成図は以下のとおり。

はじめかた

以下のようにコマンドを実行する。

$ git clone https://github.com/tomoyamachi/terraform-private-ec2-ssm.git
$ cd terraform-private-ec2-ssm

# EC2インスタンスのログイン時に利用するKeypairの作成
$ ssh-keygen -t rsa -f example -N ''

$ terraform init
$ terraform apply

# 利用できる変数は、variables.tfを確認
$ terraform apply -var="instance=c5.large" var="key_name=example"

var.image_id
  AMI Image ID. Use latest Amazon Linux2 AMI when set empty value
  Enter a value: 

var.name
  prefix of resource name
  Enter a value: ssmtf

var.spot_instance
  Enter a value: true
...

Outputs:

instance_id_spot = "i-0c5755b82722b0922"
ssh_commands_spot = "ssh -i <key> <user>@i-0c5755b82722b0922"

applyが完了すると、sshコマンドが表示される。ただ、sshするためにはSession Managerプラグインの導入と、.ssh/configで設定をする必要がある。

SSHでログインする

AWS CLIからSessionを開始する場合、Session Managerプラグインをインストールする。
プラグインのインストール方法はこちら

Session Managerプラグインのインストールに加え、.ssh/configを以下のように書き換えることで、 ssh user@i-xxxxxと指定したときに自動でstart-sessionしてくれる。

host i-* mi-*
    ProxyCommand sh -c "aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"

ここまでくると、先程のsshコマンドで接続できるようになる。

$ ssh -i example ec2-user@i-0c5755b82722b0922
The authenticity of host 'i-0c5755b82722b0922 (<no hostip for proxy command>)' can't be established.
ED25519 key fingerprint is SHA256:RadRmlWx2Em16gUeQa/jaSsJdnUX/T8Ylfg5qX9gYfQ.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'i-0c5755b82722b0922' (ED25519) to the list of known hosts.

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
3 package(s) needed for security, out of 7 available
Run "sudo yum update" to apply all updates.
[ec2-user@ip-10-0-11-244 ~]$

その他のTips

インスタンスで動かしているポートにアクセスしたい場合も、SessionManagerプラグインを利用する。
以下のコマンドでPortForwardを実行すると、インスタンスの8080ポートへ、localhost:8080から接続できる。

aws ssm start-session --target i-xxxxxxx --document-name AWS-StartPortForwardingSession --parameters '{"portNumber":["8080"],"localPortNumber":["8080"]}'

利用する際の注意点として、Session Manager経由の接続ではお金がかからない分、一定以上のネットワーク通信量を超えると、ネットワーク速度が大きく制限される。
詳しくはセッションマネージャーを利用してローカル PC と パブリックサブネットにある EC2 間でデータ転送したときのデータ転送料を調べてみたに記載されている。

まとめ

別にPublicSubnetにインスタンスをおいて、SecurityGroupでIP制限してもいいと思う。
ただ、自分はむず痒く感じた。結果として、安全に接続できるインスタンスを気軽に作れるようになってよかった。

Discussion