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 28, 2023
1 parent cd61327 commit 05edd7f
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 47 deletions.
33 changes: 13 additions & 20 deletions pass/pass.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,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 @@ -103,8 +98,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 @@ -146,17 +141,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 @@ -167,11 +161,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 @@ -203,9 +196,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
113 changes: 86 additions & 27 deletions pass/pass_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package pass

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

Expand All @@ -10,6 +12,82 @@ import (
func TestPassHelper(t *testing.T) {
helper := Pass{}

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.CheckInitialized()

for _, tc := range tests {
tc := tc
t.Run(tc.name, func(t *testing.T) {
helper.Add(tc.creds)
tc.creds.ServerURL = "https://foobar.docker.io:9999/v2"
helper.Add(tc.creds)

credsList, err := helper.List()
if err != nil {
t.Fatal(err)
}

for server, username := range credsList {
if !(strings.Contains(server, "2376") || strings.Contains(server, "9999")) {
t.Fatalf("invalid url: %s", tc.creds.ServerURL)
}
if username != tc.creds.Username {
t.Fatalf("invalid username: %v", username)
}
u, s, err := helper.Get(server)
if err != nil {
t.Fatal(err)
}
if u != username {
t.Fatalf("invalid username %s", u)
}
if s != tc.creds.Secret {
t.Fatalf("invalid secret: %s", s)
}
if err = helper.Delete(server); err != nil {
t.Fatal(err)
}
if _, _, err = helper.Get(server); !credentials.IsErrCredentialsNotFound(err) {
t.Fatalf("expected credentials not found, actual: %v", err)
}
}

credsList, err = helper.List()
if err != nil {
t.Fatal(err)
}

if len(credsList) != 0 {
t.Fatal("didn't delete all creds?")
}
})
}
}

func TestPassHelperBackwardCompat(t *testing.T) {
helper := Pass{}

creds := &credentials.Credentials{
ServerURL: "https://foobar.docker.io:2376/v1",
Username: "nothing",
Expand All @@ -18,58 +96,39 @@ func TestPassHelper(t *testing.T) {

_ = helper.CheckInitialized()

helper.Add(creds)

creds.ServerURL = "https://foobar.docker.io:9999/v2"
helper.Add(creds)
// add a credential with the old format
encodedServerURL := base64.URLEncoding.EncodeToString([]byte(creds.ServerURL))
_, _ = helper.runPass(creds.Secret, "insert", "-f", "-m", path.Join(PASS_FOLDER, encodedServerURL, creds.Username))

credsList, err := helper.List()
if err != nil {
t.Fatal(err)
}

for server, username := range credsList {
if !(strings.Contains(server, "2376") ||
strings.Contains(server, "9999")) {
if !(strings.Contains(server, "2376")) {
t.Fatalf("invalid url: %s", creds.ServerURL)
}

if username != "nothing" {
if username != creds.Username {
t.Fatalf("invalid username: %v", username)
}

u, s, err := helper.Get(server)
if err != nil {
t.Fatal(err)
}

if u != username {
t.Fatalf("invalid username %s", u)
}

if s != "isthebestmeshuggahalbum" {
if s != creds.Secret {
t.Fatalf("invalid secret: %s", s)
}

err = helper.Delete(server)
if err != nil {
if err = helper.Delete(server); err != nil {
t.Fatal(err)
}

_, _, err = helper.Get(server)
if !credentials.IsErrCredentialsNotFound(err) {
if _, _, err = helper.Get(server); !credentials.IsErrCredentialsNotFound(err) {
t.Fatalf("expected credentials not found, actual: %v", err)
}
}

credsList, err = helper.List()
if err != nil {
t.Fatal(err)
}

if len(credsList) != 0 {
t.Fatal("didn't delete all creds?")
}
}

func TestMissingCred(t *testing.T) {
Expand Down

0 comments on commit 05edd7f

Please sign in to comment.