Repository: redhat-openshift-ecosystem/openshift-preflight
Pull request #176 (2021-08-20 23:16:21)

Implement initial crane policies into cmd chain and migrate to that as the primary path of execution
This is a bit of a hefty PR. My apologies.

This PR defines two initial checks using the new Crane-based CheckEngine. This further enables the execution of preflight on MacOS without the need for a remote podman service[1]  🎉 Woohoo! 🎉  

- The implemented operator check is RelatedImagesAreSchemaVersion2
- The "implemented" container check is HasLicense (this is "implemented", because it's actually just staged to accept the changes made by @bcrochet in #171)

In this work, I needed to
- adjust the definition of a Check so that it used the new certification.ImageReference, which contains a bit more contextual data for the new approach to utilize per-check, such as filesystem mounts, and image metadata such as layers
- updated all the previous checks to use the signature, and then added a small migration function in the shell check engine to accommodate the new signature without breaking everything
- shifted our engine.NewForConfig ==> engine.NewShellEngineForConfig, and moved the policy naming around so that we could keep both sets of policies simultaneously while we finish the migration to crane.
- Moved the commandline invocation using the old engine to `preflight check container-old` and `preflight check operator-old` should we need them.

Happy to add more detail or demo as needed. I'm sure I'll think of more detail/clarity I can add on Monday.

Signed-off-by: Jose R. Gonzalez <josegonzalez89@gmail.com>


[1]
```
18:07:19 ~/.go/src/github.com/redhat-openshift-ecosystem/openshift-preflight ≪ branch=feature/initial-crane-policy-impl ≫
$ PFLT_LOGLEVEL=trace KUBECONFIG=foo ./preflight check operator quay.io/komish/preflight-test-bundle-passes:latest
time="2021-08-20T18:07:26-05:00" level=info msg="config file not found, proceeding without it"
time="2021-08-20T18:07:26-05:00" level=info msg="target image: quay.io/komish/preflight-test-bundle-passes:latest"
time="2021-08-20T18:07:26-05:00" level=info msg="no authentication context derived from execution configuration"
time="2021-08-20T18:07:26-05:00" level=info msg="pulling image from target registry"
time="2021-08-20T18:07:27-05:00" level=debug msg="temporary directory is/var/folders/cn/r49cg2wx5z97qwq_s48f4vm80000gn/T/preflight-453238028"
time="2021-08-20T18:07:27-05:00" level=debug msg="exporting and flattening image"
time="2021-08-20T18:07:27-05:00" level=debug msg="extracting container filesystem to/var/folders/cn/r49cg2wx5z97qwq_s48f4vm80000gn/T/preflight-453238028/fs"
time="2021-08-20T18:07:27-05:00" level=debug msg="writing container filesystem to output dir/var/folders/cn/r49cg2wx5z97qwq_s48f4vm80000gn/T/preflight-453238028/fs"
time="2021-08-20T18:07:28-05:00" level=info msg="executing checks"
time="2021-08-20T18:07:28-05:00" level=info msg="running check: RelatedImagesAreSchemaVersion2"
time="2021-08-20T18:07:28-05:00" level=info msg="check completed: RelatedImagesAreSchemaVersion2" result=PASSED
{
    "image": "quay.io/komish/preflight-test-bundle-passes:latest",
    "passed": true,
    "test_library": {
        "name": "github.com/redhat-openshift-ecosystem/openshift-preflight",
        "version": "0.0.0",
        "commit": "af50e97102a32abadafd5f37f76f47497b4e4ace"
    },
    "results": {
        "passed": [
            {
                "name": "RelatedImagesAreSchemaVersion2",
                "elapsed_time": 10,
                "description": "An operator bundle's relatedImages must be accessible at image manifest schema version 2"
            }
        ],
        "failed": [],
        "errors": []
    }
}
```


Patch:
diff --git a/certification/certification.go b/certification/certification.go
index 1c60bc6..1ecd19a 100644
--- a/certification/certification.go
+++ b/certification/certification.go
@@ -1,11 +1,15 @@
 package certification
 
+import (
+	v1 "github.com/google/go-containerregistry/pkg/v1"
+)
+
 // Check as an interface containing all methods necessary
 // to use and identify a given check.
 type Check interface {
 	// Validate will test the provided image and determine whether the
 	// image complies with the check's requirements.
-	Validate(image string) (result bool, err error)
+	Validate(imageReference ImageReference) (result bool, err error)
 	// Name returns the name of the check.
 	Name() string
 	// Metadata returns the check's metadata.
@@ -39,3 +43,9 @@ type HelpText struct {
 	// change in order to pass a check.
 	Suggestion string `json:"suggestion" xml:"suggestion"`
 }
+
+type ImageReference struct {
+	ImageURI    string
+	ImageFSPath string
+	ImageInfo   *v1.Image
+}
diff --git a/certification/engine/engine.go b/certification/engine/engine.go
index de4ff0b..c6b542a 100644
--- a/certification/engine/engine.go
+++ b/certification/engine/engine.go
@@ -6,6 +6,9 @@ import (
 
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/errors"
+	internal "github.com/redhat-openshift-ecosystem/openshift-preflight/certification/internal/engine"
+	containerpol "github.com/redhat-openshift-ecosystem/openshift-preflight/certification/internal/policy/container"
+	operatorpol "github.com/redhat-openshift-ecosystem/openshift-preflight/certification/internal/policy/operator"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/internal/shell"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/runtime"
 )
@@ -28,6 +31,34 @@ func NewForConfig(config runtime.Config) (CheckEngine, error) {
 		return nil, errors.ErrNoChecksEnabled
 	}
 
+	checks := make([]certification.Check, len(config.EnabledChecks))
+	for i, checkString := range config.EnabledChecks {
+		check := queryNewChecks(checkString)
+		if check == nil {
+			err := fmt.Errorf("%w: %s",
+				errors.ErrRequestedCheckNotFound,
+				checkString)
+			return nil, err
+		}
+
+		checks[i] = check
+	}
+
+	engine := &internal.CraneEngine{
+		Image:    config.Image,
+		Checks:   checks,
+		IsBundle: config.Bundle,
+	}
+
+	return engine, nil
+}
+
+func NewShellEngineForConfig(config runtime.Config) (CheckEngine, error) {
+	if len(config.EnabledChecks) == 0 {
+		// refuse to run if the user has not specified any checks
+		return nil, errors.ErrNoChecksEnabled
+	}
+
 	checks := make([]certification.Check, len(config.EnabledChecks))
 	for i, checkString := range config.EnabledChecks {
 		check := queryChecks(checkString)
@@ -60,13 +91,14 @@ func NewForConfig(config runtime.Config) (CheckEngine, error) {
 // if found; nil otherwise
 func queryChecks(checkName string) certification.Check {
 	// query Operator checks
-	if check, exists := operatorPolicy[checkName]; exists {
+	if check, exists := oldOperatorPolicy[checkName]; exists {
 		return check
 	}
 	// if not found in Operator Policy, query container policy
-	if check, exists := containerPolicy[checkName]; exists {
+	if check, exists := oldContainerPolicy[checkName]; exists {
 		return check
 	}
+
 	// Lastly, look at the mounted checks
 	if check, exists := unshareChecks[checkName]; exists {
 		return check
@@ -75,12 +107,27 @@ func queryChecks(checkName string) certification.Check {
 	return nil
 }
 
+// queryNewChecks queries Operator and Container checks by name, and return certification.Check
+// if found; nil otherwise. This will be collapsed when old checks are all deprecated.
+func queryNewChecks(checkName string) certification.Check {
+	// query Operator checks
+	if check, exists := operatorPolicy[checkName]; exists {
+		return check
+	}
+	// if not found in Operator Policy, query container policy
+	if check, exists := containerPolicy[checkName]; exists {
+		return check
+	}
+
+	return nil
+}
+
 // Register all checks
 var runAsNonRootCheck certification.Check = &shell.RunAsNonRootCheck{}
 var underLayerMaxCheck certification.Check = &shell.UnderLayerMaxCheck{}
 var hasRequiredLabelCheck certification.Check = &shell.HasRequiredLabelsCheck{}
 var basedOnUbiCheck certification.Check = &shell.BaseOnUBICheck{}
-var hasLicenseCheck certification.Check = &shell.HasLicenseCheck{}
+var deprecatedHasLicenseCheck certification.Check = &shell.HasLicenseCheck{}
 var hasMinimalVulnerabilitiesCheck certification.Check = &shell.HasMinimalVulnerabilitiesCheck{}
 var hasUniqueTagCheck certification.Check = &shell.HasUniqueTagCheck{}
 var hasNoProhibitedCheck certification.Check = &shell.HasNoProhibitedPackagesCheck{}
@@ -88,31 +135,43 @@ var validateOperatorBundle certification.Check = &shell.ValidateOperatorBundleCh
 var scorecardBasicSpecCheck certification.Check = &shell.ScorecardBasicSpecCheck{}
 var scorecardOlmSuiteCheck certification.Check = &shell.ScorecardOlmSuiteCheck{}
 var hasNoProhibitedMountedCheck certification.Check = &shell.HasNoProhibitedPackagesMountedCheck{}
-var relatedImageManifestSchemaVersionCheck certification.Check = &shell.RelatedImagesAreSchemaVersion2Check{}
+var deprecatedRelatedImageManifestSchemaVersionCheck certification.Check = &shell.RelatedImagesAreSchemaVersion2Check{}
 var operatorPkgNameIsUniqueMountedCheck certification.Check = &shell.OperatorPkgNameIsUniqueMountedCheck{}
 var operatorPkgNameIsUniqueCheck certification.Check = &shell.OperatorPkgNameIsUniqueCheck{}
 var hasMinimalVulnerabilitiesUnshareCheck certification.Check = &shell.HasMinimalVulnerabilitiesUnshareCheck{}
 
+// new checks for CraneEngine
+var hasLicenseCheck certification.Check = &containerpol.HasLicenseCheck{}
+var relatedImageManifestSchemaVersionCheck certification.Check = &operatorpol.RelatedImagesAreSchemaVersion2Check{}
+
+var operatorPolicy = map[string]certification.Check{
+	relatedImageManifestSchemaVersionCheck.Name(): relatedImageManifestSchemaVersionCheck,
+}
+
 var containerPolicy = map[string]certification.Check{
+	hasLicenseCheck.Name(): hasLicenseCheck,
+}
+
+var oldContainerPolicy = map[string]certification.Check{
 	runAsNonRootCheck.Name():              runAsNonRootCheck,
 	underLayerMaxCheck.Name():             underLayerMaxCheck,
 	hasRequiredLabelCheck.Name():          hasRequiredLabelCheck,
 	basedOnUbiCheck.Name():                basedOnUbiCheck,
-	hasLicenseCheck.Name():                hasLicenseCheck,
+	deprecatedHasLicenseCheck.Name():      deprecatedHasLicenseCheck,
 	hasMinimalVulnerabilitiesCheck.Name(): hasMinimalVulnerabilitiesCheck,
 	hasUniqueTagCheck.Name():              hasUniqueTagCheck,
 	hasNoProhibitedCheck.Name():           hasNoProhibitedCheck,
 }
 
-var operatorPolicy = map[string]certification.Check{
-	validateOperatorBundle.Name():                 validateOperatorBundle,
-	scorecardBasicSpecCheck.Name():                scorecardBasicSpecCheck,
-	scorecardOlmSuiteCheck.Name():                 scorecardOlmSuiteCheck,
-	relatedImageManifestSchemaVersionCheck.Name(): relatedImageManifestSchemaVersionCheck,
-	validateOperatorBundle.Name():                 validateOperatorBundle,
-	scorecardBasicSpecCheck.Name():                scorecardBasicSpecCheck,
-	scorecardOlmSuiteCheck.Name():                 scorecardOlmSuiteCheck,
-	operatorPkgNameIsUniqueCheck.Name():           operatorPkgNameIsUniqueCheck,
+var oldOperatorPolicy = map[string]certification.Check{
+	validateOperatorBundle.Name():                           validateOperatorBundle,
+	scorecardBasicSpecCheck.Name():                          scorecardBasicSpecCheck,
+	scorecardOlmSuiteCheck.Name():                           scorecardOlmSuiteCheck,
+	deprecatedRelatedImageManifestSchemaVersionCheck.Name(): deprecatedRelatedImageManifestSchemaVersionCheck,
+	validateOperatorBundle.Name():                           validateOperatorBundle,
+	scorecardBasicSpecCheck.Name():                          scorecardBasicSpecCheck,
+	scorecardOlmSuiteCheck.Name():                           scorecardOlmSuiteCheck,
+	operatorPkgNameIsUniqueCheck.Name():                     operatorPkgNameIsUniqueCheck,
 }
 
 var unshareChecks = map[string]certification.Check{
@@ -133,6 +192,14 @@ func makeCheckList(checkMap map[string]certification.Check) []string {
 	return checks
 }
 
+func OldOperatorPolicy() []string {
+	return makeCheckList(oldOperatorPolicy)
+}
+
+func OldContainerPolicy() []string {
+	return makeCheckList(oldContainerPolicy)
+}
+
 func OperatorPolicy() []string {
 	return makeCheckList(operatorPolicy)
 }
diff --git a/certification/generic_check.go b/certification/generic_check.go
index 628b15d..d631abb 100644
--- a/certification/generic_check.go
+++ b/certification/generic_check.go
@@ -2,7 +2,7 @@ package certification
 
 // ValidatorFunc describes a function that, when executed, will check that an
 // artifact (e.g. operator bundle) complies with a given check.
-type ValidatorFunc = func(string) (bool, error)
+type ValidatorFunc = func(ImageReference) (bool, error)
 
 type genericCheckDefinition struct {
 	name        string
@@ -15,8 +15,8 @@ func (pd *genericCheckDefinition) Name() string {
 	return pd.name
 }
 
-func (pd *genericCheckDefinition) Validate(image string) (bool, error) {
-	return pd.validatorFn(image)
+func (pd *genericCheckDefinition) Validate(imgRef ImageReference) (bool, error) {
+	return pd.validatorFn(imgRef)
 }
 
 func (pd *genericCheckDefinition) Metadata() Metadata {
diff --git a/certification/internal/engine/engine.go b/certification/internal/engine/engine.go
index a11087e..a835097 100644
--- a/certification/internal/engine/engine.go
+++ b/certification/internal/engine/engine.go
@@ -32,7 +32,7 @@ type CraneEngine struct {
 	// IsBundle is an indicator that the asset is a bundle.
 	IsBundle bool
 
-	imageRef ImageReference
+	imageRef certification.ImageReference
 	results  runtime.Results
 }
 
@@ -99,7 +99,7 @@ func (c *CraneEngine) ExecuteChecks() error {
 
 	// store the image internals in the engine image reference to pass to validations.
 	// TODO: pass this to validations when the new check interface includes it.
-	c.imageRef = ImageReference{
+	c.imageRef = certification.ImageReference{
 		ImageURI:    c.Image,
 		ImageFSPath: containerFSPath,
 		ImageInfo:   &img,
@@ -109,13 +109,12 @@ func (c *CraneEngine) ExecuteChecks() error {
 	log.Info("executing checks")
 	for _, check := range c.Checks {
 		c.results.TestedImage = c.Image
-		targetImage := c.Image
 
 		log.Info("running check: ", check.Name())
 
 		// run the validation
 		checkStartTime := time.Now()
-		checkPassed, err := check.Validate(targetImage)
+		checkPassed, err := check.Validate(c.imageRef)
 		checkElapsedTime := time.Since(checkStartTime)
 
 		if err != nil {
diff --git a/certification/internal/engine/types.go b/certification/internal/engine/types.go
index 0e66703..74377e9 100644
--- a/certification/internal/engine/types.go
+++ b/certification/internal/engine/types.go
@@ -1,15 +1,5 @@
 package engine
 
-import (
-	v1 "github.com/google/go-containerregistry/pkg/v1"
-)
-
-type ImageReference struct {
-	ImageURI    string
-	ImageFSPath string
-	ImageInfo   *v1.Image
-}
-
 type RegistryCredentials struct {
 	Username string
 	Password string
diff --git a/certification/internal/policy/container/has_license.go b/certification/internal/policy/container/has_license.go
new file mode 100644
index 0000000..124f55c
--- /dev/null
+++ b/certification/internal/policy/container/has_license.go
@@ -0,0 +1,51 @@
+package container
+
+import (
+	"fmt"
+	"strings"
+
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification"
+	log "github.com/sirupsen/logrus"
+)
+
+const (
+	licensePath         = "/licenses"
+	newLine             = "\n"
+	minLicenseFileCount = 1
+	//size format string for find command, c denotes bytes
+)
+
+// HasLicenseCheck evaluates that the image contains a license definition available at
+// /licenses.
+type HasLicenseCheck struct{}
+
+func (p *HasLicenseCheck) Validate(imgRef certification.ImageReference) (bool, error) {
+	// TODO Implement
+	return false, fmt.Errorf("unimplemented in migration path to crane engine")
+}
+
+func (p *HasLicenseCheck) validate(licenseFileList string) (bool, error) {
+	licenseFileCount := strings.Count(licenseFileList, newLine)
+	log.Infof("%d Licenses found", licenseFileCount)
+	return licenseFileCount >= minLicenseFileCount, nil
+}
+
+func (p *HasLicenseCheck) Name() string {
+	return "HasLicense"
+}
+
+func (p *HasLicenseCheck) Metadata() certification.Metadata {
+	return certification.Metadata{
+		Description:      "Checking if terms and conditions applicable to the software including open source licensing information are present. The license must be at /licenses",
+		Level:            "best",
+		KnowledgeBaseURL: "https://connect.redhat.com/zones/containers/container-certification-policy-guide",
+		CheckURL:         "https://connect.redhat.com/zones/containers/container-certification-policy-guide",
+	}
+}
+
+func (p *HasLicenseCheck) Help() certification.HelpText {
+	return certification.HelpText{
+		Message:    "Check HasLicense encountered an error. Please review the preflight.log file for more information.",
+		Suggestion: "Create a directory named /licenses and include all relevant licensing and/or terms and conditions as text file(s) in that directory.",
+	}
+}
diff --git a/certification/internal/policy/operator/has_v2_related_image_schema_version.go b/certification/internal/policy/operator/has_v2_related_image_schema_version.go
new file mode 100644
index 0000000..8f42d7d
--- /dev/null
+++ b/certification/internal/policy/operator/has_v2_related_image_schema_version.go
@@ -0,0 +1,177 @@
+package operator
+
+import (
+	"encoding/json"
+	"fmt"
+	"path"
+
+	"github.com/google/go-containerregistry/pkg/crane"
+	operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/errors"
+	containerutils "github.com/redhat-openshift-ecosystem/openshift-preflight/certification/internal/utils/container"
+	log "github.com/sirupsen/logrus"
+)
+
+// RelatedImagesAreSchemaVersion2Check is part of the Operator policy and implements
+// the Check interface.
+type RelatedImagesAreSchemaVersion2Check struct{}
+
+// Validate checks the image manifest for each related image referenced in a
+// ClusterServiceVersion and ensures that the schema version used is version 2.
+func (p *RelatedImagesAreSchemaVersion2Check) Validate(imgRef certification.ImageReference) (bool, error) {
+	imageToSchemaVersion, err := p.getDataToValidate(imgRef)
+	if err != nil {
+		return false, fmt.Errorf("%w: %s", errors.ErrRunContainerFailed, err)
+	}
+
+	return p.validate(imageToSchemaVersion)
+}
+
+// getDataToValidate pulls a ClusterServiceVersion from the input operator bundle,
+// checks the ClusterServiceVersion's related images declaration, and assembles a list of
+// images and their image manifest schema version values.
+func (p *RelatedImagesAreSchemaVersion2Check) getDataToValidate(imgRef certification.ImageReference) (map[string]int, error) {
+	manifestsDir := path.Join(imgRef.ImageFSPath, "manifests")
+	csv, err := p.readBundle(manifestsDir)
+	if err != nil {
+		log.Error(err)
+		return nil, fmt.Errorf("%w: %s", errors.ErrDeterminingRelatedImageSchemaVers, err)
+	}
+
+	relatedImages, err := p.getRelatedImagesForCSV(csv)
+	if err != nil {
+		log.Error(err)
+		return nil, fmt.Errorf("%w: %s", errors.ErrDeterminingRelatedImageSchemaVers, err)
+	}
+
+	imageSchemaVersionMap, err := p.inspectSchemaVersionForImage(relatedImages)
+	if err != nil {
+		log.Error(err)
+		return nil, fmt.Errorf("%w: %s", errors.ErrDeterminingRelatedImageSchemaVers, err)
+	}
+
+	return imageSchemaVersionMap, nil
+}
+
+// readBundle will accept the manifests directory where a bundle is expected to live,
+// and walks the directory to find all bundle assets.
+func (p *RelatedImagesAreSchemaVersion2Check) readBundle(manifestsDir string) (*operatorsv1alpha1.ClusterServiceVersion, error) {
+	return containerutils.ReadBundle(manifestsDir)
+}
+
+// getRelatedImagesForCSV will return a slice of strings containing the images found in the relatedImages field of
+// the input ClusterServiceVersion.
+func (p *RelatedImagesAreSchemaVersion2Check) getRelatedImagesForCSV(csv *operatorsv1alpha1.ClusterServiceVersion) ([]string, error) {
+	relatedImages := csv.Spec.RelatedImages
+
+	// no related images == nothing to check
+	if len(relatedImages) == 0 {
+		return []string{}, nil
+	}
+
+	imageStrings := make([]string, len(relatedImages))
+	for i, relatedImage := range relatedImages {
+		imageStrings[i] = relatedImage.Image
+	}
+
+	return imageStrings, nil
+}
+
+func (p *RelatedImagesAreSchemaVersion2Check) inspectSchemaVersionForImage(images []string) (map[string]int, error) {
+	// TODO: handle cases where the related images are behind authentication.
+	imageToSchemaVersion := map[string]int{}
+	for _, image := range images {
+		manifestB, err := crane.Manifest(image)
+		if err != nil {
+			return nil, err
+		}
+
+		schemaVersion, err := p.getSchemaVersionFromRawManifest(manifestB)
+		if err != nil {
+			return nil, err
+		}
+
+		imageToSchemaVersion[image] = schemaVersion
+	}
+
+	return imageToSchemaVersion, nil
+}
+
+// getSchemaVersionFromRawManifest accepts the raw manifest blob, asserts that it is the expected format,
+// and returns the value of the top-level schemaVersion key.
+func (p *RelatedImagesAreSchemaVersion2Check) getSchemaVersionFromRawManifest(manifest []byte) (int, error) {
+	var rawManifest map[string]interface{}
+	if err := json.Unmarshal(manifest, &rawManifest); err != nil {
+		log.Error("unable to unmarshal inspected manifest")
+		return 0, err
+	}
+
+	schemaVersionIface, found := rawManifest["schemaVersion"]
+	if !found {
+		return 0, fmt.Errorf("rawManifest is an unexpected format")
+	}
+
+	// when unmarshalled by json, number will be a float64
+	schemaVersionf64, ok := schemaVersionIface.(float64)
+	if !ok {
+		return 0, fmt.Errorf("schemaVersion value is an unexpected type")
+	}
+
+	// We don't expect the schemaVersion value to be large, so converting to
+	// an int should be okay.
+	schemaVersion := int(schemaVersionf64)
+
+	return schemaVersion, nil
+}
+
+// validate checks each image's schema value and returns true if they're all version 2.
+func (p *RelatedImagesAreSchemaVersion2Check) validate(imageToSchemaVersionMap map[string]int) (bool, error) {
+
+	// if the map is empty or nil, then we auto pass this check.
+	// note that internally, len(nil) == 0 according to staticcheck
+	if len(imageToSchemaVersionMap) == 0 {
+		return true, nil
+	}
+
+	v2ImageManifests := []string{}
+	notv2ImageManifests := []string{}
+
+	for image, schemaVersion := range imageToSchemaVersionMap {
+		if schemaVersion == 2 {
+			v2ImageManifests = append(v2ImageManifests, image)
+		} else {
+			notv2ImageManifests = append(notv2ImageManifests, image)
+		}
+	}
+
+	// if we determine that all images are using schemaVersion 2, then we pass the check
+	if len(v2ImageManifests) == len(imageToSchemaVersionMap) {
+		return true, nil
+	}
+
+	log.Info("the following related images found in CSV were not image manifests with schema version 2", notv2ImageManifests)
+	return false, nil
+}
+
+func (p *RelatedImagesAreSchemaVersion2Check) Name() string {
+	return "RelatedImagesAreSchemaVersion2"
+}
+
+func (p *RelatedImagesAreSchemaVersion2Check) Metadata() certification.Metadata {
+	return certification.Metadata{
+		Description:      "An operator bundle's relatedImages must be accessible at image manifest schema version 2",
+		Level:            "best",
+		KnowledgeBaseURL: "https://connect.redhat.com/zones/containers/container-certification-policy-guide",
+		CheckURL:         "https://connect.redhat.com/zones/containers/container-certification-policy-guide",
+	}
+}
+
+func (p *RelatedImagesAreSchemaVersion2Check) Help() certification.HelpText {
+	return certification.HelpText{
+		// TODO
+		Message: "Check RelatedImagesAreSchemaVersion2 has encountered an error. Please review the preflight.log for more information.",
+		Suggestion: "Ensure that the related images listed in your ClusterServiceVersion contain images respecting schema version 2 " +
+			"as defined here: https://docs.docker.com/registry/spec/manifest-v2-2/",
+	}
+}
diff --git a/certification/internal/shell/base_on_ubi.go b/certification/internal/shell/base_on_ubi.go
index 5aacf1d..06a1ddd 100644
--- a/certification/internal/shell/base_on_ubi.go
+++ b/certification/internal/shell/base_on_ubi.go
@@ -15,8 +15,8 @@ import (
 // Name value is `Red Hat Enterprise Linux`
 type BaseOnUBICheck struct{}
 
-func (p *BaseOnUBICheck) Validate(image string) (bool, error) {
-	lines, err := p.getDataToValidate(image)
+func (p *BaseOnUBICheck) Validate(imgRef certification.ImageReference) (bool, error) {
+	lines, err := p.getDataToValidate(imgRef.ImageURI)
 	if err != nil {
 		log.Debugf("Stdout: %s", lines)
 		return false, fmt.Errorf("%w: %s", errors.ErrRunContainerFailed, err)
diff --git a/certification/internal/shell/engine.go b/certification/internal/shell/engine.go
index 2855047..79d7536 100644
--- a/certification/internal/shell/engine.go
+++ b/certification/internal/shell/engine.go
@@ -7,6 +7,7 @@ import (
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/errors"
 	containerutil "github.com/redhat-openshift-ecosystem/openshift-preflight/certification/internal/utils/container"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/internal/utils/migration"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/runtime"
 	log "github.com/sirupsen/logrus"
 )
@@ -57,7 +58,7 @@ func (e *CheckEngine) ExecuteChecks() error {
 		checkStartTime := time.Now()
 
 		// run the validation
-		checkPassed, err := check.Validate(targetImage)
+		checkPassed, err := check.Validate(migration.ImageToImageReference(targetImage))
 
 		checkElapsedTime := time.Since(checkStartTime)
 
diff --git a/certification/internal/shell/has_license.go b/certification/internal/shell/has_license.go
index 09c87f3..1bacae2 100644
--- a/certification/internal/shell/has_license.go
+++ b/certification/internal/shell/has_license.go
@@ -21,8 +21,8 @@ const (
 // /licenses.
 type HasLicenseCheck struct{}
 
-func (p *HasLicenseCheck) Validate(image string) (bool, error) {
-	licenseFileList, err := p.getDataToValidate(image)
+func (p *HasLicenseCheck) Validate(imgRef certification.ImageReference) (bool, error) {
+	licenseFileList, err := p.getDataToValidate(imgRef.ImageURI)
 	if err != nil {
 		return false, err
 	}
diff --git a/certification/internal/shell/has_minimal_vulns.go b/certification/internal/shell/has_minimal_vulns.go
index 5fde9d1..d9be98c 100644
--- a/certification/internal/shell/has_minimal_vulns.go
+++ b/certification/internal/shell/has_minimal_vulns.go
@@ -9,9 +9,9 @@ import (
 // In an Unshare environment. It does not require a mounted image.
 type HasMinimalVulnerabilitiesCheck struct{}
 
-func (p *HasMinimalVulnerabilitiesCheck) Validate(image string) (bool, error) {
+func (p *HasMinimalVulnerabilitiesCheck) Validate(imgRef certification.ImageReference) (bool, error) {
 	mounted := false
-	result, err := podmanEngine.UnshareWithCheck("HasMinimalVulnerabilitiesUnshare", image, mounted)
+	result, err := podmanEngine.UnshareWithCheck("HasMinimalVulnerabilitiesUnshare", imgRef.ImageURI, mounted)
 	if err != nil {
 		log.Trace("unable to execute preflight in the unshare env")
 		log.Debugf("Stdout: %s", result.Stdout)
diff --git a/certification/internal/shell/has_minimal_vulns_unshare.go b/certification/internal/shell/has_minimal_vulns_unshare.go
index 6962cf1..3f64826 100644
--- a/certification/internal/shell/has_minimal_vulns_unshare.go
+++ b/certification/internal/shell/has_minimal_vulns_unshare.go
@@ -15,8 +15,8 @@ import (
 // OVAL definition.
 type HasMinimalVulnerabilitiesUnshareCheck struct{}
 
-func (p *HasMinimalVulnerabilitiesUnshareCheck) Validate(image string) (bool, error) {
-	lines, err := p.scanImage(image)
+func (p *HasMinimalVulnerabilitiesUnshareCheck) Validate(imgRef certification.ImageReference) (bool, error) {
+	lines, err := p.scanImage(imgRef.ImageURI)
 	if err != nil {
 		log.Debugf("Stdout: %s", lines)
 		return false, fmt.Errorf("%w: %s", errors.ErrImageScanFailed, err)
diff --git a/certification/internal/shell/has_prohibited_packages.go b/certification/internal/shell/has_prohibited_packages.go
index e2a15f0..69fb8c3 100644
--- a/certification/internal/shell/has_prohibited_packages.go
+++ b/certification/internal/shell/has_prohibited_packages.go
@@ -9,9 +9,9 @@ import (
 // which refers to packages that are not redistributable without an appropriate license.
 type HasNoProhibitedPackagesCheck struct{}
 
-func (p *HasNoProhibitedPackagesCheck) Validate(image string) (bool, error) {
+func (p *HasNoProhibitedPackagesCheck) Validate(imgRef certification.ImageReference) (bool, error) {
 	mounted := true
-	result, err := podmanEngine.UnshareWithCheck("HasNoProhibitedPackagesMounted", image, mounted)
+	result, err := podmanEngine.UnshareWithCheck("HasNoProhibitedPackagesMounted", imgRef.ImageURI, mounted)
 	if err != nil {
 		log.Trace("unable to execute preflight in the unshare env")
 		log.Debugf("Stdout: %s", result.Stdout)
diff --git a/certification/internal/shell/has_prohibited_packages_mounted.go b/certification/internal/shell/has_prohibited_packages_mounted.go
index 501dc17..fd51bcf 100644
--- a/certification/internal/shell/has_prohibited_packages_mounted.go
+++ b/certification/internal/shell/has_prohibited_packages_mounted.go
@@ -13,8 +13,8 @@ import (
 // which refers to packages that are not redistributable without an appropriate license.
 type HasNoProhibitedPackagesMountedCheck struct{}
 
-func (p *HasNoProhibitedPackagesMountedCheck) Validate(image string) (bool, error) {
-	pkgList, err := p.getDataToValidate(image)
+func (p *HasNoProhibitedPackagesMountedCheck) Validate(imgRef certification.ImageReference) (bool, error) {
+	pkgList, err := p.getDataToValidate(imgRef.ImageURI)
 	if err != nil {
 		log.Error("unable to get a list of all packages in the image")
 		return false, err
diff --git a/certification/internal/shell/has_required_labels.go b/certification/internal/shell/has_required_labels.go
index dc9cc78..d7318c8 100644
--- a/certification/internal/shell/has_required_labels.go
+++ b/certification/internal/shell/has_required_labels.go
@@ -12,9 +12,9 @@ var requiredLabels = []string{"name", "vendor", "version", "release", "summary",
 // labels are present on the image asset as it exists in its current container registry.
 type HasRequiredLabelsCheck struct{}
 
-func (p *HasRequiredLabelsCheck) Validate(image string) (bool, error) {
+func (p *HasRequiredLabelsCheck) Validate(imgRef certification.ImageReference) (bool, error) {
 	// TODO: if we're going have the image json on disk already, we should use it here instead of podman inspect-ing.
-	labels, err := p.getDataForValidate(image)
+	labels, err := p.getDataForValidate(imgRef.ImageURI)
 	if err != nil {
 		return false, err
 	}
diff --git a/certification/internal/shell/has_unique_tag.go b/certification/internal/shell/has_unique_tag.go
index 171849b..37d608c 100644
--- a/certification/internal/shell/has_unique_tag.go
+++ b/certification/internal/shell/has_unique_tag.go
@@ -12,12 +12,12 @@ import (
 // represent the same image over time.
 type HasUniqueTagCheck struct{}
 
-func (p *HasUniqueTagCheck) Validate(image string) (bool, error) {
-	tags, err := p.getDataToValidate(image)
+func (p *HasUniqueTagCheck) Validate(imgRef certification.ImageReference) (bool, error) {
+	tags, err := p.getDataToValidate(imgRef.ImageURI)
 	if err != nil {
 		return false, err
 	}
-	return p.validate(image, tags)
+	return p.validate(imgRef.ImageURI, tags)
 }
 
 func (p *HasUniqueTagCheck) getDataToValidate(image string) ([]string, error) {
diff --git a/certification/internal/shell/has_v2_related_image_schema_version.go b/certification/internal/shell/has_v2_related_image_schema_version.go
index 9a0bbc2..77e880c 100644
--- a/certification/internal/shell/has_v2_related_image_schema_version.go
+++ b/certification/internal/shell/has_v2_related_image_schema_version.go
@@ -18,8 +18,8 @@ type RelatedImagesAreSchemaVersion2Check struct{}
 
 // Validate checks the image manifest for each related image referenced in a
 // ClusterServiceVersion and ensures that the schema version used is version 2.
-func (p *RelatedImagesAreSchemaVersion2Check) Validate(image string) (bool, error) {
-	imageToSchemaVersion, err := p.getDataToValidate(image)
+func (p *RelatedImagesAreSchemaVersion2Check) Validate(imgRef certification.ImageReference) (bool, error) {
+	imageToSchemaVersion, err := p.getDataToValidate(imgRef.ImageURI)
 	if err != nil {
 		return false, fmt.Errorf("%w: %s", errors.ErrRunContainerFailed, err)
 	}
diff --git a/certification/internal/shell/less_than_max_layers.go b/certification/internal/shell/less_than_max_layers.go
index a2a10d8..b447e39 100644
--- a/certification/internal/shell/less_than_max_layers.go
+++ b/certification/internal/shell/less_than_max_layers.go
@@ -15,9 +15,9 @@ const (
 // UnderLayerMaxCheck ensures that the image has less layers in its assembly than a predefined maximum.
 type UnderLayerMaxCheck struct{}
 
-func (p *UnderLayerMaxCheck) Validate(image string) (bool, error) {
+func (p *UnderLayerMaxCheck) Validate(imageRef certification.ImageReference) (bool, error) {
 	// TODO: if we're going have the image json on disk already, we should use it here instead of podman inspect-ing.
-	layers, err := p.getDataToValidate(image)
+	layers, err := p.getDataToValidate(imageRef.ImageURI)
 	if err != nil {
 		return false, err
 	}
diff --git a/certification/internal/shell/operator_pkg_name_uniqueness.go b/certification/internal/shell/operator_pkg_name_uniqueness.go
index e899780..c453f4d 100644
--- a/certification/internal/shell/operator_pkg_name_uniqueness.go
+++ b/certification/internal/shell/operator_pkg_name_uniqueness.go
@@ -7,9 +7,9 @@ import (
 
 type OperatorPkgNameIsUniqueCheck struct{}
 
-func (p *OperatorPkgNameIsUniqueCheck) Validate(image string) (bool, error) {
+func (p *OperatorPkgNameIsUniqueCheck) Validate(imgRef certification.ImageReference) (bool, error) {
 	mounted := true
-	result, err := podmanEngine.UnshareWithCheck("OperatorPackageNameIsUniqueMounted", image, mounted)
+	result, err := podmanEngine.UnshareWithCheck("OperatorPackageNameIsUniqueMounted", imgRef.ImageURI, mounted)
 	if err != nil {
 		log.Trace("unable to execute preflight in the unshare env")
 		log.Debugf("Stdout: %s", result.Stdout)
diff --git a/certification/internal/shell/operator_pkg_name_uniqueness_mounted.go b/certification/internal/shell/operator_pkg_name_uniqueness_mounted.go
index 60e3afa..dfce9ea 100644
--- a/certification/internal/shell/operator_pkg_name_uniqueness_mounted.go
+++ b/certification/internal/shell/operator_pkg_name_uniqueness_mounted.go
@@ -45,8 +45,8 @@ type packageData struct {
 // check.
 type OperatorPkgNameIsUniqueMountedCheck struct{}
 
-func (p *OperatorPkgNameIsUniqueMountedCheck) Validate(bundle string) (bool, error) {
-	annotations, err := p.getAnnotationsFromBundle(bundle)
+func (p *OperatorPkgNameIsUniqueMountedCheck) Validate(bundleRef certification.ImageReference) (bool, error) {
+	annotations, err := p.getAnnotationsFromBundle(bundleRef.ImageURI)
 	if err != nil {
 		log.Errorf("unable to get annotations.yaml from the bundle")
 		return false, err
diff --git a/certification/internal/shell/podman.go b/certification/internal/shell/podman.go
index 6146017..3c17947 100644
--- a/certification/internal/shell/podman.go
+++ b/certification/internal/shell/podman.go
@@ -14,7 +14,6 @@ import (
 	"time"
 
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/errors"
-	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/internal/utils/file"
 	fileutils "github.com/redhat-openshift-ecosystem/openshift-preflight/certification/internal/utils/file"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/cli"
 	log "github.com/sirupsen/logrus"
@@ -102,7 +101,7 @@ func (pe PodmanCLIEngine) ScanImage(image string) (*cli.ImageScanReport, error)
 	ovalFilePath := filepath.Join(dir, ovalFilename)
 	log.Debugf("Oval file path: %s", ovalFilePath)
 
-	err = file.DownloadFile(ovalFilePath, ovalFileUrl)
+	err = fileutils.DownloadFile(ovalFilePath, ovalFileUrl)
 	if err != nil {
 		log.Error("Unable to download Oval file", err)
 		return nil, err
@@ -111,7 +110,7 @@ func (pe PodmanCLIEngine) ScanImage(image string) (*cli.ImageScanReport, error)
 	r := regexp.MustCompile(`(?P<filename>.*).bz2`)
 	ovalFilePathDecompressed := filepath.Join(dir, r.FindStringSubmatch(ovalFilename)[1])
 
-	err = file.Unzip(ovalFilePath, ovalFilePathDecompressed)
+	err = fileutils.Unzip(ovalFilePath, ovalFilePathDecompressed)
 	if err != nil {
 		log.Error("Unable to unzip Oval file: ", err)
 		return nil, err
diff --git a/certification/internal/shell/runs_as_nonroot.go b/certification/internal/shell/runs_as_nonroot.go
index bc7b845..3ae11b6 100644
--- a/certification/internal/shell/runs_as_nonroot.go
+++ b/certification/internal/shell/runs_as_nonroot.go
@@ -13,9 +13,9 @@ import (
 // which correlates to the root user.
 type RunAsNonRootCheck struct{}
 
-func (p *RunAsNonRootCheck) Validate(image string) (bool, error) {
+func (p *RunAsNonRootCheck) Validate(imgRef certification.ImageReference) (bool, error) {
 
-	line, err := p.getDataToValidate(image)
+	line, err := p.getDataToValidate(imgRef.ImageURI)
 	if err != nil {
 		return false, err
 	}
diff --git a/certification/internal/shell/scorecard_basic_check_spec.go b/certification/internal/shell/scorecard_basic_check_spec.go
index f2a28f0..6432374 100644
--- a/certification/internal/shell/scorecard_basic_check_spec.go
+++ b/certification/internal/shell/scorecard_basic_check_spec.go
@@ -13,11 +13,11 @@ type ScorecardBasicSpecCheck struct {
 
 const scorecardBasicCheckResult string = "operator_bundle_scorecard_BasicSpecCheck.json"
 
-func (p *ScorecardBasicSpecCheck) Validate(bundleImage string) (bool, error) {
-	log.Debug("Running operator-sdk scorecard check for ", bundleImage)
+func (p *ScorecardBasicSpecCheck) Validate(bundleRef certification.ImageReference) (bool, error) {
+	log.Debug("Running operator-sdk scorecard check for ", bundleRef.ImageURI)
 	selector := []string{"test=basic-check-spec-test"}
 	log.Debugf("--selector=%s", selector)
-	scorecardReport, err := p.getDataToValidate(bundleImage, selector, scorecardBasicCheckResult)
+	scorecardReport, err := p.getDataToValidate(bundleRef.ImageURI, selector, scorecardBasicCheckResult)
 	if err != nil {
 		return false, err
 	}
diff --git a/certification/internal/shell/scorecard_olm_suite.go b/certification/internal/shell/scorecard_olm_suite.go
index e499ba6..a48442c 100644
--- a/certification/internal/shell/scorecard_olm_suite.go
+++ b/certification/internal/shell/scorecard_olm_suite.go
@@ -13,11 +13,11 @@ type ScorecardOlmSuiteCheck struct {
 
 const scorecardOlmSuiteResult string = "operator_bundle_scorecard_OlmSuiteCheck.json"
 
-func (p *ScorecardOlmSuiteCheck) Validate(bundleImage string) (bool, error) {
-	log.Debug("Running operator-sdk scorecard Check for ", bundleImage)
+func (p *ScorecardOlmSuiteCheck) Validate(bundleRef certification.ImageReference) (bool, error) {
+	log.Debug("Running operator-sdk scorecard Check for ", bundleRef.ImageURI)
 	selector := []string{"suite=olm"}
 	log.Debugf("--selector=%s", selector)
-	scorecardReport, err := p.getDataToValidate(bundleImage, selector, scorecardOlmSuiteResult)
+	scorecardReport, err := p.getDataToValidate(bundleRef.ImageURI, selector, scorecardOlmSuiteResult)
 	if err != nil {
 		return false, err
 	}
diff --git a/certification/internal/shell/shell.go b/certification/internal/shell/shell.go
index 18fa75c..5031203 100644
--- a/certification/internal/shell/shell.go
+++ b/certification/internal/shell/shell.go
@@ -3,7 +3,9 @@
 // various shell tools are installed.
 package shell
 
-import "github.com/redhat-openshift-ecosystem/openshift-preflight/cli"
+import (
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/cli"
+)
 
 // Create a package-level podmanEngine variable, that can be overridden
 // at the test level.
diff --git a/certification/internal/shell/validate_operator_bundle.go b/certification/internal/shell/validate_operator_bundle.go
index 3fdc376..bd1df76 100644
--- a/certification/internal/shell/validate_operator_bundle.go
+++ b/certification/internal/shell/validate_operator_bundle.go
@@ -11,8 +11,8 @@ import (
 type ValidateOperatorBundleCheck struct {
 }
 
-func (p ValidateOperatorBundleCheck) Validate(bundle string) (bool, error) {
-	report, err := p.getDataToValidate(bundle)
+func (p ValidateOperatorBundleCheck) Validate(bundleRef certification.ImageReference) (bool, error) {
+	report, err := p.getDataToValidate(bundleRef.ImageURI)
 	if err != nil {
 		log.Error("Error while executing operator-sdk bundle validate: ", err)
 		return false, err
diff --git a/certification/internal/utils/container/helper.go b/certification/internal/utils/container/helper.go
index ac30f7f..b711dd3 100644
--- a/certification/internal/utils/container/helper.go
+++ b/certification/internal/utils/container/helper.go
@@ -8,8 +8,12 @@ import (
 	"path/filepath"
 	"strings"
 
+	"github.com/operator-framework/api/pkg/manifests"
+	operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/errors"
 	fileutils "github.com/redhat-openshift-ecosystem/openshift-preflight/certification/internal/utils/file"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/internal/utils/migration"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/cli"
 	log "github.com/sirupsen/logrus"
 )
@@ -70,7 +74,7 @@ func SaveContainerToFilesystem(podmanEngine cli.PodmanEngine, imageLog string) (
 	return tarpath, nil
 }
 
-type ContainerFn func(string) (bool, error)
+type ContainerFn func(certification.ImageReference) (bool, error)
 
 // RunInsideImageFS executes a provided function by mounting the image filesystem
 // to the host. Note that any ContainerFn that is expected to run using this function
@@ -92,7 +96,7 @@ func RunInsideImageFS(podmanEngine cli.PodmanEngine, image string, containerFn C
 		}
 	}()
 
-	return containerFn(strings.TrimSpace(report.MountDir))
+	return containerFn(migration.ImageToImageReference(strings.TrimSpace(report.MountDir)))
 }
 
 func GenerateBundleHash(podmanEngine cli.PodmanEngine, image string) (string, error) {
@@ -115,3 +119,14 @@ func GenerateBundleHash(podmanEngine cli.PodmanEngine, image string) (string, er
 
 	return fmt.Sprintf("%x", sum), nil
 }
+
+// ReadBundle will accept the manifests directory where a bundle is expected to live,
+// and walks the directory to find all bundle assets.
+func ReadBundle(manifestsDir string) (*operatorsv1alpha1.ClusterServiceVersion, error) {
+	bundle, err := manifests.GetBundleFromDir(manifestsDir)
+	if err != nil {
+		return nil, err
+	}
+
+	return bundle.CSV, nil
+}
diff --git a/certification/internal/utils/migration/migration.go b/certification/internal/utils/migration/migration.go
new file mode 100644
index 0000000..3e87311
--- /dev/null
+++ b/certification/internal/utils/migration/migration.go
@@ -0,0 +1,10 @@
+package migration
+
+import "github.com/redhat-openshift-ecosystem/openshift-preflight/certification"
+
+// ImageToImageReference converts an image string, used in early Check.Validate
+// interface definitions and replaces it with an ImageReference used in later
+// implementations.
+func ImageToImageReference(image string) certification.ImageReference {
+	return certification.ImageReference{ImageURI: image}
+}
diff --git a/cmd/check_container.go b/cmd/check_container.go
index 7b22882..7916c1b 100644
--- a/cmd/check_container.go
+++ b/cmd/check_container.go
@@ -82,7 +82,7 @@ var checkContainerCmd = &cobra.Command{
 }
 
 func init() {
-	checks := strings.Join(engine.ContainerPolicy(), "\n- ")
+	checks := strings.Join(engine.OldContainerPolicy(), "\n- ")
 
 	usage := "\n" + `The checks that will be executed are the following:` + "\n- " +
 		checks + "\n\n" +
diff --git a/cmd/check_container_old.go b/cmd/check_container_old.go
new file mode 100644
index 0000000..919189a
--- /dev/null
+++ b/cmd/check_container_old.go
@@ -0,0 +1,98 @@
+package cmd
+
+import (
+	"fmt"
+	"io"
+	"os"
+	"strings"
+
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/engine"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/errors"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/formatters"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/runtime"
+	"github.com/spf13/cobra"
+)
+
+var oldCheckContainerCmd = &cobra.Command{
+	Use:   "container-old",
+	Short: "Run checks for a container using the previous engine",
+	Long:  `This command will run the Certification checks for a container image. `,
+	Args: func(cmd *cobra.Command, args []string) error {
+		if len(args) != 1 {
+			return fmt.Errorf("%w: A container image positional argument is required", errors.ErrInsufficientPosArguments)
+		}
+		return nil
+	},
+	RunE: func(cmd *cobra.Command, args []string) error {
+		// Expect exactly one positional arg. Check here instead of using builtin Args key
+		// so that we can get a more user-friendly error message
+
+		containerImage := args[0]
+
+		cfg := runtime.Config{
+			Image:          containerImage,
+			EnabledChecks:  engine.OldContainerPolicy(),
+			ResponseFormat: DefaultOutputFormat,
+		}
+
+		engine, err := engine.NewShellEngineForConfig(cfg)
+		if err != nil {
+			return err
+		}
+
+		formatter, err := formatters.NewForConfig(cfg)
+		if err != nil {
+			return err
+		}
+
+		// create the results file early to catch cases where we are not
+		// able to write to the filesystem before we attempt to execute checks.
+		resultsFile, err := os.OpenFile(
+			resultsFilenameWithExtension(formatter.FileExtension()),
+			os.O_WRONLY|os.O_CREATE|os.O_TRUNC,
+			0600,
+		)
+
+		if err != nil {
+			return err
+		}
+
+		// also write to stdout
+		resultsOutputTarget := io.MultiWriter(os.Stdout, resultsFile)
+
+		// execute the checks
+		if err := engine.ExecuteChecks(); err != nil {
+			return err
+		}
+		results := engine.Results()
+
+		// return results to the user and then close output files
+		formattedResults, err := formatter.Format(results)
+		if err != nil {
+			return err
+		}
+
+		fmt.Fprint(resultsOutputTarget, string(formattedResults))
+		if err := resultsFile.Close(); err != nil {
+			return err
+		}
+
+		return nil
+	},
+}
+
+func init() {
+	checks := strings.Join(engine.OldContainerPolicy(), "\n- ")
+
+	usage := "\n" + `The checks that will be executed are the following:` + "\n- " +
+		checks + "\n\n" +
+		`Usage:
+  preflight check container <url to container image> [flags]
+	
+Flags:
+  -h, --help   help for container
+`
+	checkContainerCmd.SetUsageTemplate(usage)
+
+	checkCmd.AddCommand(oldCheckContainerCmd)
+}
diff --git a/cmd/check_operator.go b/cmd/check_operator.go
index 4273f28..e62ea30 100644
--- a/cmd/check_operator.go
+++ b/cmd/check_operator.go
@@ -87,7 +87,7 @@ var checkOperatorCmd = &cobra.Command{
 }
 
 func init() {
-	checks := strings.Join(engine.OperatorPolicy(), "\n- ")
+	checks := strings.Join(engine.OldOperatorPolicy(), "\n- ")
 
 	usage := "\n" + `The checks that will be executed are the following:` + "\n- " +
 		checks + "\n\n" +
diff --git a/cmd/check_operator_old.go b/cmd/check_operator_old.go
new file mode 100644
index 0000000..d396467
--- /dev/null
+++ b/cmd/check_operator_old.go
@@ -0,0 +1,102 @@
+package cmd
+
+import (
+	"fmt"
+	"io"
+	"os"
+	"strings"
+
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/engine"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/errors"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/formatters"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/runtime"
+	"github.com/spf13/cobra"
+)
+
+var oldCheckOperatorCmd = &cobra.Command{
+	Use:   "operator-old",
+	Short: "Run checks for an Operator using the previous engine",
+	Long:  `This command will run the Certification checks for an Operator bundle image. `,
+	Args: func(cmd *cobra.Command, args []string) error {
+		if len(args) != 1 {
+			return fmt.Errorf("%w: An operator image positional argument is required", errors.ErrInsufficientPosArguments)
+		}
+		return nil
+	},
+	RunE: func(cmd *cobra.Command, args []string) error {
+		// Expect exactly one positional arg. Check here instead of using builtin Args key
+		// so that we can get a more user-friendly error message
+
+		operatorImage := args[0]
+
+		if _, ok := os.LookupEnv("KUBECONFIG"); !ok {
+			return errors.ErrNoKubeconfig
+		}
+
+		cfg := runtime.Config{
+			Image:          operatorImage,
+			EnabledChecks:  engine.OldOperatorPolicy(),
+			ResponseFormat: DefaultOutputFormat,
+			Bundle:         true,
+		}
+
+		engine, err := engine.NewShellEngineForConfig(cfg)
+		if err != nil {
+			return err
+		}
+
+		formatter, err := formatters.NewForConfig(cfg)
+		if err != nil {
+			return err
+		}
+
+		// create the results file early to catch cases where we are not
+		// able to write to the filesystem before we attempt to execute checks.
+		resultsFile, err := os.OpenFile(
+			resultsFilenameWithExtension(formatter.FileExtension()),
+			os.O_WRONLY|os.O_CREATE|os.O_TRUNC,
+			0600,
+		)
+
+		if err != nil {
+			return err
+		}
+
+		// also write to stdout
+		resultsOutputTarget := io.MultiWriter(os.Stdout, resultsFile)
+
+		// execute the checks
+		if err := engine.ExecuteChecks(); err != nil {
+			return err
+		}
+		results := engine.Results()
+
+		// return results to the user and then close output files
+		formattedResults, err := formatter.Format(results)
+		if err != nil {
+			return err
+		}
+
+		fmt.Fprint(resultsOutputTarget, string(formattedResults))
+		if err := resultsFile.Close(); err != nil {
+			return err
+		}
+
+		return nil
+	},
+}
+
+func init() {
+	checks := strings.Join(engine.OldOperatorPolicy(), "\n- ")
+
+	usage := "\n" + `The checks that will be executed are the following:` + "\n- " +
+		checks + "\n\n" +
+		`Usage:
+  preflight check operator <url to Operator bundle image> [flags]
+	
+Flags:
+  -h, --help   help for operator
+`
+	checkOperatorCmd.SetUsageTemplate(usage)
+	checkCmd.AddCommand(oldCheckOperatorCmd)
+}
diff --git a/cmd/check_run.go b/cmd/check_run.go
index 093dfab..6a136f5 100644
--- a/cmd/check_run.go
+++ b/cmd/check_run.go
@@ -45,7 +45,7 @@ It takes its input from environment variables only.`,
 			Mounted:        mounted == "true",
 		}
 
-		engine, err := engine.NewForConfig(cfg)
+		engine, err := engine.NewShellEngineForConfig(cfg)
 		if err != nil {
 			return err
 		}
diff --git a/cmd/support.go b/cmd/support.go
index a5bf5cf..61c2be0 100644
--- a/cmd/support.go
+++ b/cmd/support.go
@@ -1,104 +1,18 @@
 package cmd
 
 import (
-	"errors"
 	"fmt"
-	"net/url"
-	"regexp"
 
-	"github.com/manifoldco/promptui"
-	log "github.com/sirupsen/logrus"
 	"github.com/spf13/cobra"
 )
 
-const (
-	baseURL              = "https://connect.redhat.com/support/technology-partner/#/case/new?"
-	typeParam            = "type"
-	typeValue            = "CERT"
-	sourceParam          = "source"
-	sourceValue          = "preflight"
-	certProjectTypeParam = "cert_project_type"
-	certProjectIDParam   = "cert_project_id"
-	pullRequestURLParam  = "pull_request_url"
-	promptErrorMessage   = "Prompt Failed, Please Try re-running support command."
-)
-
 var supportCmd = &cobra.Command{
 	Use:   "support",
 	Short: "Submits a support request",
-	Long: `This interactive command will generate a URL; based on user input which can then be used to create a Red Hat Support Ticket.
+	Long: `This command will submit a support request to Red Hat along with the logs from the latest Preflight checck.
 	This command can be used when you'd like assistance from Red Hat Support when attempting to pass your certification checks. `,
-	RunE: func(cmd *cobra.Command, args []string) error {
-
-		certProjectTypeLabel := promptui.Select{
-			Label: "Select a Certification Project Type",
-			Items: []string{"Container Image", "Operator Bundle Image"},
-		}
-
-		_, certProjectTypeValue, err := certProjectTypeLabel.Run()
-
-		if err != nil {
-			fmt.Println(promptErrorMessage)
-			return err
-		}
-
-		log.Debugf("certification project type: %s", certProjectTypeValue)
-
-		certProjectIDLabel := promptui.Prompt{
-			Label: "Please Enter Connect Certification Project ID",
-			Validate: func(s string) error {
-				isLegacy, _ := regexp.MatchString(`^p.*`, s)
-				if isLegacy {
-					return errors.New("please remove leading character p from project id")
-				}
-
-				isOSPID, _ := regexp.MatchString(`^ospid-.*`, s)
-				if isOSPID {
-					return errors.New("please remove leading character ospid- from project id")
-				}
-
-				return nil
-			},
-		}
-
-		certProjectIDValue, err := certProjectIDLabel.Run()
-
-		if err != nil {
-			fmt.Println(promptErrorMessage)
-			return err
-		}
-
-		log.Debugf("certification project id: %s", certProjectIDValue)
-
-		pullRequestURLLabel := promptui.Prompt{
-			Label: "Please Enter Your Pull Request URL",
-		}
-
-		pullRequestURLValue, err := pullRequestURLLabel.Run()
-
-		if err != nil {
-			fmt.Println(promptErrorMessage)
-			return err
-		}
-
-		log.Debugf("pull request url: %s", pullRequestURLValue)
-
-		// building and encoding query params
-		queryParams := url.Values{}
-		queryParams.Add(typeParam, typeValue)
-		queryParams.Add(sourceParam, sourceValue)
-		queryParams.Add(certProjectTypeParam, certProjectTypeValue)
-		queryParams.Add(certProjectIDParam, certProjectIDValue)
-		queryParams.Add(pullRequestURLParam, pullRequestURLValue)
-
-		fmt.Printf("Create a support ticket by: \n"+
-			"\t1. Copying URL: %s\n"+
-			"\t2. Paste above URL in a browser\n"+
-			"\t3. Login with Red Hat SSO\n"+
-			"\t4. Enter an issue summary and description\n"+
-			"\t5. Preview and Submit your ticket\n", baseURL+queryParams.Encode())
-
-		return nil
+	Run: func(cmd *cobra.Command, args []string) {
+		fmt.Println("Support command not implemented")
 	},
 }
 
diff --git a/docs/dev/IMPLEMENT_A_CHECK.md b/docs/dev/IMPLEMENT_A_CHECK.md
index 76e2882..3965b60 100644
--- a/docs/dev/IMPLEMENT_A_CHECK.md
+++ b/docs/dev/IMPLEMENT_A_CHECK.md
@@ -48,7 +48,7 @@ type ValidateThingCheck struct{
     // your struct fields here
 }
 
-func (p *ValidateThingCheck) Validate(image string) (bool, error) {
+func (p *ValidateThingCheck) Validate(image certification.ImageReference) (bool, error) {
     // your logic here ...
 }
 
diff --git a/go.mod b/go.mod
index b6ba999..44e4cd5 100644
--- a/go.mod
+++ b/go.mod
@@ -7,7 +7,6 @@ require (
 	github.com/docker/docker v20.10.7+incompatible
 	github.com/google/go-containerregistry v0.6.0
 	github.com/knqyf263/go-rpmdb v0.0.0-20201215100354-a9e3110d8ee1
-	github.com/manifoldco/promptui v0.8.0
 	github.com/mattn/go-isatty v0.0.13 // indirect
 	github.com/onsi/ginkgo v1.16.4
 	github.com/onsi/gomega v1.13.0


Test patch:
diff --git a/certification/engine/engine_test.go b/certification/engine/engine_test.go
index fe596d3..166a4c9 100644
--- a/certification/engine/engine_test.go
+++ b/certification/engine/engine_test.go
@@ -46,7 +46,7 @@ var _ = Describe("Engine Creation", func() {
 			}
 
 			It("should return an engine and no error", func() {
-				engine, err := NewForConfig(cfg)
+				engine, err := NewShellEngineForConfig(cfg)
 				Expect(err).ToNot(HaveOccurred())
 				Expect(engine).ToNot(BeNil())
 			})
@@ -60,7 +60,7 @@ var _ = Describe("Engine Creation", func() {
 			}
 
 			It("should return an error indicating no checks were provided", func() {
-				engine, err := NewForConfig(cfg)
+				engine, err := NewShellEngineForConfig(cfg)
 				Expect(err).To(HaveOccurred())
 				Expect(engine).To(BeNil())
 			})
@@ -74,7 +74,7 @@ var _ = Describe("Engine Creation", func() {
 			}
 
 			It("should return an error indicating no checks were provided", func() {
-				engine, err := NewForConfig(cfg)
+				engine, err := NewShellEngineForConfig(cfg)
 				Expect(err).To(HaveOccurred())
 				Expect(engine).To(BeNil())
 			})
diff --git a/certification/internal/shell/base_on_ubi_test.go b/certification/internal/shell/base_on_ubi_test.go
index 12acad9..a908319 100644
--- a/certification/internal/shell/base_on_ubi_test.go
+++ b/certification/internal/shell/base_on_ubi_test.go
@@ -3,6 +3,7 @@ package shell
 import (
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/internal/utils/migration"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/cli"
 	log "github.com/sirupsen/logrus"
 )
@@ -32,7 +33,7 @@ NAME="Red Hat Enterprise Linux"
 				podmanEngine = fakeEngine
 			})
 			It("should pass Validate", func() {
-				ok, err := baseOnUbiCheck.Validate("dummy/image")
+				ok, err := baseOnUbiCheck.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).ToNot(HaveOccurred())
 				Expect(ok).To(BeTrue())
 			})
@@ -45,7 +46,7 @@ NAME="Red Hat Enterprise Linux"
 			})
 			It("should not pass Validate", func() {
 				log.Errorf("Run Report: %s", podmanEngine)
-				ok, err := baseOnUbiCheck.Validate("dummy/image")
+				ok, err := baseOnUbiCheck.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).ToNot(HaveOccurred())
 				Expect(ok).To(BeFalse())
 			})
@@ -58,7 +59,7 @@ NAME="Red Hat Enterprise Linux"
 		})
 		Context("When PodMan throws an error", func() {
 			It("should fail Validate and return an error", func() {
-				ok, err := baseOnUbiCheck.Validate("dummy/image")
+				ok, err := baseOnUbiCheck.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).To(HaveOccurred())
 				Expect(ok).To(BeFalse())
 			})
diff --git a/certification/internal/shell/has_license_test.go b/certification/internal/shell/has_license_test.go
index a7df72b..d6b917b 100644
--- a/certification/internal/shell/has_license_test.go
+++ b/certification/internal/shell/has_license_test.go
@@ -3,6 +3,7 @@ package shell
 import (
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/internal/utils/migration"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/cli"
 )
 
@@ -24,7 +25,7 @@ var _ = Describe("HasLicense", func() {
 				podmanEngine = fakeEngine
 			})
 			It("Should pass Validate", func() {
-				ok, err := HasLicense.Validate("dummy/image")
+				ok, err := HasLicense.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).ToNot(HaveOccurred())
 				Expect(ok).To(BeTrue())
 			})
@@ -36,7 +37,7 @@ var _ = Describe("HasLicense", func() {
 				podmanEngine = engine
 			})
 			It("Should not pass Validate", func() {
-				ok, err := HasLicense.Validate("dummy/image")
+				ok, err := HasLicense.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).ToNot(HaveOccurred())
 				Expect(ok).To(BeFalse())
 			})
@@ -48,7 +49,7 @@ var _ = Describe("HasLicense", func() {
 				podmanEngine = engine
 			})
 			It("Should not pass Validate", func() {
-				ok, err := HasLicense.Validate("dummy/image")
+				ok, err := HasLicense.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).ToNot(HaveOccurred())
 				Expect(ok).To(BeFalse())
 			})
@@ -61,7 +62,7 @@ var _ = Describe("HasLicense", func() {
 		})
 		Context("When PodMan throws an error", func() {
 			It("should fail Validate and return an error", func() {
-				ok, err := HasLicense.Validate("dummy/image")
+				ok, err := HasLicense.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).To(HaveOccurred())
 				Expect(ok).To(BeFalse())
 			})
diff --git a/certification/internal/shell/has_minimal_vulns_test.go b/certification/internal/shell/has_minimal_vulns_test.go
index 4d1aa50..bf4d7be 100644
--- a/certification/internal/shell/has_minimal_vulns_test.go
+++ b/certification/internal/shell/has_minimal_vulns_test.go
@@ -3,6 +3,7 @@ package shell
 import (
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/internal/utils/migration"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/cli"
 	log "github.com/sirupsen/logrus"
 )
@@ -34,7 +35,7 @@ var _ = Describe("HasMinimalVulns", func() {
 				podmanEngine = engine
 			})
 			It("should pass Validate", func() {
-				ok, err := hasMinimalVulnCheck.Validate("dummy/image")
+				ok, err := hasMinimalVulnCheck.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).ToNot(HaveOccurred())
 				Expect(ok).To(BeTrue())
 			})
@@ -47,7 +48,7 @@ var _ = Describe("HasMinimalVulns", func() {
 			})
 			It("should not pass Validate", func() {
 				log.Errorf("Run Report: %s", podmanEngine)
-				ok, err := hasMinimalVulnCheck.Validate("dummy/image")
+				ok, err := hasMinimalVulnCheck.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).ToNot(HaveOccurred())
 				Expect(ok).To(BeFalse())
 			})
@@ -60,7 +61,7 @@ var _ = Describe("HasMinimalVulns", func() {
 		})
 		Context("When PodMan throws an error", func() {
 			It("should fail Validate and return an error", func() {
-				ok, err := hasMinimalVulnCheck.Validate("dummy/image")
+				ok, err := hasMinimalVulnCheck.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).To(HaveOccurred())
 				Expect(ok).To(BeFalse())
 			})
diff --git a/certification/internal/shell/has_prohibited_packages_test.go b/certification/internal/shell/has_prohibited_packages_test.go
index 3df12a4..9dcece9 100644
--- a/certification/internal/shell/has_prohibited_packages_test.go
+++ b/certification/internal/shell/has_prohibited_packages_test.go
@@ -5,6 +5,7 @@ import (
 
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/internal/utils/migration"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/cli"
 )
 
@@ -79,7 +80,7 @@ var _ = Describe("HasNoProhibitedPackages", func() {
 		Context("When calling the Unshare", func() {
 			Context("When PodMan throws an error", func() {
 				It("should fail Validate and return an error", func() {
-					ok, err := HasNoProhibitedPackages.Validate("dummy/image")
+					ok, err := HasNoProhibitedPackages.Validate(migration.ImageToImageReference("dummy/image"))
 					Expect(err).To(HaveOccurred())
 					Expect(ok).To(BeFalse())
 				})
diff --git a/certification/internal/shell/has_required_labels_test.go b/certification/internal/shell/has_required_labels_test.go
index c302239..8e5652b 100644
--- a/certification/internal/shell/has_required_labels_test.go
+++ b/certification/internal/shell/has_required_labels_test.go
@@ -3,6 +3,7 @@ package shell
 import (
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/internal/utils/migration"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/cli"
 )
 
@@ -39,7 +40,7 @@ var _ = Describe("HasRequiredLabels", func() {
 	Describe("Checking for required labels", func() {
 		Context("When it has required labels", func() {
 			It("should pass Validate", func() {
-				ok, err := hasRequiredLabelsCheck.Validate("dummy/image")
+				ok, err := hasRequiredLabelsCheck.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).ToNot(HaveOccurred())
 				Expect(ok).To(BeTrue())
 			})
@@ -50,7 +51,7 @@ var _ = Describe("HasRequiredLabels", func() {
 				delete(engine.ImageInspectReport.Images[0].Config.Labels, "description")
 			})
 			It("should not succeed the check", func() {
-				ok, err := hasRequiredLabelsCheck.Validate("dummy/image")
+				ok, err := hasRequiredLabelsCheck.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).ToNot(HaveOccurred())
 				Expect(ok).To(BeFalse())
 			})
@@ -63,7 +64,7 @@ var _ = Describe("HasRequiredLabels", func() {
 		})
 		Context("When PodMan throws an error", func() {
 			It("should fail Validate and return an error", func() {
-				ok, err := hasRequiredLabelsCheck.Validate("dummy/image")
+				ok, err := hasRequiredLabelsCheck.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).To(HaveOccurred())
 				Expect(ok).To(BeFalse())
 			})
diff --git a/certification/internal/shell/has_unique_tag_test.go b/certification/internal/shell/has_unique_tag_test.go
index 3e8633c..9946c25 100644
--- a/certification/internal/shell/has_unique_tag_test.go
+++ b/certification/internal/shell/has_unique_tag_test.go
@@ -3,6 +3,7 @@ package shell
 import (
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/internal/utils/migration"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/cli"
 	log "github.com/sirupsen/logrus"
 )
@@ -31,7 +32,7 @@ var _ = Describe("UniqueTag", func() {
 				skopeoEngine = fakeEngine
 			})
 			It("should pass Validate", func() {
-				ok, err := hasUniqueTagCheck.Validate("dummy/image")
+				ok, err := hasUniqueTagCheck.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).ToNot(HaveOccurred())
 				Expect(ok).To(BeTrue())
 			})
@@ -46,7 +47,7 @@ var _ = Describe("UniqueTag", func() {
 			})
 			It("should not pass Validate", func() {
 				log.Errorf("Run Report: %s", skopeoEngine)
-				ok, err := hasUniqueTagCheck.Validate("dummy/image")
+				ok, err := hasUniqueTagCheck.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).ToNot(HaveOccurred())
 				Expect(ok).To(BeFalse())
 			})
@@ -59,7 +60,7 @@ var _ = Describe("UniqueTag", func() {
 		})
 		Context("When Skopeo throws an error", func() {
 			It("should fail Validate and return an error", func() {
-				ok, err := hasUniqueTagCheck.Validate("dummy/image")
+				ok, err := hasUniqueTagCheck.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).To(HaveOccurred())
 				Expect(ok).To(BeFalse())
 			})
diff --git a/certification/internal/shell/less_than_max_layers_test.go b/certification/internal/shell/less_than_max_layers_test.go
index 594920e..f5076f1 100644
--- a/certification/internal/shell/less_than_max_layers_test.go
+++ b/certification/internal/shell/less_than_max_layers_test.go
@@ -5,6 +5,7 @@ import (
 
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/internal/utils/migration"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/cli"
 )
 
@@ -38,7 +39,7 @@ var _ = Describe("LessThanMaxLayers", func() {
 	Describe("Checking for less than max layers", func() {
 		Context("When it has fewer layers than max", func() {
 			It("should pass Validate", func() {
-				ok, err := lessThanMaxLayers.Validate("dummy/image")
+				ok, err := lessThanMaxLayers.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).ToNot(HaveOccurred())
 				Expect(ok).To(BeTrue())
 			})
@@ -53,7 +54,7 @@ var _ = Describe("LessThanMaxLayers", func() {
 				engine.ImageInspectReport.Images[0].RootFS.Layers = layers
 			})
 			It("should not succeed the check", func() {
-				ok, err := lessThanMaxLayers.Validate("dummy/image")
+				ok, err := lessThanMaxLayers.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).ToNot(HaveOccurred())
 				Expect(ok).To(BeFalse())
 			})
@@ -66,7 +67,7 @@ var _ = Describe("LessThanMaxLayers", func() {
 		})
 		Context("When PodMan throws an error", func() {
 			It("should fail Validate and return an error", func() {
-				ok, err := lessThanMaxLayers.Validate("dummy/image")
+				ok, err := lessThanMaxLayers.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).To(HaveOccurred())
 				Expect(ok).To(BeFalse())
 			})
diff --git a/certification/internal/shell/runs_as_nonroot_test.go b/certification/internal/shell/runs_as_nonroot_test.go
index e087e4c..ec1a239 100644
--- a/certification/internal/shell/runs_as_nonroot_test.go
+++ b/certification/internal/shell/runs_as_nonroot_test.go
@@ -3,6 +3,7 @@ package shell
 import (
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/internal/utils/migration"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/cli"
 )
 
@@ -25,7 +26,7 @@ var _ = Describe("RunAsNonRoot", func() {
 				podmanEngine = fakeEngine
 			})
 			It("should pass Validate", func() {
-				ok, err := RunAsNonRoot.Validate("dummy/image")
+				ok, err := RunAsNonRoot.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).ToNot(HaveOccurred())
 				Expect(ok).To(BeTrue())
 			})
@@ -37,7 +38,7 @@ var _ = Describe("RunAsNonRoot", func() {
 				podmanEngine = engine
 			})
 			It("should not pass Validate", func() {
-				ok, err := RunAsNonRoot.Validate("dummy/image")
+				ok, err := RunAsNonRoot.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).ToNot(HaveOccurred())
 				Expect(ok).To(BeFalse())
 			})
@@ -50,7 +51,7 @@ var _ = Describe("RunAsNonRoot", func() {
 		})
 		Context("When PodMan throws an error", func() {
 			It("should fail Validate and return an error", func() {
-				ok, err := RunAsNonRoot.Validate("dummy/image")
+				ok, err := RunAsNonRoot.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).To(HaveOccurred())
 				Expect(ok).To(BeFalse())
 			})
diff --git a/certification/internal/shell/scorecard_basic_check_test.go b/certification/internal/shell/scorecard_basic_check_test.go
index b70c0e4..2b09c0a 100644
--- a/certification/internal/shell/scorecard_basic_check_test.go
+++ b/certification/internal/shell/scorecard_basic_check_test.go
@@ -3,6 +3,7 @@ package shell
 import (
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/internal/utils/migration"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/cli"
 )
 
@@ -71,7 +72,7 @@ var _ = Describe("ScorecardBasicCheck", func() {
 	Describe("Operator Bundle Scorecard", func() {
 		Context("When Operator Bundle Scorecard Basic Check has a pass", func() {
 			It("Should pass Validate", func() {
-				ok, err := scorecardBasicCheck.Validate("dummy/image")
+				ok, err := scorecardBasicCheck.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).ToNot(HaveOccurred())
 				Expect(ok).To(BeTrue())
 			})
@@ -83,7 +84,7 @@ var _ = Describe("ScorecardBasicCheck", func() {
 				operatorSdkEngine = engine
 			})
 			It("Should not pass Validate", func() {
-				ok, err := scorecardBasicCheck.Validate("dummy/image")
+				ok, err := scorecardBasicCheck.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).ToNot(HaveOccurred())
 				Expect(ok).To(BeFalse())
 			})
@@ -96,7 +97,7 @@ var _ = Describe("ScorecardBasicCheck", func() {
 		})
 		Context("When OperatorSdk throws an error", func() {
 			It("should fail Validate and return an error", func() {
-				ok, err := scorecardBasicCheck.Validate("dummy/image")
+				ok, err := scorecardBasicCheck.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).To(HaveOccurred())
 				Expect(ok).To(BeFalse())
 			})
diff --git a/certification/internal/shell/scorecard_olm_suite_test.go b/certification/internal/shell/scorecard_olm_suite_test.go
index 3ada0b6..d19f063 100644
--- a/certification/internal/shell/scorecard_olm_suite_test.go
+++ b/certification/internal/shell/scorecard_olm_suite_test.go
@@ -3,6 +3,7 @@ package shell
 import (
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/internal/utils/migration"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/cli"
 )
 
@@ -71,7 +72,7 @@ var _ = Describe("ScorecardBasicCheck", func() {
 	Describe("Operator Bundle Scorecard", func() {
 		Context("When Operator Bundle Scorecard OLM Suite Check has a pass", func() {
 			It("Should pass Validate", func() {
-				ok, err := scorecardOlmSuiteCheck.Validate("dummy/image")
+				ok, err := scorecardOlmSuiteCheck.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).ToNot(HaveOccurred())
 				Expect(ok).To(BeTrue())
 			})
@@ -83,7 +84,7 @@ var _ = Describe("ScorecardBasicCheck", func() {
 				operatorSdkEngine = engine
 			})
 			It("Should not pass Validate", func() {
-				ok, err := scorecardOlmSuiteCheck.Validate("dummy/image")
+				ok, err := scorecardOlmSuiteCheck.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).ToNot(HaveOccurred())
 				Expect(ok).To(BeFalse())
 			})
@@ -96,7 +97,7 @@ var _ = Describe("ScorecardBasicCheck", func() {
 		})
 		Context("When OperatorSdk throws an error", func() {
 			It("should fail Validate and return an error", func() {
-				ok, err := scorecardOlmSuiteCheck.Validate("dummy/image")
+				ok, err := scorecardOlmSuiteCheck.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).To(HaveOccurred())
 				Expect(ok).To(BeFalse())
 			})
diff --git a/certification/internal/shell/validate_operator_bundle_test.go b/certification/internal/shell/validate_operator_bundle_test.go
index eda7a6f..c2ff76b 100644
--- a/certification/internal/shell/validate_operator_bundle_test.go
+++ b/certification/internal/shell/validate_operator_bundle_test.go
@@ -3,6 +3,7 @@ package shell
 import (
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
+	"github.com/redhat-openshift-ecosystem/openshift-preflight/certification/internal/utils/migration"
 	"github.com/redhat-openshift-ecosystem/openshift-preflight/cli"
 )
 
@@ -32,7 +33,7 @@ var _ = Describe("BundleValidateCheck", func() {
 	Describe("Operator Bundle Validate", func() {
 		Context("When Operator Bundle Validate passes", func() {
 			It("Should pass Validate", func() {
-				ok, err := bundleValidateCheck.Validate("dummy/image")
+				ok, err := bundleValidateCheck.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).ToNot(HaveOccurred())
 				Expect(ok).To(BeTrue())
 			})
@@ -48,7 +49,7 @@ var _ = Describe("BundleValidateCheck", func() {
 				operatorSdkEngine = engine
 			})
 			It("Should not pass Validate", func() {
-				ok, err := bundleValidateCheck.Validate("dummy/image")
+				ok, err := bundleValidateCheck.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).ToNot(HaveOccurred())
 				Expect(ok).To(BeFalse())
 			})
@@ -61,7 +62,7 @@ var _ = Describe("BundleValidateCheck", func() {
 		})
 		Context("When OperatorSdk throws an error", func() {
 			It("should fail Validate and return an error", func() {
-				ok, err := bundleValidateCheck.Validate("dummy/image")
+				ok, err := bundleValidateCheck.Validate(migration.ImageToImageReference("dummy/image"))
 				Expect(err).To(HaveOccurred())
 				Expect(ok).To(BeFalse())
 			})
diff --git a/test/e2e/e2e_test.go b/test/e2e/e2e_test.go
index 09c9a20..fb9c9d7 100644
--- a/test/e2e/e2e_test.go
+++ b/test/e2e/e2e_test.go
@@ -23,10 +23,10 @@ var _ = Describe("policy validation", func() {
 
 			cfg := runtime.Config{
 				Image:         goodImage,
-				EnabledChecks: engine.OperatorPolicy(),
+				EnabledChecks: engine.OldOperatorPolicy(),
 			}
 
-			engine, err := engine.NewForConfig(cfg)
+			engine, err := engine.NewShellEngineForConfig(cfg)
 			Expect(err).ToNot(HaveOccurred())
 
 			engine.ExecuteChecks()
@@ -40,10 +40,10 @@ var _ = Describe("policy validation", func() {
 		Context("with a known-bad image", func() {
 			cfg := runtime.Config{
 				Image:         badImage,
-				EnabledChecks: engine.OperatorPolicy(),
+				EnabledChecks: engine.OldOperatorPolicy(),
 			}
 
-			engine, err := engine.NewForConfig(cfg)
+			engine, err := engine.NewShellEngineForConfig(cfg)
 			Expect(err).To(BeNil())
 
 			engine.ExecuteChecks()
@@ -68,10 +68,10 @@ var _ = Describe("policy validation", func() {
 
 			cfg := runtime.Config{
 				Image:         goodImage,
-				EnabledChecks: engine.ContainerPolicy(),
+				EnabledChecks: engine.OldContainerPolicy(),
 			}
 
-			engine, err := engine.NewForConfig(cfg)
+			engine, err := engine.NewShellEngineForConfig(cfg)
 			Expect(err).ToNot(HaveOccurred())
 
 			engine.ExecuteChecks()
@@ -90,10 +90,10 @@ var _ = Describe("policy validation", func() {
 		XContext("with a known-bad image", func() {
 			cfg := runtime.Config{
 				Image:         badImage,
-				EnabledChecks: engine.ContainerPolicy(),
+				EnabledChecks: engine.OldContainerPolicy(),
 			}
 
-			engine, err := engine.NewForConfig(cfg)
+			engine, err := engine.NewShellEngineForConfig(cfg)
 			Expect(err).ToNot(HaveOccurred())
 
 			engine.ExecuteChecks()