mirror of
https://github.com/docker/docker-credential-helpers.git
synced 2026-06-28 07:11:36 +05:30
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e68b300c17 | |||
| 7d02ef740b | |||
| bcc242e1ad | |||
| 8727ffc77b | |||
| 2275377a31 | |||
| 0fb2225199 | |||
| a96948acb3 |
+17
-4
@@ -1,15 +1,24 @@
|
||||
---
|
||||
# See appveyor.yml for windows build.
|
||||
sudo: false
|
||||
sudo: required
|
||||
language: go
|
||||
dist: trusty
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
notifications:
|
||||
email: false
|
||||
go:
|
||||
- 1.6
|
||||
install: make deps
|
||||
before_script: make validate
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libsecret-1-dev
|
||||
before_script:
|
||||
- "export DISPLAY=:99.0"
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sh ci/before_script_linux.sh; fi
|
||||
- make validate
|
||||
script: make test
|
||||
|
||||
before_deploy:
|
||||
@@ -19,13 +28,17 @@
|
||||
provider: releases
|
||||
api_key:
|
||||
secure: "cGs5cao/MeVQVnum+Pr/Tpv+w83NsqGVS3wxvi3LYEf2ON4Kkmtd+Alwi0YFkGPJmSY0jZOct8NVK/M70qSnIU4l+AAq9+3KSMv23u4xrmy2sQog3AF+Ve3Rac+iYwZHOWwGs9I67CSuVv0vjJNVsDsTVefc25lHJImjRvXIS4p9xYzRPeUDCoqAo/QMVE+vFiMyxydsvt8fhd0gZCjPYWEpyHe9tjZ1tr1HsHZKFAjVb6AmF45d8rvadPoVUuLaOtr35wDC3XRKEvCZUefQpwLkrNj7j2L1rVGlY1xTE2APpLtvfd7R1Mx6kSfS1Gm3Pwcv3mugadXIhecL0lsdnU+BANjX3VUiv4ryzTPbsge966mv9ZQYwAzgCQTWRtMNJqsAnPZTeAkiOntd+HMQbPpxljOxv1sjDPY+EIZesyB3yQRJI8vMxqFcAjxeRyLcBqEnRFC2nd/Ln0KZ7ZFu16FcpNqRojdBayyypuXKqAiBNwtp4ti/65x8eHfBJuNjJtNZkRsJEYam4CYMRLxds9plKQfkaZ8045PKpyXO8fMpUhrfqSVID4IrYvD+io6XoXtdR4Lk6isZ2EgrjdrqgdG70S5lwKihL4iAi2F2ZCWhngFhkeNVOZunEWE6qZMk5wKODajR9sixGDApGPZQVojHwCNRGILZaHZ39JCIj3s="
|
||||
file: docker-credential-osxkeychain-${TRAVIS_TAG}-amd64.tar.gz
|
||||
# upload file artifacts using a glob expression.
|
||||
# It requires both options `file_glob` and `file`:
|
||||
# https://github.com/travis-ci/dpl/blob/master/lib/dpl/provider/releases.rb#L47-L53
|
||||
file_glob: true
|
||||
file: docker-credential-*-${TRAVIS_TAG}-amd64.tar.gz
|
||||
# don't delete the artifacts from previous phases
|
||||
skip_cleanup: true
|
||||
# deploy when a new tag is pushed
|
||||
on:
|
||||
tags: true
|
||||
|
||||
|
||||
branches:
|
||||
only:
|
||||
# Pushes and PR to the master branch
|
||||
|
||||
@@ -4,6 +4,11 @@ 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.2.0 (Mac OS X, Windows, Linux)
|
||||
|
||||
- Initial release of docker-credential-secretservice for Linux.
|
||||
- Use new secrets payload introduced in https://github.com/docker/docker/pull/20970.
|
||||
|
||||
## v0.1.0 (Mac OS X, Windows)
|
||||
|
||||
- Initial release of docker-credential-osxkeychain for Mac OS X.
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
.PHONY: all deps osxkeychain test validate wincred
|
||||
.PHONY: all deps osxkeychain secretservice test validate wincred
|
||||
|
||||
TRAVIS_OS_NAME ?= linux
|
||||
|
||||
all: test
|
||||
|
||||
@@ -9,15 +11,29 @@ osxkeychain:
|
||||
mkdir -p bin
|
||||
go build -o bin/docker-credential-osxkeychain osxkeychain/cmd/main_darwin.go
|
||||
|
||||
test:
|
||||
# tests all packages except vendor
|
||||
go test -v `go list ./... | grep -v /vendor/`
|
||||
|
||||
validate:
|
||||
go vet ./credentials ./osxkeychain
|
||||
golint `go list ./... | grep -v /vendor/`
|
||||
gofmt -s -l `ls **/*.go | grep -v vendor`
|
||||
secretservice:
|
||||
mkdir -p bin
|
||||
go build -o bin/docker-credential-secretservice secretservice/cmd/main_linux.go
|
||||
|
||||
wincred:
|
||||
mkdir -p bin
|
||||
go build -o bin/docker-credential-wincred wincred/cmd/main_windows.go
|
||||
|
||||
test:
|
||||
# tests all packages except vendor
|
||||
go test -v `go list ./... | grep -v /vendor/`
|
||||
|
||||
vet: vet_$(TRAVIS_OS_NAME)
|
||||
go vet ./credentials
|
||||
|
||||
vet_osx:
|
||||
go vet ./osxkeychain
|
||||
|
||||
vet_linux:
|
||||
go vet ./secretservice
|
||||
|
||||
validate: vet
|
||||
for p in `go list ./... | grep -v /vendor/`; do \
|
||||
golint $$p ; \
|
||||
done
|
||||
gofmt -s -l `ls **/*.go | grep -v vendor`
|
||||
|
||||
@@ -38,13 +38,14 @@ 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.
|
||||
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.
|
||||
|
||||
## Development
|
||||
|
||||
A credential helper can be any program that can read values from the standard input. We use the first argument in the command line to differentiate the kind of command to execute. There are three valid values:
|
||||
|
||||
- `store`: Adds credentials to the keychain. The payload in the standard input is a JSON document with `ServerURL`, `Username` and `Password`.
|
||||
- `store`: Adds credentials to the keychain. The payload in the standard input is a JSON document with `ServerURL`, `Username` and `Secret`.
|
||||
- `get`: Retrieves credentials from the keychain. The payload in the standard input is the raw value for the `ServerURL`.
|
||||
- `erase`: Removes credentials from the keychain. The payload in the standard input is the raw value for the `ServerURL`.
|
||||
|
||||
|
||||
+12
-3
@@ -1,6 +1,15 @@
|
||||
set -ex
|
||||
|
||||
mkdir bin
|
||||
go build -o bin/docker-credential-osxkeychain osxkeychain/cmd/main_darwin.go
|
||||
cd bin
|
||||
tar czf ../docker-credential-osxkeychain-${TRAVIS_TAG}-amd64.tar.gz docker-credential-osxkeychain
|
||||
case "$TRAVIS_OS_NAME" in
|
||||
"osx")
|
||||
go build -o bin/docker-credential-osxkeychain osxkeychain/cmd/main_darwin.go
|
||||
cd bin
|
||||
tar czf ../docker-credential-osxkeychain-${TRAVIS_TAG}-amd64.tar.gz docker-credential-osxkeychain
|
||||
;;
|
||||
"linux")
|
||||
go build -o bin/docker-credential-secretservice secretservice/cmd/main_linux.go
|
||||
cd bin
|
||||
tar czf ../docker-credential-secretservice-${TRAVIS_TAG}-amd64.tar.gz docker-credential-secretservice
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
set -ex
|
||||
|
||||
sh -e /etc/init.d/xvfb start
|
||||
sleep 3 # give xvfb some time to start
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
|
||||
type credentialsGetResponse struct {
|
||||
Username string
|
||||
Password string
|
||||
Secret string
|
||||
}
|
||||
|
||||
// Serve initializes the credentials helper and parses the action argument.
|
||||
@@ -73,14 +73,14 @@ func get(helper Helper, reader io.Reader, writer io.Writer) error {
|
||||
|
||||
serverURL := strings.TrimSpace(buffer.String())
|
||||
|
||||
username, password, err := helper.Get(serverURL)
|
||||
username, secret, err := helper.Get(serverURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resp := credentialsGetResponse{
|
||||
Username: username,
|
||||
Password: password,
|
||||
Secret: secret,
|
||||
}
|
||||
|
||||
buffer.Reset()
|
||||
|
||||
@@ -33,7 +33,7 @@ func (m *memoryStore) Get(serverURL string) (string, string, error) {
|
||||
if !ok {
|
||||
return "", "", fmt.Errorf("creds not found for %s", serverURL)
|
||||
}
|
||||
return c.Username, c.Password, nil
|
||||
return c.Username, c.Secret, nil
|
||||
}
|
||||
|
||||
func TestStore(t *testing.T) {
|
||||
@@ -41,7 +41,7 @@ func TestStore(t *testing.T) {
|
||||
creds := &Credentials{
|
||||
ServerURL: serverURL,
|
||||
Username: "foo",
|
||||
Password: "bar",
|
||||
Secret: "bar",
|
||||
}
|
||||
b, err := json.Marshal(creds)
|
||||
if err != nil {
|
||||
@@ -63,8 +63,8 @@ func TestStore(t *testing.T) {
|
||||
t.Fatalf("expected username foo, got %s\n", c.Username)
|
||||
}
|
||||
|
||||
if c.Password != "bar" {
|
||||
t.Fatalf("expected username bar, got %s\n", c.Password)
|
||||
if c.Secret != "bar" {
|
||||
t.Fatalf("expected username bar, got %s\n", c.Secret)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ func TestGet(t *testing.T) {
|
||||
creds := &Credentials{
|
||||
ServerURL: serverURL,
|
||||
Username: "foo",
|
||||
Password: "bar",
|
||||
Secret: "bar",
|
||||
}
|
||||
b, err := json.Marshal(creds)
|
||||
if err != nil {
|
||||
@@ -105,8 +105,8 @@ func TestGet(t *testing.T) {
|
||||
t.Fatalf("expected username foo, got %s\n", c.Username)
|
||||
}
|
||||
|
||||
if c.Password != "bar" {
|
||||
t.Fatalf("expected username bar, got %s\n", c.Password)
|
||||
if c.Secret != "bar" {
|
||||
t.Fatalf("expected username bar, got %s\n", c.Secret)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ func TestErase(t *testing.T) {
|
||||
creds := &Credentials{
|
||||
ServerURL: serverURL,
|
||||
Username: "foo",
|
||||
Password: "bar",
|
||||
Secret: "bar",
|
||||
}
|
||||
b, err := json.Marshal(creds)
|
||||
if err != nil {
|
||||
|
||||
@@ -6,7 +6,7 @@ import "errors"
|
||||
type Credentials struct {
|
||||
ServerURL string
|
||||
Username string
|
||||
Password string
|
||||
Secret string
|
||||
}
|
||||
|
||||
// Helper is the interface a credentials store helper must implement.
|
||||
|
||||
@@ -10,7 +10,7 @@ char *get_error(OSStatus status) {
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *keychain_add(struct Server *server, char *username, char *password) {
|
||||
char *keychain_add(struct Server *server, char *username, char *secret) {
|
||||
OSStatus status = SecKeychainAddInternetPassword(
|
||||
NULL,
|
||||
strlen(server->host), server->host,
|
||||
@@ -20,7 +20,7 @@ char *keychain_add(struct Server *server, char *username, char *password) {
|
||||
server->port,
|
||||
server->proto,
|
||||
kSecAuthenticationTypeDefault,
|
||||
strlen(password), password,
|
||||
strlen(secret), secret,
|
||||
NULL
|
||||
);
|
||||
if (status) {
|
||||
@@ -29,7 +29,7 @@ char *keychain_add(struct Server *server, char *username, char *password) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *keychain_get(struct Server *server, unsigned int *username_l, char **username, unsigned int *password_l, char **password) {
|
||||
char *keychain_get(struct Server *server, unsigned int *username_l, char **username, unsigned int *secret_l, char **secret) {
|
||||
char *tmp;
|
||||
SecKeychainItemRef item;
|
||||
|
||||
@@ -42,14 +42,14 @@ char *keychain_get(struct Server *server, unsigned int *username_l, char **usern
|
||||
server->port,
|
||||
server->proto,
|
||||
kSecAuthenticationTypeDefault,
|
||||
password_l, (void **)&tmp,
|
||||
secret_l, (void **)&tmp,
|
||||
&item);
|
||||
|
||||
if (status) {
|
||||
return get_error(status);
|
||||
}
|
||||
|
||||
*password = strdup(tmp);
|
||||
*secret = strdup(tmp);
|
||||
SecKeychainItemFreeContent(NULL, tmp);
|
||||
|
||||
SecKeychainAttributeList list;
|
||||
|
||||
@@ -39,10 +39,10 @@ func (h osxkeychain) Add(creds *credentials.Credentials) error {
|
||||
|
||||
username := C.CString(creds.Username)
|
||||
defer C.free(unsafe.Pointer(username))
|
||||
password := C.CString(creds.Password)
|
||||
defer C.free(unsafe.Pointer(password))
|
||||
secret := C.CString(creds.Secret)
|
||||
defer C.free(unsafe.Pointer(secret))
|
||||
|
||||
errMsg := C.keychain_add(s, username, password)
|
||||
errMsg := C.keychain_add(s, username, secret)
|
||||
if errMsg != nil {
|
||||
defer C.free(unsafe.Pointer(errMsg))
|
||||
return errors.New(C.GoString(errMsg))
|
||||
@@ -68,7 +68,7 @@ func (h osxkeychain) Delete(serverURL string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get returns the username and password to use for a given registry server URL.
|
||||
// Get returns the username and secret to use for a given registry server URL.
|
||||
func (h osxkeychain) Get(serverURL string) (string, string, error) {
|
||||
s, err := splitServer(serverURL)
|
||||
if err != nil {
|
||||
@@ -78,12 +78,12 @@ func (h osxkeychain) Get(serverURL string) (string, string, error) {
|
||||
|
||||
var usernameLen C.uint
|
||||
var username *C.char
|
||||
var passwordLen C.uint
|
||||
var password *C.char
|
||||
var secretLen C.uint
|
||||
var secret *C.char
|
||||
defer C.free(unsafe.Pointer(username))
|
||||
defer C.free(unsafe.Pointer(password))
|
||||
defer C.free(unsafe.Pointer(secret))
|
||||
|
||||
errMsg := C.keychain_get(s, &usernameLen, &username, &passwordLen, &password)
|
||||
errMsg := C.keychain_get(s, &usernameLen, &username, &secretLen, &secret)
|
||||
if errMsg != nil {
|
||||
defer C.free(unsafe.Pointer(errMsg))
|
||||
goMsg := C.GoString(errMsg)
|
||||
@@ -96,7 +96,7 @@ func (h osxkeychain) Get(serverURL string) (string, string, error) {
|
||||
}
|
||||
|
||||
user := C.GoStringN(username, C.int(usernameLen))
|
||||
pass := C.GoStringN(password, C.int(passwordLen))
|
||||
pass := C.GoStringN(secret, C.int(secretLen))
|
||||
return user, pass, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,6 @@ struct Server {
|
||||
unsigned int port;
|
||||
};
|
||||
|
||||
char *keychain_add(struct Server *server, char *username, char *password);
|
||||
char *keychain_get(struct Server *server, unsigned int *username_l, char **username, unsigned int *password_l, char **password);
|
||||
char *keychain_add(struct Server *server, char *username, char *secret);
|
||||
char *keychain_get(struct Server *server, unsigned int *username_l, char **username, unsigned int *secret_l, char **secret);
|
||||
char *keychain_delete(struct Server *server);
|
||||
|
||||
@@ -10,7 +10,7 @@ func TestOSXKeychainHelper(t *testing.T) {
|
||||
creds := &credentials.Credentials{
|
||||
ServerURL: "https://foobar.docker.io:2376/v1",
|
||||
Username: "foobar",
|
||||
Password: "foobarbaz",
|
||||
Secret: "foobarbaz",
|
||||
}
|
||||
|
||||
helper := New()
|
||||
@@ -18,7 +18,7 @@ func TestOSXKeychainHelper(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
username, password, err := helper.Get(creds.ServerURL)
|
||||
username, secret, err := helper.Get(creds.ServerURL)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -27,8 +27,8 @@ func TestOSXKeychainHelper(t *testing.T) {
|
||||
t.Fatalf("expected %s, got %s\n", "foobar", username)
|
||||
}
|
||||
|
||||
if password != "foobarbaz" {
|
||||
t.Fatalf("expected %s, got %s\n", "foobarbaz", password)
|
||||
if secret != "foobarbaz" {
|
||||
t.Fatalf("expected %s, got %s\n", "foobarbaz", secret)
|
||||
}
|
||||
|
||||
if err := helper.Delete(creds.ServerURL); err != nil {
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/docker/docker-credential-helpers/credentials"
|
||||
"github.com/docker/docker-credential-helpers/secretservice"
|
||||
)
|
||||
|
||||
func main() {
|
||||
credentials.Serve(secretservice.New())
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
#include <string.h>
|
||||
#include "secretservice_linux.h"
|
||||
|
||||
const SecretSchema *docker_get_schema(void)
|
||||
{
|
||||
static const SecretSchema docker_schema = {
|
||||
"io.docker.Credentials", SECRET_SCHEMA_NONE,
|
||||
{
|
||||
{ "server", SECRET_SCHEMA_ATTRIBUTE_STRING },
|
||||
{ "username", SECRET_SCHEMA_ATTRIBUTE_STRING },
|
||||
{ "docker_cli", SECRET_SCHEMA_ATTRIBUTE_STRING },
|
||||
{ "NULL", 0 },
|
||||
}
|
||||
};
|
||||
return &docker_schema;
|
||||
}
|
||||
|
||||
GError *add(char *server, char *username, char *secret) {
|
||||
GError *err = NULL;
|
||||
|
||||
secret_password_store_sync (DOCKER_SCHEMA, SECRET_COLLECTION_DEFAULT,
|
||||
server, secret, NULL, &err,
|
||||
"server", server,
|
||||
"username", username,
|
||||
"docker_cli", "1",
|
||||
NULL);
|
||||
return err;
|
||||
}
|
||||
|
||||
GError *delete(char *server) {
|
||||
GError *err = NULL;
|
||||
|
||||
secret_password_clear_sync(DOCKER_SCHEMA, NULL, &err,
|
||||
"server", server,
|
||||
"docker_cli", "1",
|
||||
NULL);
|
||||
if (err != NULL)
|
||||
return err;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *get_username(SecretItem *item) {
|
||||
GHashTable *attributes;
|
||||
GHashTableIter iter;
|
||||
gchar *value, *key;
|
||||
|
||||
attributes = secret_item_get_attributes(item);
|
||||
g_hash_table_iter_init(&iter, attributes);
|
||||
while (g_hash_table_iter_next(&iter, (void **)&key, (void **)&value)) {
|
||||
if (strncmp(key, "username", strlen(key)) == 0)
|
||||
return (char *)value;
|
||||
}
|
||||
g_hash_table_unref(attributes);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GError *get(char *server, char **username, char **secret) {
|
||||
GError *err = NULL;
|
||||
GHashTable *attributes;
|
||||
SecretService *service;
|
||||
GList *items, *l;
|
||||
SecretSearchFlags flags = SECRET_SEARCH_LOAD_SECRETS | SECRET_SEARCH_ALL | SECRET_SEARCH_UNLOCK;
|
||||
SecretValue *secretValue;
|
||||
gsize length;
|
||||
gchar *value;
|
||||
|
||||
attributes = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
|
||||
g_hash_table_insert(attributes, g_strdup("server"), g_strdup(server));
|
||||
g_hash_table_insert(attributes, g_strdup("docker_cli"), g_strdup("1"));
|
||||
|
||||
service = secret_service_get_sync(SECRET_SERVICE_NONE, NULL, &err);
|
||||
if (err == NULL) {
|
||||
items = secret_service_search_sync(service, NULL, attributes, flags, NULL, &err);
|
||||
if (err == NULL) {
|
||||
for (l = items; l != NULL; l = g_list_next(l)) {
|
||||
value = secret_item_get_schema_name(l->data);
|
||||
if (strncmp(value, "io.docker.Credentials", strlen(value)) != 0) {
|
||||
g_free(value);
|
||||
continue;
|
||||
}
|
||||
g_free(value);
|
||||
secretValue = secret_item_get_secret(l->data);
|
||||
if (secret != NULL) {
|
||||
*secret = strdup(secret_value_get(secretValue, &length));
|
||||
secret_value_unref(secretValue);
|
||||
}
|
||||
*username = get_username(l->data);
|
||||
}
|
||||
g_list_free_full(items, g_object_unref);
|
||||
}
|
||||
g_object_unref(service);
|
||||
}
|
||||
g_hash_table_unref(attributes);
|
||||
if (err != NULL) {
|
||||
return err;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package secretservice
|
||||
|
||||
/*
|
||||
#cgo pkg-config: libsecret-1
|
||||
|
||||
#include "secretservice_linux.h"
|
||||
#include <stdlib.h>
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"errors"
|
||||
"unsafe"
|
||||
|
||||
"github.com/docker/docker-credential-helpers/credentials"
|
||||
)
|
||||
|
||||
type secretservice struct{}
|
||||
|
||||
// New creates a new secretservice.
|
||||
func New() credentials.Helper {
|
||||
return secretservice{}
|
||||
}
|
||||
|
||||
// Add adds new credentials to the keychain.
|
||||
func (h secretservice) Add(creds *credentials.Credentials) error {
|
||||
if creds == nil {
|
||||
return errors.New("missing credentials")
|
||||
}
|
||||
server := C.CString(creds.ServerURL)
|
||||
defer C.free(unsafe.Pointer(server))
|
||||
username := C.CString(creds.Username)
|
||||
defer C.free(unsafe.Pointer(username))
|
||||
secret := C.CString(creds.Secret)
|
||||
defer C.free(unsafe.Pointer(secret))
|
||||
|
||||
if err := C.add(server, username, secret); err != nil {
|
||||
defer C.g_error_free(err)
|
||||
errMsg := (*C.char)(unsafe.Pointer(err.message))
|
||||
return errors.New(C.GoString(errMsg))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Delete removes credentials from the keychain.
|
||||
func (h secretservice) Delete(serverURL string) error {
|
||||
if serverURL == "" {
|
||||
return errors.New("missing server url")
|
||||
}
|
||||
server := C.CString(serverURL)
|
||||
defer C.free(unsafe.Pointer(server))
|
||||
|
||||
if err := C.delete(server); err != nil {
|
||||
defer C.g_error_free(err)
|
||||
errMsg := (*C.char)(unsafe.Pointer(err.message))
|
||||
return errors.New(C.GoString(errMsg))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get returns the username and secret to use for a given registry server URL.
|
||||
func (h secretservice) Get(serverURL string) (string, string, error) {
|
||||
if serverURL == "" {
|
||||
return "", "", errors.New("missing server url")
|
||||
}
|
||||
var username *C.char
|
||||
defer C.free(unsafe.Pointer(username))
|
||||
var secret *C.char
|
||||
defer C.free(unsafe.Pointer(secret))
|
||||
server := C.CString(serverURL)
|
||||
defer C.free(unsafe.Pointer(server))
|
||||
|
||||
err := C.get(server, &username, &secret)
|
||||
if err != nil {
|
||||
defer C.g_error_free(err)
|
||||
errMsg := (*C.char)(unsafe.Pointer(err.message))
|
||||
return "", "", errors.New(C.GoString(errMsg))
|
||||
}
|
||||
user := C.GoString(username)
|
||||
pass := C.GoString(secret)
|
||||
if pass == "" {
|
||||
return "", "", credentials.ErrCredentialsNotFound
|
||||
}
|
||||
return user, pass, nil
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#define SECRET_WITH_UNSTABLE 1
|
||||
#define SECRET_API_SUBJECT_TO_CHANGE 1
|
||||
#include <libsecret/secret.h>
|
||||
|
||||
const SecretSchema *docker_get_schema(void) G_GNUC_CONST;
|
||||
|
||||
#define DOCKER_SCHEMA docker_get_schema()
|
||||
|
||||
GError *add(char *server, char *username, char *secret);
|
||||
GError *delete(char *server);
|
||||
GError *get(char *server, char **username, char **secret);
|
||||
@@ -0,0 +1,49 @@
|
||||
package secretservice
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker-credential-helpers/credentials"
|
||||
)
|
||||
|
||||
func TestSecretServiceHelper(t *testing.T) {
|
||||
t.Skip("test requires gnome-keyring but travis CI doesn't have it")
|
||||
|
||||
creds := &credentials.Credentials{
|
||||
ServerURL: "https://foobar.docker.io:2376/v1",
|
||||
Username: "foobar",
|
||||
Secret: "foobarbaz",
|
||||
}
|
||||
|
||||
helper := New()
|
||||
if err := helper.Add(creds); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
username, secret, err := helper.Get(creds.ServerURL)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if username != "foobar" {
|
||||
t.Fatalf("expected %s, got %s\n", "foobar", username)
|
||||
}
|
||||
|
||||
if secret != "foobarbaz" {
|
||||
t.Fatalf("expected %s, got %s\n", "foobarbaz", secret)
|
||||
}
|
||||
|
||||
if err := helper.Delete(creds.ServerURL); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMissingCredentials(t *testing.T) {
|
||||
t.Skip("test requires gnome-keyring but travis CI doesn't have it")
|
||||
|
||||
helper := New()
|
||||
_, _, err := helper.Get("https://adsfasdf.wrewerwer.com/asdfsdddd")
|
||||
if err != credentials.ErrCredentialsNotFound {
|
||||
t.Fatalf("exptected ErrCredentialsNotFound, got %v", err)
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@ func New() credentials.Helper {
|
||||
func (h wincred) Add(creds *credentials.Credentials) error {
|
||||
g := winc.NewGenericCredential(creds.ServerURL)
|
||||
g.UserName = creds.Username
|
||||
g.CredentialBlob = []byte(creds.Password)
|
||||
g.CredentialBlob = []byte(creds.Secret)
|
||||
g.Persist = winc.PersistLocalMachine
|
||||
return g.Write()
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ func TestWinCredHelper(t *testing.T) {
|
||||
creds := &credentials.Credentials{
|
||||
ServerURL: "https://foobar.docker.io:2376/v1",
|
||||
Username: "foobar",
|
||||
Password: "foobarbaz",
|
||||
Secret: "foobarbaz",
|
||||
}
|
||||
|
||||
helper := New()
|
||||
@@ -18,7 +18,7 @@ func TestWinCredHelper(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
username, password, err := helper.Get(creds.ServerURL)
|
||||
username, secret, err := helper.Get(creds.ServerURL)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -27,8 +27,8 @@ func TestWinCredHelper(t *testing.T) {
|
||||
t.Fatalf("expected %s, got %s\n", "foobar", username)
|
||||
}
|
||||
|
||||
if password != "foobarbaz" {
|
||||
t.Fatalf("expected %s, got %s\n", "foobarbaz", password)
|
||||
if secret != "foobarbaz" {
|
||||
t.Fatalf("expected %s, got %s\n", "foobarbaz", secret)
|
||||
}
|
||||
|
||||
if err := helper.Delete(creds.ServerURL); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user