前提
固定IPがないので,SecurityGroupをうまく設定できない.でも0.0.0.0/0
を許可したくない.
方針
vagrant-triggersでがんばってみる
vagrant-triggersを使うと,vagrantの任意のサブコマンドの前後に処理を挟みこめます.
しかし,vagrant ssh
時においては,接続前のトリガーはうまく動いたものの,切断したときはトリガーが発動せず,断念しました.
config.ssh.ssh_command
を設定する
ドキュメントには見当らなかったのですが,config.ssh.ssh_command
を設定することで,vagrant ssh
時に使用されるsshプログラムを指定することができる模様.ソースだとこのあたり
そこで,sshする前に現在のIPからSSHを許可するSecurityGroupを作り,ssh切れたらSecurityGroupを消滅させるシェルを書き,それをvagrant ssh
で勝手に使ってくれるようにしました.
ソース
Vagrantfileに1つしかVM定義がない前提です.また,VM名を指定してる場合はinstance-idが書かれたファイルのパスが変わるはずです.
あと,awscliをインストールしておく必要があります.
ec2ssh
#!/bin/bash
# 事前にaws configureで設定は済ませておく
export AWS_DEFAULT_PROFILE=sample
set -e
# vagrant upは終わっている前提
# ファイルに書かれているinstance-idを読みとる
test -e .vagrant/machines/default/aws/id
INSTANCE_ID=$(cat .vagrant/machines/default/aws/id)
test -n $INSTANCE_ID
# SecurityGroupを作るために当該インスタンスが属しているVPCを調べる
VPC_ID=$(aws ec2 describe-instances \
--filter "Name=instance-id,Values=$INSTANCE_ID" \
--query "Reservations[0].Instances[0].VpcId" \
--output text)
test -n $VPC_ID
# デフォルトのSecurityGroupを用意しておく
# EC2インスタンスには最低1つSecurityGroup付ける必要があるため.
# どこからも接続できないようなSecurityGroupでOK
DEFAULT_SECURITY_GROUP=$(aws ec2 describe-security-groups \
--filter "Name=group-name,Values=default" \
--query "SecurityGroups[0].GroupId" \
--output text)
test -n $DEFAULT_SECURITY_GROUP
# 新しいSecurityGroupを作成
SECURITY_GROUP=$(aws ec2 create-security-group \
--group-name "ec2ssh-$(date +%Y%m%d-%H%M%S)" \
--description "SSH from CURRENT_IP" \
--vpc-id $VPC_ID \
--output text)
test -n $SECURITY_GROUP && echo "security-group $SECURITY_GROUP created successfully."
# 現在のIPを調べる
CURRENT_IP=$(curl -s https://api.ipify.org)
# 作ったSecurityGroupに,現在のIPからのSSHを許可するようなルールを作成する
aws ec2 authorize-security-group-ingress \
--group-id $SECURITY_GROUP --ip-protocol tcp \
--from-port 22 --to-port 22 --cidr-ip "$CURRENT_IP/32"
aws ec2 modify-instance-attribute \
--instance-id $INSTANCE_ID \
--groups $SECURITY_GROUP
echo "SSH connection would be authorized from $CURRENT_IP/32"
# sshが異常終了した場合でも処理を継続するように.
set +e
ssh $*
set -e
# 当該インスタンスのSecurityGroupをデフォルトのみに戻す
aws ec2 modify-instance-attribute \
--instance-id $INSTANCE_ID \
--groups $DEFAULT_SECURITY_GROUP
# 作ったSecurityGroupを削除する
aws ec2 delete-security-group \
--group-id $SECURITY_GROUP
echo "security-group $SECURITY_GROUP deleted successfully."
echo "SSH connection would be revoked from $CURRENT_IP/32"
exit 0
こんなシェルをVagrantfileと同じ場所に置いておく
あとは,Vagrantfile内のsshの設定をやってるところでssh_command
に設定する.
Vagrantfile
override.ssh.username = "ec2-user"
override.ssh.private_key_path = "~/.ssh/private.pem"
override.ssh.ssh_command = './ec2ssh' # <-これ
結果
uraura@rosemary $ vagrant ssh
security-group sg-xxxxxxxx created successfully.
SSH connection would be authorized from xxx.xxx.xxx.xxx/32
Last login: Fri Jan 22 11:15:01 2016 from xxx.xxx.xxx.xxx
__| __|_ )
_| ( / Amazon Linux AMI
___|\___|___|
https://aws.amazon.com/amazon-linux-ami/2015.09-release-notes/
1 package(s) needed for security, out of 1 available
Run "sudo yum update" to apply all updates.
[ec2-user@ip-172-31-8-18 ~]$
[ec2-user@ip-172-31-8-18 ~]$ exit
Connection to ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com closed.
security-group sg-xxxxxxxx deleted successfully.
SSH connection would be revoked from xxx.xxx.xxx.xxx/32
SSHがタイムアウトしたとか,SSH中にインスタンスが停止した場合でも,ちゃんとSecurityGroupが消えます.