Replace md5 with oslo version
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
This commit is contained in:
parent
c3d8c2ed96
commit
54448e9d8b
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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]
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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'}
|
||||
|
Loading…
x
Reference in New Issue
Block a user