diff options
author | Ade Lee <alee@redhat.com> | 2020-10-06 14:35:00 -0400 |
---|---|---|
committer | Ade Lee <alee@redhat.com> | 2020-10-29 15:44:36 -0400 |
commit | 54448e9d8b968c6d537a4a3b648ed280174b4f2c (patch) | |
tree | b7b314553fca7c65205aca731ab2298e7ff22ae2 | |
parent | c3d8c2ed9629522291da69ab61f38a8009466a04 (diff) | |
download | tooz-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.txt | 2 | ||||
-rw-r--r-- | tooz/drivers/ipc.py | 5 | ||||
-rw-r--r-- | tooz/drivers/pgsql.py | 4 | ||||
-rw-r--r-- | tooz/hashring.py | 18 | ||||
-rw-r--r-- | tooz/tests/test_hashring.py | 14 |
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'} |