セキュアなEC2インスタンスをTerraformで作成する
最初に
以下の条件を満たすEC2インスタンスを作成したかった。
- ちょっとした作業をするときにすぐ作成/削除できる
- インターネットへの接続が可能
- インスタンスがインターネットからアクセスできない
- インスタンスへのログイン時にIAMユーザを利用した認証をしたい
- MFAを強制するとより安全
意外とそういうコードがGitHub上で見つからず、自分用にTerraformコードを書き、数ヶ月運用して問題なさそうだったので公開する。
構成図は以下のとおり。
はじめかた
以下のようにコマンドを実行する。
$ 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