1
0
mirror of https://github.com/getsops/sops.git synced 2026-02-05 12:45:21 +01:00

pgp: improve handling of GnuPG home dir

There have been reports about the new logic breaking certain GnuPG
shims (#1294).

As this behavior is only really required when SDK users are making
use of the GnuPG using SOPS as an SDK. Prefer any runtime configuration
when no custom GnuPG home is configured on the key source, instead of
providing an absolute `--homedir` to `gpg`.

Signed-off-by: Hidde Beydals <hidde@hhh.computer>
This commit is contained in:
Hidde Beydals
2023-09-19 22:41:31 +02:00
parent 6cd7ca173f
commit f21d5256f0
2 changed files with 43 additions and 44 deletions

View File

@@ -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.

View File

@@ -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)