Quantum metadata handler now uses X-Forwarded-For

fixes bug 1097524

The guest IP address was not properly forwarded from the Quantum
metadata proxy.  This patch adds support in Nova for reading this
X-Forwarded-For header.  Previously, the internal proxy IP was
mistakenly used exposing internal infrastructure details.

Change-Id: I6d7d21e2aea4ca5debf1ca4ba6802012537f78a5
This commit is contained in:
Mark McClain 2013-01-08 18:59:20 -05:00
parent 77dbed11a6
commit 2fc0097c5b
2 changed files with 46 additions and 22 deletions

View File

@ -142,7 +142,7 @@ class MetadataRequestHandler(wsgi.Application):
def _handle_instance_id_request(self, req): def _handle_instance_id_request(self, req):
instance_id = req.headers.get('X-Instance-ID') instance_id = req.headers.get('X-Instance-ID')
signature = req.headers.get('X-Instance-ID-Signature') signature = req.headers.get('X-Instance-ID-Signature')
remote_address = req.remote_addr remote_address = req.headers.get('X-Forwarded-For')
# Ensure that only one header was passed # Ensure that only one header was passed

View File

@ -20,6 +20,8 @@
import base64 import base64
import copy import copy
import hashlib
import hmac
import json import json
import re import re
@ -461,15 +463,19 @@ class MetadataHandlerTestCase(test.TestCase):
expected_instance_id = 'a-b-c-d' expected_instance_id = 'a-b-c-d'
def fake_get_metadata(instance_id, remote_address): def fake_get_metadata(instance_id, remote_address):
if instance_id == expected_instance_id: if remote_address is None:
raise Exception('Expected X-Forwared-For header')
elif instance_id == expected_instance_id:
return self.mdinst return self.mdinst
else: else:
# raise the exception to aid with 500 response code test # raise the exception to aid with 500 response code test
raise Exception("Expected instance_id of %s, got %s" % raise Exception("Expected instance_id of %s, got %s" %
(expected_instance_id, instance_id)) (expected_instance_id, instance_id))
signed = ('d98d0dd53b026a24df2c06b464ffa5da' signed = hmac.new(
'db922ae41af7bd3ecc3cae75aef65771') CONF.quantum_metadata_proxy_shared_secret,
expected_instance_id,
hashlib.sha256).hexdigest()
# try a request with service disabled # try a request with service disabled
response = fake_request( response = fake_request(
@ -481,8 +487,33 @@ class MetadataHandlerTestCase(test.TestCase):
self.assertEqual(response.status_int, 200) self.assertEqual(response.status_int, 200)
# now enable the service # now enable the service
self.flags(service_quantum_metadata_proxy=True) self.flags(service_quantum_metadata_proxy=True)
response = fake_request(
self.stubs, self.mdinst,
relpath="/2009-04-04/user-data",
address="192.192.192.2",
fake_get_metadata_by_instance_id=fake_get_metadata,
headers={'X-Forwarded-For': '192.192.192.2',
'X-Instance-ID': 'a-b-c-d',
'X-Instance-ID-Signature': signed})
self.assertEqual(response.status_int, 200)
self.assertEqual(response.body,
base64.b64decode(self.instance['user_data']))
# mismatched signature
response = fake_request(
self.stubs, self.mdinst,
relpath="/2009-04-04/user-data",
address="192.192.192.2",
fake_get_metadata_by_instance_id=fake_get_metadata,
headers={'X-Forwarded-For': '192.192.192.2',
'X-Instance-ID': 'a-b-c-d',
'X-Instance-ID-Signature': ''})
self.assertEqual(response.status_int, 403)
# without X-Forwarded-For
response = fake_request( response = fake_request(
self.stubs, self.mdinst, self.stubs, self.mdinst,
relpath="/2009-04-04/user-data", relpath="/2009-04-04/user-data",
@ -491,29 +522,22 @@ class MetadataHandlerTestCase(test.TestCase):
headers={'X-Instance-ID': 'a-b-c-d', headers={'X-Instance-ID': 'a-b-c-d',
'X-Instance-ID-Signature': signed}) 'X-Instance-ID-Signature': signed})
self.assertEqual(response.status_int, 200) self.assertEqual(response.status_int, 500)
self.assertEqual(response.body,
base64.b64decode(self.instance['user_data'])) # unexpected Instance-ID
signed = hmac.new(
CONF.quantum_metadata_proxy_shared_secret,
'z-z-z-z',
hashlib.sha256).hexdigest()
response = fake_request( response = fake_request(
self.stubs, self.mdinst, self.stubs, self.mdinst,
relpath="/2009-04-04/user-data", relpath="/2009-04-04/user-data",
address="192.192.192.2", address="192.192.192.2",
fake_get_metadata_by_instance_id=fake_get_metadata, fake_get_metadata_by_instance_id=fake_get_metadata,
headers={'X-Instance-ID': 'a-b-c-d', headers={'X-Forwarded-For': '192.192.192.2',
'X-Instance-ID-Signature': ''}) 'X-Instance-ID': 'z-z-z-z',
'X-Instance-ID-Signature': signed})
self.assertEqual(response.status_int, 403)
response = fake_request(
self.stubs, self.mdinst,
relpath="/2009-04-04/user-data",
address="192.192.192.2",
fake_get_metadata_by_instance_id=fake_get_metadata,
headers={'X-Instance-ID': 'z-z-z-z',
'X-Instance-ID-Signature': '81f42e3fc77ba3a3e8d83142746e0'
'8387b96cbc5bd2474665192d2ec28'
'8ffb67'})
self.assertEqual(response.status_int, 500) self.assertEqual(response.status_int, 500)