Repository: vmware/tern
Pull request #533 (2020-02-11 13:33:06)

__main__.py: Check docker image string
This PR tests that the docker image string provided to tern is of image:tag or image@digest_type:digest format

Closes https://github.com/vmware/tern/issues/519

Signed-off-by: PrajwalM2212 <prajwalmmath@gmail.com>

PrajwalM2212: The regex used here is meant to confirm `image@digest_type:digest` and `image:tag` format. 
nishakm: > The regex used here is meant to confirm `image@digest_type:digest` and `image:tag` format. It is not for ascertaining whether the image string is according the image naming guidelines.

There are no real naming guidelines currently. However, we may have to add a detection for transport (`docker:// vs oci://`), but we can worry about that later.
nishakm: Looks good. Merging. Thanks a lot @PrajwalM2212!

Patch:
diff --git a/tern/__main__.py b/tern/__main__.py
index 7c6b87c..666a208 100755
--- a/tern/__main__.py
+++ b/tern/__main__.py
@@ -23,6 +23,8 @@ from tern.report import errors
 
 
 # global logger
+from tern.utils.general import check_image_string
+
 logger = logging.getLogger(constants.logger_name)
 logger.setLevel(logging.DEBUG)
 
@@ -86,6 +88,14 @@ def do_main(args):
         if args.dockerfile:
             run.execute_dockerfile(args)
         if args.docker_image:
+            # Check if the image is of image:tag
+            # or image@digest_type:digest format
+            if not check_image_string(args.docker_image):
+                sys.stderr.write('Error running Tern\n'
+                                 'Please provide docker image '
+                                 'string in image:tag or '
+                                 'image@digest_type:digest format\n')
+                sys.exit(1)
             if general.check_tar(args.docker_image):
                 logger.error("%s", errors.incorrect_raw_option)
             else:
diff --git a/tern/utils/general.py b/tern/utils/general.py
index 21d4b2c..e5d86dd 100644
--- a/tern/utils/general.py
+++ b/tern/utils/general.py
@@ -140,3 +140,11 @@ def check_root():
     if os.getuid() == 0:
         return True
     return False
+
+
+def check_image_string(image_str: str):
+    tag_format = r'.+:.+'
+    digest_format = r'.+@.+:.+'
+    if re.match(tag_format, image_str) or re.match(digest_format, image_str):
+        return True
+    return False


Test patch:
diff --git a/tests/test_util_general.py b/tests/test_util_general.py
new file mode 100644
index 0000000..8dc9c80
--- /dev/null
+++ b/tests/test_util_general.py
@@ -0,0 +1,27 @@
+import unittest
+from tern.utils.general import check_image_string
+
+
+class TestUtilGeneral(unittest.TestCase):
+
+    def testImageString(self):
+        correct_strings = [
+            'image@digest_type:digest',
+            'image:tag',
+            'debian:buster',
+            'golang:1.12-alpine',
+            'p12/test@sha256:737aaa0caf3b8f64baa41ebf78c6cd0c43f34fadccc1275a32b8ab5d5b75c344'
+        ]
+
+        incorrect_strings = [
+            'debian',
+            'image',
+            'debian@sha',
+            'test/v1.56'
+        ]
+
+        for image_str in correct_strings:
+            self.assertTrue(check_image_string(image_str))
+
+        for image_str in incorrect_strings:
+            self.assertFalse(check_image_string(image_str))