diff --git a/pgp/keysource.go b/pgp/keysource.go index b6c77bde0..ffeb0b1a2 100644 --- a/pgp/keysource.go +++ b/pgp/keysource.go @@ -318,7 +318,7 @@ func (key *MasterKey) encryptWithGnuPG(dataKey []byte) error { fingerprint, "--no-encrypt-to", } - err, stdout, stderr := gpgExec(key.gnuPGHome(), args, bytes.NewReader(dataKey)) + err, stdout, stderr := gpgExec(key.gnuPGHomeDir, args, bytes.NewReader(dataKey)) if err != nil { return fmt.Errorf("failed to encrypt sops data key with pgp: %s", strings.TrimSpace(stderr.String())) } @@ -407,7 +407,7 @@ func (key *MasterKey) decryptWithGnuPG() ([]byte, error) { args := []string{ "-d", } - err, stdout, stderr := gpgExec(key.gnuPGHome(), args, strings.NewReader(key.EncryptedKey)) + err, stdout, stderr := gpgExec(key.gnuPGHomeDir, args, strings.NewReader(key.EncryptedKey)) if err != nil { return nil, fmt.Errorf("failed to decrypt sops data key with pgp: %s", strings.TrimSpace(stderr.String())) @@ -436,27 +436,6 @@ func (key MasterKey) ToMap() map[string]interface{} { return out } -// gnuPGHome determines the GnuPG home directory for the MasterKey, and returns -// its path. In order of preference: -// 1. MasterKey.gnuPGHomeDir -// 2. $GNUPGHOME -// 3. user.Current().HomeDir/.gnupg -// 4. $HOME/.gnupg -func (key *MasterKey) gnuPGHome() string { - if key.gnuPGHomeDir == "" { - dir := os.Getenv("GNUPGHOME") - if dir == "" { - usr, err := user.Current() - if err != nil { - return filepath.Join(os.Getenv("HOME"), ".gnupg") - } - return filepath.Join(usr.HomeDir, ".gnupg") - } - return dir - } - return key.gnuPGHomeDir -} - // retrievePubKey attempts to retrieve the public key from the public keyring // by Fingerprint. func (key *MasterKey) retrievePubKey() (openpgp.Entity, error) { @@ -479,7 +458,7 @@ func (key *MasterKey) retrievePubKey() (openpgp.Entity, error) { func (key *MasterKey) getPubRing() (openpgp.EntityList, error) { path := key.pubRing if path == "" { - path = filepath.Join(key.gnuPGHome(), defaultPubRing) + path = filepath.Join(gnuPGHome(key.gnuPGHomeDir), defaultPubRing) } return loadRing(path) } @@ -490,7 +469,7 @@ func (key *MasterKey) getPubRing() (openpgp.EntityList, error) { func (key *MasterKey) getSecRing() (openpgp.EntityList, error) { path := key.secRing if path == "" { - path = filepath.Join(key.gnuPGHome(), defaultSecRing) + path = filepath.Join(gnuPGHome(key.gnuPGHomeDir), defaultSecRing) } if _, err := os.Lstat(path); err != nil { if !os.IsNotExist(err) { @@ -609,6 +588,28 @@ func gpgBinary() string { return binary } +// gnuPGHome determines the GnuPG home directory, and returns its path. +// In order of preference: +// 1. customPath +// 2. $GNUPGHOME +// 3. user.Current().HomeDir/.gnupg +// 4. $HOME/.gnupg +func gnuPGHome(customPath string) string { + if customPath != "" { + return customPath + } + + dir := os.Getenv("GNUPGHOME") + if dir == "" { + usr, err := user.Current() + if err != nil { + return filepath.Join(os.Getenv("HOME"), ".gnupg") + } + return filepath.Join(usr.HomeDir, ".gnupg") + } + return dir +} + // shortenFingerprint returns the short ID of the given fingerprint. // This is mostly used for compatability reasons, as older versions of GnuPG // do not always like long IDs. diff --git a/pgp/keysource_test.go b/pgp/keysource_test.go index 58cb32040..187a75b1d 100644 --- a/pgp/keysource_test.go +++ b/pgp/keysource_test.go @@ -271,7 +271,7 @@ func TestMasterKey_encryptWithGnuPG(t *testing.T) { args := []string{ "-d", } - err, stdout, stderr := gpgExec(key.gnuPGHome(), args, strings.NewReader(key.EncryptedKey)) + err, stdout, stderr := gpgExec(key.gnuPGHomeDir, args, strings.NewReader(key.EncryptedKey)) assert.NoError(t, err, stderr.String()) assert.Equal(t, data, stdout.Bytes()) }) @@ -529,24 +529,6 @@ func TestMasterKey_ToMap(t *testing.T) { }, key.ToMap()) } -func TestMasterKey_gnuPGHome(t *testing.T) { - key := &MasterKey{} - - usr, err := user.Current() - if err == nil { - assert.Equal(t, filepath.Join(usr.HomeDir, ".gnupg"), key.gnuPGHome()) - } else { - assert.Equal(t, filepath.Join(os.Getenv("HOME"), ".gnupg"), key.gnuPGHome()) - } - - gnupgHome := "/overwrite/home" - t.Setenv("GNUPGHOME", gnupgHome) - assert.Equal(t, gnupgHome, key.gnuPGHome()) - - key.gnuPGHomeDir = "/home/dir/overwrite" - assert.Equal(t, key.gnuPGHomeDir, key.gnuPGHome()) -} - func TestMasterKey_retrievePubKey(t *testing.T) { t.Run("existing fingerprint", func(t *testing.T) { key := NewMasterKeyFromFingerprint(mockFingerprint) @@ -671,6 +653,22 @@ func Test_gpgBinary(t *testing.T) { assert.Equal(t, overwrite, gpgBinary()) } +func Test_gnuPGHome(t *testing.T) { + usr, err := user.Current() + if err == nil { + assert.Equal(t, filepath.Join(usr.HomeDir, ".gnupg"), gnuPGHome("")) + } else { + assert.Equal(t, filepath.Join(os.Getenv("HOME"), ".gnupg"), gnuPGHome("")) + } + + gnupgHome := "/overwrite/home" + t.Setenv("GNUPGHOME", gnupgHome) + assert.Equal(t, gnupgHome, gnuPGHome("")) + + customP := "/home/dir/overwrite" + assert.Equal(t, customP, gnuPGHome(customP)) +} + func Test_shortenFingerprint(t *testing.T) { shortId := shortenFingerprint(mockFingerprint) assert.Equal(t, "9732075EA221A7EA", shortId)