summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/pull.go20
-rw-r--r--cmd/podman/push.go18
-rw-r--r--docs/podman-build.1.md3
-rw-r--r--docs/podman-login.1.md3
-rw-r--r--docs/podman-pull.1.md7
-rw-r--r--docs/podman-push.1.md7
-rw-r--r--libpod/common/common.go28
-rw-r--r--pkg/util/utils.go46
-rw-r--r--vendor.conf2
-rw-r--r--vendor/github.com/containers/image/docker/docker_client.go50
10 files changed, 108 insertions, 76 deletions
diff --git a/cmd/podman/pull.go b/cmd/podman/pull.go
index 5726b20f1..c19e6715b 100644
--- a/cmd/podman/pull.go
+++ b/cmd/podman/pull.go
@@ -1,16 +1,14 @@
package main
import (
- "fmt"
"io"
"os"
- "golang.org/x/crypto/ssh/terminal"
-
"github.com/containers/image/types"
"github.com/pkg/errors"
"github.com/projectatomic/libpod/libpod"
"github.com/projectatomic/libpod/libpod/common"
+ "github.com/projectatomic/libpod/pkg/util"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
)
@@ -80,19 +78,11 @@ func pullCmd(c *cli.Context) error {
image := args[0]
var registryCreds *types.DockerAuthConfig
- if c.String("creds") != "" {
- creds, err := common.ParseRegistryCreds(c.String("creds"))
+
+ if c.IsSet("creds") {
+ creds, err := util.ParseRegistryCreds(c.String("creds"))
if err != nil {
- if err == common.ErrNoPassword {
- fmt.Print("Password: ")
- password, err := terminal.ReadPassword(0)
- if err != nil {
- return errors.Wrapf(err, "could not read password from terminal")
- }
- creds.Password = string(password)
- } else {
- return err
- }
+ return err
}
registryCreds = creds
}
diff --git a/cmd/podman/push.go b/cmd/podman/push.go
index 69d6e6629..2f0d73ffa 100644
--- a/cmd/podman/push.go
+++ b/cmd/podman/push.go
@@ -13,8 +13,8 @@ import (
"github.com/pkg/errors"
"github.com/projectatomic/libpod/libpod"
"github.com/projectatomic/libpod/libpod/common"
+ "github.com/projectatomic/libpod/pkg/util"
"github.com/urfave/cli"
- "golang.org/x/crypto/ssh/terminal"
)
var (
@@ -97,25 +97,15 @@ func pushCmd(c *cli.Context) error {
}
}
- registryCredsString := c.String("creds")
certPath := c.String("cert-dir")
skipVerify := !c.BoolT("tls-verify")
removeSignatures := c.Bool("remove-signatures")
signBy := c.String("sign-by")
- if registryCredsString != "" {
- creds, err := common.ParseRegistryCreds(registryCredsString)
+ if c.IsSet("creds") {
+ creds, err := util.ParseRegistryCreds(c.String("creds"))
if err != nil {
- if err == common.ErrNoPassword {
- fmt.Print("Password: ")
- password, err := terminal.ReadPassword(0)
- if err != nil {
- return errors.Wrapf(err, "could not read password from terminal")
- }
- creds.Password = string(password)
- } else {
- return err
- }
+ return err
}
registryCreds = creds
}
diff --git a/docs/podman-build.1.md b/docs/podman-build.1.md
index 61c8d8aaa..d4e9af175 100644
--- a/docs/podman-build.1.md
+++ b/docs/podman-build.1.md
@@ -38,7 +38,8 @@ resulting image's configuration.
**--cert-dir** *path*
-Use certificates at *path* (*.crt, *.cert, *.key) to connect to the registry
+Use certificates at *path* (*.crt, *.cert, *.key) to connect to the registry.
+Default certificates directory is _/etc/containers/certs.d_.
**--creds** *creds*
diff --git a/docs/podman-login.1.md b/docs/podman-login.1.md
index fcf32870a..b22a02553 100644
--- a/docs/podman-login.1.md
+++ b/docs/podman-login.1.md
@@ -38,7 +38,8 @@ Username for registry
Path of the authentication file. Default is ${XDG_\RUNTIME\_DIR}/containers/auth.json
**--cert-dir**
-Pathname of a directory containing TLS certificates and keys used to connect to the registry
+Pathname of a directory containing TLS certificates and keys used to connect to the registry.
+Default certificates directory is _/etc/containers/certs.d_.
**--tls-verify**
Require HTTPS and verify certificates when contacting registries (default: true)
diff --git a/docs/podman-pull.1.md b/docs/podman-pull.1.md
index b1212ee6b..1a1611fd0 100644
--- a/docs/podman-pull.1.md
+++ b/docs/podman-pull.1.md
@@ -61,11 +61,14 @@ If the authorization state is not found there, $HOME/.docker/config.json is chec
**--cert-dir**
-Pathname of a directory containing TLS certificates and keys
+Pathname of a directory containing TLS certificates and keys.
+Default certificates directory is _/etc/containers/certs.d_.
**--creds**
-Credentials (USERNAME:PASSWORD) to use for authenticating to a registry
+The [username[:password]] to use to authenticate with the registry if required.
+If one or both values are not supplied, a command line prompt will appear and the
+value can be entered. The password is entered without echo.
**--quiet, -q**
diff --git a/docs/podman-push.1.md b/docs/podman-push.1.md
index 63c75ea36..964758da6 100644
--- a/docs/podman-push.1.md
+++ b/docs/podman-push.1.md
@@ -53,11 +53,14 @@ If the authorization state is not found there, $HOME/.docker/config.json is chec
**--creds="CREDENTIALS"**
-Credentials (USERNAME:PASSWORD) to use for authenticating to a registry
+The [username[:password]] to use to authenticate with the registry if required.
+If one or both values are not supplied, a command line prompt will appear and the
+value can be entered. The password is entered without echo.
**cert-dir="PATHNAME"**
-Pathname of a directory containing TLS certificates and keys
+Pathname of a directory containing TLS certificates and keys.
+Default certificates directory is _/etc/containers/certs.d_.
**--compress**
diff --git a/libpod/common/common.go b/libpod/common/common.go
index 6af3cd232..932f1f6da 100644
--- a/libpod/common/common.go
+++ b/libpod/common/common.go
@@ -2,17 +2,9 @@ package common
import (
"io"
- "strings"
- "syscall"
cp "github.com/containers/image/copy"
"github.com/containers/image/types"
- "github.com/pkg/errors"
-)
-
-var (
- // ErrNoPassword is returned if the user did not supply a password
- ErrNoPassword = errors.Wrapf(syscall.EINVAL, "password was not supplied")
)
// GetCopyOptions constructs a new containers/image/copy.Options{} struct from the given parameters
@@ -60,23 +52,3 @@ func IsFalse(str string) bool {
func IsValidBool(str string) bool {
return IsTrue(str) || IsFalse(str)
}
-
-// ParseRegistryCreds takes a credentials string in the form USERNAME:PASSWORD
-// and returns a DockerAuthConfig
-func ParseRegistryCreds(creds string) (*types.DockerAuthConfig, error) {
- if creds == "" {
- return nil, errors.New("no credentials supplied")
- }
- if !strings.Contains(creds, ":") {
- return &types.DockerAuthConfig{
- Username: creds,
- Password: "",
- }, ErrNoPassword
- }
- v := strings.SplitN(creds, ":", 2)
- cfg := &types.DockerAuthConfig{
- Username: v[0],
- Password: v[1],
- }
- return cfg, nil
-}
diff --git a/pkg/util/utils.go b/pkg/util/utils.go
new file mode 100644
index 000000000..9a93021e4
--- /dev/null
+++ b/pkg/util/utils.go
@@ -0,0 +1,46 @@
+package util
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/containers/image/types"
+ "github.com/pkg/errors"
+ "golang.org/x/crypto/ssh/terminal"
+)
+
+// Helper function to determine the username/password passed
+// in the creds string. It could be either or both.
+func parseCreds(creds string) (string, string) {
+ if creds == "" {
+ return "", ""
+ }
+ up := strings.SplitN(creds, ":", 2)
+ if len(up) == 1 {
+ return up[0], ""
+ }
+ return up[0], up[1]
+}
+
+// ParseRegistryCreds takes a credentials string in the form USERNAME:PASSWORD
+// and returns a DockerAuthConfig
+func ParseRegistryCreds(creds string) (*types.DockerAuthConfig, error) {
+ username, password := parseCreds(creds)
+ if username == "" {
+ fmt.Print("Username: ")
+ fmt.Scanln(&username)
+ }
+ if password == "" {
+ fmt.Print("Password: ")
+ termPassword, err := terminal.ReadPassword(0)
+ if err != nil {
+ return nil, errors.Wrapf(err, "could not read password from terminal")
+ }
+ password = string(termPassword)
+ }
+
+ return &types.DockerAuthConfig{
+ Username: username,
+ Password: password,
+ }, nil
+}
diff --git a/vendor.conf b/vendor.conf
index 4e7bff400..ea659eab8 100644
--- a/vendor.conf
+++ b/vendor.conf
@@ -1,6 +1,6 @@
#
github.com/sirupsen/logrus v1.0.0
-github.com/containers/image 2524e50daed223ad84b827238ed409bbf44296c5
+github.com/containers/image 3ab2e31e6ff9fc2b21b81188c1f6cf545658ff4a
github.com/docker/docker-credential-helpers d68f9aeca33f5fd3f08eeae5e9d175edf4e731d1
github.com/ostreedev/ostree-go master
github.com/containers/storage 1824cf917a6b42d8c41179e807bb20a5fd6c0f0a
diff --git a/vendor/github.com/containers/image/docker/docker_client.go b/vendor/github.com/containers/image/docker/docker_client.go
index b1256b9cb..ff1af8f65 100644
--- a/vendor/github.com/containers/image/docker/docker_client.go
+++ b/vendor/github.com/containers/image/docker/docker_client.go
@@ -9,6 +9,7 @@ import (
"io/ioutil"
"net/http"
"net/url"
+ "os"
"path/filepath"
"strconv"
"strings"
@@ -30,8 +31,6 @@ const (
dockerV1Hostname = "index.docker.io"
dockerRegistry = "registry-1.docker.io"
- systemPerHostCertDirPath = "/etc/docker/certs.d"
-
resolvedPingV2URL = "%s://%s/v2/"
resolvedPingV1URL = "%s://%s/v1/_ping"
tagsPath = "/v2/%s/tags/list"
@@ -52,6 +51,7 @@ var (
ErrV1NotSupported = errors.New("can't talk to a V1 docker registry")
// ErrUnauthorizedForCredentials is returned when the status code returned is 401
ErrUnauthorizedForCredentials = errors.New("unable to retrieve auth token: invalid username/password")
+ systemPerHostCertDirPaths = [2]string{"/etc/containers/certs.d", "/etc/docker/certs.d"}
)
// extensionSignature and extensionSignatureList come from github.com/openshift/origin/pkg/dockerregistry/server/signaturedispatcher.go:
@@ -131,19 +131,42 @@ func serverDefault() *tls.Config {
}
// dockerCertDir returns a path to a directory to be consumed by tlsclientconfig.SetupCertificates() depending on ctx and hostPort.
-func dockerCertDir(ctx *types.SystemContext, hostPort string) string {
+func dockerCertDir(ctx *types.SystemContext, hostPort string) (string, error) {
if ctx != nil && ctx.DockerCertPath != "" {
- return ctx.DockerCertPath
+ return ctx.DockerCertPath, nil
}
- var hostCertDir string
if ctx != nil && ctx.DockerPerHostCertDirPath != "" {
- hostCertDir = ctx.DockerPerHostCertDirPath
- } else if ctx != nil && ctx.RootForImplicitAbsolutePaths != "" {
- hostCertDir = filepath.Join(ctx.RootForImplicitAbsolutePaths, systemPerHostCertDirPath)
- } else {
- hostCertDir = systemPerHostCertDirPath
+ return filepath.Join(ctx.DockerPerHostCertDirPath, hostPort), nil
}
- return filepath.Join(hostCertDir, hostPort)
+
+ var (
+ hostCertDir string
+ fullCertDirPath string
+ )
+ for _, systemPerHostCertDirPath := range systemPerHostCertDirPaths {
+ if ctx != nil && ctx.RootForImplicitAbsolutePaths != "" {
+ hostCertDir = filepath.Join(ctx.RootForImplicitAbsolutePaths, systemPerHostCertDirPath)
+ } else {
+ hostCertDir = systemPerHostCertDirPath
+ }
+
+ fullCertDirPath = filepath.Join(hostCertDir, hostPort)
+ _, err := os.Stat(fullCertDirPath)
+ if err == nil {
+ break
+ }
+ if os.IsNotExist(err) {
+ continue
+ }
+ if os.IsPermission(err) {
+ logrus.Debugf("error accessing certs directory due to permissions: %v", err)
+ continue
+ }
+ if err != nil {
+ return "", err
+ }
+ }
+ return fullCertDirPath, nil
}
// newDockerClientFromRef returns a new dockerClient instance for refHostname (a host a specified in the Docker image reference, not canonicalized to dockerRegistry)
@@ -177,7 +200,10 @@ func newDockerClientWithDetails(ctx *types.SystemContext, registry, username, pa
// dockerHostname here, because it is more symmetrical to read the configuration in that case as well, and because
// generally the UI hides the existence of the different dockerRegistry. But note that this behavior is
// undocumented and may change if docker/docker changes.
- certDir := dockerCertDir(ctx, hostName)
+ certDir, err := dockerCertDir(ctx, hostName)
+ if err != nil {
+ return nil, err
+ }
if err := tlsclientconfig.SetupCertificates(certDir, tr.TLSClientConfig); err != nil {
return nil, err
}