lunixbochs / go-keychain

Simple OS keychain bindings for password storage in Go (Golang)
MIT License
26 stars 9 forks source link

add Internet Password support #3

Open tmaher opened 8 years ago

tmaher commented 8 years ago

@lunixbochs : Keychain has two types of "passwords": generic and internet. The major difference is the metadata tracked with each. Generic only has two attributes: Account and Service. Internet passwords get both of those, as well as "security domain", "path", "port", "protocol", and "authentication type". Also, generic and internet each have their own helper functions. git's credential helper for OS X uses the "internet" type, and I'd like to be able to use those from this package.

lunixbochs commented 8 years ago

thanks for looking at this - I intend to add backends for other platforms eventually, so I want the API to take that into account... any thoughts?

tmaher commented 8 years ago

I intend to add backends for other platforms eventually, so I want the API to take that into account... any thoughts?

I think that's a definitional question for this package. The two distinct needs are:

  1. Many developers need a drop-dead-simple API for securely, cross-platformingly storing/retrieving credentials from local disk, without needing to learn cryptography or crypto key management. The OS-provided mechanisms are good, but suffer from excess complexity. Ignoring this PR, go-keychain's simplicity is perfect.
  2. Comparatively fewer developers need to use the more complex bits of OS-provided credential management, for interoperability or whatever. That's what I need here, to get access to git-credential-osxkeychain's backend storage.

A simple API is a much greater community need, and I don't want to compromise that. OS-complete, complex APIs could be satisfied by creating different golang packages for each OS, and making go-keychain a abstraction layer that calls out to a backend. Alternatively, it could all live in the same package, with the the complicated stuff off in its own namespace, with clear docs pointing people at the simple API first.

A while back, I wrote most of a cross-platform library for credential management in Ruby. The four big targets I could find were...

Ruby's support for calling into C has gotten better in the last couple years, so if I were to do it again, I'd have used their newer Fiddle wrapper for FFI, rather than the not-included-in-ruby-core ffi gem.

For Windows, I used DPAPI for backward-compatability reasons (present in XP and Win2K). Microsoft has since re-designed credential management a bit in each of Windows 7, 8, and 10. Current market share of Windows versions puts Windows 7 at about 48%. Given that, I think best bet for supporting a simple Go API (read/write/delete) I think is to limit it to Windows 7 APIs. CredWrite, CredRead, and the CREDENTIAL struct are supported in later OS versions. Even that, however, has a bunch of complexity hidden in the struct. You can do things like store TLS certificates.

tmaher commented 8 years ago

For an idea where I'm going with this: Hashicorp's Vault is a distributed credential management system, targeted towards servers. There's a handy CLI for developers to access it. There are a number of authentication mechanisms, including GitHub personal access tokens. My main goal in this PR is to let Vault's CLI use OS-native credential management. Operationally for me, OS X is the most important platform to do that first.