def download(self, session, stream=False, output=None, chunk_size=1024): """Download the data contained in an image""" # TODO(briancurtin): This method should probably offload the get # operation into another thread or something of that nature. url = utils.urljoin(self.base_path, self.id, 'file') resp = session.get(url, stream=stream) # See the following bug report for details on why the checksum # code may sometimes depend on a second GET call. # https://storyboard.openstack.org/#!/story/1619675 checksum = resp.headers.get("Content-MD5") if checksum is None: # If we don't receive the Content-MD5 header with the download, # make an additional call to get the image details and look at # the checksum attribute. details = self.fetch(session) checksum = details.checksum md5 = utils.md5(usedforsecurity=False) if output: try: if isinstance(output, io.IOBase): for chunk in resp.iter_content(chunk_size=chunk_size): output.write(chunk) md5.update(chunk) else: with open(output, 'wb') as fd: for chunk in resp.iter_content( chunk_size=chunk_size): fd.write(chunk) md5.update(chunk) _verify_checksum(md5, checksum) return resp except Exception as e: raise exceptions.SDKException( "Unable to download image: %s" % e) # if we are returning the repsonse object, ensure that it # has the content-md5 header so that the caller doesn't # need to jump through the same hoops through which we # just jumped. if stream: resp.headers['content-md5'] = checksum return resp if checksum is not None: _verify_checksum(utils.md5(resp.content, usedforsecurity=False), checksum) else: session.log.warning( "Unable to verify the integrity of image %s", (self.id)) return resp
def test_md5_without_data(self): if not self.fips_enabled: test_md5 = utils.md5() test_md5.update(self.md5_test_data) digest = test_md5.hexdigest() self.assertEqual(digest, self.md5_digest) else: self.assertRaises(ValueError, utils.md5) if not self.fips_enabled: test_md5 = utils.md5(usedforsecurity=True) test_md5.update(self.md5_test_data) digest = test_md5.hexdigest() self.assertEqual(digest, self.md5_digest) else: self.assertRaises(ValueError, utils.md5, usedforsecurity=True) test_md5 = utils.md5(usedforsecurity=False) test_md5.update(self.md5_test_data) digest = test_md5.hexdigest() self.assertEqual(digest, self.md5_digest)
def test_md5_with_data(self): if not self.fips_enabled: digest = utils.md5(self.md5_test_data).hexdigest() self.assertEqual(digest, self.md5_digest) else: # on a FIPS enabled system, this throws a ValueError: # [digital envelope routines: EVP_DigestInit_ex] disabled for FIPS self.assertRaises(ValueError, utils.md5, self.md5_test_data) if not self.fips_enabled: digest = utils.md5(self.md5_test_data, usedforsecurity=True).hexdigest() self.assertEqual(digest, self.md5_digest) else: self.assertRaises( ValueError, utils.md5, self.md5_test_data, usedforsecurity=True) digest = utils.md5(self.md5_test_data, usedforsecurity=False).hexdigest() self.assertEqual(digest, self.md5_digest)
def _calculate_data_hashes(self, data): md5 = utils.md5(usedforsecurity=False) sha256 = hashlib.sha256() if hasattr(data, 'read'): for chunk in iter(lambda: data.read(8192), b''): md5.update(chunk) sha256.update(chunk) else: md5.update(data) sha256.update(data) return (md5.hexdigest(), sha256.hexdigest())
def make_fake_image(image_id=None, md5=NO_MD5, sha256=NO_SHA256, status='active', image_name=u'fake_image', data=None, checksum=u'ee36e35a297980dee1b514de9803ec6d'): if data: md5 = utils.md5(usedforsecurity=False) sha256 = hashlib.sha256() with open(data, 'rb') as file_obj: for chunk in iter(lambda: file_obj.read(8192), b''): md5.update(chunk) sha256.update(chunk) md5 = md5.hexdigest() sha256 = sha256.hexdigest() return { u'image_state': u'available', u'container_format': u'bare', u'min_ram': 0, u'ramdisk_id': 'fake_ramdisk_id', u'updated_at': u'2016-02-10T05:05:02Z', u'file': '/v2/images/' + image_id + '/file', u'size': 3402170368, u'image_type': u'snapshot', u'disk_format': u'qcow2', u'id': image_id, u'schema': u'/v2/schemas/image', u'status': status, u'tags': [], u'visibility': u'private', u'locations': [{ u'url': u'http://127.0.0.1/images/' + image_id, u'metadata': {} }], u'min_disk': 40, u'virtual_size': None, u'name': image_name, u'checksum': md5 or checksum, u'created_at': u'2016-02-10T05:03:11Z', u'owner_specified.openstack.md5': md5 or NO_MD5, u'owner_specified.openstack.sha256': sha256 or NO_SHA256, u'owner_specified.openstack.object': 'images/{name}'.format(name=image_name), u'protected': False }
def calculate_md5_checksum(data): checksum = utils.md5(usedforsecurity=False) for chunk in data: checksum.update(chunk) return checksum.hexdigest()