Allow empty credentials registry (#1004)

* Allow empty credentials registry

Useful when using local unsecured registry.

Signed-off-by: Matej Vasek <mvasek@redhat.com>

* Added tests for empty credentials registries

Signed-off-by: Matej Vasek <mvasek@redhat.com>
This commit is contained in:
Matej Vasek 2022-05-05 20:42:28 +02:00 committed by GitHub
parent 75fe105969
commit ac8f1d2d66
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 74 additions and 31 deletions

View File

@ -36,13 +36,6 @@ type VerifyCredentialsCallback func(ctx context.Context, registry string, creden
// CheckAuth verifies that credentials are correct
func CheckAuth(ctx context.Context, registry string, credentials docker.Credentials, trans http.RoundTripper) error {
serverAddress := registry
if !strings.HasPrefix(serverAddress, "https://") && !strings.HasPrefix(serverAddress, "http://") {
serverAddress = "https://" + serverAddress
}
url := fmt.Sprintf("%s/v2/", serverAddress)
authenticator := &authn.Basic{
Username: credentials.Username,
Password: credentials.Password,
@ -53,6 +46,13 @@ func CheckAuth(ctx context.Context, registry string, credentials docker.Credenti
return err
}
serverAddress := registry
if !strings.HasPrefix(serverAddress, "https://") && !strings.HasPrefix(serverAddress, "http://") {
serverAddress = reg.Scheme() + "://" + serverAddress
}
url := fmt.Sprintf("%s/v2/", serverAddress)
tr, err := transport.NewWithContext(ctx, reg, authenticator, trans, nil)
if err != nil {
var transportErr *transport.Error
@ -189,6 +189,9 @@ func NewCredentialsProvider(opts ...Opt) docker.CredentialsProvider {
dockerConfigPath := filepath.Join(home, ".docker", "config.json")
var defaultCredentialLoaders = []CredentialsCallback{
func(registry string) (docker.Credentials, error) { // empty credentials provider for unsecured registries
return docker.Credentials{}, nil
},
func(registry string) (docker.Credentials, error) {
creds, err := config.GetCredentials(sys, registry)
if err != nil {
@ -220,20 +223,22 @@ func (c *credentialsProvider) getCredentials(ctx context.Context, registry strin
result, err = load(registry)
if err != nil && !errors.Is(err, errCredentialsNotFound) {
if err != nil {
if errors.Is(err, errCredentialsNotFound) {
continue
}
return docker.Credentials{}, err
}
if result != (docker.Credentials{}) {
err = c.verifyCredentials(ctx, registry, result)
if err == nil {
return result, nil
} else {
if !errors.Is(err, ErrUnauthorized) {
return docker.Credentials{}, err
}
err = c.verifyCredentials(ctx, registry, result)
if err == nil {
return result, nil
} else {
if !errors.Is(err, ErrUnauthorized) {
return docker.Credentials{}, err
}
}
}
if c.promptForCredentials == nil {

View File

@ -68,8 +68,15 @@ func Test_registryEquals(t *testing.T) {
}
func TestCheckAuth(t *testing.T) {
localhost, localhostTLS, stopServer := startServer(t)
defer stopServer()
const (
uname = "testuser"
pwd = "testpwd"
incorrectPwd = "badpwd"
)
localhost, localhostTLS, stopServer := startServer(t, uname, pwd)
t.Cleanup(stopServer)
_, portTLS, err := net.SplitHostPort(localhostTLS)
if err != nil {
@ -93,8 +100,8 @@ func TestCheckAuth(t *testing.T) {
name: "correct credentials localhost no-TLS",
args: args{
ctx: context.Background(),
username: "testuser",
password: "testpwd",
username: uname,
password: pwd,
registry: localhost,
},
wantErr: false,
@ -103,8 +110,8 @@ func TestCheckAuth(t *testing.T) {
name: "correct credentials localhost",
args: args{
ctx: context.Background(),
username: "testuser",
password: "testpwd",
username: uname,
password: pwd,
registry: localhostTLS,
},
wantErr: false,
@ -114,8 +121,8 @@ func TestCheckAuth(t *testing.T) {
name: "correct credentials non-localhost",
args: args{
ctx: context.Background(),
username: "testuser",
password: "testpwd",
username: uname,
password: pwd,
registry: nonLocalhostTLS,
},
wantErr: false,
@ -124,8 +131,8 @@ func TestCheckAuth(t *testing.T) {
name: "incorrect credentials localhost no-TLS",
args: args{
ctx: context.Background(),
username: "testuser",
password: "badpwd",
username: uname,
password: incorrectPwd,
registry: localhost,
},
wantErr: true,
@ -134,8 +141,8 @@ func TestCheckAuth(t *testing.T) {
name: "incorrect credentials localhost",
args: args{
ctx: context.Background(),
username: "testuser",
password: "badpwd",
username: uname,
password: incorrectPwd,
registry: localhostTLS,
},
wantErr: true,
@ -154,7 +161,17 @@ func TestCheckAuth(t *testing.T) {
}
}
func startServer(t *testing.T) (addr, addrTLS string, stopServer func()) {
func TestCheckAuthEmptyCreds(t *testing.T) {
localhost, _, stopServer := startServer(t, "", "")
t.Cleanup(stopServer)
err := creds.CheckAuth(context.Background(), localhost, docker.Credentials{}, http.DefaultTransport)
if err != nil {
t.Error(err)
}
}
func startServer(t *testing.T, uname, pwd string) (addr, addrTLS string, stopServer func()) {
// TODO: this should be refactored to use OS-chosen ports so as not to
// fail when a user is running a Function on the default port.)
listener, err := net.Listen("tcp", "localhost:0")
@ -170,10 +187,14 @@ func startServer(t *testing.T) (addr, addrTLS string, stopServer func()) {
addrTLS = listenerTLS.Addr().String()
handler := http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
if uname == "" || pwd == "" {
resp.WriteHeader(http.StatusOK)
return
}
// TODO add also test for token based auth
resp.Header().Add("WWW-Authenticate", "basic")
if user, pwd, ok := req.BasicAuth(); ok {
if user == "testuser" && pwd == "testpwd" {
if u, p, ok := req.BasicAuth(); ok {
if u == uname && p == pwd {
resp.WriteHeader(http.StatusOK)
return
}
@ -401,6 +422,23 @@ func TestNewCredentialsProvider(t *testing.T) {
}
}
func TestNewCredentialsProviderEmptyCreds(t *testing.T) {
credentialsProvider := creds.NewCredentialsProvider(creds.WithVerifyCredentials(func(ctx context.Context, registry string, credentials docker.Credentials) error {
if registry == "localhost:5000" && credentials == (docker.Credentials{}) {
return nil
}
t.Fatal("unreachable")
return nil
}))
c, err := credentialsProvider(context.Background(), "localhost:5000")
if err != nil {
t.Error(err)
}
if c != (docker.Credentials{}) {
t.Error("unexpected credentials")
}
}
func TestCredentialsProviderSavingFromUserInput(t *testing.T) {
defer withCleanHome(t)()