1
0
mirror of https://github.com/docker/docker-credential-helpers.git synced 2026-06-28 07:11:36 +05:30

Compare commits

...

13 Commits

Author SHA1 Message Date
David Calavera 5128fa1bad Release v0.3.0.
Signed-off-by: David Calavera <david.calavera@gmail.com>
2016-05-31 17:41:15 -07:00
Vincent Demeester fee9277aa7 Merge pull request #15 from calavera/client
Add client functions to allow integrations within other CLIs.
2016-06-01 00:08:41 +02:00
David Calavera d80b179703 Merge pull request #16 from calavera/maintainers_file
Add maintainers file.
2016-05-31 14:52:43 -07:00
David Calavera c4fc9c07dd Add client functions to allow integrations within other CLIs.
This is a simplification of how the docker engine implements
this feature, but it will be ported there once this is merged.

Signed-off-by: David Calavera <david.calavera@gmail.com>
2016-05-30 12:32:26 -07:00
David Calavera 2c63e775b4 Add maintainers file.
Signed-off-by: David Calavera <david.calavera@gmail.com>
2016-05-27 18:19:08 -07:00
David Calavera 00703eb6db Merge pull request #13 from calavera/export_helpers
Publish helper structs and methods.
2016-03-24 15:56:00 -07:00
David Calavera df8c7a02f1 Publish helper structs and methods.
Signed-off-by: David Calavera <david.calavera@gmail.com>
2016-03-24 15:08:17 -07:00
David Calavera 4b8917b1cf Merge pull request #12 from calavera/export_library
Export credentials functions to be able to use them as a library.
2016-03-24 13:32:25 -07:00
David Calavera 039c315f22 Export credentials functions to be able to use them as a library.
Signed-off-by: David Calavera <david.calavera@gmail.com>
2016-03-24 14:52:17 -04:00
David Calavera 6bbb56ae3c Merge pull request #11 from mgreau/fix-doc
Update related to the move to Docker Organization
2016-03-18 13:21:15 -07:00
Maxime Gréau ec937eebe2 Update related to the move to Docker Organization
- Fix link to project releases
  - Fix go command

Signed-off-by: Maxime Gréau <greaumaxime@gmail.com>
2016-03-17 00:18:01 +01:00
David Calavera fa24bb8912 Merge pull request #10 from calavera/release_description
Add a link to the Changelog in each release.
2016-03-15 10:27:01 -07:00
David Calavera 76055c2deb Add a link to the Changelog in each release.
Signed-off-by: David Calavera <david.calavera@gmail.com>
2016-03-14 14:04:17 -04:00
20 changed files with 603 additions and 89 deletions
+4
View File
@@ -4,6 +4,10 @@ This changelog tracks the releases of docker-credential-helpers.
This project includes different binaries per platform.
The platform released is identified after the tag name.
## v0.3.0 (Go client)
- Add Go client library to talk with the native programs.
## v0.2.0 (Mac OS X, Windows, Linux)
- Initial release of docker-credential-secretservice for Linux.
+160
View File
@@ -0,0 +1,160 @@
# docker-credential-helpers maintainers file
#
# This file describes who runs the docker/docker-credential-helpers project and how.
# This is a living document - if you see something out of date or missing, speak up!
#
# It is structured to be consumable by both humans and programs.
# To extract its contents programmatically, use any TOML-compliant parser.
#
# This file is compiled into the MAINTAINERS file in docker/opensource.
#
[Org]
[Org."Core maintainers"]
people = [
"aaronlehmann",
"calavera",
"coolljt0725",
"cpuguy83",
"crosbymichael",
"dnephin",
"dongluochen",
"duglin",
"estesp",
"icecrime",
"jhowardmsft",
"lk4d4",
"mavenugo",
"mhbauer",
"runcom",
"stevvooe",
"thajeztah",
"tianon",
"tibor",
"tonistiigi",
"unclejack",
"vdemeester",
"vieux"
]
[people]
# A reference list of all people associated with the project.
# All other sections should refer to people by their canonical key
# in the people section.
# ADD YOURSELF HERE IN ALPHABETICAL ORDER
[people.aaronlehmann]
Name = "Aaron Lehmann"
Email = "aaron.lehmann@docker.com"
GitHub = "aaronlehmann"
[people.calavera]
Name = "David Calavera"
Email = "david.calavera@gmail.com"
GitHub = "calavera"
[people.coolljt0725]
Name = "Lei Jitang"
Email = "leijitang@huawei.com"
GitHub = "coolljt0725"
[people.cpuguy83]
Name = "Brian Goff"
Email = "cpuguy83@gmail.com"
Github = "cpuguy83"
[people.crosbymichael]
Name = "Michael Crosby"
Email = "crosbymichael@gmail.com"
GitHub = "crosbymichael"
[people.dnephin]
Name = "Daniel Nephin"
Email = "dnephin@gmail.com"
GitHub = "dnephin"
[people.dongluochen]
Name = "Dongluo Chen"
Email = "dongluo.chen@docker.com"
GitHub = "dongluochen"
[people.duglin]
Name = "Doug Davis"
Email = "dug@us.ibm.com"
GitHub = "duglin"
[people.estesp]
Name = "Phil Estes"
Email = "estesp@linux.vnet.ibm.com"
GitHub = "estesp"
[people.icecrime]
Name = "Arnaud Porterie"
Email = "arnaud@docker.com"
GitHub = "icecrime"
[people.jhowardmsft]
Name = "John Howard"
Email = "jhoward@microsoft.com"
GitHub = "jhowardmsft"
[people.lk4d4]
Name = "Alexander Morozov"
Email = "lk4d4@docker.com"
GitHub = "lk4d4"
[people.mavenugo]
Name = "Madhu Venugopal"
Email = "madhu@docker.com"
GitHub = "mavenugo"
[people.mhbauer]
Name = "Morgan Bauer"
Email = "mbauer@us.ibm.com"
GitHub = "mhbauer"
[people.runcom]
Name = "Antonio Murdaca"
Email = "runcom@redhat.com"
GitHub = "runcom"
[people.stevvooe]
Name = "Stephen Day"
Email = "stephen.day@docker.com"
GitHub = "stevvooe"
[people.thajeztah]
Name = "Sebastiaan van Stijn"
Email = "github@gone.nl"
GitHub = "thaJeztah"
[people.tianon]
Name = "Tianon Gravi"
Email = "admwiggin@gmail.com"
GitHub = "tianon"
[people.tibor]
Name = "Tibor Vass"
Email = "tibor@docker.com"
GitHub = "tiborvass"
[people.tonistiigi]
Name = "Tõnis Tiigi"
Email = "tonis@docker.com"
GitHub = "tonistiigi"
[people.unclejack]
Name = "Cristian Staretu"
Email = "cristian.staretu@gmail.com"
GitHub = "unclejack"
[people.vdemeester]
Name = "Vincent Demeester"
Email = "vincent@sbr.pm"
GitHub = "vdemeester"
[people.vieux]
Name = "Victor Vieux"
Email = "vieux@docker.com"
GitHub = "vieux"
+20 -5
View File
@@ -4,7 +4,7 @@ docker-credential-helpers is a suite of programs to use native stores to keep Do
## Installation
Go to the [Releases](https://github.com/calavera/docker-credential-helpers/releases) page and download the binary that works better for you. Put that binary in your `$PATH`, so Docker can find it.
Go to the [Releases](https://github.com/docker/docker-credential-helpers/releases) page and download the binary that works better for you. Put that binary in your `$PATH`, so Docker can find it.
### Building from scratch
@@ -13,13 +13,13 @@ The programs in this repository are written with the Go programming language. Th
1 - Download the source and put it in your `$GOPATH` with `go get`.
```
$ go get github.com/calavera/docker-credential-helpers
$ go get github.com/docker/docker-credential-helpers
```
2 - Use `make` to build the program you want. That will leave any executable in the `bin` directory inside the repository.
```
$ cd $GOPATH/calavera/docker-credentials-helpers
$ cd $GOPATH/docker/docker-credentials-helpers
$ make osxkeychain
```
@@ -27,6 +27,8 @@ $ make osxkeychain
## Usage
### With the Docker Engine
Set the `credsStore` option in your `.docker/config.json` file with the suffix of the program you want to use. For instance, set it to `osxkeychain` if you want to use `docker-credential-osxkeychain`.
```json
@@ -35,11 +37,24 @@ Set the `credsStore` option in your `.docker/config.json` file with the suffix o
}
```
### With other command line applications
The sub-package [client](https://godoc.org/github.com/docker/docker-credential-helpers/client) includes
functions to call external programs from your own command line applications.
There are three things you need to know if you need to interact with a helper:
1. The name of the program to execute, for instance `docker-credential-osxkeychain`.
2. The server address to identify the credentials, for instance `https://example.com`.
3. The username and secret to store, when you want to store credentials.
You can see examples of each function in the [client](https://godoc.org/github.com/docker/docker-credential-helpers/client) documentation.
### Available programs
1. osxkeychain: Provides a helper to use the OS X keychain as credentials store.
1. secretservice: Provides a helper to use the D-Bus secret service as credentials store.
2. wincred: Provides a helper to use Windows credentials manager as store.
2. secretservice: Provides a helper to use the D-Bus secret service as credentials store.
3. wincred: Provides a helper to use Windows credentials manager as store.
## Development
+1
View File
@@ -53,6 +53,7 @@ artifacts:
deploy:
# All the zipped artifacts will be deployed
description: "Visit the [Changelog](https://github.com/docker/docker-credential-helpers/blob/master/CHANGELOG.md) for a detailed description of what's new in this release."
artifact: /.*\.zip/
auth_token:
secure: ixWmTXZs8aV5+9s6vPXziIcdMMLd+lBVINJ0K/Sy++2wllpRxUec4/TPVKUGLqvL
+70
View File
@@ -0,0 +1,70 @@
package client
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"github.com/docker/docker-credential-helpers/credentials"
)
// Store uses an external program to save credentials.
func Store(program ProgramFunc, credentials *credentials.Credentials) error {
cmd := program("store")
buffer := new(bytes.Buffer)
if err := json.NewEncoder(buffer).Encode(credentials); err != nil {
return err
}
cmd.Input(buffer)
out, err := cmd.Output()
if err != nil {
t := strings.TrimSpace(string(out))
return fmt.Errorf("error storing credentials - err: %v, out: `%s`", err, t)
}
return nil
}
// Get executes an external program to get the credentials from a native store.
func Get(program ProgramFunc, serverURL string) (*credentials.Credentials, error) {
cmd := program("get")
cmd.Input(strings.NewReader(serverURL))
out, err := cmd.Output()
if err != nil {
t := strings.TrimSpace(string(out))
if credentials.IsErrCredentialsNotFoundMessage(t) {
return nil, credentials.NewErrCredentialsNotFound()
}
return nil, fmt.Errorf("error getting credentials - err: %v, out: `%s`", err, t)
}
resp := &credentials.Credentials{
ServerURL: serverURL,
}
if err := json.NewDecoder(bytes.NewReader(out)).Decode(resp); err != nil {
return nil, err
}
return resp, nil
}
// Erase executes a program to remove the server credentails from the native store.
func Erase(program ProgramFunc, serverURL string) error {
cmd := program("erase")
cmd.Input(strings.NewReader(serverURL))
out, err := cmd.Output()
if err != nil {
t := strings.TrimSpace(string(out))
return fmt.Errorf("error erasing credentials - err: %v, out: `%s`", err, t)
}
return nil
}
+192
View File
@@ -0,0 +1,192 @@
package client
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"strings"
"testing"
"github.com/docker/docker-credential-helpers/credentials"
)
const (
validServerAddress = "https://index.docker.io/v1"
validServerAddress2 = "https://example.com:5002"
invalidServerAddress = "https://foobar.example.com"
missingCredsAddress = "https://missing.docker.io/v1"
)
var errProgramExited = fmt.Errorf("exited 1")
// mockProgram simulates interactions between the docker client and a remote
// credentials helper.
// Unit tests inject this mocked command into the remote to control execution.
type mockProgram struct {
arg string
input io.Reader
}
// Output returns responses from the remote credentials helper.
// It mocks those responses based in the input in the mock.
func (m *mockProgram) Output() ([]byte, error) {
in, err := ioutil.ReadAll(m.input)
if err != nil {
return nil, err
}
inS := string(in)
switch m.arg {
case "erase":
switch inS {
case validServerAddress:
return nil, nil
default:
return []byte("program failed"), errProgramExited
}
case "get":
switch inS {
case validServerAddress:
return []byte(`{"Username": "foo", "Secret": "bar"}`), nil
case validServerAddress2:
return []byte(`{"Username": "<token>", "Secret": "abcd1234"}`), nil
case missingCredsAddress:
return []byte(credentials.NewErrCredentialsNotFound().Error()), errProgramExited
case invalidServerAddress:
return []byte("program failed"), errProgramExited
}
case "store":
var c credentials.Credentials
err := json.NewDecoder(strings.NewReader(inS)).Decode(&c)
if err != nil {
return []byte("error storing credentials"), errProgramExited
}
switch c.ServerURL {
case validServerAddress:
return nil, nil
case validServerAddress2:
return nil, nil
default:
return []byte("error storing credentials"), errProgramExited
}
}
return []byte(fmt.Sprintf("unknown argument %q with %q", m.arg, inS)), errProgramExited
}
// Input sets the input to send to a remote credentials helper.
func (m *mockProgram) Input(in io.Reader) {
m.input = in
}
func mockProgramFn(args ...string) Program {
return &mockProgram{
arg: args[0],
}
}
func ExampleStore() {
p := NewShellProgramFunc("docker-credential-secretservice")
c := &credentials.Credentials{
ServerURL: "https://example.com",
Username: "calavera",
Secret: "my super secret token",
}
if err := Store(p, c); err != nil {
fmt.Println(err)
}
}
func TestStore(t *testing.T) {
valid := []credentials.Credentials{
{validServerAddress, "foo", "bar"},
{validServerAddress2, "<token>", "abcd1234"},
}
for _, v := range valid {
if err := Store(mockProgramFn, &v); err != nil {
t.Fatal(err)
}
}
invalid := []credentials.Credentials{
{invalidServerAddress, "foo", "bar"},
}
for _, v := range invalid {
if err := Store(mockProgramFn, &v); err == nil {
t.Fatalf("Expected error for server %s, got nil", v.ServerURL)
}
}
}
func ExampleGet() {
p := NewShellProgramFunc("docker-credential-secretservice")
creds, err := Get(p, "https://example.com")
if err != nil {
fmt.Println(err)
}
fmt.Printf("Got credentials for user `%s` in `%s`\n", creds.Username, creds.ServerURL)
}
func TestGet(t *testing.T) {
valid := []credentials.Credentials{
{validServerAddress, "foo", "bar"},
{validServerAddress2, "<token>", "abcd1234"},
}
for _, v := range valid {
c, err := Get(mockProgramFn, v.ServerURL)
if err != nil {
t.Fatal(err)
}
if c.Username != v.Username {
t.Fatalf("expected username `%s`, got %s", v.Username, c.Username)
}
if c.Secret != v.Secret {
t.Fatalf("expected secret `%s`, got %s", v.Secret, c.Secret)
}
}
invalid := []struct {
serverURL string
err string
}{
{missingCredsAddress, credentials.NewErrCredentialsNotFound().Error()},
{invalidServerAddress, "error getting credentials - err: exited 1, out: `program failed`"},
}
for _, v := range invalid {
_, err := Get(mockProgramFn, v.serverURL)
if err == nil {
t.Fatalf("Expected error for server %s, got nil", v.serverURL)
}
if err.Error() != v.err {
t.Fatalf("Expected error `%s`, got `%v`", v.err, err)
}
}
}
func ExampleErase() {
p := NewShellProgramFunc("docker-credential-secretservice")
if err := Erase(p, "https://example.com"); err != nil {
fmt.Println(err)
}
}
func TestErase(t *testing.T) {
if err := Erase(mockProgramFn, validServerAddress); err != nil {
t.Fatal(err)
}
if err := Erase(mockProgramFn, invalidServerAddress); err == nil {
t.Fatalf("Expected error for server %s, got nil", invalidServerAddress)
}
}
+37
View File
@@ -0,0 +1,37 @@
package client
import (
"io"
"os/exec"
)
// Program is an interface to execute external programs.
type Program interface {
Output() ([]byte, error)
Input(in io.Reader)
}
// ProgramFunc is a type of function that initializes programs based on arguments.
type ProgramFunc func(args ...string) Program
// NewShellProgramFunc creates programs that are executed in a Shell.
func NewShellProgramFunc(name string) ProgramFunc {
return func(args ...string) Program {
return &Shell{cmd: exec.Command(name, args...)}
}
}
// Shell invokes shell commands to talk with a remote credentials helper.
type Shell struct {
cmd *exec.Cmd
}
// Output returns responses from the remote credentials helper.
func (s *Shell) Output() ([]byte, error) {
return s.cmd.Output()
}
// Input sets the input to send to a remote credentials helper.
func (s *Shell) Input(in io.Reader) {
s.cmd.Stdin = in
}
+35 -16
View File
@@ -10,36 +10,50 @@ import (
"strings"
)
type credentialsGetResponse struct {
// Credentials holds the information shared between docker and the credentials store.
type Credentials struct {
ServerURL string
Username string
Secret string
}
// Serve initializes the credentials helper and parses the action argument.
// This function is designed to be called from a command line interface.
// It uses os.Args[1] as the key for the action.
// It uses os.Stdin as input and os.Stdout as output.
// This function terminates the program with os.Exit(1) if there is an error.
func Serve(helper Helper) {
if err := handleCommand(helper); err != nil {
var err error
if len(os.Args) != 2 {
err = fmt.Errorf("Usage: %s <store|get|erase>", os.Args[0])
}
if err == nil {
err = HandleCommand(helper, os.Args[1], os.Stdin, os.Stdout)
}
if err != nil {
fmt.Fprintf(os.Stdout, "%v\n", err)
os.Exit(1)
}
}
func handleCommand(helper Helper) error {
if len(os.Args) != 2 {
return fmt.Errorf("Usage: %s <store|get|erase>", os.Args[0])
}
switch os.Args[1] {
// HandleCommand uses a helper and a key to run a credential action.
func HandleCommand(helper Helper, key string, in io.Reader, out io.Writer) error {
switch key {
case "store":
return store(helper, os.Stdin)
return Store(helper, in)
case "get":
return get(helper, os.Stdin, os.Stdout)
return Get(helper, in, out)
case "erase":
return erase(helper, os.Stdin)
return Erase(helper, in)
}
return fmt.Errorf("Usage: %s <store|get|erase>", os.Args[0])
return fmt.Errorf("Unknown credential action `%s`", key)
}
func store(helper Helper, reader io.Reader) error {
// Store uses a helper and an input reader to save credentials.
// The reader must contain the JSON serialization of a Credentials struct.
func Store(helper Helper, reader io.Reader) error {
scanner := bufio.NewScanner(reader)
buffer := new(bytes.Buffer)
@@ -59,7 +73,10 @@ func store(helper Helper, reader io.Reader) error {
return helper.Add(&creds)
}
func get(helper Helper, reader io.Reader, writer io.Writer) error {
// Get retrieves the credentials for a given server url.
// The reader must contain the server URL to search.
// The writer is used to write the JSON serialization of the credentials.
func Get(helper Helper, reader io.Reader, writer io.Writer) error {
scanner := bufio.NewScanner(reader)
buffer := new(bytes.Buffer)
@@ -78,7 +95,7 @@ func get(helper Helper, reader io.Reader, writer io.Writer) error {
return err
}
resp := credentialsGetResponse{
resp := Credentials{
Username: username,
Secret: secret,
}
@@ -92,7 +109,9 @@ func get(helper Helper, reader io.Reader, writer io.Writer) error {
return nil
}
func erase(helper Helper, reader io.Reader) error {
// Erase removes credentials from the store.
// The reader must contain the server URL to remove.
func Erase(helper Helper, reader io.Reader) error {
scanner := bufio.NewScanner(reader)
buffer := new(bytes.Buffer)
+7 -7
View File
@@ -50,7 +50,7 @@ func TestStore(t *testing.T) {
in := bytes.NewReader(b)
h := newMemoryStore()
if err := store(h, in); err != nil {
if err := Store(h, in); err != nil {
t.Fatal(err)
}
@@ -82,13 +82,13 @@ func TestGet(t *testing.T) {
in := bytes.NewReader(b)
h := newMemoryStore()
if err := store(h, in); err != nil {
if err := Store(h, in); err != nil {
t.Fatal(err)
}
buf := strings.NewReader(serverURL)
w := new(bytes.Buffer)
if err := get(h, buf, w); err != nil {
if err := Get(h, buf, w); err != nil {
t.Fatal(err)
}
@@ -96,7 +96,7 @@ func TestGet(t *testing.T) {
t.Fatalf("expected output in the writer, got %d", w.Len())
}
var c credentialsGetResponse
var c Credentials
if err := json.NewDecoder(w).Decode(&c); err != nil {
t.Fatal(err)
}
@@ -124,17 +124,17 @@ func TestErase(t *testing.T) {
in := bytes.NewReader(b)
h := newMemoryStore()
if err := store(h, in); err != nil {
if err := Store(h, in); err != nil {
t.Fatal(err)
}
buf := strings.NewReader(serverURL)
if err := erase(h, buf); err != nil {
if err := Erase(h, buf); err != nil {
t.Fatal(err)
}
w := new(bytes.Buffer)
if err := get(h, buf, w); err == nil {
if err := Get(h, buf, w); err == nil {
t.Fatal("expected error getting missing creds, got empty")
}
}
+37
View File
@@ -0,0 +1,37 @@
package credentials
// ErrCredentialsNotFound standarizes the not found error, so every helper returns
// the same message and docker can handle it properly.
const errCredentialsNotFoundMessage = "credentials not found in native keychain"
// errCredentialsNotFound represents an error
// raised when credentials are not in the store.
type errCredentialsNotFound struct{}
// Error returns the standard error message
// for when the credentials are not in the store.
func (errCredentialsNotFound) Error() string {
return errCredentialsNotFoundMessage
}
// NewErrCredentialsNotFound creates a new error
// for when the credentials are not in the store.
func NewErrCredentialsNotFound() error {
return errCredentialsNotFound{}
}
// IsErrCredentialsNotFound returns true if the error
// was caused by not having a set of credentials in a store.
func IsErrCredentialsNotFound(err error) bool {
_, ok := err.(errCredentialsNotFound)
return ok
}
// IsErrCredentialsNotFoundMessage returns true if the error
// was caused by not having a set of credentials in a store.
//
// This function helps to check messages returned by an
// external program via its standard output.
func IsErrCredentialsNotFoundMessage(err string) bool {
return err == errCredentialsNotFoundMessage
}
+4 -13
View File
@@ -1,21 +1,12 @@
package credentials
import "errors"
// Credentials holds the information shared between docker and the credentials store.
type Credentials struct {
ServerURL string
Username string
Secret string
}
// Helper is the interface a credentials store helper must implement.
type Helper interface {
// Add appends credentials to the store.
Add(*Credentials) error
// Delete removes credentials from the store.
Delete(serverURL string) error
// Get retrieves credentials from the store.
// It returns username and secret as strings.
Get(serverURL string) (string, string, error)
}
// ErrCredentialsNotFound standarizes the not found error, so every helper returns
// the same message and docker can handle it properly.
var ErrCredentialsNotFound = errors.New("credentials not found in native keychain")
+1 -1
View File
@@ -6,5 +6,5 @@ import (
)
func main() {
credentials.Serve(osxkeychain.New())
credentials.Serve(osxkeychain.Osxkeychain{})
}
+6 -10
View File
@@ -22,15 +22,11 @@ import (
// when the credentials are not in the keychain.
const errCredentialsNotFound = "The specified item could not be found in the keychain."
type osxkeychain struct{}
// New creates a new osxkeychain.
func New() credentials.Helper {
return osxkeychain{}
}
// Osxkeychain handles secrets using the OS X Keychain as store.
type Osxkeychain struct{}
// Add adds new credentials to the keychain.
func (h osxkeychain) Add(creds *credentials.Credentials) error {
func (h Osxkeychain) Add(creds *credentials.Credentials) error {
s, err := splitServer(creds.ServerURL)
if err != nil {
return err
@@ -52,7 +48,7 @@ func (h osxkeychain) Add(creds *credentials.Credentials) error {
}
// Delete removes credentials from the keychain.
func (h osxkeychain) Delete(serverURL string) error {
func (h Osxkeychain) Delete(serverURL string) error {
s, err := splitServer(serverURL)
if err != nil {
return err
@@ -69,7 +65,7 @@ func (h osxkeychain) Delete(serverURL string) error {
}
// Get returns the username and secret to use for a given registry server URL.
func (h osxkeychain) Get(serverURL string) (string, string, error) {
func (h Osxkeychain) Get(serverURL string) (string, string, error) {
s, err := splitServer(serverURL)
if err != nil {
return "", "", err
@@ -89,7 +85,7 @@ func (h osxkeychain) Get(serverURL string) (string, string, error) {
goMsg := C.GoString(errMsg)
if goMsg == errCredentialsNotFound {
return "", "", credentials.ErrCredentialsNotFound
return "", "", credentials.NewErrCredentialsNotFound()
}
return "", "", errors.New(goMsg)
+4 -4
View File
@@ -13,7 +13,7 @@ func TestOSXKeychainHelper(t *testing.T) {
Secret: "foobarbaz",
}
helper := New()
helper := Osxkeychain{}
if err := helper.Add(creds); err != nil {
t.Fatal(err)
}
@@ -37,9 +37,9 @@ func TestOSXKeychainHelper(t *testing.T) {
}
func TestMissingCredentials(t *testing.T) {
helper := New()
helper := Osxkeychain{}
_, _, err := helper.Get("https://adsfasdf.wrewerwer.com/asdfsdddd")
if err != credentials.ErrCredentialsNotFound {
t.Fatalf("exptected ErrCredentialsNotFound, got %v", err)
if !credentials.IsErrCredentialsNotFound(err) {
t.Fatalf("expected ErrCredentialsNotFound, got %v", err)
}
}
+1 -1
View File
@@ -6,5 +6,5 @@ import (
)
func main() {
credentials.Serve(secretservice.New())
credentials.Serve(secretservice.Secretservice{})
}
+7 -11
View File
@@ -14,15 +14,11 @@ import (
"github.com/docker/docker-credential-helpers/credentials"
)
type secretservice struct{}
// New creates a new secretservice.
func New() credentials.Helper {
return secretservice{}
}
// Secretservice handles secrets using Linux secret-service as a store.
type Secretservice struct{}
// Add adds new credentials to the keychain.
func (h secretservice) Add(creds *credentials.Credentials) error {
func (h Secretservice) Add(creds *credentials.Credentials) error {
if creds == nil {
return errors.New("missing credentials")
}
@@ -41,8 +37,8 @@ func (h secretservice) Add(creds *credentials.Credentials) error {
return nil
}
// Delete removes credentials from the keychain.
func (h secretservice) Delete(serverURL string) error {
// Delete removes credentials from the store.
func (h Secretservice) Delete(serverURL string) error {
if serverURL == "" {
return errors.New("missing server url")
}
@@ -58,7 +54,7 @@ func (h secretservice) Delete(serverURL string) error {
}
// Get returns the username and secret to use for a given registry server URL.
func (h secretservice) Get(serverURL string) (string, string, error) {
func (h Secretservice) Get(serverURL string) (string, string, error) {
if serverURL == "" {
return "", "", errors.New("missing server url")
}
@@ -78,7 +74,7 @@ func (h secretservice) Get(serverURL string) (string, string, error) {
user := C.GoString(username)
pass := C.GoString(secret)
if pass == "" {
return "", "", credentials.ErrCredentialsNotFound
return "", "", credentials.NewErrCredentialsNotFound()
}
return user, pass, nil
}
+4 -4
View File
@@ -15,7 +15,7 @@ func TestSecretServiceHelper(t *testing.T) {
Secret: "foobarbaz",
}
helper := New()
helper := Secretservice{}
if err := helper.Add(creds); err != nil {
t.Fatal(err)
}
@@ -41,9 +41,9 @@ func TestSecretServiceHelper(t *testing.T) {
func TestMissingCredentials(t *testing.T) {
t.Skip("test requires gnome-keyring but travis CI doesn't have it")
helper := New()
helper := Secretservice{}
_, _, err := helper.Get("https://adsfasdf.wrewerwer.com/asdfsdddd")
if err != credentials.ErrCredentialsNotFound {
t.Fatalf("exptected ErrCredentialsNotFound, got %v", err)
if !credentials.IsErrCredentialsNotFound(err) {
t.Fatalf("expected ErrCredentialsNotFound, got %v", err)
}
}
+1 -1
View File
@@ -6,5 +6,5 @@ import (
)
func main() {
credentials.Serve(wincred.New())
credentials.Serve(wincred.Wincred{})
}
+6 -10
View File
@@ -5,15 +5,11 @@ import (
"github.com/docker/docker-credential-helpers/credentials"
)
type wincred struct{}
// New creates a new wincred.
func New() credentials.Helper {
return wincred{}
}
// Wincred handles secrets using the Windows credential service.
type Wincred struct{}
// Add adds new credentials to the windows credentials manager.
func (h wincred) Add(creds *credentials.Credentials) error {
func (h Wincred) Add(creds *credentials.Credentials) error {
g := winc.NewGenericCredential(creds.ServerURL)
g.UserName = creds.Username
g.CredentialBlob = []byte(creds.Secret)
@@ -22,7 +18,7 @@ func (h wincred) Add(creds *credentials.Credentials) error {
}
// Delete removes credentials from the windows credentials manager.
func (h wincred) Delete(serverURL string) error {
func (h Wincred) Delete(serverURL string) error {
g, err := winc.GetGenericCredential(serverURL)
if g == nil {
return nil
@@ -34,10 +30,10 @@ func (h wincred) Delete(serverURL string) error {
}
// Get retrieves credentials from the windows credentials manager.
func (h wincred) Get(serverURL string) (string, string, error) {
func (h Wincred) Get(serverURL string) (string, string, error) {
g, _ := winc.GetGenericCredential(serverURL)
if g == nil {
return "", "", credentials.ErrCredentialsNotFound
return "", "", credentials.NewErrCredentialsNotFound()
}
return g.UserName, string(g.CredentialBlob), nil
}
+4 -4
View File
@@ -13,7 +13,7 @@ func TestWinCredHelper(t *testing.T) {
Secret: "foobarbaz",
}
helper := New()
helper := Wincred{}
if err := helper.Add(creds); err != nil {
t.Fatal(err)
}
@@ -37,9 +37,9 @@ func TestWinCredHelper(t *testing.T) {
}
func TestMissingCredentials(t *testing.T) {
helper := New()
helper := Wincred{}
_, _, err := helper.Get("https://adsfasdf.wrewerwer.com/asdfsdddd")
if err != credentials.ErrCredentialsNotFound {
t.Fatalf("exptected ErrCredentialsNotFound, got %v", err)
if !credentials.IsErrCredentialsNotFound(err) {
t.Fatalf("expected ErrCredentialsNotFound, got %v", err)
}
}