AWS IAMユーザーのアクセスキーをスクリプト一発でローテーションする

AWS IAMユーザーのアクセスキーをスクリプト一発でローテーションする

AWS IAMユーザーのアクセスキーを簡単にローテーションできるスクリプトを書きましたのでシェアさせてください。
Clock Icon2019.05.16

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは。サービスグループの武田です。

AWSのセキュリティチェックツールを使ってみたら、君のアクセスキーが古いっていうアラート *1が出たから更新しといて」

「(よくわかってないけど)わかりました!」

さてAWSを使っているとこんな会話をすることもあるのではないでしょうか。アクセスキーとはAWS CLIなどからAWSを利用するためのクレデンシャル(認証情報)です。そしてこのアクセスキーは定期的にローテーション(更新)することが推奨されています。

IAM ユーザーのアクセスキーの管理 - AWS Identity and Access Management

また都元も次のようなエントリを以前にポストしています。当時のUIキャプチャで今とは多少異なりますが更新の手順は分かりますね。

AWSアクセスキー・ローテーションのススメ

ところで、セキュリティ上必要な作業だということは理解できますが、ぶっちゃけ面倒じゃないですか?手作業って。というわけで、面倒くさがりな自分のために簡単にキーローテーションできるスクリプトを書きましたのでシェアさせてください。

先にお断り

今回書いたスクリプトですが、自分のローカルPCのクレデンシャルしか更新しません。そのため複数の環境でアクセスキーを共有している場合、それらのプログラムが動かなくなります。そのようなケースでは使用しないでください。

スクリプトがエラーなどで途中で停止した場合、古いアクセスキーなどが残ったりします。そのようなケースでは手動でクリーンアップ処理を行ってください。またクレデンシャルファイル(credentials)はスクリプト内でコピーしています。必要であれば利用または削除などを行ってください。

環境

次のような環境で動作確認をしています。

$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.14.5
BuildVersion:	18F132

$ aws --version
aws-cli/1.16.145 Python/3.7.0 Darwin/18.6.0 botocore/1.12.135

$ jq -V
jq-1.5

$ echo $BASH_VERSION
4.4.23(1)-release

スクリプトの紹介

スクリプトはgistに上げてあります。好きに使ってください。

#!/bin/bash -euo pipefail
#
# Usage:
# $ aws-iam-user-key-rotation.sh [profile] [credential_file]
#
declare -x AWS_DEFAULT_PROFILE=${1:-default}
declare credential_file=${2:-~/.aws/credentials}
declare -x AWS_SHARED_CREDENTIALS_FILE=$credential_file
echo "${AWS_DEFAULT_PROFILE} プロファイルのアクセスキーをローテーションします。"
declare iam_user_name
iam_user_name=$(aws iam get-user | jq -r '.User.UserName')
declare current_access_keys
current_access_keys=$(aws iam list-access-keys)
echo "対象のIAMユーザーは ${iam_user_name} です。"
# AWSのアクセスキーは一度に2個までしか作成できないため先にチェックしておく
if (( $(echo "$current_access_keys" | jq '.AccessKeyMetadata | length') == 2 )); then
echo "アクセスキーが2個存在しています。使用していないアクセスキーを削除してから再実行してください。" 1>&2
exit 1
fi
cp "$credential_file"{,.bak}
declare new_credentials
new_credentials=$(aws iam create-access-key --user-name "$iam_user_name")
echo "新規アクセスキーを作成しました。"
declare response_text="$(echo "$new_credentials" | jq -r '.AccessKey.AccessKeyId')
$(echo "$new_credentials" | jq -r '.AccessKey.SecretAccessKey')
"
echo "$response_text" | aws configure > /dev/null
echo "クレデンシャルファイルを更新しました。"
declare updated_access_keys
echo "新しいアクセスキーで試行します。"
set +e
while :; do
echo "5秒待機します..."
sleep 5s
# このコマンドは新しいアクセスキーで実行される
updated_access_keys=$(aws iam list-access-keys 2> /dev/null)
(( $? == 0 )) && break
done
set -e
# ここがfalseになることはないはず
if (( $(echo "$updated_access_keys" | jq '.AccessKeyMetadata | length') != 2 )); then
echo "アクセスキーが2個存在していません。何かおかしいようです。" 1>&2
exit 1
fi
aws iam delete-access-key --user-name "$iam_user_name" --access-key-id "$(echo "$current_access_keys" | jq -r '.AccessKeyMetadata[0].AccessKeyId')"
echo "古いアクセスキーを削除しました。"

基本的な使い方としてはダウンロード後、次にように第1引数にローテーションしたいプロファイルを指定するだけです。省略した場合はdefaultプロファイルを対象とします。

$ curl https://gist.githubusercontent.com/TAKEDA-Takashi/f06df456847a29fbdd752e19ab8389cb/raw/aws-iam-user-key-rotation.sh -o aws-iam-user-key-rotation.sh
$ chmod +x aws-iam-user-key-rotation.sh
$ ./aws-iam-user-key-rotation.sh classmethod

クレデンシャルファイルのパスを~/.aws/credentials以外に設定している場合は、次のように、第2引数にそのパスを指定してください。

$ ./aws-iam-user-key-rotation.sh classmethod /tmp/cred

スクリプト内の処理は大まかに次の順番で行っています。詳細は中身を見てください。

  1. 使用中のアクセスキーIDを取得
  2. クレデンシャルファイルコピー(バックアップ)
  3. 新規アクセスキーを作成
  4. クレデンシャルファイルに新しいアクセスキーを設定
  5. 新しいアクセスキーでAPIアクセス
  6. 古いアクセスキーを削除

最後に

管理するアクセスキーは少ないほど好ましいです。更新するアクセスキーが多いなという方はIAMロールに変更できないかなど検討してみてください。また前述したようにキーローテーションは定期的に実行することが推奨されています。今回紹介したスクリプトをたとえば60日ごとに自動実行されるように設定することで、意識しなくてもセキュリティを向上できます。ぜひこのあたりのことも検討してみてください。

脚注

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.