diff --git a/command/exec.go b/command/exec.go index 0fc22b465..9fb07d513 100644 --- a/command/exec.go +++ b/command/exec.go @@ -54,7 +54,12 @@ func (c *ExecCommand) Run(args []string) int { } if c.Keyring == nil { - c.Keyring = keyring.DefaultKeyring + var err error + c.Keyring, err = keyring.DefaultKeyring() + if err != nil { + c.Ui.Error(err.Error()) + return 1 + } } if c.profileConfig == nil { diff --git a/command/list.go b/command/list.go index 260cc8512..1a1dd6f15 100644 --- a/command/list.go +++ b/command/list.go @@ -15,7 +15,12 @@ type ListCommand struct { func (c *ListCommand) Run(args []string) int { if c.Keyring == nil { - c.Keyring = keyring.DefaultKeyring + var err error + c.Keyring, err = keyring.DefaultKeyring() + if err != nil { + c.Ui.Error(err.Error()) + return 1 + } } profileNames, err := c.Keyring.List(vault.ServiceName) diff --git a/command/remove.go b/command/remove.go index 3cd84a1b3..4f68950bf 100644 --- a/command/remove.go +++ b/command/remove.go @@ -31,7 +31,12 @@ func (c *RemoveCommand) Run(args []string) int { } if c.Keyring == nil { - c.Keyring = keyring.DefaultKeyring + var err error + c.Keyring, err = keyring.DefaultKeyring() + if err != nil { + c.Ui.Error(err.Error()) + return 1 + } } if c.profileConfig == nil { diff --git a/command/store.go b/command/store.go index 48eec0276..6facf45ff 100644 --- a/command/store.go +++ b/command/store.go @@ -31,7 +31,12 @@ func (c *StoreCommand) Run(args []string) int { } if c.Keyring == nil { - c.Keyring = keyring.DefaultKeyring + var err error + c.Keyring, err = keyring.DefaultKeyring() + if err != nil { + c.Ui.Error(err.Error()) + return 1 + } } if c.profileConfig == nil { diff --git a/keyring/keychain_darwin.go b/keyring/keychain_darwin.go index 8e71616d3..b43b0597d 100644 --- a/keyring/keychain_darwin.go +++ b/keyring/keychain_darwin.go @@ -1,8 +1,16 @@ package keyring -import keychain "github.com/99designs/aws-vault/Godeps/_workspace/src/github.com/99designs/go-osxkeychain" +import ( + "os" + "os/user" + + keychain "github.com/99designs/aws-vault/Godeps/_workspace/src/github.com/99designs/go-osxkeychain" +) + +var keychainFile string type OSXKeychain struct { + path string } func (k *OSXKeychain) Get(service, key string) ([]byte, error) { @@ -11,6 +19,10 @@ func (k *OSXKeychain) Get(service, key string) ([]byte, error) { AccountName: key, } + if k.path != "" { + attributes.Keychain = []string{k.path} + } + if b, err := keychain.FindGenericPassword(&attributes); err == keychain.ErrItemNotFound { return b, ErrKeyNotFound } else { @@ -25,6 +37,18 @@ func (k *OSXKeychain) Set(service, key string, secret []byte) error { Password: secret, } + if k.path != "" { + if _, err := os.Stat(k.path); os.IsNotExist(err) { + pass := os.Getenv("AWS_KEYCHAIN_PASSWORD") + if pass != "" { + keychain.CreateKeychain(k.path, pass) + } else { + keychain.CreateKeychainViaPrompt(k.path) + } + } + attributes.Keychain = []string{k.path} + } + err := keychain.AddGenericPassword(&attributes) if err == keychain.ErrDuplicateItem { return keychain.RemoveAndAddGenericPassword(&attributes) @@ -39,6 +63,10 @@ func (k *OSXKeychain) Remove(service, key string) error { AccountName: key, } + if k.path != "" { + attributes.Keychain = []string{k.path} + } + if err := keychain.FindAndRemoveGenericPassword(&attributes); err == keychain.ErrItemNotFound { return ErrKeyNotFound } else { @@ -47,9 +75,24 @@ func (k *OSXKeychain) Remove(service, key string) error { } func (k *OSXKeychain) List(service string) ([]string, error) { - return keychain.GetAllAccountNames(service) + keychains := []string{} + + if k.path != "" { + keychains = []string{k.path} + } + + return keychain.GetAllAccountNames(service, keychains...) } func init() { - DefaultKeyring = &OSXKeychain{} + file := os.Getenv("AWS_KEYCHAIN_FILE") + if file == "" { + usr, err := user.Current() + if err != nil { + panic(err) + } + file = usr.HomeDir + "/Library/Keychains/aws-vault.keychain" + } + + keyrings = append(keyrings, &OSXKeychain{file}) } diff --git a/keyring/keyring.go b/keyring/keyring.go index 2c843d482..1e7e71b4c 100644 --- a/keyring/keyring.go +++ b/keyring/keyring.go @@ -31,6 +31,14 @@ func Unmarshal(k Keyring, service, key string, obj interface{}) error { return nil } -var DefaultKeyring Keyring +func DefaultKeyring() (Keyring, error) { + if len(keyrings) == 0 { + return nil, ErrNoAvailImpl + } + return keyrings[0], nil +} + +var keyrings []Keyring +var ErrNoAvailImpl = errors.New("No keyring implementation for your platform available.") var ErrKeyNotFound = errors.New("The specified item could not be found in the keychain.")