From b1d5bf03262b69fd08a5d13b7ac058b935f61d55 Mon Sep 17 00:00:00 2001 From: Albin Kerouanton Date: Fri, 28 Feb 2025 19:16:05 +0100 Subject: [PATCH] osxkeychain: list: return full server URIs Commit 4cdcdc2 changed the format of `list` output. Before that commit, the json keys were containing full URIs (scheme://host/path[:port]), but afterward, the keys were only containing the path component. With this commit, the `list` operation now returns full URIs (fixing the regression), and also fixes the malformed URIs issue when a port is specified (introduced by 19ec1c3, and affecting >=v0.4.2, --- osxkeychain/osxkeychain.go | 18 ++++++++++-- osxkeychain/osxkeychain_test.go | 51 ++++++++++++++++++++++++--------- 2 files changed, 53 insertions(+), 16 deletions(-) diff --git a/osxkeychain/osxkeychain.go b/osxkeychain/osxkeychain.go index b513763..9d277d3 100644 --- a/osxkeychain/osxkeychain.go +++ b/osxkeychain/osxkeychain.go @@ -12,6 +12,8 @@ import "C" import ( "errors" + "net" + "net/url" "strconv" "github.com/docker/docker-credential-helpers/credentials" @@ -121,10 +123,20 @@ func (h Osxkeychain) List() (map[string]string, error) { resp := make(map[string]string) for _, r := range res { - if r.Path == "" { - continue + proto := "http" + if r.Protocol == kSecProtocolTypeHTTPS { + proto = "https" } - resp[r.Path] = r.Account + host := r.Server + if r.Port != 0 { + host = net.JoinHostPort(host, strconv.Itoa(int(r.Port))) + } + u := url.URL{ + Scheme: proto, + Host: host, + Path: r.Path, + } + resp[u.String()] = r.Account } return resp, nil } diff --git a/osxkeychain/osxkeychain_test.go b/osxkeychain/osxkeychain_test.go index c4adddf..7764ecb 100644 --- a/osxkeychain/osxkeychain_test.go +++ b/osxkeychain/osxkeychain_test.go @@ -15,11 +15,6 @@ func TestOSXKeychainHelper(t *testing.T) { Username: "foobar", Secret: "foobarbaz", } - creds1 := &credentials.Credentials{ - ServerURL: "https://foobar.example.com:2376/v2", - Username: "foobarbaz", - Secret: "foobar", - } helper := Osxkeychain{} if err := helper.Add(creds); err != nil { t.Fatal(err) @@ -43,19 +38,49 @@ func TestOSXKeychainHelper(t *testing.T) { t.Fatal(err) } - helper.Add(creds1) - defer helper.Delete(creds1.ServerURL) - newauths, err := helper.List() - if len(newauths)-len(auths) != 1 { - if err == nil { - t.Fatalf("Error: len(newauths): %d, len(auths): %d", len(newauths), len(auths)) - } - t.Fatalf("Error: len(newauths): %d, len(auths): %d\n Error= %v", len(newauths), len(auths), err) + if _, ok := auths[creds.ServerURL]; !ok { + t.Fatalf("server %s not found in list, got: %+v", creds.ServerURL, auths) } + // Insert another token and check if it is in the list + creds1 := &credentials.Credentials{ + ServerURL: "https://foobar.example.com:2376/v2", + Username: "foobarbaz", + Secret: "foobar", + } + helper.Add(creds1) + defer helper.Delete(creds1.ServerURL) + + auths, err = helper.List() + if err != nil { + t.Fatalf("operation List failed: %+v", err) + } + + if _, ok := auths[creds.ServerURL]; !ok { + t.Fatalf("server %s not found in list, got: %+v", creds.ServerURL, auths) + } + if _, ok := auths[creds1.ServerURL]; !ok { + t.Fatalf("server %s not found in list, got: %+v", creds1.ServerURL, auths) + } + + // Delete the 1st token inserted if err := helper.Delete(creds.ServerURL); err != nil { t.Fatal(err) } + + auths, err = helper.List() + if err != nil { + t.Fatalf("operation List failed: %+v", err) + } + + // First token should have been deleted + if _, ok := auths[creds.ServerURL]; ok { + t.Fatalf("server %s was not deleted, got: %+v", creds.ServerURL, auths) + } + // Second token should still be there + if _, ok := auths[creds1.ServerURL]; !ok { + t.Fatalf("server %s not found in list, got: %+v", creds1.ServerURL, auths) + } } // TestOSXKeychainHelperRetrieveAliases verifies that secrets can be accessed