Patch extraction and validation enhancements

This commit updates patch extraction process to read and untar
specific files. Additionally, it updates the process used to
extract sw_version from deeply nested tar archives of a patch
file.

Test Plan:
[PASS] Ran below command in DC env that invokes this code path
sw-patch --os-region-name SystemController upload <patch>.patch
[PASS] Uploaded an in-service and RR patch

Story: 2010993
Task: 49289
Change-Id: I7ada7b55f458c50ed3bf51e66841cc49592f2f71
Signed-off-by: Jessica Castelino <jessica.castelino@windriver.com>
This commit is contained in:
Jessica Castelino 2023-12-15 22:02:17 +00:00
parent 8aed4785a3
commit 00575b6dc2
4 changed files with 41 additions and 28 deletions

View File

@ -202,8 +202,7 @@ def parse_pkgver(pkgver):
def get_release_from_patch(patchfile):
rel = ""
try:
cmd = "tar xf %s -O metadata.tar | tar x -O" % patchfile
metadata_str = subprocess.check_output(cmd, shell=True)
metadata_str = subprocess.check_output(['tar', '--to-command=tar -xO', '-xf', patchfile, 'metadata.tar'])
root = ElementTree.fromstring(metadata_str)
# Extract release version
rel = root.findtext('sw_version')

View File

@ -157,8 +157,7 @@ def write_xml_file(top,
def get_release_from_patch(patchfile):
rel = ""
try:
cmd = "tar xf %s -O metadata.tar | tar x -O" % patchfile
metadata_str = subprocess.check_output(cmd, shell=True)
metadata_str = subprocess.check_output(['tar', '--to-command=tar -xO', '-xf', patchfile, 'metadata.tar'])
root = ElementTree.fromstring(metadata_str)
# Extract release version
rel = root.findtext('sw_version')
@ -625,22 +624,21 @@ class PatchFile(object):
# Open the patch file and extract the contents to the current dir
tar = tarfile.open(path, "r:gz")
filelist = []
for f in tar.getmembers():
filelist.append(f.name)
if detached_signature_file not in filelist:
msg = "Patch not signed"
tar.extract("signature")
try:
tar.extract(detached_signature_file)
except KeyError:
msg = "Patch has not been signed"
LOG.warning(msg)
for f in filelist:
tar.extract(f)
# Filelist used for signature validation and verification
sig_filelist = ["metadata.tar", "software.tar"]
if "semantics.tar" in filelist:
if "semantics.tar" in [f.name for f in tar.getmembers()]:
sig_filelist.append("semantics.tar")
for f in sig_filelist:
tar.extract(f)
# Verify the data integrity signature first
sigfile = open("signature", "r")
sig = int(sigfile.read(), 16)
@ -676,6 +674,11 @@ class PatchFile(object):
LOG.error(msg)
raise ReleaseValidationFailure(msg)
# Restart script
for f in tar.getmembers():
if f.name not in sig_filelist:
tar.extract(f)
tar = tarfile.open("metadata.tar")
tar.extractall()

View File

@ -157,8 +157,7 @@ def write_xml_file(top,
def get_release_from_patch(patchfile):
rel = ""
try:
cmd = "tar xf %s -O metadata.tar | tar x -O" % patchfile
metadata_str = subprocess.check_output(cmd, shell=True)
metadata_str = subprocess.check_output(['tar', '--to-command=tar -xO', '-xf', patchfile, 'metadata.tar'])
root = ElementTree.fromstring(metadata_str)
# Extract release version
rel = root.findtext('sw_version')
@ -618,22 +617,21 @@ class PatchFile(object):
# Open the patch file and extract the contents to the current dir
tar = tarfile.open(path, "r:gz")
filelist = []
for f in tar.getmembers():
filelist.append(f.name)
if detached_signature_file not in filelist:
msg = "Patch not signed"
tar.extract("signature")
try:
tar.extract(detached_signature_file)
except KeyError:
msg = "Patch has not been signed"
LOG.warning(msg)
for f in filelist:
tar.extract(f)
# Filelist used for signature validation and verification
sig_filelist = ["metadata.tar", "software.tar"]
if "semantics.tar" in filelist:
if "semantics.tar" in [f.name for f in tar.getmembers()]:
sig_filelist.append("semantics.tar")
for f in sig_filelist:
tar.extract(f)
# Verify the data integrity signature first
sigfile = open("signature", "r")
sig = int(sigfile.read(), 16)
@ -669,6 +667,11 @@ class PatchFile(object):
LOG.error(msg)
raise PatchValidationFailure(msg)
# Restart script
for f in tar.getmembers():
if f.name not in sig_filelist:
tar.extract(f)
tar = tarfile.open("metadata.tar")
tar.extractall()

View File

@ -106,6 +106,14 @@ class FakeTar(object):
return True
class NoSignatureTar(FakeTar):
def extract(self, filename):
if filename == "signature.v2": # pylint: disable=no-else-raise
raise KeyError("Signature doesn't exist")
else:
return filename
class CgcsPatchFunctionsTestCase(testtools.TestCase):
def create_element_tree_from_dict(self, tree_root, dict_obj):
@ -208,9 +216,9 @@ class CgcsPatchFunctionsTestCase(testtools.TestCase):
_mock_log_warning,
_mock_open):
test_obj = PatchFile()
_mock_open.return_value = FakeTar(["file1"])
_mock_open.return_value = NoSignatureTar(["file1"])
self.assertRaises(PatchValidationFailure, test_obj.read_patch, "fake_path")
_mock_log_warning.assert_any_call('Patch not signed')
_mock_log_warning.assert_any_call('Patch has not been signed')
_mock_log_error.assert_any_call('Patch failed verification')
@mock.patch.object(tarfile, "open")