summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAde Lee <alee@redhat.com>2020-10-06 14:35:00 -0400
committerAde Lee <alee@redhat.com>2020-10-29 15:44:36 -0400
commit54448e9d8b968c6d537a4a3b648ed280174b4f2c (patch)
treeb7b314553fca7c65205aca731ab2298e7ff22ae2
parentc3d8c2ed9629522291da69ab61f38a8009466a04 (diff)
downloadtooz-54448e9d8b968c6d537a4a3b648ed280174b4f2c.tar.gz
Replace md5 with oslo version2.8.0
md5 is not an approved algorithm in FIPS mode, and trying to instantiate a hashlib.md5() will fail when the system is running in FIPS mode. md5 is allowed when in a non-security context. There is a plan to add a keyword parameter (usedforsecurity) to hashlib.md5() to annotate whether or not the instance is being used in a security context. In the case where it is not, the instantiation of md5 will be allowed. See https://bugs.python.org/issue9216 for more details. Some downstream python versions already support this parameter. To support these versions, a new encapsulation of md5() has been added to oslo_utils. See https://review.opendev.org/#/c/750031/ This patch is to replace the instances of hashlib.md5() with this new encapsulation, adding an annotation indicating whether the usage is a security context or not. Reviewers need to pay particular attention as to whether the keyword parameter (usedforsecurity) is set correctly. Change-Id: Idbef0f0896753765372c8dfac8ab15e6be49922f Depends-On: https://review.opendev.org/#/c/760160
-rw-r--r--requirements.txt2
-rw-r--r--tooz/drivers/ipc.py5
-rw-r--r--tooz/drivers/pgsql.py4
-rw-r--r--tooz/hashring.py18
-rw-r--r--tooz/tests/test_hashring.py14
5 files changed, 32 insertions, 11 deletions
diff --git a/requirements.txt b/requirements.txt
index a448b67..7e40c1f 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -8,5 +8,5 @@ msgpack>=0.4.0 # Apache-2.0
fasteners>=0.7 # Apache-2.0
tenacity>=3.2.1 # Apache-2.0
futurist>=1.2.0 # Apache-2.0
-oslo.utils>=3.15.0 # Apache-2.0
+oslo.utils>=4.7.0 # Apache-2.0
oslo.serialization>=1.10.0 # Apache-2.0
diff --git a/tooz/drivers/ipc.py b/tooz/drivers/ipc.py
index bcb7a00..7358244 100644
--- a/tooz/drivers/ipc.py
+++ b/tooz/drivers/ipc.py
@@ -14,13 +14,14 @@
# License for the specific language governing permissions and limitations
# under the License.
-import hashlib
import struct
import time
import msgpack
import sysv_ipc
+from oslo_utils.secretutils import md5
+
import tooz
from tooz import coordination
from tooz import locking
@@ -35,7 +36,7 @@ else:
def ftok(name, project):
# Similar to ftok & http://semanchuk.com/philip/sysv_ipc/#ftok_weakness
# but hopefully without as many weaknesses...
- h = hashlib.md5()
+ h = md5(usedforsecurity=False)
if not isinstance(project, bytes):
project = project.encode('ascii')
h.update(project)
diff --git a/tooz/drivers/pgsql.py b/tooz/drivers/pgsql.py
index 71b7ae3..df8dbac 100644
--- a/tooz/drivers/pgsql.py
+++ b/tooz/drivers/pgsql.py
@@ -15,10 +15,10 @@
# under the License.
import contextlib
-import hashlib
import logging
from oslo_utils import encodeutils
+from oslo_utils.secretutils import md5
import psycopg2
import tooz
@@ -98,7 +98,7 @@ class PostgresLock(locking.Lock):
self._conn = None
self._parsed_url = parsed_url
self._options = options
- h = hashlib.md5()
+ h = md5(usedforsecurity=False)
h.update(name)
self.key = h.digest()[0:2]
diff --git a/tooz/hashring.py b/tooz/hashring.py
index f6dac31..581bc9c 100644
--- a/tooz/hashring.py
+++ b/tooz/hashring.py
@@ -16,6 +16,8 @@
import bisect
import hashlib
+from oslo_utils.secretutils import md5
+
import tooz
from tooz import utils
@@ -80,7 +82,10 @@ class HashRing(object):
"""
for node in nodes:
key = utils.to_binary(node, 'utf-8')
- key_hash = hashlib.new(self._hash_function, key)
+ if self._hash_function == 'md5':
+ key_hash = md5(key, usedforsecurity=False)
+ else:
+ key_hash = hashlib.new(self._hash_function, key)
for r in range(self._partition_number * weight):
key_hash.update(key)
self._ring[self._hash2int(key_hash)] = node
@@ -102,7 +107,10 @@ class HashRing(object):
raise UnknownNode(node)
key = utils.to_binary(node, 'utf-8')
- key_hash = hashlib.new(self._hash_function, key)
+ if self._hash_function == 'md5':
+ key_hash = md5(key, usedforsecurity=False)
+ else:
+ key_hash = hashlib.new(self._hash_function, key)
for r in range(self._partition_number * weight):
key_hash.update(key)
del self._ring[self._hash2int(key_hash)]
@@ -114,7 +122,11 @@ class HashRing(object):
return int(key.hexdigest(), 16)
def _get_partition(self, data):
- hashed_key = self._hash2int(hashlib.new(self._hash_function, data))
+ if self._hash_function == 'md5':
+ hashed_key = self._hash2int(md5(data, usedforsecurity=False))
+ else:
+ hashed_key = self._hash2int(
+ hashlib.new(self._hash_function, data))
position = bisect.bisect(self._partitions, hashed_key)
return position if position < len(self._partitions) else 0
diff --git a/tooz/tests/test_hashring.py b/tooz/tests/test_hashring.py
index d44c1d1..01dd642 100644
--- a/tooz/tests/test_hashring.py
+++ b/tooz/tests/test_hashring.py
@@ -31,7 +31,13 @@ class HashRingTestCase(testcase.TestCase):
# fake -> foo, bar, baz
# fake-again -> bar, baz, foo
- @mock.patch.object(hashlib, 'new', autospec=True)
+ try:
+ _ = hashlib.md5(usedforsecurity=False)
+ _fips_enabled = True
+ except TypeError:
+ _fips_enabled = False
+
+ @mock.patch.object(hashlib, 'md5', autospec=True)
def test_hash2int_returns_int(self, mock_md5):
r1 = 32 * 'a'
r2 = 32 * 'b'
@@ -44,8 +50,10 @@ class HashRingTestCase(testcase.TestCase):
self.assertIn(int(r1, 16), ring._ring)
self.assertIn(int(r2, 16), ring._ring)
-
- mock_md5.assert_called_with('md5', mock.ANY)
+ if self._fips_enabled:
+ mock_md5.assert_called_with(mock.ANY, usedforsecurity=False)
+ else:
+ mock_md5.assert_called_with(mock.ANY)
def test_create_ring(self):
nodes = {'foo', 'bar'}