From 0e58ec74747ac7fbb0dccd364765b83b212657c9 Mon Sep 17 00:00:00 2001
From: baude <bbaude@redhat.com>
Date: Wed, 9 May 2018 12:04:28 -0500
Subject: [PATCH] podman push should honor registries.conf

Like podman pull, when you push an image, podman should check
if the registry is listed as insecure and if so, it should
--tls-verify=false unless the user overrides this.

Signed-off-by: baude <bbaude@redhat.com>

Closes: #738
Approved by: mheon
---
 cmd/podman/push.go       |  7 ++++++-
 cmd/podman/save.go       |  2 +-
 libpod/image/image.go    | 20 ++++++++++++++++++--
 pkg/varlinkapi/images.go |  4 ++--
 4 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/cmd/podman/push.go b/cmd/podman/push.go
index dc1894ebba..272c49e324 100644
--- a/cmd/podman/push.go
+++ b/cmd/podman/push.go
@@ -80,6 +80,7 @@ func pushCmd(c *cli.Context) error {
 	var (
 		registryCreds *types.DockerAuthConfig
 		destName      string
+		forceSecure   bool
 	)
 
 	args := c.Args()
@@ -143,6 +144,10 @@ func pushCmd(c *cli.Context) error {
 		}
 	}
 
+	if c.IsSet("tls-verify") {
+		forceSecure = c.Bool("tls-verify")
+	}
+
 	dockerRegistryOptions := image.DockerRegistryOptions{
 		DockerRegistryCreds:         registryCreds,
 		DockerCertPath:              certPath,
@@ -160,5 +165,5 @@ func pushCmd(c *cli.Context) error {
 	}
 
 	//return runtime.PushImage(srcName, destName, options)
-	return newImage.PushImage(getContext(), destName, manifestType, c.String("authfile"), c.String("signature-policy"), writer, c.Bool("compress"), so, &dockerRegistryOptions)
+	return newImage.PushImage(getContext(), destName, manifestType, c.String("authfile"), c.String("signature-policy"), writer, c.Bool("compress"), so, &dockerRegistryOptions, forceSecure)
 }
diff --git a/cmd/podman/save.go b/cmd/podman/save.go
index ce82b588aa..c3e87f145b 100644
--- a/cmd/podman/save.go
+++ b/cmd/podman/save.go
@@ -121,7 +121,7 @@ func saveCmd(c *cli.Context) error {
 		if err != nil {
 			return err
 		}
-		if err := newImage.PushImage(getContext(), dest, manifestType, "", "", writer, c.Bool("compress"), libpodImage.SigningOptions{}, &libpodImage.DockerRegistryOptions{}); err != nil {
+		if err := newImage.PushImage(getContext(), dest, manifestType, "", "", writer, c.Bool("compress"), libpodImage.SigningOptions{}, &libpodImage.DockerRegistryOptions{}, false); err != nil {
 			if err2 := os.Remove(output); err2 != nil {
 				logrus.Errorf("error deleting %q: %v", output, err)
 			}
diff --git a/libpod/image/image.go b/libpod/image/image.go
index db0fdab905..b7d9200ec8 100644
--- a/libpod/image/image.go
+++ b/libpod/image/image.go
@@ -26,7 +26,9 @@ import (
 	"github.com/projectatomic/libpod/libpod/common"
 	"github.com/projectatomic/libpod/libpod/driver"
 	"github.com/projectatomic/libpod/pkg/inspect"
+	"github.com/projectatomic/libpod/pkg/registries"
 	"github.com/projectatomic/libpod/pkg/util"
+	"github.com/sirupsen/logrus"
 )
 
 // imageConversions is used to cache image "cast" types
@@ -426,7 +428,7 @@ func (i *Image) UntagImage(tag string) error {
 }
 
 // PushImage pushes the given image to a location described by the given path
-func (i *Image) PushImage(ctx context.Context, destination, manifestMIMEType, authFile, signaturePolicyPath string, writer io.Writer, forceCompress bool, signingOptions SigningOptions, dockerRegistryOptions *DockerRegistryOptions) error {
+func (i *Image) PushImage(ctx context.Context, destination, manifestMIMEType, authFile, signaturePolicyPath string, writer io.Writer, forceCompress bool, signingOptions SigningOptions, dockerRegistryOptions *DockerRegistryOptions, forceSecure bool) error {
 	if destination == "" {
 		return errors.Wrapf(syscall.EINVAL, "destination image name must be specified")
 	}
@@ -458,9 +460,23 @@ func (i *Image) PushImage(ctx context.Context, destination, manifestMIMEType, au
 	if err != nil {
 		return errors.Wrapf(err, "error getting source imageReference for %q", i.InputName)
 	}
-
+	insecureRegistries, err := registries.GetInsecureRegistries()
+	if err != nil {
+		return err
+	}
 	copyOptions := getCopyOptions(writer, signaturePolicyPath, nil, dockerRegistryOptions, signingOptions, authFile, manifestMIMEType, forceCompress)
+	if strings.HasPrefix(DockerTransport, dest.Transport().Name()) {
+		imgRef, err := reference.Parse(dest.DockerReference().String())
+		if err != nil {
+			return err
+		}
+		registry := reference.Domain(imgRef.(reference.Named))
 
+		if util.StringInSlice(registry, insecureRegistries) && !forceSecure {
+			copyOptions.DestinationCtx.DockerInsecureSkipTLSVerify = true
+			logrus.Info(fmt.Sprintf("%s is an insecure registry; pushing with tls-verify=false", registry))
+		}
+	}
 	// Copy the image to the remote destination
 	err = cp.Image(ctx, policyContext, dest, src, copyOptions)
 	if err != nil {
diff --git a/pkg/varlinkapi/images.go b/pkg/varlinkapi/images.go
index 16bc461070..f488a10fe0 100644
--- a/pkg/varlinkapi/images.go
+++ b/pkg/varlinkapi/images.go
@@ -137,7 +137,7 @@ func (i *LibpodAPI) PushImage(call ioprojectatomicpodman.VarlinkCall, name, tag
 
 	so := image.SigningOptions{}
 
-	if err := newImage.PushImage(getContext(), destname, "", "", "", nil, false, so, &dockerRegistryOptions); err != nil {
+	if err := newImage.PushImage(getContext(), destname, "", "", "", nil, false, so, &dockerRegistryOptions, false); err != nil {
 		return call.ReplyErrorOccurred(err.Error())
 	}
 	return call.ReplyPushImage(newImage.ID())
@@ -272,7 +272,7 @@ func (i *LibpodAPI) ExportImage(call ioprojectatomicpodman.VarlinkCall, name, de
 	if err != nil {
 		return call.ReplyImageNotFound(name)
 	}
-	if err := newImage.PushImage(getContext(), destination, "", "", "", nil, compress, image.SigningOptions{}, &image.DockerRegistryOptions{}); err != nil {
+	if err := newImage.PushImage(getContext(), destination, "", "", "", nil, compress, image.SigningOptions{}, &image.DockerRegistryOptions{}, false); err != nil {
 		return call.ReplyErrorOccurred(err.Error())
 	}
 	return call.ReplyExportImage(newImage.ID())