diff --git a/Makefile b/Makefile index 7ca9899..e2e465b 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,10 @@ osxkeychain: mkdir -p bin go build -o bin/docker-credential-osxkeychain osxkeychain/cmd/main_darwin.go +wincred: + mkdir -p bin + go build -o bin/docker-credential-wincred wincred/cmd/main_windows.go + test: go test -v ./... diff --git a/README.md b/README.md index b6f5627..9251f47 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ Set the `credsStore` option in your `.docker/config.json` file with the suffix o ### Available programs 1. osxkeychain: Provides a helper to use the OS X keychain as credentials store. +2. wincred: Provides a helper to use Windows credentials manager as store. ## Development diff --git a/wincred/cmd/main_windows.go b/wincred/cmd/main_windows.go new file mode 100644 index 0000000..6113445 --- /dev/null +++ b/wincred/cmd/main_windows.go @@ -0,0 +1,10 @@ +package main + +import ( + "github.com/docker/docker-credential-helpers/credentials" + "github.com/docker/docker-credential-helpers/wincred" +) + +func main() { + credentials.Serve(wincred.New()) +} diff --git a/wincred/wincred_windows.go b/wincred/wincred_windows.go new file mode 100644 index 0000000..1cecf33 --- /dev/null +++ b/wincred/wincred_windows.go @@ -0,0 +1,43 @@ +package wincred + +import ( + winc "github.com/danieljoos/wincred" + "github.com/docker/docker-credential-helpers/credentials" +) + +type wincred struct{} + +// New creates a new wincred. +func New() credentials.Helper { + return wincred{} +} + +// Add adds new credentials to the windows credentials manager. +func (h wincred) Add(creds *credentials.Credentials) error { + g := winc.NewGenericCredential(creds.ServerURL) + g.UserName = creds.Username + g.CredentialBlob = []byte(creds.Password) + g.Persist = winc.PersistLocalMachine + return g.Write() +} + +// Delete removes credentials from the windows credentials manager. +func (h wincred) Delete(serverURL string) error { + g, err := winc.GetGenericCredential(serverURL) + if g == nil { + return nil + } + if err != nil { + return err + } + return g.Delete() +} + +// Get retrieves credentials from the windows credentials manager. +func (h wincred) Get(serverURL string) (string, string, error) { + g, _ := winc.GetGenericCredential(serverURL) + if g == nil { + return "", "", credentials.ErrCredentialsNotFound + } + return g.UserName, string(g.CredentialBlob), nil +} diff --git a/wincred/wincred_windows_test.go b/wincred/wincred_windows_test.go new file mode 100644 index 0000000..79d0453 --- /dev/null +++ b/wincred/wincred_windows_test.go @@ -0,0 +1,45 @@ +package wincred + +import ( + "testing" + + "github.com/docker/docker-credential-helpers/credentials" +) + +func TestWinCredHelper(t *testing.T) { + creds := &credentials.Credentials{ + ServerURL: "https://foobar.docker.io:2376/v1", + Username: "foobar", + Password: "foobarbaz", + } + + helper := New() + if err := helper.Add(creds); err != nil { + t.Fatal(err) + } + + username, password, err := helper.Get(creds.ServerURL) + if err != nil { + t.Fatal(err) + } + + if username != "foobar" { + t.Fatalf("expected %s, got %s\n", "foobar", username) + } + + if password != "foobarbaz" { + t.Fatalf("expected %s, got %s\n", "foobarbaz", password) + } + + if err := helper.Delete(creds.ServerURL); err != nil { + t.Fatal(err) + } +} + +func TestMissingCredentials(t *testing.T) { + helper := New() + _, _, err := helper.Get("https://adsfasdf.wrewerwer.com/asdfsdddd") + if err != credentials.ErrCredentialsNotFound { + t.Fatalf("exptected ErrCredentialsNotFound, got %v", err) + } +}