Serverless Frameworkは ~/.aws/config
に書いたAssume Roleの設定を読んでくれないようなので、先日、EC2にアタッチされたIAM Roleからassume roleして、一時クレデンシャルを取得して、Serverless Frameworkを実行するスクリプトを書きました。 credential_source=EC2InstanceMetadata
の場合だけの場当たり的な処理を追加したスクリプトでした。今回は source_profile
にも対応しました。
スクリプト
シェルスクリプトですが、Pythonコードも埋め込まれています。
#!/bin/bash # serverlessコマンドのラッパーとして機能する簡易的なスクリプト。 # # --aws-profile が指定されていた場合に # ~/.aws/config を読み込み、 # credential_sourceまたはsource_profile と role_arn が指定されていた場合は、 # 一時クレデンシャルを取得してserverlessを実行する。 # --aws-profile は先頭に必要で、途中では認識しない。 profile= if [ $# -ge 2 ]; then if [ "$1" = --aws-profile ]; then profile="$2" shift shift fi fi if [ -z "$profile" ]; then # そのままserverlessを実行 echo serverless "$@" exec serverless "$@" fi ################################ # boto3で一時クレデンシャル取得 ################################ tmpfile=$(mktemp) python <<EOF > $tmpfile import configparser import os import sys import boto3 home_path = "$HOME" aws_config_filepath = home_path + "/.aws/config" profile = "$profile" if not os.path.exists(aws_config_filepath): sys.exit(0) aws_config = configparser.ConfigParser() aws_config.read(aws_config_filepath) section_name = "profile " + profile def get_config(name): try: return aws_config.get(section_name, name) except configparser.NoOptionError: return None except configparser.NoSectionError: return None credential_source = get_config("credential_source") source_profile = get_config("source_profile") role_arn = get_config("role_arn") if credential_source == "Ec2InstanceMetadata": session = boto3.session.Session() sts_client = session.client("sts") res = sts_client.assume_role( RoleArn = role_arn, RoleSessionName = "serverless", DurationSeconds = 900, ) elif source_profile != None: session = boto3.session.Session(profile_name = profile) sts_client = session.client("sts") res = sts_client.assume_role( RoleArn = role_arn, RoleSessionName = "serverless", DurationSeconds = 900, ) else: session = boto3.session.Session(profile_name = profile) sts_client = session.client("sts") res = sts_client.get_session_token( DurationSeconds = 900, ) access_key_id = res["Credentials"]["AccessKeyId"] secret_access_key = res["Credentials"]["SecretAccessKey"] session_token = res["Credentials"]["SessionToken"] print(f"export AWS_ACCESS_KEY_ID={access_key_id}") print(f"export AWS_SECRET_ACCESS_KEY=\"{secret_access_key}\"") print(f"export AWS_SESSION_TOKEN=\"{session_token}\"") EOF . $tmpfile rm $tmpfile ################################ # 取得したアクセスキーでserverless実行 ################################ echo serverless "$@" exec serverless "$@" ################################
適当な名前で実行権限を付けて、PATH
の通るところに置けば、普通のserverless
コマンドと同じように動かせます。
すごく変なことをしている気がするのですが、どうするのが正しいんだろう。
リンク
このスクリプトに至る経緯