Skip to content

Commit

Permalink
fix: use security cmd for keychain secret
Browse files Browse the repository at this point in the history
Signed-off-by: Dmitry K. Anisimov <[email protected]>
  • Loading branch information
anisimovdk committed Nov 30, 2024
1 parent e1afc0e commit 2d717de
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 13 deletions.
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
53 changes: 41 additions & 12 deletions pkg/providers/keychain/keychain.go
Original file line number Diff line number Diff line change
@@ -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"
Expand All @@ -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) {
Expand Down

0 comments on commit 2d717de

Please sign in to comment.