diff --git a/certification/config.go b/certification/config.go index e0bd0405b..1d3e6e8c0 100644 --- a/certification/config.go +++ b/certification/config.go @@ -30,6 +30,7 @@ type containerConfig interface { PyxisAPIToken() string Submit() bool Platform() string + Insecure() bool } // operatorConfig are configurables relevant to diff --git a/certification/internal/engine/engine.go b/certification/internal/engine/engine.go index 1376800c4..627351350 100644 --- a/certification/internal/engine/engine.go +++ b/certification/internal/engine/engine.go @@ -85,6 +85,10 @@ func (c *CraneEngine) ExecuteChecks(ctx context.Context) error { retryOnceAfter(5 * time.Second), } + if c.Config.Insecure() { + options = append(options, crane.Insecure) + } + // pull the image and save to fs log.Debug("pulling image from target registry") img, err := crane.Pull(c.Image, options...) diff --git a/certification/runtime/config.go b/certification/runtime/config.go index 4d1138ff8..23525d984 100644 --- a/certification/runtime/config.go +++ b/certification/runtime/config.go @@ -25,6 +25,7 @@ type Config struct { DockerConfig string Submit bool Platform string + Insecure bool // Operator-Specific Fields Namespace string ServiceAccount string @@ -65,6 +66,7 @@ func (c *Config) storeContainerPolicyConfiguration(vcfg viper.Viper) { c.PyxisHost = pyxisHostLookup(vcfg.GetString("pyxis_env"), vcfg.GetString("pyxis_host")) c.CertificationProjectID = vcfg.GetString("certification_project_id") c.Platform = vcfg.GetString("platform") + c.Insecure = vcfg.GetBool("insecure") } // storeOperatorPolicyConfiguration reads operator-policy-specific config diff --git a/certification/runtime/config_read.go b/certification/runtime/config_read.go index 096932e81..ccdcabfd9 100644 --- a/certification/runtime/config_read.go +++ b/certification/runtime/config_read.go @@ -97,3 +97,7 @@ func (ro *ReadOnlyConfig) IndexImage() string { func (ro *ReadOnlyConfig) Platform() string { return ro.cfg.Platform } + +func (ro *ReadOnlyConfig) Insecure() bool { + return ro.cfg.Insecure +} diff --git a/certification/runtime/config_read_test.go b/certification/runtime/config_read_test.go index d7a434e21..128fb4eb4 100644 --- a/certification/runtime/config_read_test.go +++ b/certification/runtime/config_read_test.go @@ -22,6 +22,7 @@ var _ = Describe("Runtime ReadOnlyConfig test", func() { DockerConfig: "dockercfg", Submit: true, Platform: "s390x", + Insecure: true, Namespace: "ns", ServiceAccount: "sa", ScorecardImage: "scorecardimg", @@ -46,6 +47,7 @@ var _ = Describe("Runtime ReadOnlyConfig test", func() { Expect(cro.DockerConfig()).To(Equal("dockercfg")) Expect(cro.Submit()).To(Equal(true)) Expect(cro.Platform()).To(Equal("s390x")) + Expect(cro.Insecure()).To(BeTrue()) Expect(cro.Namespace()).To(Equal("ns")) Expect(cro.ServiceAccount()).To(Equal("sa")) Expect(cro.ScorecardImage()).To(Equal("scorecardimg")) diff --git a/certification/runtime/config_test.go b/certification/runtime/config_test.go index ac29c6d3f..678d4e179 100644 --- a/certification/runtime/config_test.go +++ b/certification/runtime/config_test.go @@ -39,6 +39,8 @@ var _ = Describe("Viper to Runtime Config", func() { expectedRuntimeCfg.CertificationProjectID = "000000000000" baseViperCfg.Set("platform", "s390x") expectedRuntimeCfg.Platform = "s390x" + baseViperCfg.Set("insecure", true) + expectedRuntimeCfg.Insecure = true baseViperCfg.Set("namespace", "myns") expectedRuntimeCfg.Namespace = "myns" diff --git a/cmd/preflight/cmd/check_container.go b/cmd/preflight/cmd/check_container.go index 960c4ab98..c59e4346a 100644 --- a/cmd/preflight/cmd/check_container.go +++ b/cmd/preflight/cmd/check_container.go @@ -31,22 +31,30 @@ func checkContainerCmd() *cobra.Command { RunE: checkContainerRunE, } - checkContainerCmd.Flags().BoolVarP(&submit, "submit", "s", false, "submit check container results to red hat") - _ = viper.BindPFlag("submit", checkContainerCmd.Flags().Lookup("submit")) + flags := checkContainerCmd.Flags() - checkContainerCmd.Flags().String("pyxis-api-token", "", "API token for Pyxis authentication (env: PFLT_PYXIS_API_TOKEN)") - _ = viper.BindPFlag("pyxis_api_token", checkContainerCmd.Flags().Lookup("pyxis-api-token")) + flags.BoolVarP(&submit, "submit", "s", false, "submit check container results to Red Hat") + _ = viper.BindPFlag("submit", flags.Lookup("submit")) - checkContainerCmd.Flags().String("pyxis-host", "", fmt.Sprintf("Host to use for Pyxis submissions. This will override Pyxis Env. Only set this if you know what you are doing.\n"+ + flags.Bool("insecure", false, "Use insecure protocol for the registry. Default is False. Cannot be used with submit.") + _ = viper.BindPFlag("insecure", flags.Lookup("insecure")) + + // Make --submit mutually exclusive to --insecure + checkContainerCmd.MarkFlagsMutuallyExclusive("submit", "insecure") + + flags.String("pyxis-api-token", "", "API token for Pyxis authentication (env: PFLT_PYXIS_API_TOKEN)") + _ = viper.BindPFlag("pyxis_api_token", flags.Lookup("pyxis-api-token")) + + flags.String("pyxis-host", "", fmt.Sprintf("Host to use for Pyxis submissions. This will override Pyxis Env. Only set this if you know what you are doing.\n"+ "If you do set it, it should include just the host, and the URI path. (env: PFLT_PYXIS_HOST)")) - _ = viper.BindPFlag("pyxis_host", checkContainerCmd.Flags().Lookup("pyxis-host")) + _ = viper.BindPFlag("pyxis_host", flags.Lookup("pyxis-host")) - checkContainerCmd.Flags().String("pyxis-env", certification.DefaultPyxisEnv, "Env to use for Pyxis submissions.") - _ = viper.BindPFlag("pyxis_env", checkContainerCmd.Flags().Lookup("pyxis-env")) + flags.String("pyxis-env", certification.DefaultPyxisEnv, "Env to use for Pyxis submissions.") + _ = viper.BindPFlag("pyxis_env", flags.Lookup("pyxis-env")) - checkContainerCmd.Flags().String("certification-project-id", "", fmt.Sprintf("Certification Project ID from connect.redhat.com/projects/{certification-project-id}/overview\n"+ + flags.String("certification-project-id", "", fmt.Sprintf("Certification Project ID from connect.redhat.com/projects/{certification-project-id}/overview\n"+ "URL paramater. This value may differ from the PID on the overview page. (env: PFLT_CERTIFICATION_PROJECT_ID)")) - _ = viper.BindPFlag("certification_project_id", checkContainerCmd.Flags().Lookup("certification-project-id")) + _ = viper.BindPFlag("certification_project_id", flags.Lookup("certification-project-id")) checkContainerCmd.Flags().String("platform", rt.GOARCH, "Architecture of image to pull. Defaults to current platform.") _ = viper.BindPFlag("platform", checkContainerCmd.Flags().Lookup("platform")) diff --git a/cmd/preflight/cmd/check_container_test.go b/cmd/preflight/cmd/check_container_test.go index 2656ab1aa..a8082c5cc 100644 --- a/cmd/preflight/cmd/check_container_test.go +++ b/cmd/preflight/cmd/check_container_test.go @@ -55,6 +55,7 @@ var _ = Describe("Check Container Command", func() { Entry("certification-project-id flag is present but empty because of '='", "cannot be empty when --submit is present", []string{"foo", "--submit", "--certification-project-id=", "--pyxis-api-token=footoken"}), Entry("submit is passed after empty api token", "pyxis API token and certification ID are required when --submit is present", []string{"foo", "--certification-project-id=fooid", "--pyxis-api-token", "--submit"}), Entry("submit is passed with explicit value after empty api token", "pyxis API token and certification ID are required when --submit is present", []string{"foo", "--certification-project-id=fooid", "--pyxis-api-token", "--submit=true"}), + Entry("submit is passed and insecure is specified", "if any flags in the group [submit insecure] are set", []string{"foo", "--submit", "--insecure", "--certification-project-id=fooid", "--pyxis-api-token=footoken"}), ) When("the user enables the submit flag", func() { diff --git a/docs/RECIPES.md b/docs/RECIPES.md index 272345fc0..c87e4c4cb 100644 --- a/docs/RECIPES.md +++ b/docs/RECIPES.md @@ -229,3 +229,19 @@ $CONTAINER_TOOL run \ -v ./temp-authfile.json:/temp-authfile.json:ro \ quay.io/opdev/preflight:stable check container registry.example.org/your-namespace/your-bundle-image:sometag --submit ``` + +### Testing a local container, i.e. not yet pushed to a registry + +Preflight does not support certifying against a local image, that is not pushed to +a registry. In some cases, like a CI system, it is desirable to run preflight against +an image BEFORE pushing to a public registry. In order to support that, one should +start a local registry, push to it, and point preflight at the local registry. + +```bash +podman run -p 5000:5000 docker.io/library/registry +podman push --tls-verify=false localhost/myrepo/mycontainer:v1.0 localhost:5000/myrepo/mycontainer:v1.0 +preflight check container --insecure localhost:5000/myrepo/mycontainer:v1.0 +``` + +Note: --submit and --insecure are mutually exclusive. A container cannot be fully +certified and submitted unless it is on a secure registry.