1
0
Fork 0
mirror of https://github.com/fog/fog-aws.git synced 2022-11-09 13:50:52 -05:00

Gracefully handle failure of IMDSv2 and allow fallback to IMDSv1

This commit is contained in:
Ash Tyndall 2020-05-18 07:10:29 +08:00
parent ca288482c8
commit 3fba7a9a26
2 changed files with 36 additions and 4 deletions

View file

@ -26,14 +26,12 @@ module Fog
if region.nil?
connection = options[:metadata_connection] || Excon.new(INSTANCE_METADATA_HOST)
token = connection.put(:path => INSTANCE_METADATA_TOKEN, :idempotent => true, :expects => 200, :headers => { "X-aws-ec2-metadata-token-ttl-seconds" => "300" }).body
token_header = { "X-aws-ec2-metadata-token" => token }
token_header = fetch_credentials_token_header(connection, options[:disable_imds_v2])
region = connection.get(:path => INSTANCE_METADATA_AZ, :idempotent => true, :expects => 200, :headers => token_header).body[0..-2]
end
else
connection = options[:connection] || Excon.new(INSTANCE_METADATA_HOST)
token = connection.put(:path => INSTANCE_METADATA_TOKEN, :idempotent => true, :expects => 200, :headers => { "X-aws-ec2-metadata-token-ttl-seconds" => "300" }).body
token_header = { "X-aws-ec2-metadata-token" => token }
token_header = fetch_credentials_token_header(connection, options[:disable_imds_v2])
role_name = connection.get(:path => INSTANCE_METADATA_PATH, :idempotent => true, :expects => 200, :headers => token_header).body
role_data = connection.get(:path => INSTANCE_METADATA_PATH+role_name, :idempotent => true, :expects => 200, :headers => token_header).body
region ||= connection.get(:path => INSTANCE_METADATA_AZ, :idempotent => true, :expects => 200, :headers => token_header).body[0..-2]
@ -58,6 +56,23 @@ module Fog
super
end
end
def fetch_credentials_token_header(connection, disable_imds_v2)
return nil if disable_imds_v2
token = connection.put(
:path => INSTANCE_METADATA_TOKEN,
:idempotent => true,
:expects => 200,
:retry_interval => 1,
:retry_limit => 3,
:headers => { "X-aws-ec2-metadata-token-ttl-seconds" => "300" }
).body
{ "X-aws-ec2-metadata-token" => token }
rescue Excon::Error
nil
end
end
module ConnectionMethods

View file

@ -30,6 +30,23 @@ Shindo.tests('AWS | credentials', ['aws']) do
aws_credentials_expire_at: expires_at) { Fog::AWS::Compute.fetch_credentials(use_iam_profile: true) }
end
tests('#fetch_credentials when the v2 token 404s') do
Excon.stub({ method: :put, path: '/latest/api/token' }, { status: 404, body: 'not found' })
returns(aws_access_key_id: 'dummykey',
aws_secret_access_key: 'dummysecret',
aws_session_token: 'dummytoken',
region: 'us-west-1',
aws_credentials_expire_at: expires_at) { Fog::AWS::Compute.fetch_credentials(use_iam_profile: true) }
end
tests('#fetch_credentials when the v2 disabled') do
returns(aws_access_key_id: 'dummykey',
aws_secret_access_key: 'dummysecret',
aws_session_token: 'dummytoken',
region: 'us-west-1',
aws_credentials_expire_at: expires_at) { Fog::AWS::Compute.fetch_credentials(use_iam_profile: true, disable_imds_v2: true) }
end
ENV['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI'] = '/v1/credentials?id=task_id'
Excon.stub({ method: :get, path: '/v1/credentials?id=task_id' }, { status: 200, body: Fog::JSON.encode(credentials) })