Adds more robust checking of the status code during compute engine auth.

Currently the implementation does not verify that a 200 response is received
before attempting to parse the JSON response.

This PR updates the behaviour to fail with an authorization error, similar to
how other auth library implementations.
This commit is contained in:
Tim Emiola 2015-04-23 09:50:11 -07:00
parent 2924980b52
commit 98816f7b67
3 changed files with 59 additions and 5 deletions

View File

@ -1,15 +1,15 @@
# This configuration was generated by `rubocop --auto-gen-config`
# on 2015-03-06 19:51:00 -0800 using RuboCop version 0.28.0.
# on 2015-04-23 09:39:10 -0700 using RuboCop version 0.30.0.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.
# Offense count: 3
# Offense count: 4
Metrics/AbcSize:
Max: 24
# Offense count: 3
# Offense count: 6
# Configuration parameters: CountComments.
Metrics/MethodLength:
Max: 11
Max: 12

View File

@ -35,13 +35,24 @@ module Google
# Module Auth provides classes that provide Google-specific authorization
# used to access Google APIs.
module Auth
NO_METADATA_SERVER_ERROR = <<END
Error code 404 trying to get security access token
from Compute Engine metadata for the default service account. This
may be because the virtual machine instance does not have permission
scopes specified.
END
UNEXPECTED_ERROR_SUFFIX = <<END
trying to get security access token from Compute Engine metadata for
the default service account
END
# Extends Signet::OAuth2::Client so that the auth token is obtained from
# the GCE metadata server.
class GCECredentials < Signet::OAuth2::Client
# The IP Address is used in the URIs to speed up failures on non-GCE
# systems.
COMPUTE_AUTH_TOKEN_URI = 'http://169.254.169.254/computeMetadata/v1/'\
'instance/service-accounts/default/token'
'instance/service-accounts/default/token'
COMPUTE_CHECK_URI = 'http://169.254.169.254'
class << self
@ -78,6 +89,13 @@ module Google
c = options[:connection] || Faraday.default_connection
c.headers = { 'Metadata-Flavor' => 'Google' }
resp = c.get(COMPUTE_AUTH_TOKEN_URI)
if resp.status == 404
fail(Signet::AuthorizationError, NO_METADATA_SERVER_ERROR)
end
if resp.status != 200
msg = "Unexpected error code #{resp.status}" + UNEXPECTED_ERROR_SUFFIX
fail(Signet::AuthorizationError, msg)
end
Signet::OAuth2.parse_credentials(resp.body,
resp.headers['content-type'])
end

View File

@ -60,6 +60,42 @@ describe Google::Auth::GCECredentials do
it_behaves_like 'apply/apply! are OK'
context 'metadata is unavailable' do
describe '#fetch_access_token' do
it 'should fail if the metadata request returns a 404' do
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
stub.get(MD_URI) do |_env|
[404,
{ 'Metadata-Flavor' => 'Google' },
'']
end
end
c = Faraday.new do |b|
b.adapter(:test, stubs)
end
blk = proc { @client.fetch_access_token!(connection: c) }
expect(&blk).to raise_error Signet::AuthorizationError
stubs.verify_stubbed_calls
end
it 'should fail if metadata the request returns an unexpected codes' do
stubs = Faraday::Adapter::Test::Stubs.new do |stub|
stub.get(MD_URI) do |_env|
[503,
{ 'Metadata-Flavor' => 'Google' },
'']
end
end
c = Faraday.new do |b|
b.adapter(:test, stubs)
end
blk = proc { @client.fetch_access_token!(connection: c) }
expect(&blk).to raise_error Signet::AuthorizationError
stubs.verify_stubbed_calls
end
end
end
describe '#on_gce?' do
it 'should be true when Metadata-Flavor is Google' do
stubs = Faraday::Adapter::Test::Stubs.new do |stub|