Skip to content

Commit 831d686

Browse files
authored
Revert "EC2 IMDS security updates (#2167)" (#2169)
This reverts commit 71ace3c.
1 parent 71ace3c commit 831d686

File tree

5 files changed

+86
-364
lines changed

5 files changed

+86
-364
lines changed

CHANGELOG.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
Unreleased Changes
22
------------------
33

4-
* Feature = Aws::Core - Support EC2 IMDS updates.
5-
64
2.11.400 (2019-11-18)
75
------------------
86

aws-sdk-core/lib/aws-sdk-core/instance_profile_credentials.rb

Lines changed: 8 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,6 @@ class InstanceProfileCredentials
1111
# @api private
1212
class Non200Response < RuntimeError; end
1313

14-
# @api private
15-
class TokenRetrivalError < RuntimeError; end
16-
17-
# @api private
18-
class TokenExpiredError < RuntimeError; end
19-
20-
# @api private
21-
class TokenRetrivalUnavailableError < RuntimeError; end
22-
2314
# These are the errors we trap when attempting to talk to the
2415
# instance metadata service. Any of these imply the service
2516
# is not present, no responding or some other non-recoverable
@@ -35,14 +26,6 @@ class TokenRetrivalUnavailableError < RuntimeError; end
3526
Non200Response,
3627
]
3728

38-
# Path base for GET request for profile and credentials
39-
# @api private
40-
METADATA_PATH_BASE = '/latest/meta-data/iam/security-credentials/'
41-
42-
# Path for PUT request for token
43-
# @api private
44-
METADATA_TOKEN_PATH = '/latest/api/token'
45-
4629
# @param [Hash] options
4730
# @option options [Integer] :retries (5) Number of times to retry
4831
# when retrieving credentials.
@@ -57,8 +40,6 @@ class TokenRetrivalUnavailableError < RuntimeError; end
5740
# @option options [IO] :http_debug_output (nil) HTTP wire
5841
# traces are sent to this object. You can specify something
5942
# like $stdout.
60-
# @option options [Integer] :token_ttl (21600) Time-to-Live in seconds for
61-
# EC2 Metadata Token used for fetching Metadata Profile Credentials.
6243
def initialize options = {}
6344
@retries = options[:retries] || 5
6445
@ip_address = options[:ip_address] || '169.254.169.254'
@@ -67,13 +48,11 @@ def initialize options = {}
6748
@http_read_timeout = options[:http_read_timeout] || 5
6849
@http_debug_output = options[:http_debug_output]
6950
@backoff = backoff(options[:backoff])
70-
@token_ttl = options[:token_ttl] || 21600
7151
super
7252
end
7353

74-
# @return [Integer] Number of times to retry when retrieving credentials
75-
# from the instance metadata service. Defaults to 0 when resolving from
76-
# the default credential chain ({Aws::CredentialProviderChain}).
54+
# @return [Integer] The number of times to retry failed attempts to
55+
# fetch credentials from the instance metadata service. Defaults to 0.
7756
attr_reader :retries
7857

7958
private
@@ -114,11 +93,9 @@ def get_credentials
11493
begin
11594
retry_errors(NETWORK_ERRORS, max_retries: @retries) do
11695
open_connection do |conn|
117-
_token_attempt(conn)
118-
token_value = @token.value if token_set?
119-
profile_name = http_get(conn, METADATA_PATH_BASE, token_value)
120-
.lines.first.strip
121-
http_get(conn, METADATA_PATH_BASE + profile_name, token_value)
96+
path = '/latest/meta-data/iam/security-credentials/'
97+
profile_name = http_get(conn, path).lines.first.strip
98+
http_get(conn, path + profile_name)
12299
end
123100
end
124101
rescue
@@ -127,28 +104,6 @@ def get_credentials
127104
end
128105
end
129106

130-
def token_set?
131-
@token && !@token.expired?
132-
end
133-
134-
# attempt to fetch token with retries baked in
135-
# would be skipped if token already set
136-
def _token_attempt(conn)
137-
begin
138-
retry_errors(NETWORK_ERRORS, max_retries: @retries) do
139-
unless token_set?
140-
token_value, ttl = http_put(conn, METADATA_TOKEN_PATH, @token_ttl)
141-
@token = Token.new(token_value, ttl) if token_value && ttl
142-
end
143-
end
144-
rescue *NETWORK_ERRORS, TokenRetrivalUnavailableError
145-
# token attempt failed with allowable errors (those indicating
146-
# token retrieval not available on the instance), reset token to
147-
# allow safe failover to non-token mode
148-
@token = nil
149-
end
150-
end
151-
152107
def _metadata_disabled?
153108
flag = ENV["AWS_EC2_METADATA_DISABLED"]
154109
!flag.nil? && flag.downcase == "true"
@@ -163,40 +118,10 @@ def open_connection
163118
yield(http).tap { http.finish }
164119
end
165120

166-
# GET request fetch profile and credentials
167-
def http_get(connection, path, token=nil)
168-
headers = {"User-Agent" => "aws-sdk-ruby2/#{VERSION}"}
169-
headers["x-aws-ec2-metadata-token"] = token if token
170-
response = connection.request(Net::HTTP::Get.new(path, headers))
171-
case response.code.to_i
172-
when 200
121+
def http_get(connection, path)
122+
response = connection.request(Net::HTTP::Get.new(path))
123+
if response.code.to_i == 200
173124
response.body
174-
when 401
175-
raise TokenExpiredError
176-
else
177-
raise Non200Response
178-
end
179-
end
180-
181-
# PUT request fetch token with ttl
182-
def http_put(connection, path, ttl)
183-
headers = {
184-
"User-Agent" => "aws-sdk-ruby2/#{VERSION}",
185-
"x-aws-ec2-metadata-token-ttl-seconds" => ttl.to_s
186-
}
187-
response = connection.request(Net::HTTP::Put.new(path, headers))
188-
case response.code.to_i
189-
when 200
190-
[
191-
response.body,
192-
response.header["x-aws-ec2-metadata-token-ttl-seconds"].to_i
193-
]
194-
when 400
195-
raise TokenRetrivalError
196-
when 403
197-
when 404
198-
when 405
199-
raise TokenRetrivalUnavailableError
200125
else
201126
raise Non200Response
202127
end
@@ -218,24 +143,5 @@ def retry_errors(error_classes, options = {}, &block)
218143
end
219144
end
220145

221-
# @api private
222-
# Token used to fetch IMDS profile and credentials
223-
class Token
224-
225-
def initialize(value, ttl)
226-
@ttl = ttl
227-
@value = value
228-
@created_time = Time.now
229-
end
230-
231-
# [String] token value
232-
attr_reader :value
233-
234-
def expired?
235-
Time.now - @created_time > @ttl
236-
end
237-
238-
end
239-
240146
end
241147
end

aws-sdk-core/spec/aws/credential_resolution_chain_spec.rb

Lines changed: 27 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,6 @@ module Aws
1313
'..', 'fixtures', 'credentials', 'mock_shared_config'))
1414
}
1515

16-
let(:imds_url) {
17-
'http://169.254.169.254/latest/meta-data/iam/security-credentials/'
18-
}
19-
20-
let(:imds_token_url) {
21-
'http://169.254.169.254/latest/api/token'
22-
}
23-
2416
describe "default behavior" do
2517
before(:each) do
2618
stub_const('ENV', {})
@@ -64,32 +56,28 @@ module Aws
6456
"AR_TOKEN"
6557
)
6658
client = Aws::S3::Client.new(profile: "ar_plus_creds", region: "us-east-1")
67-
expect(client.config.credentials.credentials.access_key_id).to eq("AR_AKID")
59+
expect(client.config.credentials.access_key_id).to eq("AR_AKID")
6860
end
6961

7062
it 'prefers shared credential file static credentials over shared config' do
7163
client = Aws::S3::Client.new(profile: "credentials_first", region: "us-east-1")
72-
expect(client.config.credentials.credentials.access_key_id).to eq("ACCESS_KEY_CRD")
64+
expect(client.config.credentials.access_key_id).to eq("ACCESS_KEY_CRD")
7365
end
7466

7567
it 'will source static credentials from shared config after shared credentials' do
7668
client = Aws::S3::Client.new(profile: "incomplete_cred", region: "us-east-1")
77-
expect(client.config.credentials.credentials.access_key_id).to eq("ACCESS_KEY_SC1")
69+
expect(client.config.credentials.access_key_id).to eq("ACCESS_KEY_SC1")
7870
end
7971

8072
it 'attempts to fetch metadata credentials last' do
81-
stub_request(:put, imds_token_url)
82-
.to_return(
83-
:status => 200,
84-
:body => "my-token\n",
85-
:headers => {"x-aws-ec2-metadata-token-ttl-seconds": "21600"}
86-
)
87-
stub_request(:get, imds_url)
88-
.with(:headers => {"x-aws-ec2-metadata-token": "my-token"})
89-
.to_return(:status => 200, :body => "profile-name\n")
90-
stub_request(:get, "#{imds_url}profile-name")
91-
.with(:headers => {"x-aws-ec2-metadata-token": "my-token"})
92-
.to_return(:status => 200, :body => <<-JSON.strip)
73+
stub_request(
74+
:get,
75+
"http://169.254.169.254/latest/meta-data/iam/security-credentials/"
76+
).to_return(:status => 200, :body => "profile-name\n")
77+
stub_request(
78+
:get,
79+
"http://169.254.169.254/latest/meta-data/iam/security-credentials/profile-name"
80+
).to_return(:status => 200, :body => <<-JSON.strip)
9381
{
9482
"Code" : "Success",
9583
"LastUpdated" : "2013-11-22T20:03:48Z",
@@ -101,11 +89,11 @@ module Aws
10189
}
10290
JSON
10391
client = Aws::S3::Client.new(profile: "nonexistant", region: "us-east-1")
104-
expect(client.config.credentials.credentials.access_key_id).to eq("akid-md")
92+
expect(client.config.credentials.access_key_id).to eq("akid-md")
10593
end
10694

10795
describe 'Assume Role Resolution' do
108-
it 'will not assume a role without a source present' do
96+
it 'will not assume a role without source_profile present' do
10997
expect {
11098
Aws::S3::Client.new(profile: "ar_no_src", region: "us-east-1")
11199
}.to raise_error(Errors::NoSourceProfileError)
@@ -126,7 +114,7 @@ module Aws
126114
"AR_TOKEN"
127115
)
128116
client = Aws::S3::Client.new(profile: "assumerole_sc", region: "us-east-1")
129-
expect(client.config.credentials.credentials.access_key_id).to eq("AR_AKID")
117+
expect(client.config.credentials.access_key_id).to eq("AR_AKID")
130118
end
131119

132120
it 'will then try to assume a role from shared config' do
@@ -138,7 +126,7 @@ module Aws
138126
"AR_TOKEN"
139127
)
140128
client = Aws::S3::Client.new(profile: "ar_from_self", region: "us-east-1")
141-
expect(client.config.credentials.credentials.access_key_id).to eq("AR_AKID")
129+
expect(client.config.credentials.access_key_id).to eq("AR_AKID")
142130
end
143131

144132
it 'will assume a role from config using source credentials in shared credentials' do
@@ -150,10 +138,9 @@ module Aws
150138
"AR_TOKEN"
151139
)
152140
client = Aws::S3::Client.new(profile: "creds_from_sc", region: "us-east-1")
153-
expect(client.config.credentials.credentials.access_key_id).to eq("AR_AKID")
141+
expect(client.config.credentials.access_key_id).to eq("AR_AKID")
154142
end
155143
end
156-
157144
end
158145

159146
describe "AWS_SDK_CONFIG_OPT_OUT set" do
@@ -178,7 +165,7 @@ module Aws
178165
profile: "fooprofile",
179166
region: "us-east-1"
180167
)
181-
expect(client.config.credentials.credentials.access_key_id).to eq("ACCESS_DIRECT")
168+
expect(client.config.credentials.access_key_id).to eq("ACCESS_DIRECT")
182169
end
183170

184171
it 'prefers ENV credentials over shared config' do
@@ -187,7 +174,7 @@ module Aws
187174
"AWS_SECRET_ACCESS_KEY" => "SECRET_ENV_STUB"
188175
})
189176
client = Aws::S3::Client.new(profile: "fooprofile", region: "us-east-1")
190-
expect(client.config.credentials.credentials.access_key_id).to eq("AKID_ENV_STUB")
177+
expect(client.config.credentials.access_key_id).to eq("AKID_ENV_STUB")
191178
end
192179

193180
it 'will not load credentials from shared config' do
@@ -201,18 +188,14 @@ module Aws
201188
end
202189

203190
it 'attempts to fetch metadata credentials last' do
204-
stub_request(:put, imds_token_url)
205-
.to_return(
206-
:status => 200,
207-
:body => "my-token\n",
208-
:headers => {"x-aws-ec2-metadata-token-ttl-seconds": "21600"}
209-
)
210-
stub_request(:get, imds_url)
211-
.with(:headers => {"x-aws-ec2-metadata-token": "my-token"})
212-
.to_return(:status => 200, :body => "profile-name\n")
213-
stub_request(:get, "#{imds_url}profile-name")
214-
.with(:headers => {"x-aws-ec2-metadata-token": "my-token"})
215-
.to_return(:status => 200, :body => <<-JSON.strip)
191+
stub_request(
192+
:get,
193+
"http://169.254.169.254/latest/meta-data/iam/security-credentials/"
194+
).to_return(:status => 200, :body => "profile-name\n")
195+
stub_request(
196+
:get,
197+
"http://169.254.169.254/latest/meta-data/iam/security-credentials/profile-name"
198+
).to_return(:status => 200, :body => <<-JSON.strip)
216199
{
217200
"Code" : "Success",
218201
"LastUpdated" : "2013-11-22T20:03:48Z",
@@ -224,7 +207,7 @@ module Aws
224207
}
225208
JSON
226209
client = Aws::S3::Client.new(profile: "nonexistant", region: "us-east-1")
227-
expect(client.config.credentials.credentials.access_key_id).to eq("akid-md")
210+
expect(client.config.credentials.access_key_id).to eq("akid-md")
228211
end
229212
end
230213

0 commit comments

Comments
 (0)