1
0
mirror of https://github.com/docker/docker-credential-helpers.git synced 2026-06-13 16:01:28 +05:30

Add a Docker Credentials label support for macOS

Signed-off-by: Nassim 'Nass' Eddequiouaq <eddequiouaq.nassim@gmail.com>
This commit is contained in:
Nassim 'Nass' Eddequiouaq
2017-03-08 17:08:22 +01:00
parent 595b7f2531
commit 406812bf8e
4 changed files with 33 additions and 9 deletions
+22 -3
View File
@@ -14,7 +14,9 @@ char *get_error(OSStatus status) {
return buf; return buf;
} }
char *keychain_add(struct Server *server, char *username, char *secret) { char *keychain_add(struct Server *server, char *label, char *username, char *secret) {
SecKeychainItemRef item;
OSStatus status = SecKeychainAddInternetPassword( OSStatus status = SecKeychainAddInternetPassword(
NULL, NULL,
strlen(server->host), server->host, strlen(server->host), server->host,
@@ -25,11 +27,27 @@ char *keychain_add(struct Server *server, char *username, char *secret) {
server->proto, server->proto,
kSecAuthenticationTypeDefault, kSecAuthenticationTypeDefault,
strlen(secret), secret, strlen(secret), secret,
NULL &item
); );
if (status) { if (status) {
return get_error(status); return get_error(status);
} }
SecKeychainAttribute attribute;
SecKeychainAttributeList attrs;
attribute.tag = kSecLabelItemAttr;
attribute.data = label;
attribute.length = strlen(label);
attrs.count = 1;
attrs.attr = &attribute;
status = SecKeychainItemModifyContent(item, &attrs, 0, NULL);
if (status) {
return get_error(status);
}
return NULL; return NULL;
} }
@@ -116,11 +134,12 @@ char * CFStringToCharArr(CFStringRef aString) {
return NULL; return NULL;
} }
char *keychain_list(char *** paths, char *** accts, unsigned int *list_l) { char *keychain_list(char *credsLabel, char *** paths, char *** accts, unsigned int *list_l) {
CFMutableDictionaryRef query = CFDictionaryCreateMutable (NULL, 1, NULL, NULL); CFMutableDictionaryRef query = CFDictionaryCreateMutable (NULL, 1, NULL, NULL);
CFDictionaryAddValue(query, kSecClass, kSecClassInternetPassword); CFDictionaryAddValue(query, kSecClass, kSecClassInternetPassword);
CFDictionaryAddValue(query, kSecReturnAttributes, kCFBooleanTrue); CFDictionaryAddValue(query, kSecReturnAttributes, kCFBooleanTrue);
CFDictionaryAddValue(query, kSecMatchLimit, kSecMatchLimitAll); CFDictionaryAddValue(query, kSecMatchLimit, kSecMatchLimitAll);
CFDictionaryAddValue(query, kSecAttrLabel, CFSTR(credsLabel));
//Use this query dictionary //Use this query dictionary
CFTypeRef result= NULL; CFTypeRef result= NULL;
OSStatus status = SecItemCopyMatching( OSStatus status = SecItemCopyMatching(
+8 -3
View File
@@ -35,12 +35,14 @@ func (h Osxkeychain) Add(creds *credentials.Credentials) error {
} }
defer freeServer(s) defer freeServer(s)
label := C.CString(creds.Label)
defer C.free(unsafe.Pointer(label))
username := C.CString(creds.Username) username := C.CString(creds.Username)
defer C.free(unsafe.Pointer(username)) defer C.free(unsafe.Pointer(username))
secret := C.CString(creds.Secret) secret := C.CString(creds.Secret)
defer C.free(unsafe.Pointer(secret)) defer C.free(unsafe.Pointer(secret))
errMsg := C.keychain_add(s, username, secret) errMsg := C.keychain_add(s, label, username, secret)
if errMsg != nil { if errMsg != nil {
defer C.free(unsafe.Pointer(errMsg)) defer C.free(unsafe.Pointer(errMsg))
return errors.New(C.GoString(errMsg)) return errors.New(C.GoString(errMsg))
@@ -98,13 +100,16 @@ func (h Osxkeychain) Get(serverURL string) (string, string, error) {
} }
// List returns the stored URLs and corresponding usernames. // List returns the stored URLs and corresponding usernames.
func (h Osxkeychain) List() (map[string]string, error) { func (h Osxkeychain) List(credsLabel string) (map[string]string, error) {
credsLabelC := C.CString(credsLabel)
defer C.free(unsafe.Pointer(credsLabelC))
var pathsC **C.char var pathsC **C.char
defer C.free(unsafe.Pointer(pathsC)) defer C.free(unsafe.Pointer(pathsC))
var acctsC **C.char var acctsC **C.char
defer C.free(unsafe.Pointer(acctsC)) defer C.free(unsafe.Pointer(acctsC))
var listLenC C.uint var listLenC C.uint
errMsg := C.keychain_list(&pathsC, &acctsC, &listLenC) errMsg := C.keychain_list(credsLabelC, &pathsC, &acctsC, &listLenC)
if errMsg != nil { if errMsg != nil {
defer C.free(unsafe.Pointer(errMsg)) defer C.free(unsafe.Pointer(errMsg))
goMsg := C.GoString(errMsg) goMsg := C.GoString(errMsg)
+1 -1
View File
@@ -7,7 +7,7 @@ struct Server {
unsigned int port; unsigned int port;
}; };
char *keychain_add(struct Server *server, char *username, char *secret); char *keychain_add(struct Server *server, char *label, char *username, char *secret);
char *keychain_get(struct Server *server, unsigned int *username_l, char **username, unsigned int *secret_l, 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); char *keychain_delete(struct Server *server);
char *keychain_list(char *** data, char *** accts, unsigned int *list_l); char *keychain_list(char *** data, char *** accts, unsigned int *list_l);
+2 -2
View File
@@ -34,14 +34,14 @@ func TestOSXKeychainHelper(t *testing.T) {
t.Fatalf("expected %s, got %s\n", "foobarbaz", secret) t.Fatalf("expected %s, got %s\n", "foobarbaz", secret)
} }
auths, err := helper.List() auths, err := helper.List(credentials.CredsLabel)
if err != nil || len(auths) == 0 { if err != nil || len(auths) == 0 {
t.Fatal(err) t.Fatal(err)
} }
helper.Add(creds1) helper.Add(creds1)
defer helper.Delete(creds1.ServerURL) defer helper.Delete(creds1.ServerURL)
newauths, err := helper.List() newauths, err := helper.List(credentials.CredsLabel)
if len(newauths)-len(auths) != 1 { if len(newauths)-len(auths) != 1 {
if err == nil { if err == nil {
t.Fatalf("Error: len(newauths): %d, len(auths): %d", len(newauths), len(auths)) t.Fatalf("Error: len(newauths): %d, len(auths): %d", len(newauths), len(auths))