Skip to content

Commit

Permalink
Merge #2894
Browse files Browse the repository at this point in the history
2894: Use IAM role to extract security-credentials for EC2 instance r=bronzdoc a=apakulov-stripe

# Description:
Accidentally used the wrong metadata endpoint that is reserved for the internal use. If we want to use proper EC2 instance-profile credentials we need to extract the role-name first by calling `iam/info` and use it to construct `iam/security-credentials/role-name`.

If `iam_role` is not attached to the instance it will raise an exception `ec2_metadata_request` since `iam/info` will return 404.

See metadata documentation for more details: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html

Is there a chance we can have a new release for this? (I've been waiting for `3.0.5`/`3.0.6`, but unfortunately notice this issue just now).

Thank you!

I will abide by the [code of conduct](https://github.com/rubygems/rubygems/blob/master/CODE_OF_CONDUCT.md).

Co-authored-by: Alexander Pakulov <apakulov@stripe.com>
  • Loading branch information
2 people authored and hsbt committed Feb 18, 2020
1 parent b026596 commit ca46220
Showing 1 changed file with 13 additions and 5 deletions.
18 changes: 13 additions & 5 deletions lib/rubygems/s3_uri_signer.rb
Expand Up @@ -150,16 +150,23 @@ def ec2_metadata_credentials_json
require 'rubygems/request/connection_pools'
require 'json'

metadata_uri = URI(EC2_METADATA_CREDENTIALS)
@request_pool ||= create_request_pool(metadata_uri)
request = Gem::Request.new(metadata_uri, Net::HTTP::Get, nil, @request_pool)
iam_info = ec2_metadata_request(EC2_IAM_INFO)
# Expected format: arn:aws:iam::<id>:instance-profile/<role_name>
role_name = iam_info['InstanceProfileArn'].split('/').last
ec2_metadata_request(EC2_IAM_SECURITY_CREDENTIALS + role_name)
end

def ec2_metadata_request(url)
uri = URI(url)
@request_pool ||= create_request_pool(uri)
request = Gem::Request.new(uri, Net::HTTP::Get, nil, @request_pool)
response = request.fetch

case response
when Net::HTTPOK then
JSON.parse(response.body)
else
raise InstanceProfileError.new("Unable to fetch AWS credentials from #{metadata_uri}: #{response.message} #{response.code}")
raise InstanceProfileError.new("Unable to fetch AWS metadata from #{uri}: #{response.message} #{response.code}")
end
end

Expand All @@ -170,6 +177,7 @@ def create_request_pool(uri)
end

BASE64_URI_TRANSLATE = { "+" => "%2B", "/" => "%2F", "=" => "%3D", "\n" => "" }.freeze
EC2_METADATA_CREDENTIALS = "http://169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance".freeze
EC2_IAM_INFO = "http://169.254.169.254/latest/meta-data/iam/info".freeze
EC2_IAM_SECURITY_CREDENTIALS = "http://169.254.169.254/latest/meta-data/iam/security-credentials/".freeze

end

0 comments on commit ca46220

Please sign in to comment.