他サーバーから権限を絞ったiamユーザを使用してAmazonRDSの削除、復元を行う

#他サーバーから権限を絞ったiamユーザを使用してAmazonRDSの削除、復元を行う
料金節約やセキュリティを上げる為、決まった時間以外動作が不必要な時間が多いサーバなどは止めておきたい。
他のサーバーからコントロールする。
尚、RDSはec2のようにストップするといった概念がないため、スナップショットをとって削除するしかない。
スタートはスナップショットからの復元、開始となる。

##前提
今回は外部のサーバーからではなく、別サブネットに属するEC2からこのコマンドを発行する。
awsコマンドの返り値でjsonを使用したいので「jq」をインストールします。

```lang:
yum install jq
```

##aws側にグループ、ユーザを作成します
awsのコンソールよりポリシー、グループ、ユーザを作成します。
グループには新たに作成したポリシーをアタッチします。
更にグループにユーザを所属させ、そのユーザは
・コンソールへのログイン不可
・APIを使用するためアクセスキーを発行します


ちなみに私のポリシーはこんな感じになりました。
特定のインスタンスだけにしたい場合は更にResourceを指定してあげてください。
今回はEC2からの実行を想定しているので
"aws:sourceVpc"を指定しています。

```lang:ポリシー
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "hogehogehogehoge",
            "Effect": "Allow",
            "Action": [
                "rds:DeleteDBInstance",
                "rds:DescribeDBInstances",
                "rds:DescribeDBSnapshots",
                "rds:ModifyDBInstance",
                "rds:RebootDBInstance",
                "rds:RestoreDBInstanceFromDBSnapshot"
            ],
            "Resource": [
                "*"
            ],
            "Condition": {
                "StringNotEquals": {
                    "aws:sourceVpc": "サブネットID"
                }
            }
        }
    ]
}
```

##aws configureでアクセスキーやシークレットキーを設定します
尚、複数ユーザがいて、色々切り替えたい場合は
別途exportで環境変数を設定したり
aws configureに--profileを与えてユーザごとに設定できるようです。

その場合はawsコマンドを実行する時に--profileを入れるのではなく、
後述する環境変数でユーザだけ切り替えたら便利そう。

```lang:
aws configure
AWS Access Key ID [None]:先程発行したユーザのアクセスキー
AWS Secret Access Key [None]:先程発行したユーザのシークレットキー
Default region name [ap-northeast-1]:東京リージョンを使っているのでそのままEnter
Default output format [text]: json
```

```lang:環境変数
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
AWS_SESSION_TOKEN
AWS_DEFAULT_PROFILE
AWS_DEFAULT_REGION
AWS_DEFAULT_OUTPUT
```

##実際にコマンドを使ってみよう
準備が整ったので立ち上がっているかどうかをコマンドで取得してみます。

```lang:
  aws rds describe-db-instances | jq '.DBInstances | map(select(.DBInstanceIdentifier == "'対象RDSのIDENTIFIER'"))[] | .DBInstanceStatus' | tr -d '"'
```
起動していれば「available」と返ってきます。

##応用編：起動・停止シェル
下記のようなシェルを作成してみました。

ほぼ、
http://dev.classmethod.jp/cloud/aws/rds-redshift-start-stop/
を参考にさせて頂きました。

startはスナップショットを用いてインスタンスを新しく作るといったイメージです。
ただ、エンドポイントは変わらないので外部からは変わっていないように見えます。
しかし、上記ページ時から若干仕様が変わったようでスナップショットからの復元時にセキュリティグループを指定できない、パラメータグループも指定できない模様。
なのでスナップショットから復元し、復元が終わりステータスが正常になった段階で
セキュリティグループとパラメータグループをmodifyしています。
modify後は再起動かけています。
今回は--no-multi-az \にしています。任意で変更してください。

```lang:使い方
./rdscontrol.sh start
./rdscontrol.sh stop
```
といった感じです。実行権限を与えてください。

```lang:rdscontrol.sh
#!/bin/bash
RDS_IDENTIFIER=対象のIDENTIFIER（ARNの最後のやつです。）
RDS_INSTANCE_CLASS=対象のクラス（「db.t2.micro」など。））
AZ=アベイラビリティーゾーン（ap-northeast-1aなど）
DB_SUBNET_GROUP=DBが属するサブネットグループ
STORAGE_TYPE=ストレージのタイプ名。例えば「gp2」 #汎用（SSD）
VPC_SECURITY_GROUP=セキュリティグループ
DB_PARAMETER_GROUP=パラメータグループ

RDS_STATUS=`aws rds describe-db-instances | jq '.DBInstances | map(select(.DBInstanceIdentifier == "'"${RDS_IDENTIFIER}"'"))[] | .DBInstanceStatus' | tr -d '"'`

function rds_detail() {
  aws rds describe-db-instances \
    --db-instance-identifier ${RDS_IDENTIFIER} \
    --query "DBInstances[].{DBInstanceIdentifier:DBInstanceIdentifier,DBInstanceStatus:DBInstanceStatus}" \
    --output table
}

case $1 in
  start)
    if [ -n "$RDS_STATUS" ] && [ $RDS_STATUS = 'available' ] ; then
        ## 稼働中であれば特に何もしない.
        echo "status is available. nothing to do."
        exit 0
    fi

    LAST_RDS_SNAPSHOT=$(aws rds describe-db-snapshots \
      --query "reverse(sort_by(DBSnapshots,&SnapshotCreateTime))[?DBInstanceIdentifier==\`${RDS_IDENTIFIER}\`]|[0].[DBSnapshotIdentifier]" \
      --output text)
    aws rds restore-db-instance-from-db-snapshot \
      --db-instance-identifier ${RDS_IDENTIFIER} \
      --db-snapshot-identifier ${LAST_RDS_SNAPSHOT} \
      --db-instance-class ${RDS_INSTANCE_CLASS} \
      --availability-zone ${AZ} \
      --db-subnet-group-name ${DB_SUBNET_GROUP} \
      --no-multi-az \
      --no-publicly-accessible \
      --storage-type ${STORAGE_TYPE}
    aws rds wait db-instance-available --db-instance-identifier ${RDS_IDENTIFIER}
    aws rds modify-db-instance \
            --db-instance-identifier ${RDS_IDENTIFIER} \
            --vpc-security-group-ids ${VPC_SECURITY_GROUP} \
            --db-parameter-group-name ${DB_PARAMETER_GROUP}
    aws rds reboot-db-instance \
            --db-instance-identifier ${RDS_IDENTIFIER}
    aws rds wait db-instance-available --db-instance-identifier ${RDS_IDENTIFIER}
    rds_detail
    ;;
  stop)
    if [ -n "$RDS_STATUS" ] && [ $RDS_STATUS = 'deleting' ] ; then
        ## 既に削除されているので何もしない.
        echo "status is deleting. nothing to do."
        exit 0
    fi

    RDS_SNAPSHOT_NAME=${RDS_IDENTIFIER}-$(date +'%Y%m%d-%H%M%S')
    aws rds delete-db-instance \
      --db-instance-identifier ${RDS_IDENTIFIER} \
      --no-skip-final-snapshot \
      --final-db-snapshot-identifier ${RDS_SNAPSHOT_NAME}
    rds_detail
    ;;
  status)
    echo $RDS_STATUS
    ;;
  detail)
    rds_detail
    ;;
  *)
    echo "Usage: $0 {start|stop|status|detail}"
    ;;
esac

exit 0
```

以上