healthcheck: Limit source IP range
This change introduces the new [healthcheck] allowed_source_ranges option, to restrict access to healthcheck endpoint within specific network ranges. This parameter is useful to avoid access from external network, because healthcheck endpoint has no authentication usually. Change-Id: I2b88704c260edd1a4c49cfde9de4cee4b90be862
This commit is contained in:
parent
43ab17010a
commit
9ce08a6f0f
@ -16,6 +16,7 @@
|
||||
import collections
|
||||
import gc
|
||||
import io
|
||||
import ipaddress
|
||||
import json
|
||||
import platform
|
||||
import socket
|
||||
@ -391,6 +392,9 @@ Reason
|
||||
group='healthcheck')
|
||||
self._path = self._conf_get('path')
|
||||
self._show_details = self._conf_get('detailed')
|
||||
self._source_ranges = [
|
||||
ipaddress.ip_network(r)
|
||||
for r in self._conf_get('allowed_source_ranges')]
|
||||
self._backends = stevedore.NamedExtensionManager(
|
||||
self.NAMESPACE, self._conf_get('backends'),
|
||||
name_order=True, invoke_on_load=True,
|
||||
@ -550,6 +554,17 @@ Reason
|
||||
def process_request(self, req):
|
||||
if not self._ignore_path and req.path != self._path:
|
||||
return None
|
||||
|
||||
if self._source_ranges:
|
||||
remote_addr = ipaddress.ip_address(req.remote_addr)
|
||||
for r in self._source_ranges:
|
||||
if r.version == remote_addr.version and remote_addr in r:
|
||||
break
|
||||
else:
|
||||
# Because source ip is not included in allowed ranges, ignore
|
||||
# the request in this middleware.
|
||||
return None
|
||||
|
||||
results = [ext.obj.healthcheck(req.server_port)
|
||||
for ext in self._backends]
|
||||
healthy = self._are_results_healthy(results)
|
||||
|
@ -29,6 +29,11 @@ HEALTHCHECK_OPTS = [
|
||||
default=[],
|
||||
help='Additional backends that can perform health checks and '
|
||||
'report that information back as part of a request.'),
|
||||
cfg.ListOpt('allowed_source_ranges',
|
||||
default=[],
|
||||
help='A list of network addresses to limit source ip allowed '
|
||||
'to access healthcheck information. Any request from ip '
|
||||
'outside of these network addresses are ignored.'),
|
||||
]
|
||||
|
||||
|
||||
|
@ -63,20 +63,22 @@ class HealthcheckTests(test_base.BaseTestCase):
|
||||
|
||||
def _do_test_request(self, conf={}, path='/healthcheck',
|
||||
accept='text/plain', method='GET',
|
||||
server_port=80):
|
||||
server_port=80, remote_addr='127.0.0.1'):
|
||||
self.app = healthcheck.Healthcheck(self.application, conf)
|
||||
req = webob.Request.blank(path, accept=accept, method=method)
|
||||
req.server_port = server_port
|
||||
req.remote_addr = remote_addr
|
||||
res = req.get_response(self.app)
|
||||
return res
|
||||
|
||||
def _do_test(self, conf={}, path='/healthcheck',
|
||||
expected_code=webob.exc.HTTPOk.code,
|
||||
expected_body=b'', accept='text/plain',
|
||||
method='GET', server_port=80):
|
||||
method='GET', server_port=80, remote_addr='127.0.0.1'):
|
||||
res = self._do_test_request(conf=conf, path=path,
|
||||
accept=accept, method=method,
|
||||
server_port=server_port)
|
||||
server_port=server_port,
|
||||
remote_addr=remote_addr)
|
||||
self.assertEqual(expected_code, res.status_int)
|
||||
self.assertEqual(expected_body, res.body)
|
||||
|
||||
@ -200,3 +202,16 @@ class HealthcheckTests(test_base.BaseTestCase):
|
||||
sort_keys=True).encode('utf-8')
|
||||
self._do_test(expected_body=expected_body,
|
||||
accept='application/json')
|
||||
|
||||
def test_source_within_allowed_ranges(self):
|
||||
conf = {'allowed_source_ranges': ['192.168.0.0/24', '192.168.1.0/24']}
|
||||
self._do_test(conf,
|
||||
expected_code=webob.exc.HTTPOk.code,
|
||||
remote_addr='192.168.0.1')
|
||||
|
||||
def test_source_out_of_allowed_ranges(self):
|
||||
conf = {'allowed_source_ranges': ['192.168.0.0/24', '192.168.1.0/24']}
|
||||
self._do_test(conf,
|
||||
expected_code=webob.exc.HTTPOk.code,
|
||||
expected_body=b'Hello, World!!!',
|
||||
remote_addr='192.168.3.1')
|
||||
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
The new ``[healthcheck] allowed_source_ranges`` parameter has been added.
|
||||
This parameter defines a list of network ranges from which access to
|
||||
``/healthcheck`` endpoint is allowed.
|
Loading…
Reference in New Issue
Block a user