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.
In this case, all hashlib.md5() invocations are to run tempest tests
so this is not a security context. With this patch, we can run tempest
tests from a FIPS enabled machine.
Change-Id: Ib301466bb0a1996997c63599918fa96059a927bd
diff --git a/tempest/api/object_storage/test_object_services.py b/tempest/api/object_storage/test_object_services.py
index fc9b1a2..93f6fdb 100644
--- a/tempest/api/object_storage/test_object_services.py
+++ b/tempest/api/object_storage/test_object_services.py
@@ -13,12 +13,12 @@
# License for the specific language governing permissions and limitations
# under the License.
-import hashlib
import random
import re
import time
import zlib
+from oslo_utils.secretutils import md5
from tempest.api.object_storage import base
from tempest.common import custom_matchers
from tempest import config
@@ -151,8 +151,8 @@
"""Test creating object with Etag"""
object_name = data_utils.rand_name(name='TestObject')
data = data_utils.random_bytes()
- md5 = hashlib.md5(data).hexdigest()
- metadata = {'Etag': md5}
+ create_md5 = md5(data, usedforsecurity=False).hexdigest()
+ metadata = {'Etag': create_md5}
resp, _ = self.object_client.create_object(
self.container_name,
object_name,
@@ -641,7 +641,7 @@
"""Test getting object with if_match"""
object_name = data_utils.rand_name(name='TestObject')
data = data_utils.random_bytes(10)
- create_md5 = hashlib.md5(data).hexdigest()
+ create_md5 = md5(data, usedforsecurity=False).hexdigest()
create_metadata = {'Etag': create_md5}
self.object_client.create_object(self.container_name,
object_name,
@@ -681,7 +681,7 @@
"""Test getting object with if_none_match"""
object_name = data_utils.rand_name(name='TestObject')
data = data_utils.random_bytes()
- create_md5 = hashlib.md5(data).hexdigest()
+ create_md5 = md5(data, usedforsecurity=False).hexdigest()
create_metadata = {'Etag': create_md5}
self.object_client.create_object(self.container_name,
object_name,
@@ -689,7 +689,7 @@
metadata=create_metadata)
list_data = data_utils.random_bytes()
- list_md5 = hashlib.md5(list_data).hexdigest()
+ list_md5 = md5(list_data, usedforsecurity=False).hexdigest()
list_metadata = {'If-None-Match': list_md5}
resp, body = self.object_client.get_object(
self.container_name,
@@ -978,8 +978,8 @@
"""
object_name, data = self.create_object(self.container_name)
# local copy is identical, no download
- md5 = hashlib.md5(data).hexdigest()
- headers = {'If-None-Match': md5}
+ object_md5 = md5(data, usedforsecurity=False).hexdigest()
+ headers = {'If-None-Match': object_md5}
url = "%s/%s" % (self.container_name, object_name)
resp, _ = self.object_client.get(url, headers=headers)
self.assertEqual(resp['status'], '304')
@@ -993,8 +993,8 @@
# local copy is different, download
local_data = "something different"
- md5 = hashlib.md5(local_data.encode()).hexdigest()
- headers = {'If-None-Match': md5}
+ other_md5 = md5(local_data.encode(), usedforsecurity=False).hexdigest()
+ headers = {'If-None-Match': other_md5}
resp, _ = self.object_client.get(url, headers=headers)
self.assertHeaders(resp, 'Object', 'GET')
diff --git a/tempest/api/object_storage/test_object_slo.py b/tempest/api/object_storage/test_object_slo.py
index 664bbc8..0c84357 100644
--- a/tempest/api/object_storage/test_object_slo.py
+++ b/tempest/api/object_storage/test_object_slo.py
@@ -12,10 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
-import hashlib
-
from oslo_serialization import jsonutils as json
+from oslo_utils.secretutils import md5
from tempest.api.object_storage import base
from tempest.common import utils
from tempest.lib.common.utils import data_utils
@@ -70,10 +69,12 @@
path_object_2 = '/%s/%s' % (self.container_name,
object_name_base_2)
data_manifest = [{'path': path_object_1,
- 'etag': hashlib.md5(self.content).hexdigest(),
+ 'etag': md5(self.content,
+ usedforsecurity=False).hexdigest(),
'size_bytes': data_size},
{'path': path_object_2,
- 'etag': hashlib.md5(self.content).hexdigest(),
+ 'etag': md5(self.content,
+ usedforsecurity=False).hexdigest(),
'size_bytes': data_size}]
return json.dumps(data_manifest)
diff --git a/tempest/lib/common/preprov_creds.py b/tempest/lib/common/preprov_creds.py
index 313d3eb..6c57566 100644
--- a/tempest/lib/common/preprov_creds.py
+++ b/tempest/lib/common/preprov_creds.py
@@ -12,11 +12,11 @@
# License for the specific language governing permissions and limitations
# under the License.
-import hashlib
import os
from oslo_concurrency import lockutils
from oslo_log import log as logging
+from oslo_utils.secretutils import md5
import yaml
from tempest.lib import auth
@@ -134,7 +134,7 @@
scope = 'domain'
elif 'system' in account:
scope = 'system'
- temp_hash = hashlib.md5()
+ temp_hash = md5(usedforsecurity=False)
account_for_hash = dict((k, v) for (k, v) in account.items()
if k in cls.HASH_CRED_FIELDS)
temp_hash.update(str(account_for_hash).encode('utf-8'))
diff --git a/tempest/tests/lib/common/test_preprov_creds.py b/tempest/tests/lib/common/test_preprov_creds.py
index 499b6fe..fe7fcd2 100644
--- a/tempest/tests/lib/common/test_preprov_creds.py
+++ b/tempest/tests/lib/common/test_preprov_creds.py
@@ -12,7 +12,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import hashlib
import os
import shutil
from unittest import mock
@@ -22,6 +21,7 @@
import fixtures
from oslo_concurrency.fixture import lockutils as lockutils_fixtures
from oslo_config import cfg
+from oslo_utils.secretutils import md5
from tempest import config
from tempest.lib import auth
@@ -105,7 +105,7 @@
hash_fields = (
preprov_creds.PreProvisionedCredentialProvider.HASH_CRED_FIELDS)
for account in accounts_list:
- hash = hashlib.md5()
+ hash = md5(usedforsecurity=False)
account_for_hash = dict((k, v) for (k, v) in account.items()
if k in hash_fields)
hash.update(str(account_for_hash).encode('utf-8'))