api: Log correct client IP if load balancer in use
When Nova-Api runs behind the load balancer or Reverse proxy, Loadbalancer IP is getting logged in nova_api.log instead of end user source ip by RequestLog It should check for CONF.api.use_forwarded_for and then uses key 'HTTP_X_FORWARDED_FOR' to get the client ip. Co-Authored-By: melanie witt <melwittt@gmail.com> Closes-Bug: #1913605 Change-Id: Id2703ea4439d587a1a7a878796a79709fae5ea61
This commit is contained in:
@@ -21,6 +21,9 @@ import webob.exc
|
||||
|
||||
from nova.api.openstack import wsgi
|
||||
from nova.api import wsgi as base_wsgi
|
||||
import nova.conf
|
||||
|
||||
CONF = nova.conf.CONF
|
||||
|
||||
# TODO(sdague) maybe we can use a better name here for the logger
|
||||
LOG = logging.getLogger(__name__)
|
||||
@@ -65,8 +68,17 @@ class RequestLog(base_wsgi.Middleware):
|
||||
# wsgi stack, res is going to be an empty dict for the
|
||||
# fallback logging. So never count on it having attributes.
|
||||
status = getattr(res, "status", "500 Error").split(None, 1)[0]
|
||||
|
||||
remote_address = req.environ.get('REMOTE_ADDR', '-')
|
||||
|
||||
# If the API is configured to treat the X-Forwarded-For header as the
|
||||
# canonical remote address, use its value instead.
|
||||
if CONF.api.use_forwarded_for:
|
||||
remote_address = req.environ.get(
|
||||
'HTTP_X_FORWARDED_FOR', remote_address)
|
||||
|
||||
data = {
|
||||
'REMOTE_ADDR': req.environ.get('REMOTE_ADDR', '-'),
|
||||
'REMOTE_ADDR': remote_address,
|
||||
'REQUEST_METHOD': req.environ['REQUEST_METHOD'],
|
||||
'REQUEST_URI': self._get_uri(req.environ),
|
||||
'status': status,
|
||||
|
||||
@@ -58,7 +58,7 @@ class TestRequestLogMiddleware(testtools.TestCase):
|
||||
"""
|
||||
|
||||
emit.return_value = True
|
||||
self.useFixture(fixtures.ConfFixture())
|
||||
conf = self.useFixture(fixtures.ConfFixture()).conf
|
||||
self.useFixture(fixtures.RPCFixture('nova.test'))
|
||||
api = self.useFixture(fixtures.OSAPIFixture()).api
|
||||
|
||||
@@ -73,6 +73,25 @@ class TestRequestLogMiddleware(testtools.TestCase):
|
||||
'"GET /" status: 200 len: %s' % content_length)
|
||||
self.assertIn(log1, self.stdlog.logger.output)
|
||||
|
||||
# Verify handling of X-Forwarded-For header, example: load balancer.
|
||||
# First, try without setting CONF.api.use_forwarded_for, it should not
|
||||
# use the header value.
|
||||
headers = {'X-Forwarded-For': '1.2.3.4'}
|
||||
resp = api.api_request('/', strip_version=True, headers=headers)
|
||||
content_length = resp.headers['content-length']
|
||||
log2 = ('INFO [nova.api.openstack.requestlog] 127.0.0.1 '
|
||||
'"GET /" status: 200 len: %s' % content_length)
|
||||
self.assertIn(log2, self.stdlog.logger.output)
|
||||
|
||||
# Now set CONF.api.use_forwarded_for, it should use the header value.
|
||||
conf.set_override('use_forwarded_for', True, 'api')
|
||||
headers = {'X-Forwarded-For': '1.2.3.4'}
|
||||
resp = api.api_request('/', strip_version=True, headers=headers)
|
||||
content_length = resp.headers['content-length']
|
||||
log3 = ('INFO [nova.api.openstack.requestlog] 1.2.3.4 '
|
||||
'"GET /" status: 200 len: %s' % content_length)
|
||||
self.assertIn(log3, self.stdlog.logger.output)
|
||||
|
||||
@mock.patch('nova.api.openstack.requestlog.RequestLog._should_emit')
|
||||
def test_logs_mv(self, emit):
|
||||
"""Ensure logs register microversion if passed.
|
||||
|
||||
Reference in New Issue
Block a user