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.

It looks like the usage of md5() here is solely to determine a checksum
of an image.

With this patch and the dependent patch for glance_store, all the
unit and functional tests pass on a FIPS enabled system.

Depends-On: https://review.opendev.org/#/c/756157
Depends-On: https://review.opendev.org/#/c/760160
Change-Id: I3b6d78d9792d4655bf0f4989cf82aced3f27491b
This commit is contained in:
Ade Lee 2020-10-01 15:50:18 -04:00
parent c0e54c0aa0
commit 8027d90710
5 changed files with 39 additions and 23 deletions

View File

@ -17,13 +17,12 @@
LRU Cache for Image Data
"""
import hashlib
from oslo_config import cfg
from oslo_log import log as logging
from oslo_utils import encodeutils
from oslo_utils import excutils
from oslo_utils import importutils
from oslo_utils.secretutils import md5
from oslo_utils import units
from glance.common import exception
@ -347,7 +346,7 @@ class ImageCache(object):
def cache_tee_iter(self, image_id, image_iter, image_checksum):
try:
current_checksum = hashlib.md5()
current_checksum = md5(usedforsecurity=False)
with self.driver.open_for_write(image_id) as cache_file:
for chunk in image_iter:

View File

@ -21,6 +21,7 @@ import time
import uuid
from oslo_serialization import jsonutils
from oslo_utils.secretutils import md5
from oslo_utils import units
import requests
import six
@ -206,7 +207,8 @@ class TestImages(functional.FunctionalTest):
status='active',
max_sec=10,
delay_sec=0.2)
expect_c = six.text_type(hashlib.md5(image_data).hexdigest())
expect_c = six.text_type(md5(image_data,
usedforsecurity=False).hexdigest())
expect_h = six.text_type(hashlib.sha512(image_data).hexdigest())
func_utils.verify_image_hashes_and_status(self,
image_id,
@ -349,7 +351,8 @@ class TestImages(functional.FunctionalTest):
delay_sec=0.2,
start_delay_sec=1)
with requests.get(image_data_uri) as r:
expect_c = six.text_type(hashlib.md5(r.content).hexdigest())
expect_c = six.text_type(md5(r.content,
usedforsecurity=False).hexdigest())
expect_h = six.text_type(hashlib.sha512(r.content).hexdigest())
func_utils.verify_image_hashes_and_status(self,
image_id,
@ -726,7 +729,8 @@ class TestImages(functional.FunctionalTest):
response = requests.put(path, headers=headers, data=image_data)
self.assertEqual(http.NO_CONTENT, response.status_code)
expect_c = six.text_type(hashlib.md5(image_data).hexdigest())
expect_c = six.text_type(md5(image_data,
usedforsecurity=False).hexdigest())
expect_h = six.text_type(hashlib.sha512(image_data).hexdigest())
func_utils.verify_image_hashes_and_status(self, image_id, expect_c,
expect_h, 'active')
@ -1165,7 +1169,8 @@ class TestImages(functional.FunctionalTest):
image_data = b'ZZZZZ'
response = requests.put(path, headers=headers, data=image_data)
self.assertEqual(http.NO_CONTENT, response.status_code)
expect_c = six.text_type(hashlib.md5(image_data).hexdigest())
expect_c = six.text_type(md5(image_data,
usedforsecurity=False).hexdigest())
expect_h = six.text_type(hashlib.sha512(image_data).hexdigest())
func_utils.verify_image_hashes_and_status(self,
image_id,
@ -1178,7 +1183,8 @@ class TestImages(functional.FunctionalTest):
image_data = b'WWWWW'
response = requests.put(path, headers=headers, data=image_data)
self.assertEqual(http.NO_CONTENT, response.status_code)
expect_c = six.text_type(hashlib.md5(image_data).hexdigest())
expect_c = six.text_type(md5(image_data,
usedforsecurity=False).hexdigest())
expect_h = six.text_type(hashlib.sha512(image_data).hexdigest())
func_utils.verify_image_hashes_and_status(self,
image2_id,
@ -4621,7 +4627,8 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest):
status='active',
max_sec=15,
delay_sec=0.2)
expect_c = six.text_type(hashlib.md5(image_data).hexdigest())
expect_c = six.text_type(md5(image_data,
usedforsecurity=False).hexdigest())
expect_h = six.text_type(hashlib.sha512(image_data).hexdigest())
func_utils.verify_image_hashes_and_status(self,
image_id,
@ -4784,7 +4791,8 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest):
status='active',
max_sec=15,
delay_sec=0.2)
expect_c = six.text_type(hashlib.md5(image_data).hexdigest())
expect_c = six.text_type(md5(image_data,
usedforsecurity=False).hexdigest())
expect_h = six.text_type(hashlib.sha512(image_data).hexdigest())
func_utils.verify_image_hashes_and_status(self,
image_id,
@ -4948,7 +4956,8 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest):
delay_sec=0.2,
start_delay_sec=1)
with requests.get(image_data_uri) as r:
expect_c = six.text_type(hashlib.md5(r.content).hexdigest())
expect_c = six.text_type(md5(r.content,
usedforsecurity=False).hexdigest())
expect_h = six.text_type(hashlib.sha512(r.content).hexdigest())
func_utils.verify_image_hashes_and_status(self,
image_id,
@ -5111,7 +5120,8 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest):
delay_sec=0.2,
start_delay_sec=1)
with requests.get(image_data_uri) as r:
expect_c = six.text_type(hashlib.md5(r.content).hexdigest())
expect_c = six.text_type(md5(r.content,
usedforsecurity=False).hexdigest())
expect_h = six.text_type(hashlib.sha512(r.content).hexdigest())
func_utils.verify_image_hashes_and_status(self,
image_id,
@ -5273,7 +5283,8 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest):
delay_sec=0.2,
start_delay_sec=1)
with requests.get(image_data_uri) as r:
expect_c = six.text_type(hashlib.md5(r.content).hexdigest())
expect_c = six.text_type(md5(r.content,
usedforsecurity=False).hexdigest())
expect_h = six.text_type(hashlib.sha512(r.content).hexdigest())
func_utils.verify_image_hashes_and_status(self,
image_id,
@ -5435,7 +5446,8 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest):
delay_sec=0.2,
start_delay_sec=1)
with requests.get(image_data_uri) as r:
expect_c = six.text_type(hashlib.md5(r.content).hexdigest())
expect_c = six.text_type(md5(r.content,
usedforsecurity=False).hexdigest())
expect_h = six.text_type(hashlib.sha512(r.content).hexdigest())
func_utils.verify_image_hashes_and_status(self,
image_id,
@ -5630,7 +5642,8 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest):
delay_sec=0.2,
start_delay_sec=1)
with requests.get(image_data_uri) as r:
expect_c = six.text_type(hashlib.md5(r.content).hexdigest())
expect_c = six.text_type(md5(r.content,
usedforsecurity=False).hexdigest())
expect_h = six.text_type(hashlib.sha512(r.content).hexdigest())
func_utils.verify_image_hashes_and_status(self,
image_id,
@ -5888,7 +5901,8 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest):
delay_sec=0.2,
start_delay_sec=1)
with requests.get(image_data_uri) as r:
expect_c = six.text_type(hashlib.md5(r.content).hexdigest())
expect_c = six.text_type(md5(r.content,
usedforsecurity=False).hexdigest())
expect_h = six.text_type(hashlib.sha512(r.content).hexdigest())
func_utils.verify_image_hashes_and_status(self,
image_id,
@ -6029,7 +6043,8 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest):
response = requests.put(path, headers=headers, data=image_data)
self.assertEqual(http.NO_CONTENT, response.status_code)
expect_c = six.text_type(hashlib.md5(image_data).hexdigest())
expect_c = six.text_type(md5(image_data,
usedforsecurity=False).hexdigest())
expect_h = six.text_type(hashlib.sha512(image_data).hexdigest())
func_utils.verify_image_hashes_and_status(self,
image_id,
@ -6202,7 +6217,8 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest):
response = requests.put(path, headers=headers, data=image_data)
self.assertEqual(http.NO_CONTENT, response.status_code)
expect_c = six.text_type(hashlib.md5(image_data).hexdigest())
expect_c = six.text_type(md5(image_data,
usedforsecurity=False).hexdigest())
expect_h = six.text_type(hashlib.sha512(image_data).hexdigest())
func_utils.verify_image_hashes_and_status(self,
image_id,
@ -6738,7 +6754,8 @@ class TestCopyImagePermissions(functional.MultipleBackendFunctionalTest):
delay_sec=0.2,
start_delay_sec=1)
with requests.get(image_data_uri) as r:
expect_c = six.text_type(hashlib.md5(r.content).hexdigest())
expect_c = six.text_type(md5(r.content,
usedforsecurity=False).hexdigest())
expect_h = six.text_type(hashlib.sha512(r.content).hexdigest())
func_utils.verify_image_hashes_and_status(self,
image_id,

View File

@ -15,11 +15,11 @@
from contextlib import contextmanager
import datetime
import hashlib
import os
import time
import fixtures
from oslo_utils import secretutils
from oslo_utils import units
import six
# NOTE(jokke): simplified transition to py3, behaves like py2 xrange
@ -409,7 +409,7 @@ class ImageCacheTestCase(object):
image = b"12345678990abcdefghijklmnop"
image_id = 123
md5 = hashlib.md5()
md5 = secretutils.md5(usedforsecurity=False)
md5.update(image)
checksum = md5.hexdigest()

View File

@ -69,7 +69,7 @@ oslo.reports==1.18.0
oslo.serialization==2.25.0
oslo.service==1.41.1
oslo.upgradecheck==0.1.0
oslo.utils==3.40.2
oslo.utils==4.7.0
oslotest==3.2.0
osprofiler==1.4.0
Paste==2.0.2

View File

@ -19,7 +19,7 @@ oslo.config>=5.2.0 # Apache-2.0
oslo.concurrency>=3.26.0 # Apache-2.0
oslo.context>=2.22.0 # Apache-2.0
oslo.upgradecheck>=0.1.0 # Apache-2.0
oslo.utils>=3.40.2 # Apache-2.0
oslo.utils>=4.7.0 # Apache-2.0
stevedore!=3.0.0,>=1.20.0 # Apache-2.0
futurist>=1.2.0 # Apache-2.0
taskflow>=4.0.0 # Apache-2.0