Skip to content

Commit

Permalink
pass: base64 encoded username with backward compatility
Browse files Browse the repository at this point in the history
Signed-off-by: CrazyMax <[email protected]>
  • Loading branch information
crazy-max committed May 29, 2023
1 parent 7f4fa5e commit f78bca3
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 27 deletions.
33 changes: 13 additions & 20 deletions pass/pass.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,9 @@ func (p Pass) Add(creds *credentials.Credentials) error {
return errors.New("missing credentials")
}

encoded := base64.URLEncoding.EncodeToString([]byte(creds.ServerURL))

username := creds.Username
if strings.Contains(username, "/") {
username = base64.URLEncoding.EncodeToString([]byte(creds.Username))
}

_, err := p.runPass(creds.Secret, "insert", "-f", "-m", path.Join(PASS_FOLDER, encoded, username))
encodedServerURL := base64.URLEncoding.EncodeToString([]byte(creds.ServerURL))
encodedUsername := base64.URLEncoding.EncodeToString([]byte(creds.Username))
_, err := p.runPass(creds.Secret, "insert", "-f", "-m", path.Join(PASS_FOLDER, encodedServerURL, encodedUsername))
return err
}

Expand All @@ -104,8 +99,8 @@ func (p Pass) Delete(serverURL string) error {
return errors.New("missing server url")
}

encoded := base64.URLEncoding.EncodeToString([]byte(serverURL))
_, err := p.runPass("", "rm", "-rf", path.Join(PASS_FOLDER, encoded))
encodedServerURL := base64.URLEncoding.EncodeToString([]byte(serverURL))
_, err := p.runPass("", "rm", "-rf", path.Join(PASS_FOLDER, encodedServerURL))
return err
}

Expand Down Expand Up @@ -147,17 +142,16 @@ func (p Pass) Get(serverURL string) (string, string, error) {
return "", "", errors.New("missing server url")
}

encoded := base64.URLEncoding.EncodeToString([]byte(serverURL))

if _, err := os.Stat(path.Join(getPassDir(), PASS_FOLDER, encoded)); err != nil {
encodedServerURL := base64.URLEncoding.EncodeToString([]byte(serverURL))
if _, err := os.Stat(path.Join(getPassDir(), PASS_FOLDER, encodedServerURL)); err != nil {
if os.IsNotExist(err) {
return "", "", credentials.NewErrCredentialsNotFound()
}

return "", "", err
}

usernames, err := listPassDir(encoded)
usernames, err := listPassDir(encodedServerURL)
if err != nil {
return "", "", err
}
Expand All @@ -168,11 +162,10 @@ func (p Pass) Get(serverURL string) (string, string, error) {

actual := strings.TrimSuffix(usernames[0].Name(), ".gpg")
username := actual
decodedUsername, err := base64.URLEncoding.DecodeString(actual)
if err == nil {
if decodedUsername, err := base64.URLEncoding.DecodeString(actual); err == nil {
username = string(decodedUsername)
}
secret, err := p.runPass("", "show", path.Join(PASS_FOLDER, encoded, actual))
secret, err := p.runPass("", "show", path.Join(PASS_FOLDER, encodedServerURL, actual))
return username, secret, err
}

Expand Down Expand Up @@ -204,9 +197,9 @@ func (p Pass) List() (map[string]string, error) {
return nil, fmt.Errorf("no usernames for %s", serverURL)
}

resp[string(serverURL)] = strings.TrimSuffix(usernames[0].Name(), ".gpg")
decodedUsername, err := base64.URLEncoding.DecodeString(strings.TrimSuffix(usernames[0].Name(), ".gpg"))
if err == nil {
username := strings.TrimSuffix(usernames[0].Name(), ".gpg")
resp[string(serverURL)] = username
if decodedUsername, err := base64.URLEncoding.DecodeString(username); err == nil {
resp[string(serverURL)] = string(decodedUsername)
}
}
Expand Down
76 changes: 69 additions & 7 deletions pass/pass_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,76 @@
package pass

import (
"encoding/base64"
"path"
"strings"
"testing"

"github.com/docker/docker-credential-helpers/credentials"
)

func TestPassHelperCheckInit(t *testing.T) {
helper := Pass{}
if v := helper.CheckInitialized(); !v {
t.Errorf("expected true, actual: %v", v)
}
}

func TestPassHelper(t *testing.T) {
tests := []struct {
name string
creds *credentials.Credentials
}{
{
name: "create nothing",
creds: &credentials.Credentials{
ServerURL: "https://foobar.docker.io:2376/v1",
Username: "nothing",
Secret: "isthebestmeshuggahalbum",
},
},
{
name: "create foo/bar",
creds: &credentials.Credentials{
ServerURL: "https://foobar.docker.io:2376/v1",
Username: "foo/bar",
Secret: "foobarbaz",
},
},
}

helper := Pass{}
if err := helper.checkInitialized(); err != nil {
t.Error(err)
}

for _, tc := range tests {
tc := tc
t.Run(tc.name, func(t *testing.T) {
if err := helper.Add(tc.creds); err != nil {
t.Error(err)
}
u, s, err := helper.Get(tc.creds.ServerURL)
if err != nil {
t.Error(err)
}
if u != tc.creds.Username {
t.Errorf("invalid username %s", u)
}
if s != tc.creds.Secret {
t.Errorf("invalid secret: %s", s)
}
if err := helper.Delete(tc.creds.ServerURL); err != nil {
t.Error(err)
}
if _, _, err := helper.Get(tc.creds.ServerURL); !credentials.IsErrCredentialsNotFound(err) {
t.Errorf("expected credentials not found, actual: %v", err)
}
})
}
}

func TestPassHelperBackwardCompat(t *testing.T) {
creds := &credentials.Credentials{
ServerURL: "https://foobar.docker.io:2376/v1",
Username: "nothing",
Expand All @@ -21,6 +84,12 @@ func TestPassHelper(t *testing.T) {
t.Error(err)
}

// add a credential with the old format
encodedServerURL := base64.URLEncoding.EncodeToString([]byte(creds.ServerURL))
if _, err := helper.runPass(creds.Secret, "insert", "-f", "-m", path.Join(PASS_FOLDER, encodedServerURL, creds.Username)); err != nil {
t.Error(err)
}

if err := helper.Add(creds); err != nil {
t.Error(err)
}
Expand All @@ -44,13 +113,6 @@ func TestPassHelper(t *testing.T) {
}
}

func TestPassHelperCheckInit(t *testing.T) {
helper := Pass{}
if v := helper.CheckInitialized(); !v {
t.Errorf("expected true, actual: %v", v)
}
}

func TestPassHelperList(t *testing.T) {
creds := []*credentials.Credentials{
{
Expand Down

0 comments on commit f78bca3

Please sign in to comment.