pkg/auth: re-allow http{s} prefixes

Until version v3.2, `podman login` trimmed http{s} prefixes along with
everything else but the host[:port] parts.  Starting with v3.3, `login`
supports storing credentials for namespaces and dropped support for
trimming prefixes due to ambiguities in registry URLs.

The aforementioned changes caused a regression (see BZ below) as some
users depend on the prefix trimming.  Fix that regression by enabling
the http{s} prefix trimming.  If present, everything but the host[:port]
parts will be stripped as well.

 * `login quay.io/repo` uses `quay.io/repo`
 * `login https://quay.io/repo` uses `quay.io`

Fixes: bugzilla.redhat.com/show_bug.cgi?id=2062072
Signed-off-by: Valentin Rothberg <vrothberg@redhat.com>
This commit is contained in:
Valentin Rothberg 2022-03-16 10:45:24 +01:00
parent 7d08b8b9f7
commit c9914e52de
2 changed files with 90 additions and 30 deletions

View File

@ -4,6 +4,7 @@ import (
"bufio"
"context"
"fmt"
"net/url"
"os"
"path/filepath"
"strings"
@ -165,20 +166,21 @@ func Login(ctx context.Context, systemContext *types.SystemContext, opts *LoginO
// parseCredentialsKey turns the provided argument into a valid credential key
// and computes the registry part.
func parseCredentialsKey(arg string, acceptRepositories bool) (key, registry string, err error) {
// URL arguments are replaced with their host[:port] parts.
key, err = replaceURLByHostPort(arg)
if err != nil {
return "", "", err
}
split := strings.Split(key, "/")
registry = split[0]
if !acceptRepositories {
registry = getRegistryName(arg)
key = registry
return key, registry, nil
return registry, registry, nil
}
key = trimScheme(arg)
if key != arg {
return "", "", errors.New("credentials key has https[s]:// prefix")
}
registry = getRegistryName(key)
// Return early if the key isn't namespaced or uses an http{s} prefix.
if registry == key {
// The key is not namespaced
return key, registry, nil
}
@ -202,24 +204,18 @@ func parseCredentialsKey(arg string, acceptRepositories bool) (key, registry str
return key, registry, nil
}
// getRegistryName scrubs and parses the input to get the server name
func getRegistryName(server string) string {
// removes 'http://' or 'https://' from the front of the
// server/registry string if either is there. This will be mostly used
// for user input from 'Buildah login' and 'Buildah logout'.
server = trimScheme(server)
// gets the registry from the input. If the input is of the form
// quay.io/myuser/myimage, it will parse it and just return quay.io
split := strings.Split(server, "/")
return split[0]
}
// trimScheme removes the HTTP(s) scheme from the provided repository.
func trimScheme(repository string) string {
// removes 'http://' or 'https://' from the front of the
// server/registry string if either is there. This will be mostly used
// for user input from 'Buildah login' and 'Buildah logout'.
return strings.TrimPrefix(strings.TrimPrefix(repository, "https://"), "http://")
// If the specified string starts with http{s} it is replaced with it's
// host[:port] parts; everything else is stripped. Otherwise, the string is
// returned as is.
func replaceURLByHostPort(repository string) (string, error) {
if !strings.HasPrefix(repository, "https://") && !strings.HasPrefix(repository, "http://") {
return repository, nil
}
u, err := url.Parse(repository)
if err != nil {
return "", fmt.Errorf("trimming http{s} prefix: %v", err)
}
return u.Host, nil
}
// getUserAndPass gets the username and password from STDIN if not given

View File

@ -104,10 +104,74 @@ func TestParseCredentialsKey(t *testing.T) {
expectedRegistry: "docker.io",
},
{
name: "with http[s] prefix",
name: "with http[s] prefix - accept repositories",
arg: "https://quay.io",
acceptRepositories: true,
expectedKey: "",
expectedKey: "quay.io",
expectedRegistry: "quay.io",
},
{
name: "with http[s] prefix - accept repositories",
arg: "http://example.com/v2/",
acceptRepositories: true,
expectedKey: "example.com",
expectedRegistry: "example.com",
},
{
name: "with http[s] prefix + path - accept repositories",
arg: "https://quay.io/repo/imag:tag",
acceptRepositories: true,
expectedKey: "quay.io",
expectedRegistry: "quay.io",
},
{
name: "with http[s] prefix + port - accept repositories",
arg: "https://quay.io:1234",
acceptRepositories: true,
expectedKey: "quay.io:1234",
expectedRegistry: "quay.io:1234",
},
{
name: "with http[s] prefix + port + path - accept repositories",
arg: "https://quay.io:1234/repo@foo",
acceptRepositories: true,
expectedKey: "quay.io:1234",
expectedRegistry: "quay.io:1234",
},
{
name: "with http[s] prefix",
arg: "https://quay.io",
acceptRepositories: false,
expectedKey: "quay.io",
expectedRegistry: "quay.io",
},
{
name: "with http[s] prefix",
arg: "http://example.com/v2/",
acceptRepositories: false,
expectedKey: "example.com",
expectedRegistry: "example.com",
},
{
name: "with http[s] prefix + path",
arg: "https://quay.io/repo/imag:tag",
acceptRepositories: false,
expectedKey: "quay.io",
expectedRegistry: "quay.io",
},
{
name: "with http[s] prefix + port",
arg: "https://quay.io:1234",
acceptRepositories: false,
expectedKey: "quay.io:1234",
expectedRegistry: "quay.io:1234",
},
{
name: "with http[s] prefix + port + path",
arg: "https://quay.io:1234/repo@foo",
acceptRepositories: false,
expectedKey: "quay.io:1234",
expectedRegistry: "quay.io:1234",
},
{
name: "failure with tag",