diff --git a/pgp/keysource.go b/pgp/keysource.go index 1dd975feb..8d131acf8 100644 --- a/pgp/keysource.go +++ b/pgp/keysource.go @@ -9,6 +9,7 @@ package pgp //import "github.com/getsops/sops/v3/pgp" import ( "bytes" "encoding/hex" + "errors" "fmt" "io" "os" @@ -131,9 +132,21 @@ func (d GnuPGHome) Import(armoredKey []byte) error { } args := []string{"--batch", "--import"} - _, stderr, err := gpgExec(d.String(), args, bytes.NewReader(armoredKey)) + _, stderrBuf, err := gpgExec(d.String(), args, bytes.NewReader(armoredKey)) if err != nil { - return fmt.Errorf("failed to import armored key data into GnuPG keyring: %s", strings.TrimSpace(stderr.String())) + stderr := stderrBuf.String() + errStr := err.Error() + var sb strings.Builder + sb.WriteString("failed to import armored key data into GnuPG keyring") + if len(stderr) > 0 { + fmt.Fprintf(&sb, ": %s", stderr) + if len(errStr) > 0 { + fmt.Fprintf(&sb, ": %s", errStr) + } + } else if len(errStr) > 0 { + fmt.Fprintf(&sb, ": %s", errStr) + } + return errors.New(sb.String()) } return nil } diff --git a/pgp/keysource_test.go b/pgp/keysource_test.go index b72bf8a92..5ce05a680 100644 --- a/pgp/keysource_test.go +++ b/pgp/keysource_test.go @@ -66,10 +66,27 @@ func TestGnuPGHome_Import(t *testing.T) { _, stderr, err = gpgExec(gnuPGHome.String(), []string{"--list-secret-keys", mockFingerprint}, nil) assert.NoErrorf(t, err, stderr.String()) - assert.Error(t, gnuPGHome.Import([]byte("invalid armored data"))) + err = gnuPGHome.Import([]byte("invalid armored data")) + assert.Error(t, err) + assert.ErrorContains(t, err, "gpg: no valid OpenPGP data found.\ngpg: Total number processed: 0\n: exit status 2") assert.Error(t, GnuPGHome("").Import(b)) } +func TestGnuPGHome_Import_With_Missing_Binary(t *testing.T) { + t.Setenv(SopsGpgExecEnv, "/does/not/exist") + + gnuPGHome, err := NewGnuPGHome() + assert.NoError(t, err) + t.Cleanup(func() { + _ = os.RemoveAll(gnuPGHome.String()) + }) + + b, err := os.ReadFile(mockPublicKey) + assert.NoError(t, err) + err = gnuPGHome.Import(b) + assert.ErrorContains(t, err, "failed to import armored key data into GnuPG keyring: fork/exec /does/not/exist: no such file or directory") +} + func TestGnuPGHome_ImportFile(t *testing.T) { gnuPGHome, err := NewGnuPGHome() assert.NoError(t, err)