diff --git a/go.mod b/go.mod index 484834b..07e6c6c 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,6 @@ require ( github.com/google/go-cmp v0.6.0 github.com/hashicorp/golang-lru v1.0.2 github.com/hashicorp/vault/api v1.15.0 - github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 github.com/stretchr/testify v1.10.0 github.com/tidwall/gjson v1.18.0 golang.org/x/oauth2 v0.24.0 diff --git a/pkg/providers/keychain/keychain.go b/pkg/providers/keychain/keychain.go index 7132ca0..3980aa1 100644 --- a/pkg/providers/keychain/keychain.go +++ b/pkg/providers/keychain/keychain.go @@ -1,13 +1,15 @@ package keychain import ( + "encoding/hex" "errors" + "os/exec" + "runtime" "strings" "gopkg.in/yaml.v3" "github.com/helmfile/vals/pkg/api" - "github.com/keybase/go-keychain" ) const keychainKind = "vals-secret" @@ -20,22 +22,49 @@ func New(cfg api.StaticConfig) *provider { return p } +// isHex checks if a string is a valid hexadecimal string +func isHex(s string) bool { + // Check if the string length is even + if len(s)%2 != 0 { + return false + } + + // Attempt to decode the string + _, err := hex.DecodeString(s) + return err == nil // If no error, it's valid hex +} + +// isDarwin checks if the current OS is macOS +func isDarwin() bool { + return runtime.GOOS == "darwin" +} + +// getKeychainSecret retrieves a secret from the macOS keychain with security find-generic-password func getKeychainSecret(key string) ([]byte, error) { - query := keychain.NewItem() - query.SetSecClass(keychain.SecClassGenericPassword) - query.SetLabel(key) - query.SetDescription(keychainKind) - query.SetMatchLimit(keychain.MatchLimitOne) - query.SetReturnData(true) - - results, err := keychain.QueryItem(query) + if !isDarwin() { + return nil, errors.New("keychain provider is only supported on macOS") + } + + // Get the secret from the keychain with 'security find-generic-password' command + getKeyCmd := exec.Command("security", "find-generic-password", "-w", "-D", keychainKind, "-s", key) + + result, err := getKeyCmd.Output() if err != nil { return nil, err - } else if len(results) == 0 { - return nil, errors.New("not found") } - return results[0].Data, nil + stringResult := string(result) + stringResult = strings.TrimSpace(stringResult) + + // If the result is a hexadecimal string, decode it. + if isHex(stringResult) { + result, err = hex.DecodeString(stringResult) + if err != nil { + return nil, err + } + } + + return result, nil } func (p *provider) GetString(key string) (string, error) {