diff --git a/engine/auth/auth.go b/engine/auth/auth.go deleted file mode 100644 index 997bb12..0000000 --- a/engine/auth/auth.go +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2019 Drone.IO Inc. All rights reserved. -// Use of this source code is governed by the Polyform License -// that can be found in the LICENSE file. - -package auth - -import ( - "encoding/base64" - "encoding/json" - "io" - "net/url" - "os" - "strings" - - "github.com/drone-runners/drone-runner-docker/engine" -) - -// config represents the Docker client configuration, -// typically located at ~/.docker/config.json -type config struct { - Auths map[string]auths `json:"auths"` -} - -type auths struct { - Auth string `json:"auth"` -} - -// Parse parses the registry credential from the reader. -func Parse(r io.Reader) ([]*engine.Auth, error) { - c := new(config) - err := json.NewDecoder(r).Decode(c) - if err != nil { - return nil, err - } - var auths []*engine.Auth - for k, v := range c.Auths { - username, password := decode(v.Auth) - auths = append(auths, &engine.Auth{ - Address: hostname(k), - Username: username, - Password: password, - }) - } - return auths, nil -} - -// ParseFile parses the registry credential file. -func ParseFile(filepath string) ([]*engine.Auth, error) { - f, err := os.Open(filepath) - if err != nil { - return nil, err - } - defer f.Close() - return Parse(f) -} - -// ParseString parses the registry credential file. -func ParseString(s string) ([]*engine.Auth, error) { - return Parse(strings.NewReader(s)) -} - -// encode returns the encoded credentials. -func encode(username, password string) string { - return base64.StdEncoding.EncodeToString( - []byte(username + ":" + password), - ) -} - -// decode returns the decoded credentials. -func decode(s string) (username, password string) { - d, err := base64.StdEncoding.DecodeString(s) - if err != nil { - return - } - parts := strings.SplitN(string(d), ":", 2) - if len(parts) > 0 { - username = parts[0] - } - if len(parts) > 1 { - password = parts[1] - } - return -} - -func hostname(s string) string { - uri, _ := url.Parse(s) - if uri.Host != "" { - s = uri.Host - } - return s -} - -// Encode returns the json marshaled, base64 encoded -// credential string that can be passed to the docker -// registry authentication header. -func Encode(username, password string) string { - v := struct { - Username string `json:"username,omitempty"` - Password string `json:"password,omitempty"` - }{ - Username: username, - Password: password, - } - buf, _ := json.Marshal(&v) - return base64.URLEncoding.EncodeToString(buf) -} - -// Marshal marshals the Auth credentials to a -// .docker/config.json file. -func Marshal(list []*engine.Auth) ([]byte, error) { - out := &config{} - out.Auths = map[string]auths{} - for _, item := range list { - out.Auths[item.Address] = auths{ - Auth: encode( - item.Username, - item.Password, - ), - } - } - return json.Marshal(out) -} diff --git a/engine/auth/auth_test.go b/engine/auth/auth_test.go deleted file mode 100644 index 6b94d72..0000000 --- a/engine/auth/auth_test.go +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2019 Drone.IO Inc. All rights reserved. -// Use of this source code is governed by the Polyform License -// that can be found in the LICENSE file. - -package auth - -import ( - "bytes" - "encoding/base64" - "os" - "testing" - - "github.com/drone-runners/drone-runner-docker/engine" - - "github.com/google/go-cmp/cmp" -) - -func TestParse(t *testing.T) { - got, err := ParseString(sample) - if err != nil { - t.Error(err) - return - } - want := []*engine.Auth{ - { - Address: "index.docker.io", - Username: "octocat", - Password: "correct-horse-battery-staple", - }, - } - if diff := cmp.Diff(got, want); diff != "" { - t.Errorf(diff) - } -} - -func TestParseGCR(t *testing.T) { - got, err := ParseFile("testdata/config_gcr.json") - if err != nil { - t.Error(err) - return - } - want := []*engine.Auth{ - { - Address: "gcr.io", - Username: "_json_key", - Password: "xxx:bar\n", - }, - } - if diff := cmp.Diff(got, want); diff != "" { - t.Errorf(diff) - } -} - -func TestParseErr(t *testing.T) { - _, err := ParseString("") - if err == nil { - t.Errorf("Expect unmarshal error") - } -} - -func TestParseFile(t *testing.T) { - got, err := ParseFile("./testdata/config.json") - if err != nil { - t.Error(err) - return - } - want := []*engine.Auth{ - { - Address: "index.docker.io", - Username: "octocat", - Password: "correct-horse-battery-staple", - }, - } - if diff := cmp.Diff(got, want); diff != "" { - t.Errorf(diff) - } -} - -func TestParseFileErr(t *testing.T) { - _, err := ParseFile("./testdata/x.json") - if _, ok := err.(*os.PathError); !ok { - t.Errorf("Expect error when file does not exist") - } -} - -func Test_encodeDecode(t *testing.T) { - username := "octocat" - password := "correct-horse-battery-staple" - - encoded := encode(username, password) - decodedUsername, decodedPassword := decode(encoded) - if got, want := decodedUsername, username; got != want { - t.Errorf("Want decoded username %s, got %s", want, got) - } - if got, want := decodedPassword, password; got != want { - t.Errorf("Want decoded password %s, got %s", want, got) - } -} - -func Test_decodeInvalid(t *testing.T) { - username, password := decode("b2N0b2NhdDp==") - if username != "" || password != "" { - t.Errorf("Expect decoding error") - } -} - -func TestEncode(t *testing.T) { - username := "octocat" - password := "correct-horse-battery-staple" - result := Encode(username, password) - got, err := base64.URLEncoding.DecodeString(result) - if err != nil { - t.Error(err) - return - } - want := []byte(`{"username":"octocat","password":"correct-horse-battery-staple"}`) - if bytes.Equal(got, want) == false { - t.Errorf("Could not decode credential header") - } -} - -func TestMarshal(t *testing.T) { - auths := []*engine.Auth{ - { - Address: "index.docker.io", - Username: "octocat", - Password: "correct-horse-battery-staple", - }, - } - got, _ := Marshal(auths) - want := []byte(`{"auths":{"index.docker.io":{"auth":"b2N0b2NhdDpjb3JyZWN0LWhvcnNlLWJhdHRlcnktc3RhcGxl"}}}`) - if bytes.Equal(got, want) == false { - t.Errorf("Could not decode credential header") - } -} - -var sample = `{ - "auths": { - "https://index.docker.io/v1/": { - "auth": "b2N0b2NhdDpjb3JyZWN0LWhvcnNlLWJhdHRlcnktc3RhcGxl" - } - } -}` diff --git a/engine/auth/testdata/config.json b/engine/auth/testdata/config.json deleted file mode 100644 index 382c690..0000000 --- a/engine/auth/testdata/config.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "auths": { - "https://index.docker.io/v1/": { - "auth": "b2N0b2NhdDpjb3JyZWN0LWhvcnNlLWJhdHRlcnktc3RhcGxl" - } - } -} \ No newline at end of file diff --git a/engine/auth/testdata/config_gcr.json b/engine/auth/testdata/config_gcr.json deleted file mode 100644 index 259907a..0000000 --- a/engine/auth/testdata/config_gcr.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "auths": { - "gcr.io": { - "auth": "X2pzb25fa2V5Onh4eDpiYXIK" - } - } -} \ No newline at end of file