はじめに
Version 1の場合の説明はこの記事に書かれてましたが、Version 2はソースコードの中身がVersion 1と全く違かったので調べてみました。
アクセスキーを取得する処理の実行順序
aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb
def resolve
providers.each do |method_name, options|
provider = send(method_name, options.merge(config: @config))
return provider if provider && provider.set?
end
nil
end
def providers
[
[:static_credentials, {}],
[:env_credentials, {}],
[:shared_credentials, {}],
[:instance_profile_credentials, {
retries: 0,
http_open_timeout: 1,
http_read_timeout: 1,
}],
]
end
- static_credentials
- env_credentials
- shared_credentials
- instance_profile_credentials
の順に実行されるが、アクセスキーが取得できたらそこで処理は終了。
static_credentials
aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb
def static_credentials(options)
config = options[:config]
Credentials.new(
config.access_key_id,
config.secret_access_key,
config.session_token)
end
引数で渡したアクセスキーがアクセスキーとしてセットされる。
例
Aws::EC2::Client.new(
access_key_id: 'access key',
secret_access_key: 'secret access key'
)
env_credentials
aws-sdk-core/lib/aws-sdk-core/credential_provider_chain.rb
def env_credentials(options)
key = %w(AWS_ACCESS_KEY_ID AMAZON_ACCESS_KEY_ID AWS_ACCESS_KEY)
secret = %w(AWS_SECRET_ACCESS_KEY AMAZON_SECRET_ACCESS_KEY AWS_SECRET_KEY)
token = %w(AWS_SESSION_TOKEN AMAZON_SESSION_TOKEN)
Credentials.new(envar(key), envar(secret), envar(token))
end
環境変数で設定したものがアクセスキーとしてセットされる。
shared_credentials
aws-sdk-core/lib/aws-sdk-core/shared_credentials.rb
.aws/credentialsに書いた設定からアクセスキーとしてセットされる。
instance_profile_credentials
aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb
def refresh
# Retry loading credentials up to 3 times is the instance metadata
# service is responding but is returning invalid JSON documents
# in response to the GET profile credentials call.
retry_errors([JSON::ParserError, StandardError], max_retries: 3) do
c = JSON.parse(get_credentials.to_s)
@credentials = Credentials.new(
c['AccessKeyId'],
c['SecretAccessKey'],
c['Token']
)
@expiration = c['Expiration'] ? Time.parse(c['Expiration']) : nil
end
end
def get_credentials
# Retry loading credentials a configurable number of times if
# the instance metadata service is not responding.
begin
retry_errors(NETWORK_ERRORS, max_retries: @retries) do
open_connection do |conn|
path = '/latest/meta-data/iam/security-credentials/'
profile_name = http_get(conn, path).lines.first.strip
http_get(conn, path + profile_name)
end
end
rescue
'{}'
end
end
http://169.254.169.254/latest/meta-data/iam/security-credentials/
を取得するとロール名が返って来る
そのロール名を元に
で取得することでアクセスキーの情報入ったJSONが返って来る。
なのでIAM Roleからアクセスキーの情報を取得するようになっている。
環境による切り分け方
ローカルの開発環境(IAM Roleが使えない)場合
環境変数にアクセスキーを設定して動かす。
本番環境の場合
EC2でIAM Role付きで動かしている場合、環境変数にアクセスキーを設定する必要がない。