add a new HTTPClient attr for setting the original IP
The original IP is useful in cases where keystoneclient is used by a different openstack component and we need to know who made the original request. Otherwise it gets overwritten by e.g. Dashboard's host's IP. bug 1046837 Change-Id: Ic22c565e92010afd89c8573c375919215b70d73d
This commit is contained in:
		@@ -39,7 +39,7 @@ class HTTPClient(httplib2.Http):
 | 
				
			|||||||
    def __init__(self, username=None, tenant_id=None, tenant_name=None,
 | 
					    def __init__(self, username=None, tenant_id=None, tenant_name=None,
 | 
				
			||||||
                 password=None, auth_url=None, region_name=None, timeout=None,
 | 
					                 password=None, auth_url=None, region_name=None, timeout=None,
 | 
				
			||||||
                 endpoint=None, token=None, cacert=None, key=None,
 | 
					                 endpoint=None, token=None, cacert=None, key=None,
 | 
				
			||||||
                 cert=None, insecure=False):
 | 
					                 cert=None, insecure=False, original_ip=None):
 | 
				
			||||||
        super(HTTPClient, self).__init__(timeout=timeout, ca_certs=cacert)
 | 
					        super(HTTPClient, self).__init__(timeout=timeout, ca_certs=cacert)
 | 
				
			||||||
        if cert:
 | 
					        if cert:
 | 
				
			||||||
            if key:
 | 
					            if key:
 | 
				
			||||||
@@ -54,6 +54,7 @@ class HTTPClient(httplib2.Http):
 | 
				
			|||||||
        self.version = 'v2.0'
 | 
					        self.version = 'v2.0'
 | 
				
			||||||
        self.region_name = region_name
 | 
					        self.region_name = region_name
 | 
				
			||||||
        self.auth_token = token
 | 
					        self.auth_token = token
 | 
				
			||||||
 | 
					        self.original_ip = original_ip
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.management_url = endpoint
 | 
					        self.management_url = endpoint
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -117,6 +118,9 @@ class HTTPClient(httplib2.Http):
 | 
				
			|||||||
        request_kwargs = copy.copy(kwargs)
 | 
					        request_kwargs = copy.copy(kwargs)
 | 
				
			||||||
        request_kwargs.setdefault('headers', kwargs.get('headers', {}))
 | 
					        request_kwargs.setdefault('headers', kwargs.get('headers', {}))
 | 
				
			||||||
        request_kwargs['headers']['User-Agent'] = self.USER_AGENT
 | 
					        request_kwargs['headers']['User-Agent'] = self.USER_AGENT
 | 
				
			||||||
 | 
					        if self.original_ip:
 | 
				
			||||||
 | 
					            request_kwargs['headers']['Forwarded'] = "for=%s;by=%s" % (
 | 
				
			||||||
 | 
					                self.original_ip, self.USER_AGENT)
 | 
				
			||||||
        if 'body' in kwargs:
 | 
					        if 'body' in kwargs:
 | 
				
			||||||
            request_kwargs['headers']['Content-Type'] = 'application/json'
 | 
					            request_kwargs['headers']['Content-Type'] = 'application/json'
 | 
				
			||||||
            request_kwargs['body'] = json.dumps(kwargs['body'])
 | 
					            request_kwargs['body'] = json.dumps(kwargs['body'])
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -46,6 +46,9 @@ class Client(client.HTTPClient):
 | 
				
			|||||||
                            instantiation.(optional)
 | 
					                            instantiation.(optional)
 | 
				
			||||||
    :param integer timeout: Allows customization of the timeout for client
 | 
					    :param integer timeout: Allows customization of the timeout for client
 | 
				
			||||||
                            http requests. (optional)
 | 
					                            http requests. (optional)
 | 
				
			||||||
 | 
					    :param string original_ip: The original IP of the requesting user
 | 
				
			||||||
 | 
					                               which will be sent to Keystone in a
 | 
				
			||||||
 | 
					                               'Forwarded' header. (optional)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Example::
 | 
					    Example::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -62,3 +62,17 @@ class ClientTest(utils.TestCase):
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            mock_request.assert_called_with("http://127.0.0.1:5000/hi", "POST",
 | 
					            mock_request.assert_called_with("http://127.0.0.1:5000/hi", "POST",
 | 
				
			||||||
                                            headers=headers, body='[1, 2, 3]')
 | 
					                                            headers=headers, body='[1, 2, 3]')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_forwarded_for(self):
 | 
				
			||||||
 | 
					        ORIGINAL_IP = "10.100.100.1"
 | 
				
			||||||
 | 
					        cl = client.HTTPClient(username="username", password="password",
 | 
				
			||||||
 | 
					                               tenant_id="tenant", auth_url="auth_test",
 | 
				
			||||||
 | 
					                               original_ip=ORIGINAL_IP)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        with mock.patch.object(httplib2.Http, "request", mock_request):
 | 
				
			||||||
 | 
					            res = cl.request('/', 'GET')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            args, kwargs = mock_request.call_args
 | 
				
			||||||
 | 
					            self.assertIn(
 | 
				
			||||||
 | 
					                ('Forwarded', "for=%s;by=%s" % (ORIGINAL_IP, cl.USER_AGENT)),
 | 
				
			||||||
 | 
					                kwargs['headers'].items())
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user