プログラマーのメモ書き

伊勢在住のプログラマーが気になることを気ままにメモったブログです

【EC2】 SecurityGroup のルールを動的に変更

別記事で書いたように、EC2上にSubversion+Redmineの環境を作りました。

この際、Security Group で接続元を制限しているのですが、自宅に固定IPはないので、当然IPアドレスが変わります。

 

そこで、Security Group のルールを動的に変更する処理を入れてみたいと思います。やり方は基本的にダイナミックDNSの設定で行った方法と同じです。

 

EC2 APIツールのインストール

まず、EC2のAPIを操作するために、APIツール(コマンドラインツール)を導入します。前提として、EC2 APIツールはJavaで書かれているので、JREが必要になりますので、まずJREをインストールします。

bitnami@ip-10-150-181-105:~$ sudo apt-get install default-jre

念のため、AWSのドキュメント(ツールのセットアップ)に従って、gpgでダウンロードしたファイルを検証しておきます。

 

次に、ec2-api-tool をインストールします。zipファイルを解凍後、

bitnami@ip-10-150-181-105:~$ unzip ec2-api-tools.zip
bitnami@ip-10-150-181-105:~$ sudo mv ec2-api-tools-1.6.5.2/ /usr/local/bin/
bitnami@ip-10-150-181-105:~$ cd /usr/local/bin/
bitnami@ip-10-150-181-105:/usr/local/bin$ sudo chmod -R root:root ec2-api-tools-1.6.5.2/
bitnami@ip-10-150-181-105:/usr/local/bin$ sudo ln -s ec2-api-tools-1.6.5.2 ec2-api-tools

として、/usr/local/binに入れておきます。

 

次に、ドキュメントに従って、いくつか環境変数を設定します。

環境変数にはAWSアカウントのX.509証明書も指定します。これは、AWSのサイトから『アカウント/コンソール』→『セキュリティ証明書』と選択し、『アクセス証明書』の『X.509証明書』のタブを選び、『新しい証明書を作成する』を選択し、X.509証明書を作成します。

証明書を作成したら、秘密鍵と、X.509証明書をダウンロードします。ダウンロードしたら、SFTPなどで、EC2のインスタンスにこれら2ファイルをアップロードします。

 

環境変数設定は、/etc/ec2ディレクトリを作成し、ここに bash_ec2envという名前で保存しておきます。

# bash_ec2env
#
# some definitions for ec2 command line tools
#
# written by Junichi MORI, 2012/12/7

# java environment
export JAVA_HOME=/usr

# ec2 environment
export EC2_HOME=/usr/local/bin/ec2-api-tools
export PATH=$PATH:$EC2_HOME/bin

# keys
export EC2_PRIVATE_KEY=/etc/ec2/pk-xxxxxxxxxxxxxxxxxxxxxxxxxxxx.pem
export EC2_CERT=/etc/ec2/cert-xxxxxxxxxxxxxxxxxxxxxxxxxxxx.pem

# endpoint : Tokyo region
export EC2_URL=https://ec2.ap-northeast-1.amazonaws.com

なお、エンドポイントは東京リージョンにしました。

 

ここまでできたら、コマンドラインツールが使えるか試してみます。

bitnami@ip-10-150-181-105:~$ . /etc/ec2/bash_ec2env 
bitnami@ip-10-150-181-105:~$ ec2ver 
1.6.5.2 2012-10-01
bitnami@ip-10-150-181-105:~$ 

問題なくバージョンが表示できればOKです。

 

なお、コマンドラインツールを使いたいユーザーは、.bashrcから、

# EC2 definitions.
# added by Junichi MORI, 2012/12/7
if [ -f /etc/ec2/bash_ec2env ]; then
    . /etc/ec2/bash_ec2env
fi

のようにして、bash_ec2envを読み込めばOKです。

 

 

SecurityGroupを動的に変更

これで、Security Group のルールを変更するスクリプトの準備ができました。今回作成したスクリプトec2-sg-update.shは次のようなものです。

#!/bin/bash
#
# Security Group Rules auto update
#   https access allows to my office ip address defined by dynamic dns host name
#
# written by Junichi MORI, 2012/12/7

# variables
EC2_ENV=/etc/ec2/bash_ec2env
CurrentIPFile=/etc/ec2/current_ip
TargetDomain=xxxxx.mori-soft.com
SecurityGroupName=xxx
HttpsPort=xxx

# functions
function getCurrentIP() {
    currentIP=
    if [ -f $CurrentIPFile ]
    then
        currentIP=`cat $CurrentIPFile`
    fi
}
function getNewIP() {
    newIP=`host $TargetDomain | awk '/has address/ {print $4}'`
}
function message() {
    echo `date +"%F %T %Z"` : $*
}

# environment setting
if [ ! -f $EC2_ENV ]
then
    message "error: ec2 environment difinition file is missing"
    exit -1
fi
. $EC2_ENV

# update SecurityGroup IP
getCurrentIP
getNewIP

if [ "$currentIP" != "$newIP" ]
then
    message "update current ip, $currentIP , to new ip, $newIP ."

    # write new ip
    # If there is a short interval in cron job, multi update processes exec
    # because this update process takes more time.
    # So prevent multi update processes, the guard condition sets.
    echo $newIP > $CurrentIPFile

    # check
    #message "check SecurityGroup before update"
    #ec2-describe-group --filter "group-name"=$SecurityGroupName

    # delete old one
    if [ "$currentIP" != "" ]
    then
        message "delete current ip rule"
        ec2-revoke $SecurityGroupName -P tcp -p $HttpsPort -s ${currentIP}/32
    fi

    # add new one
    message "add new ip rule"
    ec2-authorize $SecurityGroupName -P tcp -p $HttpsPort -s ${newIP}/32

    # check
    #message "check SecurityGroup after update"
    #ec2-describe-group --filter "group-name"=$SecurityGroupName

fi
# if ip address don't change, do nothing.

 

自分用のスクリプトなんで、もし、トラぶった場合は手動で直すことを前提にしているのでエラー処理は省いています。

/etc/ec2に現在割り当てられているIPアドレスを記載したファイルを作成し、IPアドレスをチェック後、もし変わっていれば自動的に変更を行います。変更は、一度、古いIPアドレスのルールを削除し、その後新しいIPアドレスのルールを追加する、という方法を取ります。

 

なお、IPアドレスをファイルへ書き出す処理を、一連の変更処理の最初に行っています。これは、Security Group の確認(checkとしてコメントアウトしている処理)を行う場合、時間がかかるケースがあり、cronの呼出し間隔によっては重複して変更処理が動くことがあったためです。

 

ここまでできれば、このスクリプトをcronで定期的に呼び出すようにします。たとえば、こんな感じにして、/etc/cron.dに入れておきます。

bitnami@ip-10-150-181-105:/etc/cron.d$ cat ec2_sg_update 
#

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
LOGDIR=/var/log

# m h dom mon dow user  command
*/1 * * * * root /etc/ec2/ec2-sg-update.sh >> $LOGDIR/ec2sg.log 2>&1
bitnami@ip-10-150-181-105:/etc/cron.d$ 

 

これで、タイムラグはあるものの、手作業でSecurity Group のIPアドレスを編集する手間が省けるようになりました。