Redis connection support password configure in zaqar
Redis connection doesn't support password configure in zaqar, so redis-server can not set a password. If redis service doesn't set a password, it will suffer a large number of attacks. The patch will support password configure in zaqar. In addition, it is needed to add unit test in the previous patch[https://review.openstack.org/#/c/511676/]. Change-Id: I03661584f1c24fdb3e76a819c9eaa0ed32f272c4
This commit is contained in:
parent
764bbb97dd
commit
856884641f
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Redis connection doesn't support password configure in zaqar,
|
||||||
|
so redis-server can not set a password. If redis service doesn't
|
||||||
|
set a password, it will suffer a large number of attacks. The
|
||||||
|
patch will support password configure for redis connection in zaqar.
|
4
tox.ini
4
tox.ini
@ -73,9 +73,9 @@ commands =
|
|||||||
|
|
||||||
[flake8]
|
[flake8]
|
||||||
exclude = .venv*,.git,.tox,dist,doc,*lib/python*,*.egg,.update-venv
|
exclude = .venv*,.git,.tox,dist,doc,*lib/python*,*.egg,.update-venv
|
||||||
# NOTE(flaper87): Our currently max-complexity is 15. Not sure what the ideal complexity
|
# NOTE(flaper87): Our currently max-complexity is 20. Not sure what the ideal complexity
|
||||||
# for Zaqar should be but lets keep it to the minimum possible.
|
# for Zaqar should be but lets keep it to the minimum possible.
|
||||||
max-complexity = 16
|
max-complexity = 20
|
||||||
# [H904] Delay string interpolations at logging calls.
|
# [H904] Delay string interpolations at logging calls.
|
||||||
enable-extensions=H904
|
enable-extensions=H904
|
||||||
|
|
||||||
|
@ -53,6 +53,13 @@ class ConnectionURI(object):
|
|||||||
path, sep, query = path.partition('?')
|
path, sep, query = path.partition('?')
|
||||||
else:
|
else:
|
||||||
query = parsed_url.query
|
query = parsed_url.query
|
||||||
|
# NOTE(gengchc2): Redis connection support password configure.
|
||||||
|
self.password = None
|
||||||
|
if '@' in path:
|
||||||
|
self.password, sep, path = path.partition('@')
|
||||||
|
netloc = parsed_url.netloc
|
||||||
|
if '@' in netloc:
|
||||||
|
self.password, sep, netloc = netloc.partition('@')
|
||||||
|
|
||||||
query_params = dict(urllib.parse.parse_qsl(query))
|
query_params = dict(urllib.parse.parse_qsl(query))
|
||||||
|
|
||||||
@ -80,7 +87,7 @@ class ConnectionURI(object):
|
|||||||
|
|
||||||
# NOTE(kgriffs): Have to parse list of sentinel hosts ourselves
|
# NOTE(kgriffs): Have to parse list of sentinel hosts ourselves
|
||||||
# since urllib doesn't support it.
|
# since urllib doesn't support it.
|
||||||
for each_host in parsed_url.netloc.split(','):
|
for each_host in netloc.split(','):
|
||||||
name, sep, port = each_host.partition(':')
|
name, sep, port = each_host.partition(':')
|
||||||
|
|
||||||
if port:
|
if port:
|
||||||
@ -101,8 +108,8 @@ class ConnectionURI(object):
|
|||||||
'sentinel hosts')
|
'sentinel hosts')
|
||||||
raise errors.ConfigurationError(msg)
|
raise errors.ConfigurationError(msg)
|
||||||
|
|
||||||
elif parsed_url.netloc:
|
elif netloc:
|
||||||
if ',' in parsed_url.netloc:
|
if ',' in netloc:
|
||||||
# NOTE(kgriffs): They probably were specifying
|
# NOTE(kgriffs): They probably were specifying
|
||||||
# a list of sentinel hostnames, but forgot to
|
# a list of sentinel hostnames, but forgot to
|
||||||
# add 'master' to the query string.
|
# add 'master' to the query string.
|
||||||
@ -276,6 +283,8 @@ def _get_redis_client(driver):
|
|||||||
if connection_uri.strategy == STRATEGY_SENTINEL:
|
if connection_uri.strategy == STRATEGY_SENTINEL:
|
||||||
sentinel = redis.sentinel.Sentinel(
|
sentinel = redis.sentinel.Sentinel(
|
||||||
connection_uri.sentinels,
|
connection_uri.sentinels,
|
||||||
|
db=connection_uri.dbid,
|
||||||
|
password=connection_uri.password,
|
||||||
socket_timeout=connection_uri.socket_timeout)
|
socket_timeout=connection_uri.socket_timeout)
|
||||||
|
|
||||||
# NOTE(prashanthr_): The socket_timeout parameter being generic
|
# NOTE(prashanthr_): The socket_timeout parameter being generic
|
||||||
@ -288,8 +297,11 @@ def _get_redis_client(driver):
|
|||||||
host=connection_uri.hostname,
|
host=connection_uri.hostname,
|
||||||
port=connection_uri.port,
|
port=connection_uri.port,
|
||||||
db=connection_uri.dbid,
|
db=connection_uri.dbid,
|
||||||
|
password=connection_uri.password,
|
||||||
socket_timeout=connection_uri.socket_timeout)
|
socket_timeout=connection_uri.socket_timeout)
|
||||||
else:
|
else:
|
||||||
return redis.StrictRedis(
|
return redis.StrictRedis(
|
||||||
unix_socket_path=connection_uri.unix_socket_path,
|
unix_socket_path=connection_uri.unix_socket_path,
|
||||||
|
db=connection_uri.dbid,
|
||||||
|
password=connection_uri.password,
|
||||||
socket_timeout=connection_uri.socket_timeout)
|
socket_timeout=connection_uri.socket_timeout)
|
||||||
|
@ -25,10 +25,13 @@ _COMMON_REDIS_OPTIONS = (
|
|||||||
group=_deprecated_group), ],
|
group=_deprecated_group), ],
|
||||||
help=('Redis connection URI, taking one of three forms. '
|
help=('Redis connection URI, taking one of three forms. '
|
||||||
'For a direct connection to a Redis server, use '
|
'For a direct connection to a Redis server, use '
|
||||||
'the form "redis://host[:port][?options]", where '
|
'the form "redis://[:password]@host[:port][?options]", '
|
||||||
'port defaults to 6379 if not specified. For an '
|
'where password is redis-server\'s password, when'
|
||||||
'HA master-slave Redis cluster using Redis Sentinel, '
|
'redis-server is set password, the password option'
|
||||||
'use the form "redis://host1[:port1]'
|
'needs to be set. port defaults to 6379 if not'
|
||||||
|
'specified. For an HA master-slave Redis cluster using'
|
||||||
|
' Redis Sentinel, use the form '
|
||||||
|
'"redis://[:password]@host1[:port1]'
|
||||||
'[,host2[:port2],...,hostN[:portN]][?options]", '
|
'[,host2[:port2],...,hostN[:portN]][?options]", '
|
||||||
'where each host specified corresponds to an '
|
'where each host specified corresponds to an '
|
||||||
'instance of redis-sentinel. In this form, the '
|
'instance of redis-sentinel. In this form, the '
|
||||||
@ -37,8 +40,8 @@ _COMMON_REDIS_OPTIONS = (
|
|||||||
'string as "master=<name>". Finally, to connect '
|
'string as "master=<name>". Finally, to connect '
|
||||||
'to a local instance of Redis over a unix socket, '
|
'to a local instance of Redis over a unix socket, '
|
||||||
'you may use the form '
|
'you may use the form '
|
||||||
'"redis:/path/to/redis.sock[?options]". In all '
|
'"redis:[:password]@/path/to/redis.sock[?options]".'
|
||||||
'forms, the "socket_timeout" option may be '
|
' In all forms, the "socket_timeout" option may be'
|
||||||
'specified in the query string. Its value is '
|
'specified in the query string. Its value is '
|
||||||
'given in seconds. If not provided, '
|
'given in seconds. If not provided, '
|
||||||
'"socket_timeout" defaults to 0.1 seconds.'
|
'"socket_timeout" defaults to 0.1 seconds.'
|
||||||
|
@ -244,6 +244,14 @@ class RedisDriverTest(testing.TestBase):
|
|||||||
self.assertEqual(7777, uri.port)
|
self.assertEqual(7777, uri.port)
|
||||||
self.assertEqual(1.0, uri.socket_timeout)
|
self.assertEqual(1.0, uri.socket_timeout)
|
||||||
|
|
||||||
|
uri = driver.ConnectionURI(
|
||||||
|
'redis://test123@example.com:7777?socket_timeout=1&dbid=5')
|
||||||
|
self.assertEqual(driver.STRATEGY_TCP, uri.strategy)
|
||||||
|
self.assertEqual(7777, uri.port)
|
||||||
|
self.assertEqual(1.0, uri.socket_timeout)
|
||||||
|
self.assertEqual(5, uri.dbid)
|
||||||
|
self.assertEqual('test123', uri.password)
|
||||||
|
|
||||||
def test_connection_uri_unix_socket(self):
|
def test_connection_uri_unix_socket(self):
|
||||||
uri = driver.ConnectionURI('redis:/tmp/redis.sock')
|
uri = driver.ConnectionURI('redis:/tmp/redis.sock')
|
||||||
self.assertEqual(driver.STRATEGY_UNIX, uri.strategy)
|
self.assertEqual(driver.STRATEGY_UNIX, uri.strategy)
|
||||||
@ -255,6 +263,14 @@ class RedisDriverTest(testing.TestBase):
|
|||||||
self.assertEqual('/tmp/redis.sock', uri.unix_socket_path)
|
self.assertEqual('/tmp/redis.sock', uri.unix_socket_path)
|
||||||
self.assertEqual(1.5, uri.socket_timeout)
|
self.assertEqual(1.5, uri.socket_timeout)
|
||||||
|
|
||||||
|
uri = driver.ConnectionURI(
|
||||||
|
'redis:test123@/tmp/redis.sock?socket_timeout=1.5&dbid=5')
|
||||||
|
self.assertEqual(driver.STRATEGY_UNIX, uri.strategy)
|
||||||
|
self.assertEqual('/tmp/redis.sock', uri.unix_socket_path)
|
||||||
|
self.assertEqual(1.5, uri.socket_timeout)
|
||||||
|
self.assertEqual(5, uri.dbid)
|
||||||
|
self.assertEqual('test123', uri.password)
|
||||||
|
|
||||||
def test_connection_uri_sentinel(self):
|
def test_connection_uri_sentinel(self):
|
||||||
uri = driver.ConnectionURI('redis://s1?master=dumbledore')
|
uri = driver.ConnectionURI('redis://s1?master=dumbledore')
|
||||||
self.assertEqual(driver.STRATEGY_SENTINEL, uri.strategy)
|
self.assertEqual(driver.STRATEGY_SENTINEL, uri.strategy)
|
||||||
@ -281,6 +297,15 @@ class RedisDriverTest(testing.TestBase):
|
|||||||
self.assertEqual('dumbledore', uri.master)
|
self.assertEqual('dumbledore', uri.master)
|
||||||
self.assertEqual(0.5, uri.socket_timeout)
|
self.assertEqual(0.5, uri.socket_timeout)
|
||||||
|
|
||||||
|
uri = driver.ConnectionURI(
|
||||||
|
'redis://test123@s1?master=dumbledore&socket_timeout=0.5&dbid=5')
|
||||||
|
self.assertEqual(driver.STRATEGY_SENTINEL, uri.strategy)
|
||||||
|
self.assertEqual([('s1', 26379)], uri.sentinels)
|
||||||
|
self.assertEqual('dumbledore', uri.master)
|
||||||
|
self.assertEqual(0.5, uri.socket_timeout)
|
||||||
|
self.assertEqual(5, uri.dbid)
|
||||||
|
self.assertEqual('test123', uri.password)
|
||||||
|
|
||||||
|
|
||||||
@testing.requires_redis
|
@testing.requires_redis
|
||||||
class RedisQueuesTest(base.QueueControllerTest):
|
class RedisQueuesTest(base.QueueControllerTest):
|
||||||
|
Loading…
Reference in New Issue
Block a user