diff --git a/src/confcom/azext_confcom/os_util.py b/src/confcom/azext_confcom/os_util.py index 6cd8156b1d9..e718b5d0aa0 100644 --- a/src/confcom/azext_confcom/os_util.py +++ b/src/confcom/azext_confcom/os_util.py @@ -95,7 +95,7 @@ def load_tar_mapping_from_file(path: str) -> dict: return raw_json -def map_image_from_tar(image_name: str, tar: TarFile, tar_location: str): +def map_image_from_tar_backwards_compatibility(image_name: str, tar: TarFile, tar_location: str): tar_dir = os.path.dirname(tar_location) # grab all files in the folder and only take the one that's named with hex values and a json extension members = tar.getmembers() @@ -139,3 +139,41 @@ def map_image_from_tar(image_name: str, tar: TarFile, tar_location: str): image_info["Architecture"] = image_info_raw.get("architecture") return image_info + + +def map_image_from_tar(image_name: str, tar: TarFile, tar_location: str): + tar_dir = os.path.dirname(tar_location) + info_file = None + info_file_name = "manifest.json" + # if there's more than one image in the tarball, we need to do some more logic + if len(info_file_name) > 0: + # extract just the manifest file and see if any of the RepoTags match the image_name we're searching for + # the manifest.json should have a list of all the image tags + # and what json files they map to to get env vars, startup cmd, etc. + tar.extract(info_file_name, path=tar_dir) + manifest_path = os.path.join(tar_dir, info_file_name) + manifest = load_json_from_file(manifest_path) + # if we match a RepoTag to the image, stop searching + for image in manifest: + if image_name in image.get("RepoTags"): + info_file = image.get("Config") + break + # remove the extracted manifest file to clean up + os.remove(manifest_path) + else: + eprint(f"Tarball at {tar_location} contains no images") + + if not info_file: + return None + tar.extract(info_file, path=tar_dir) + + # get the path of the json file and read it in + image_info_file_path = os.path.join(tar_dir, info_file) + image_info_raw = load_json_from_file(image_info_file_path) + # delete the extracted json file to clean up + os.remove(image_info_file_path) + image_info = image_info_raw.get("config") + # importing the constant from config.py gives a circular dependency error + image_info["Architecture"] = image_info_raw.get("architecture") + + return image_info diff --git a/src/confcom/azext_confcom/security_policy.py b/src/confcom/azext_confcom/security_policy.py index cddc64b7f1e..da6981f4d6c 100644 --- a/src/confcom/azext_confcom/security_policy.py +++ b/src/confcom/azext_confcom/security_policy.py @@ -412,7 +412,7 @@ def populate_policy_content_for_all_images( image.set_command(command) # merge envs for user container image - envs = image_info.get("Env") + envs = image_info.get("Env") or [] env_names = [ env_var[ config.POLICY_FIELD_CONTAINERS_ELEMENTS_ENVS_RULE diff --git a/src/confcom/azext_confcom/template_util.py b/src/confcom/azext_confcom/template_util.py index 723d18ef148..e2c0cdd4c23 100644 --- a/src/confcom/azext_confcom/template_util.py +++ b/src/confcom/azext_confcom/template_util.py @@ -81,9 +81,14 @@ def get_image_info(progress, message_queue, tar_mapping, image): if tar_location: with tarfile.open(tar_location) as tar: # get all the info out of the tarfile - image_info = os_util.map_image_from_tar( - image_name, tar, tar_location - ) + try: + image_info = os_util.map_image_from_tar_backwards_compatibility( + image_name, tar, tar_location + ) + except IndexError: + image_info = os_util.map_image_from_tar( + image_name, tar, tar_location + ) if image_info is not None: tar = True message_queue.append(f"{image_name} read from local tar file") diff --git a/src/confcom/azext_confcom/tests/latest/test_confcom_scenario.py b/src/confcom/azext_confcom/tests/latest/test_confcom_scenario.py index 6d0953f623e..af72dee9bd7 100644 --- a/src/confcom/azext_confcom/tests/latest/test_confcom_scenario.py +++ b/src/confcom/azext_confcom/tests/latest/test_confcom_scenario.py @@ -635,7 +635,7 @@ def test_docker_pull(self): self.assertEqual( image.id, - "sha256:e525c930fe751104ff24c356a7bcfad66ce4b92797780eb38dc2ff95d7a66fdc", + "sha256:d49a5025be10344cce77d178103a225cb5d7316861e5d8f106e7ff278ae51b62", ) def test_infrastructure_svn(self):